@dasasian/firebase-structured-logger 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +652 -91
  2. package/dist/client/breadcrumbs.d.ts +14 -2
  3. package/dist/client/breadcrumbs.d.ts.map +1 -1
  4. package/dist/client/breadcrumbs.js +39 -21
  5. package/dist/client/breadcrumbs.js.map +1 -1
  6. package/dist/client/index.d.ts +3 -3
  7. package/dist/client/index.d.ts.map +1 -1
  8. package/dist/client/index.js +2 -2
  9. package/dist/client/index.js.map +1 -1
  10. package/dist/client/logger.d.ts +29 -0
  11. package/dist/client/logger.d.ts.map +1 -1
  12. package/dist/client/logger.js +39 -5
  13. package/dist/client/logger.js.map +1 -1
  14. package/dist/client/rateLimiter.d.ts +8 -3
  15. package/dist/client/rateLimiter.d.ts.map +1 -1
  16. package/dist/client/rateLimiter.js +9 -4
  17. package/dist/client/rateLimiter.js.map +1 -1
  18. package/dist/functions/httpHandler.d.ts +89 -0
  19. package/dist/functions/httpHandler.d.ts.map +1 -0
  20. package/dist/functions/httpHandler.js +112 -0
  21. package/dist/functions/httpHandler.js.map +1 -0
  22. package/dist/functions/index.d.ts +6 -3
  23. package/dist/functions/index.d.ts.map +1 -1
  24. package/dist/functions/index.js +6 -2
  25. package/dist/functions/index.js.map +1 -1
  26. package/dist/functions/logHandler.d.ts +53 -2
  27. package/dist/functions/logHandler.d.ts.map +1 -1
  28. package/dist/functions/logHandler.js +38 -7
  29. package/dist/functions/logHandler.js.map +1 -1
  30. package/dist/functions/logger.d.ts.map +1 -1
  31. package/dist/functions/logger.js +95 -7
  32. package/dist/functions/logger.js.map +1 -1
  33. package/dist/functions/requestLogger.d.ts +2 -20
  34. package/dist/functions/requestLogger.d.ts.map +1 -1
  35. package/dist/functions/requestLogger.js +2 -39
  36. package/dist/functions/requestLogger.js.map +1 -1
  37. package/dist/functions/sourceMapCache.d.ts +27 -1
  38. package/dist/functions/sourceMapCache.d.ts.map +1 -1
  39. package/dist/functions/sourceMapCache.js +84 -9
  40. package/dist/functions/sourceMapCache.js.map +1 -1
  41. package/dist/functions/traceContext.d.ts +40 -0
  42. package/dist/functions/traceContext.d.ts.map +1 -0
  43. package/dist/functions/traceContext.js +93 -0
  44. package/dist/functions/traceContext.js.map +1 -0
  45. package/dist/shared/paths.d.ts +59 -0
  46. package/dist/shared/paths.d.ts.map +1 -0
  47. package/dist/shared/paths.js +126 -0
  48. package/dist/shared/paths.js.map +1 -0
  49. package/dist/shared/severity.d.ts +21 -0
  50. package/dist/shared/severity.d.ts.map +1 -1
  51. package/dist/shared/severity.js +31 -3
  52. package/dist/shared/severity.js.map +1 -1
  53. package/dist/shared/types.d.ts +1 -2
  54. package/dist/shared/types.d.ts.map +1 -1
  55. package/dist/tools/index.js +13 -4
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/tools/uploadSourceMaps.d.ts +24 -1
  58. package/dist/tools/uploadSourceMaps.d.ts.map +1 -1
  59. package/dist/tools/uploadSourceMaps.js +31 -4
  60. package/dist/tools/uploadSourceMaps.js.map +1 -1
  61. package/package.json +4 -4
  62. package/skills/logs/SKILL.md +32 -9
  63. package/skills/query-logs/SKILL.md +14 -1
@@ -1,8 +1,20 @@
1
1
  import type { BreadcrumbEntry } from '../shared/types';
2
+ /**
3
+ * How many breadcrumbs are retained — and therefore how many are sent.
4
+ *
5
+ * These were two numbers once: the trail kept 50 and the send path asked for
6
+ * 20, so 30 were retained that nothing could ever read. Exported for the send
7
+ * path to import rather than restate, because the two drifting apart is silent
8
+ * — the extra entries simply never appear in any log, and nothing fails.
9
+ *
10
+ * MAX_AGE_MS is the filter that actually matters; this is the safety net that
11
+ * bounds a long-lived tab. Sending the whole retained trail costs ~5 KB, which
12
+ * is 2% of Cloud Logging's 256 KB entry limit, against losing the steps that
13
+ * would have reproduced the bug.
14
+ */
15
+ export declare const MAX_BREADCRUMBS = 50;
2
16
  export declare function setCurrentScreen(screen: string): void;
3
- export declare function setActiveActivity(activity: string | undefined): void;
4
17
  export declare function getCurrentScreen(): string | undefined;
5
- export declare function getActiveActivity(): string | undefined;
6
18
  export declare function addBreadcrumb(type: BreadcrumbEntry['type'], name: string, data?: Record<string, unknown>): void;
7
19
  export declare function getLastBreadcrumbs(count: number): BreadcrumbEntry[];
8
20
  export declare function clearBreadcrumbs(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAStD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEpE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAEtD;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAeN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAEnE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED,eAAO,MAAM,EAAE;mBACE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACpC,MAAM;kBACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACtD,CAAA"}
1
+ {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,KAAK,CAAA;AAMjC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAoBD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAQN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAKnE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED,eAAO,MAAM,EAAE;mBACE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACtC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;kBACpC,MAAM;kBACR,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CACtD,CAAA"}
@@ -1,52 +1,70 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bc = void 0;
3
+ exports.bc = exports.MAX_BREADCRUMBS = void 0;
4
4
  exports.setCurrentScreen = setCurrentScreen;
5
- exports.setActiveActivity = setActiveActivity;
6
5
  exports.getCurrentScreen = getCurrentScreen;
7
- exports.getActiveActivity = getActiveActivity;
8
6
  exports.addBreadcrumb = addBreadcrumb;
9
7
  exports.getLastBreadcrumbs = getLastBreadcrumbs;
10
8
  exports.clearBreadcrumbs = clearBreadcrumbs;
11
- const MAX_BREADCRUMBS = 50;
9
+ /**
10
+ * How many breadcrumbs are retained — and therefore how many are sent.
11
+ *
12
+ * These were two numbers once: the trail kept 50 and the send path asked for
13
+ * 20, so 30 were retained that nothing could ever read. Exported for the send
14
+ * path to import rather than restate, because the two drifting apart is silent
15
+ * — the extra entries simply never appear in any log, and nothing fails.
16
+ *
17
+ * MAX_AGE_MS is the filter that actually matters; this is the safety net that
18
+ * bounds a long-lived tab. Sending the whole retained trail costs ~5 KB, which
19
+ * is 2% of Cloud Logging's 256 KB entry limit, against losing the steps that
20
+ * would have reproduced the bug.
21
+ */
22
+ exports.MAX_BREADCRUMBS = 50;
12
23
  const MAX_AGE_MS = 5 * 60 * 1000; // 5 minutes
13
24
  let currentScreen;
14
- let activeActivity;
15
25
  let breadcrumbs = [];
16
26
  function setCurrentScreen(screen) {
17
27
  currentScreen = screen;
18
28
  addBreadcrumb('nav', `navigate_${screen}`);
19
29
  }
20
- function setActiveActivity(activity) {
21
- activeActivity = activity;
22
- }
23
30
  function getCurrentScreen() {
24
31
  return currentScreen;
25
32
  }
26
- function getActiveActivity() {
27
- return activeActivity;
33
+ /**
34
+ * Drop anything past the age cutoff.
35
+ *
36
+ * Applied on READ as well as on write. Expiring only on write means the cutoff
37
+ * lapses exactly when nothing is happening — a user who goes idle for ten
38
+ * minutes and then hits an error sends a trail of ten-minute-old steps
39
+ * presented as the path that led there. The steps before a pause are rarely
40
+ * the ones that explain what happened after it.
41
+ *
42
+ * Entries are appended in timestamp order, so the array only needs rebuilding
43
+ * when the oldest one has actually aged out.
44
+ */
45
+ function unexpired(entries, now) {
46
+ const cutoff = now - MAX_AGE_MS;
47
+ if (entries.length === 0 || entries[0].timestamp > cutoff)
48
+ return entries;
49
+ return entries.filter((bc) => bc.timestamp > cutoff);
28
50
  }
29
51
  function addBreadcrumb(type, name, data) {
30
52
  const now = Date.now();
31
- const entry = { timestamp: now, type, name, data };
32
- breadcrumbs.push(entry);
33
- // Entries are appended in timestamp order, so only rebuild the array when the
34
- // oldest one has actually aged out — otherwise there is nothing to drop.
35
- const cutoff = now - MAX_AGE_MS;
36
- if (breadcrumbs[0].timestamp <= cutoff) {
37
- breadcrumbs = breadcrumbs.filter((bc) => bc.timestamp > cutoff);
38
- }
39
- if (breadcrumbs.length > MAX_BREADCRUMBS) {
40
- breadcrumbs = breadcrumbs.slice(breadcrumbs.length - MAX_BREADCRUMBS);
53
+ breadcrumbs.push({ timestamp: now, type, name, data });
54
+ breadcrumbs = unexpired(breadcrumbs, now);
55
+ if (breadcrumbs.length > exports.MAX_BREADCRUMBS) {
56
+ breadcrumbs = breadcrumbs.slice(breadcrumbs.length - exports.MAX_BREADCRUMBS);
41
57
  }
42
58
  }
43
59
  function getLastBreadcrumbs(count) {
60
+ // Prune the stored trail too, so an idle tab does not hold expired entries
61
+ // alive until the next write.
62
+ breadcrumbs = unexpired(breadcrumbs, Date.now());
44
63
  return breadcrumbs.slice(Math.max(0, breadcrumbs.length - count));
45
64
  }
46
65
  function clearBreadcrumbs() {
47
66
  breadcrumbs = [];
48
67
  currentScreen = undefined;
49
- activeActivity = undefined;
50
68
  }
51
69
  exports.bc = {
52
70
  action: (name, data) => addBreadcrumb('action', name, data),
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":";;;AASA,4CAGC;AAED,8CAEC;AAED,4CAEC;AAED,8CAEC;AAED,sCAmBC;AAED,gDAEC;AAED,4CAIC;AArDD,MAAM,eAAe,GAAG,EAAE,CAAA;AAC1B,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAE7C,IAAI,aAAiC,CAAA;AACrC,IAAI,cAAkC,CAAA;AACtC,IAAI,WAAW,GAAsB,EAAE,CAAA;AAEvC,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,aAAa,GAAG,MAAM,CAAA;IACtB,aAAa,CAAC,KAAK,EAAE,YAAY,MAAM,EAAE,CAAC,CAAA;AAC5C,CAAC;AAED,SAAgB,iBAAiB,CAAC,QAA4B;IAC5D,cAAc,GAAG,QAAQ,CAAA;AAC3B,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,aAAa,CAAA;AACtB,CAAC;AAED,SAAgB,iBAAiB;IAC/B,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,SAAgB,aAAa,CAC3B,IAA6B,EAC7B,IAAY,EACZ,IAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,MAAM,KAAK,GAAoB,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACnE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAEvB,8EAA8E;IAC9E,yEAAyE;IACzE,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,CAAA;IAC/B,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,MAAM,EAAE,CAAC;QACvC,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC,CAAA;IACjE,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACzC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,eAAe,CAAC,CAAA;IACvE,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,SAAgB,gBAAgB;IAC9B,WAAW,GAAG,EAAE,CAAA;IAChB,aAAa,GAAG,SAAS,CAAA;IACzB,cAAc,GAAG,SAAS,CAAA;AAC5B,CAAC;AAEY,QAAA,EAAE,GAAG;IAChB,MAAM,EAAE,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;IAC7F,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;IAC5F,GAAG,EAAK,CAAC,MAAc,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACpD,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;CAC7F,CAAA"}
1
+ {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../../src/client/breadcrumbs.ts"],"names":[],"mappings":";;;AAqBA,4CAGC;AAED,4CAEC;AAoBD,sCAYC;AAED,gDAKC;AAED,4CAGC;AAtED;;;;;;;;;;;;GAYG;AACU,QAAA,eAAe,GAAG,EAAE,CAAA;AACjC,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAE7C,IAAI,aAAiC,CAAA;AACrC,IAAI,WAAW,GAAsB,EAAE,CAAA;AAEvC,SAAgB,gBAAgB,CAAC,MAAc;IAC7C,aAAa,GAAG,MAAM,CAAA;IACtB,aAAa,CAAC,KAAK,EAAE,YAAY,MAAM,EAAE,CAAC,CAAA;AAC5C,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,aAAa,CAAA;AACtB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,SAAS,CAAC,OAA0B,EAAE,GAAW;IACxD,MAAM,MAAM,GAAG,GAAG,GAAG,UAAU,CAAA;IAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM;QAAE,OAAO,OAAO,CAAA;IACzE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC,CAAA;AACtD,CAAC;AAED,SAAgB,aAAa,CAC3B,IAA6B,EAC7B,IAAY,EACZ,IAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,WAAW,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IACtD,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;IAEzC,IAAI,WAAW,CAAC,MAAM,GAAG,uBAAe,EAAE,CAAC;QACzC,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,uBAAe,CAAC,CAAA;IACvE,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,2EAA2E;IAC3E,8BAA8B;IAC9B,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAChD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAA;AACnE,CAAC;AAED,SAAgB,gBAAgB;IAC9B,WAAW,GAAG,EAAE,CAAA;IAChB,aAAa,GAAG,SAAS,CAAA;AAC3B,CAAC;AAEY,QAAA,EAAE,GAAG;IAChB,MAAM,EAAE,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;IAC7F,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;IAC5F,GAAG,EAAK,CAAC,MAAc,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACpD,KAAK,EAAG,CAAC,IAAY,EAAE,IAA8B,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;CAC7F,CAAA"}
@@ -1,6 +1,6 @@
1
- export { initLogger, getClientLogger, triggerTestLog } from './logger';
2
- export type { Logger, InitLoggerConfig, RateLimitConfig } from './logger';
1
+ export { initLogger, getClientLogger, sendFeedback, triggerTestLog } from './logger';
2
+ export type { Logger, InitLoggerConfig, FeedbackOptions, RateLimitConfig } from './logger';
3
3
  export { setupGlobalErrorHandler, handleReactError } from './errorHandler';
4
- export { addBreadcrumb, setActiveActivity, bc } from './breadcrumbs';
4
+ export { addBreadcrumb, bc } from './breadcrumbs';
5
5
  export type { LogSeverity, LogPayload, BreadcrumbEntry, BaseLabels } from '../shared/types';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAMtE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACzE,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AACpE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAMpF,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1F,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AACjD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA"}
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bc = exports.setActiveActivity = exports.addBreadcrumb = exports.handleReactError = exports.setupGlobalErrorHandler = exports.triggerTestLog = exports.getClientLogger = exports.initLogger = void 0;
3
+ exports.bc = exports.addBreadcrumb = exports.handleReactError = exports.setupGlobalErrorHandler = exports.triggerTestLog = exports.sendFeedback = exports.getClientLogger = exports.initLogger = void 0;
4
4
  var logger_1 = require("./logger");
5
5
  Object.defineProperty(exports, "initLogger", { enumerable: true, get: function () { return logger_1.initLogger; } });
6
6
  Object.defineProperty(exports, "getClientLogger", { enumerable: true, get: function () { return logger_1.getClientLogger; } });
7
+ Object.defineProperty(exports, "sendFeedback", { enumerable: true, get: function () { return logger_1.sendFeedback; } });
7
8
  Object.defineProperty(exports, "triggerTestLog", { enumerable: true, get: function () { return logger_1.triggerTestLog; } });
8
9
  var errorHandler_1 = require("./errorHandler");
9
10
  Object.defineProperty(exports, "setupGlobalErrorHandler", { enumerable: true, get: function () { return errorHandler_1.setupGlobalErrorHandler; } });
10
11
  Object.defineProperty(exports, "handleReactError", { enumerable: true, get: function () { return errorHandler_1.handleReactError; } });
11
12
  var breadcrumbs_1 = require("./breadcrumbs");
12
13
  Object.defineProperty(exports, "addBreadcrumb", { enumerable: true, get: function () { return breadcrumbs_1.addBreadcrumb; } });
13
- Object.defineProperty(exports, "setActiveActivity", { enumerable: true, get: function () { return breadcrumbs_1.setActiveActivity; } });
14
14
  Object.defineProperty(exports, "bc", { enumerable: true, get: function () { return breadcrumbs_1.bc; } });
15
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAAA,mCAAsE;AAA7D,oGAAA,UAAU,OAAA;AAAE,yGAAA,eAAe,OAAA;AAAE,wGAAA,cAAc,OAAA;AAOpD,+CAA0E;AAAjE,uHAAA,uBAAuB,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AAClD,6CAAoE;AAA3D,4GAAA,aAAa,OAAA;AAAE,gHAAA,iBAAiB,OAAA;AAAE,iGAAA,EAAE,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAAA,mCAAoF;AAA3E,oGAAA,UAAU,OAAA;AAAE,yGAAA,eAAe,OAAA;AAAE,sGAAA,YAAY,OAAA;AAAE,wGAAA,cAAc,OAAA;AAOlE,+CAA0E;AAAjE,uHAAA,uBAAuB,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AAClD,6CAAiD;AAAxC,4GAAA,aAAa,OAAA;AAAE,iGAAA,EAAE,OAAA"}
@@ -2,6 +2,12 @@ import type { LogSeverity, LogPayload, BaseLabels } from '../shared/types';
2
2
  import { type RateLimitConfig } from './rateLimiter';
3
3
  export type { RateLimitConfig };
4
4
  type LogCallable = (data: LogPayload) => Promise<unknown>;
5
+ export interface FeedbackOptions<AppLabels extends Record<string, string | undefined> = Record<string, string | undefined>> {
6
+ /** A screenshot or any file. Rides the same GCS path as error attachments. */
7
+ attachments?: Record<string, Blob | File | string>;
8
+ /** Anything the app wants to tag — which widget, which flow, its own ticket id. */
9
+ labels?: Partial<AppLabels & BaseLabels>;
10
+ }
5
11
  export interface InitLoggerConfig<AppLabels extends Record<string, string | undefined> = Record<string, string | undefined>> {
6
12
  appId: string;
7
13
  releaseId: string;
@@ -23,8 +29,31 @@ export declare class Logger<AppLabels extends Record<string, string | undefined>
23
29
  info(message: string, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
24
30
  warning(message: string, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
25
31
  debug(message: string, labels?: Partial<AppLabels & BaseLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): void;
32
+ /**
33
+ * Send feedback a user typed, carrying everything the logger already knows.
34
+ *
35
+ * This exists because error tracking only sees things that throw. A button
36
+ * that does nothing, a total that comes out wrong, the wrong data rendered —
37
+ * none of them throw, so none are captured, and you hear about them weeks
38
+ * later. Feedback is the capture mechanism for that whole class, and it is
39
+ * actionable only because the breadcrumb trail is already in memory when the
40
+ * user hits send: "the discount didn't apply" is a complaint, the same
41
+ * sentence plus the trail is a reproduction.
42
+ *
43
+ * Headless — the app owns the UI. Returns nothing: a reference number is
44
+ * meaningless to a user with no portal to check it against. An app wanting
45
+ * correlation passes its own id as a label, which it knows before sending.
46
+ */
47
+ sendFeedback(text: string, extras?: FeedbackOptions<AppLabels>): void;
26
48
  private send;
27
49
  }
50
+ /**
51
+ * Send user feedback through the configured logger.
52
+ *
53
+ * Module-level for the same reason as `addBreadcrumb` and `bc`: the app calls
54
+ * it from wherever its feedback UI lives, without threading a logger through.
55
+ */
56
+ export declare function sendFeedback<AppLabels extends Record<string, string | undefined> = Record<string, string | undefined>>(text: string, extras?: FeedbackOptions<AppLabels>): void;
28
57
  /**
29
58
  * Trigger a test log entry to verify the logging pipeline is working end-to-end.
30
59
  * Logs at all severities with errorType: 'fsl-verify'. Safe to call in dev only.
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Logger = void 0;
4
+ exports.sendFeedback = sendFeedback;
4
5
  exports.triggerTestLog = triggerTestLog;
5
6
  exports.initLogger = initLogger;
6
7
  exports.getClientLogger = getClientLogger;
@@ -86,7 +87,7 @@ class Logger {
86
87
  errorType: error.name || 'UnknownError',
87
88
  ...labels,
88
89
  };
89
- void this.send(error.message, 'ERROR', errorLabels, context, attachments, (0, error_1.toErrorPayload)(error), (0, rateLimiter_1.signatureFor)(error, (0, breadcrumbs_1.getCurrentScreen)(), (0, breadcrumbs_1.getActiveActivity)()));
90
+ void this.send(error.message, 'ERROR', errorLabels, context, attachments, (0, error_1.toErrorPayload)(error), (0, rateLimiter_1.signatureFor)(error, (0, breadcrumbs_1.getCurrentScreen)()));
90
91
  }
91
92
  info(message, labels, context, attachments) {
92
93
  void this.send(message, 'INFO', labels, context, attachments);
@@ -97,13 +98,37 @@ class Logger {
97
98
  debug(message, labels, context, attachments) {
98
99
  void this.send(message, 'DEBUG', labels, context, attachments);
99
100
  }
100
- async send(message, severity, labels, context, attachments, error, signature) {
101
- if (severity_1.SEVERITY_ORDER[severity] > this.minLevel)
101
+ /**
102
+ * Send feedback a user typed, carrying everything the logger already knows.
103
+ *
104
+ * This exists because error tracking only sees things that throw. A button
105
+ * that does nothing, a total that comes out wrong, the wrong data rendered —
106
+ * none of them throw, so none are captured, and you hear about them weeks
107
+ * later. Feedback is the capture mechanism for that whole class, and it is
108
+ * actionable only because the breadcrumb trail is already in memory when the
109
+ * user hits send: "the discount didn't apply" is a complaint, the same
110
+ * sentence plus the trail is a reproduction.
111
+ *
112
+ * Headless — the app owns the UI. Returns nothing: a reference number is
113
+ * meaningless to a user with no portal to check it against. An app wanting
114
+ * correlation passes its own id as a label, which it knows before sending.
115
+ */
116
+ sendFeedback(text, extras) {
117
+ void this.send(text, 'NOTICE', { [severity_1.FEEDBACK_LABEL]: 'true', ...extras?.labels }, undefined, extras?.attachments, undefined, undefined, true);
118
+ }
119
+ async send(message, severity, labels, context, attachments, error, signature,
120
+ // Both gates below are volume and cost controls for events the SYSTEM
121
+ // emits. Feedback is a person sending a message that happens to travel the
122
+ // same pipe — it is rare by nature and there is nothing to throttle. The
123
+ // exemption keys on the record being feedback, not on its severity, so a
124
+ // NOTICE emitted for anything else still behaves normally.
125
+ bypassVolumeControls = false) {
126
+ if (!bypassVolumeControls && severity_1.SEVERITY_ORDER[severity] > this.minLevel)
102
127
  return;
103
128
  // One gate for every severity. Passing a signature opts this log into
104
129
  // duplicate suppression; the check and the budget spend are one operation,
105
130
  // so a log can neither be counted twice nor checked without being counted.
106
- const decision = (0, rateLimiter_1.allow)(signature);
131
+ const decision = bypassVolumeControls ? { allowed: true } : (0, rateLimiter_1.allow)(signature);
107
132
  if (!decision.allowed) {
108
133
  if (decision.reason === 'duplicate') {
109
134
  console.warn(`[fsl] Duplicate suppressed: ${decision.signature}`);
@@ -156,7 +181,7 @@ class Logger {
156
181
  severity,
157
182
  labels: allLabels,
158
183
  jsonPayload: {
159
- breadcrumbs: (0, breadcrumbs_1.getLastBreadcrumbs)(20),
184
+ breadcrumbs: (0, breadcrumbs_1.getLastBreadcrumbs)(breadcrumbs_1.MAX_BREADCRUMBS),
160
185
  context,
161
186
  error,
162
187
  },
@@ -170,6 +195,15 @@ class Logger {
170
195
  }
171
196
  }
172
197
  exports.Logger = Logger;
198
+ /**
199
+ * Send user feedback through the configured logger.
200
+ *
201
+ * Module-level for the same reason as `addBreadcrumb` and `bc`: the app calls
202
+ * it from wherever its feedback UI lives, without threading a logger through.
203
+ */
204
+ function sendFeedback(text, extras) {
205
+ getClientLogger().sendFeedback(text, extras);
206
+ }
173
207
  /**
174
208
  * Trigger a test log entry to verify the logging pipeline is working end-to-end.
175
209
  * Logs at all severities with errorType: 'fsl-verify'. Safe to call in dev only.
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/client/logger.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,15 @@ export interface RateLimitConfig {
6
6
  export declare function configureRateLimiter(options: RateLimitConfig): void;
7
7
  /**
8
8
  * Build the key used to recognise a repeat of the same problem. Two occurrences
9
- * count as duplicates only if the message, the screen and the activity all match,
10
- * so the same error from two different places is not collapsed into one.
9
+ * count as duplicates only if the message and the screen both match, so the same
10
+ * error from two different screens is not collapsed into one.
11
+ *
12
+ * This is coarse: the same error reached by two different paths on ONE screen
13
+ * still collapses, and the second path can be suppressed before anyone sees it.
14
+ * See #29 — deriving the path from breadcrumbs would discriminate properly,
15
+ * without the staleness of a span someone has to remember to clear.
11
16
  */
12
- export declare function signatureFor(error: Error | string, screen?: string, activity?: string): string;
17
+ export declare function signatureFor(error: Error | string, screen?: string): string;
13
18
  export type RateLimitDecision = {
14
19
  allowed: true;
15
20
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"rateLimiter.d.ts","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAeD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAEnE;AAmBD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,GAAG,MAAM,EACrB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAGR;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAkB3D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC"}
1
+ {"version":3,"file":"rateLimiter.d.ts","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAeD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAEnE;AAmBD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,GAAG,MAAM,EACrB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAGR;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAkB3D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC"}
@@ -36,12 +36,17 @@ function writeState(state) {
36
36
  }
37
37
  /**
38
38
  * Build the key used to recognise a repeat of the same problem. Two occurrences
39
- * count as duplicates only if the message, the screen and the activity all match,
40
- * so the same error from two different places is not collapsed into one.
39
+ * count as duplicates only if the message and the screen both match, so the same
40
+ * error from two different screens is not collapsed into one.
41
+ *
42
+ * This is coarse: the same error reached by two different paths on ONE screen
43
+ * still collapses, and the second path can be suppressed before anyone sees it.
44
+ * See #29 — deriving the path from breadcrumbs would discriminate properly,
45
+ * without the staleness of a span someone has to remember to clear.
41
46
  */
42
- function signatureFor(error, screen, activity) {
47
+ function signatureFor(error, screen) {
43
48
  const str = error instanceof Error ? `${error.name}:${error.message}` : String(error);
44
- return `${str}|${screen ?? ''}|${activity ?? ''}`;
49
+ return `${str}|${screen ?? ''}`;
45
50
  }
46
51
  /**
47
52
  * Decide whether one log may be sent, and consume its budget if so.
@@ -1 +1 @@
1
- {"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rateLimiter.js","sourceRoot":"","sources":["../../src/client/rateLimiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Receive client logs over plain HTTP, for a backend that is not Cloud Functions
3
+ * (#34).
4
+ *
5
+ * The client half was already portable — `logFunction` is any
6
+ * `(payload) => Promise<unknown>`, and `httpsCallable()` merely happens to fit.
7
+ * What was missing was a receiving end that does not require a callable.
8
+ *
9
+ * This is deliberately framework-agnostic. It reads `method`, `headers` and a
10
+ * parsed `body`, and writes through `statusCode` / `setHeader` / `end` — the
11
+ * Node core shapes, which Express, Fastify's compat layer and Cloud Run's raw
12
+ * server all satisfy. Parsing the body is the caller's job (`express.json()` or
13
+ * equivalent); reading the stream here would mean guessing at limits and
14
+ * encodings that the host framework already has opinions about.
15
+ */
16
+ import { type ClientLogHandlerConfig } from './logHandler';
17
+ /** The parts of a request this handler reads. */
18
+ export interface HttpLogRequest {
19
+ method?: string;
20
+ headers: Record<string, string | string[] | undefined>;
21
+ body?: unknown;
22
+ }
23
+ /** The parts of a response this handler writes. */
24
+ export interface HttpLogResponse {
25
+ statusCode: number;
26
+ setHeader(name: string, value: string): unknown;
27
+ end(body?: string): unknown;
28
+ }
29
+ export interface HttpLogHandlerConfig extends ClientLogHandlerConfig {
30
+ /**
31
+ * Who is allowed to POST a log.
32
+ *
33
+ * Required, and with no default, because the honest default does not exist. A
34
+ * callable gets Firebase's own token check for free; an HTTP endpoint gets
35
+ * nothing, and an open one writes to the customer's Cloud Logging bill on
36
+ * anyone's say-so.
37
+ *
38
+ * This is a **gate, not an identity check**. The handler never reads
39
+ * `request.auth` — `userId` arrives self-reported in the client's own labels
40
+ * either way. Its job is to keep strangers out, not to establish who is
41
+ * speaking.
42
+ *
43
+ * Verify a Firebase ID token:
44
+ *
45
+ * import { getAuth } from 'firebase-admin/auth'
46
+ * authorize: async (req) => {
47
+ * const header = String(req.headers.authorization ?? '')
48
+ * if (!header.startsWith('Bearer ')) return false
49
+ * try { await getAuth().verifyIdToken(header.slice(7)); return true }
50
+ * catch { return false }
51
+ * }
52
+ *
53
+ * Pass the literal `'unauthenticated'` to open the endpoint deliberately —
54
+ * behind a VPC, an API gateway, or IAM that already did the work. It is spelled
55
+ * out at the call site so nobody arrives there by omission.
56
+ */
57
+ authorize: ((request: HttpLogRequest) => boolean | Promise<boolean>) | 'unauthenticated';
58
+ /**
59
+ * Value for `Access-Control-Allow-Origin`. Defaults to `*`, matching
60
+ * `createClientLogFunction`'s `cors: true`.
61
+ *
62
+ * A browser cannot send credentials to a wildcard origin, so name your origins
63
+ * if the gate above reads a cookie. A bearer token in a header is unaffected.
64
+ */
65
+ allowOrigin?: string;
66
+ }
67
+ /**
68
+ * Build a request handler that receives `LogPayload` over HTTP.
69
+ *
70
+ * import express from 'express'
71
+ * import { createHttpLogHandler } from '@dasasian/firebase-structured-logger/functions'
72
+ *
73
+ * const app = express()
74
+ * app.use(express.json({ limit: '10mb' })) // attachments ride in the body
75
+ * app.post('/log', createHttpLogHandler({ bucketName, authorize }))
76
+ *
77
+ * On the client, point `logFunction` at it:
78
+ *
79
+ * logFunction: async (payload) => {
80
+ * const res = await fetch('/log', {
81
+ * method: 'POST',
82
+ * headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${await user.getIdToken()}` },
83
+ * body: JSON.stringify(payload),
84
+ * })
85
+ * if (!res.ok) throw new Error(`log rejected: ${res.status}`)
86
+ * }
87
+ */
88
+ export declare function createHttpLogHandler(config: HttpLogHandlerConfig): (req: HttpLogRequest, res: HttpLogResponse) => Promise<void>;
89
+ //# sourceMappingURL=httpHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpHandler.d.ts","sourceRoot":"","sources":["../../src/functions/httpHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAA0C,KAAK,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAIlG,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IACtD,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,oBAAqB,SAAQ,sBAAsB;IAClE;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,iBAAiB,CAAA;IAExF;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAiBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,oBAAoB,GAC3B,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CA4D9D"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * Receive client logs over plain HTTP, for a backend that is not Cloud Functions
4
+ * (#34).
5
+ *
6
+ * The client half was already portable — `logFunction` is any
7
+ * `(payload) => Promise<unknown>`, and `httpsCallable()` merely happens to fit.
8
+ * What was missing was a receiving end that does not require a callable.
9
+ *
10
+ * This is deliberately framework-agnostic. It reads `method`, `headers` and a
11
+ * parsed `body`, and writes through `statusCode` / `setHeader` / `end` — the
12
+ * Node core shapes, which Express, Fastify's compat layer and Cloud Run's raw
13
+ * server all satisfy. Parsing the body is the caller's job (`express.json()` or
14
+ * equivalent); reading the stream here would mean guessing at limits and
15
+ * encodings that the host framework already has opinions about.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.createHttpLogHandler = createHttpLogHandler;
19
+ const logHandler_1 = require("./logHandler");
20
+ const traceContext_1 = require("./traceContext");
21
+ const STATUS = {
22
+ 'invalid-argument': 400,
23
+ internal: 500,
24
+ };
25
+ function send(res, status, body) {
26
+ res.statusCode = status;
27
+ if (body) {
28
+ res.setHeader('Content-Type', 'application/json');
29
+ res.end(JSON.stringify(body));
30
+ }
31
+ else {
32
+ res.end();
33
+ }
34
+ }
35
+ /**
36
+ * Build a request handler that receives `LogPayload` over HTTP.
37
+ *
38
+ * import express from 'express'
39
+ * import { createHttpLogHandler } from '@dasasian/firebase-structured-logger/functions'
40
+ *
41
+ * const app = express()
42
+ * app.use(express.json({ limit: '10mb' })) // attachments ride in the body
43
+ * app.post('/log', createHttpLogHandler({ bucketName, authorize }))
44
+ *
45
+ * On the client, point `logFunction` at it:
46
+ *
47
+ * logFunction: async (payload) => {
48
+ * const res = await fetch('/log', {
49
+ * method: 'POST',
50
+ * headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${await user.getIdToken()}` },
51
+ * body: JSON.stringify(payload),
52
+ * })
53
+ * if (!res.ok) throw new Error(`log rejected: ${res.status}`)
54
+ * }
55
+ */
56
+ function createHttpLogHandler(config) {
57
+ const handler = (0, logHandler_1.createClientLogHandler)(config);
58
+ const allowOrigin = config.allowOrigin ?? '*';
59
+ return async (req, res) => {
60
+ res.setHeader('Access-Control-Allow-Origin', allowOrigin);
61
+ res.setHeader('Vary', 'Origin');
62
+ // Preflight. The client sends Content-Type and usually Authorization, both
63
+ // of which make the request non-simple.
64
+ if (req.method === 'OPTIONS') {
65
+ res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
66
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
67
+ res.setHeader('Access-Control-Max-Age', '3600');
68
+ return send(res, 204);
69
+ }
70
+ if (req.method !== 'POST') {
71
+ res.setHeader('Allow', 'POST, OPTIONS');
72
+ return send(res, 405, { error: 'Use POST' });
73
+ }
74
+ if (config.authorize !== 'unauthenticated') {
75
+ let allowed = false;
76
+ try {
77
+ allowed = await config.authorize(req);
78
+ }
79
+ catch (err) {
80
+ // A gate that threw is a gate that did not pass. Say so on the server
81
+ // and tell the caller nothing about why.
82
+ console.warn('[fsl] authorize() threw; rejecting the request:', err);
83
+ }
84
+ if (!allowed)
85
+ return send(res, 401, { error: 'Unauthorized' });
86
+ }
87
+ if (req.body === null || typeof req.body !== 'object') {
88
+ // Almost always a missing body parser rather than a bad client, and that
89
+ // is a five-minute fix once someone says it out loud.
90
+ return send(res, 400, {
91
+ error: 'Expected a parsed JSON body. Is express.json() (or equivalent) mounted before this handler?',
92
+ });
93
+ }
94
+ try {
95
+ // Cloud Logging groups a request's entries by trace. firebase-functions
96
+ // only attaches one inside its own wrapper, so out here we read the
97
+ // headers ourselves — otherwise the logs arrive uncorrelated and nothing
98
+ // says why.
99
+ await (0, traceContext_1.runWithTrace)((0, traceContext_1.traceIdFromHeaders)(req.headers), () => handler({ data: req.body }));
100
+ return send(res, 204);
101
+ }
102
+ catch (err) {
103
+ if (err instanceof logHandler_1.ClientLogError) {
104
+ // 'internal' has already been logged with its cause by the handler.
105
+ return send(res, STATUS[err.code], { error: err.message });
106
+ }
107
+ console.error('[fsl] Unhandled error in the HTTP log handler:', err);
108
+ return send(res, 500, { error: 'Failed to process log' });
109
+ }
110
+ };
111
+ }
112
+ //# sourceMappingURL=httpHandler.js.map