@duckbug/js 0.1.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +365 -73
  2. package/dist/cjs/DuckBug/DuckBugHelper.cjs +136 -0
  3. package/dist/cjs/DuckBug/DuckBugProvider.cjs +82 -13
  4. package/dist/cjs/DuckBug/DuckBugService.cjs +158 -17
  5. package/dist/cjs/DuckBug/Pond.cjs +44 -0
  6. package/dist/cjs/DuckBug/ensureEventId.cjs +47 -0
  7. package/dist/cjs/DuckBug/finalizeIngestEvent.cjs +54 -0
  8. package/dist/cjs/DuckBug/index.cjs +18 -2
  9. package/dist/cjs/DuckBug/parseDuckBugDsn.cjs +82 -0
  10. package/dist/cjs/DuckBug/sanitizeIngestPayload.cjs +67 -0
  11. package/dist/cjs/DuckBug/stripIngestSections.cjs +43 -0
  12. package/dist/cjs/DuckBug/transportTypes.cjs +18 -0
  13. package/dist/cjs/SDK/DuckSDK.cjs +129 -12
  14. package/dist/cjs/SDK/index.cjs +5 -2
  15. package/dist/cjs/contract/index.cjs +18 -0
  16. package/dist/cjs/contract/ingestEvents.cjs +18 -0
  17. package/dist/cjs/index.cjs +24 -6
  18. package/dist/cjs/integrations/node.cjs +54 -0
  19. package/dist/cjs/sdkIdentity.cjs +47 -0
  20. package/dist/esm/DuckBug/DuckBugHelper.js +99 -0
  21. package/dist/esm/DuckBug/DuckBugProvider.js +82 -13
  22. package/dist/esm/DuckBug/DuckBugService.js +156 -15
  23. package/dist/esm/DuckBug/Pond.js +10 -0
  24. package/dist/esm/DuckBug/ensureEventId.js +13 -0
  25. package/dist/esm/DuckBug/finalizeIngestEvent.js +20 -0
  26. package/dist/esm/DuckBug/index.js +5 -1
  27. package/dist/esm/DuckBug/parseDuckBugDsn.js +36 -0
  28. package/dist/esm/DuckBug/sanitizeIngestPayload.js +33 -0
  29. package/dist/esm/DuckBug/stripIngestSections.js +9 -0
  30. package/dist/esm/DuckBug/transportTypes.js +0 -0
  31. package/dist/esm/SDK/DuckSDK.js +125 -11
  32. package/dist/esm/SDK/index.js +2 -2
  33. package/dist/esm/contract/index.js +0 -0
  34. package/dist/esm/contract/ingestEvents.js +0 -0
  35. package/dist/esm/index.js +2 -0
  36. package/dist/esm/integrations/node.js +20 -0
  37. package/dist/esm/sdkIdentity.js +7 -0
  38. package/dist/types/DuckBug/DuckBugConfig.d.ts +28 -0
  39. package/dist/types/DuckBug/DuckBugHelper.d.ts +22 -0
  40. package/dist/types/DuckBug/DuckBugProvider.d.ts +12 -1
  41. package/dist/types/DuckBug/DuckBugService.d.ts +30 -8
  42. package/dist/types/DuckBug/Log.d.ts +1 -7
  43. package/dist/types/DuckBug/Pond.d.ts +9 -0
  44. package/dist/types/DuckBug/ensureEventId.d.ts +4 -0
  45. package/dist/types/DuckBug/finalizeIngestEvent.d.ts +11 -0
  46. package/dist/types/DuckBug/index.d.ts +7 -1
  47. package/dist/types/DuckBug/parseDuckBugDsn.d.ts +17 -0
  48. package/dist/types/DuckBug/sanitizeIngestPayload.d.ts +4 -0
  49. package/dist/types/DuckBug/stripIngestSections.d.ts +4 -0
  50. package/dist/types/DuckBug/transportTypes.d.ts +7 -0
  51. package/dist/types/SDK/DuckSDK.d.ts +30 -3
  52. package/dist/types/SDK/Provider.d.ts +11 -3
  53. package/dist/types/SDK/index.d.ts +3 -2
  54. package/dist/types/contract/index.d.ts +1 -0
  55. package/dist/types/contract/ingestEvents.d.ts +58 -0
  56. package/dist/types/index.d.ts +2 -0
  57. package/dist/types/integrations/node.d.ts +12 -0
  58. package/dist/types/sdkIdentity.d.ts +7 -0
  59. package/package.json +23 -7
  60. package/schemas/error-event.schema.json +147 -0
  61. package/schemas/log-event.schema.json +126 -0
@@ -27,50 +27,119 @@ __webpack_require__.d(__webpack_exports__, {
27
27
  DuckBugProvider: ()=>DuckBugProvider
28
28
  });
29
29
  const index_cjs_namespaceObject = require("../SDK/index.cjs");
30
+ const external_DuckBugHelper_cjs_namespaceObject = require("./DuckBugHelper.cjs");
30
31
  const external_DuckBugService_cjs_namespaceObject = require("./DuckBugService.cjs");
32
+ const external_finalizeIngestEvent_cjs_namespaceObject = require("./finalizeIngestEvent.cjs");
31
33
  class DuckBugProvider {
32
34
  service;
35
+ ingestConfig;
33
36
  constructor(config){
37
+ this.ingestConfig = config;
34
38
  this.service = new external_DuckBugService_cjs_namespaceObject.DuckBugService(config);
35
39
  }
40
+ static fromDSN(dsn) {
41
+ return new DuckBugProvider({
42
+ dsn
43
+ });
44
+ }
45
+ flush() {
46
+ return this.service.flush();
47
+ }
48
+ sendLog(event, meta) {
49
+ if (meta?.skipPrivacyPipeline) return void this.service.sendLog(event);
50
+ if (this.ingestConfig.beforeSend) return void this.sendLogAsync(event, meta);
51
+ const prepared = (0, external_finalizeIngestEvent_cjs_namespaceObject.finalizeIngestEvent)(event, {
52
+ extraSensitiveKeys: this.ingestConfig.extraSensitiveKeys,
53
+ stripSections: this.ingestConfig.stripSections
54
+ });
55
+ this.service.sendLog(prepared);
56
+ }
57
+ sendError(event, meta) {
58
+ if (meta?.skipPrivacyPipeline) return void this.service.sendError(event);
59
+ if (this.ingestConfig.beforeSend) return void this.sendErrorAsync(event, meta);
60
+ const prepared = (0, external_finalizeIngestEvent_cjs_namespaceObject.finalizeIngestEvent)(event, {
61
+ extraSensitiveKeys: this.ingestConfig.extraSensitiveKeys,
62
+ stripSections: this.ingestConfig.stripSections
63
+ });
64
+ this.service.sendError(prepared);
65
+ }
66
+ async sendLogAsync(event, _meta) {
67
+ const prepared = (0, external_finalizeIngestEvent_cjs_namespaceObject.finalizeIngestEvent)(event, {
68
+ extraSensitiveKeys: this.ingestConfig.extraSensitiveKeys,
69
+ stripSections: this.ingestConfig.stripSections
70
+ });
71
+ const r = await this.ingestConfig.beforeSend?.({
72
+ kind: "log",
73
+ event: prepared
74
+ });
75
+ if (null === r) return;
76
+ const toSend = r ?? prepared;
77
+ this.service.sendLog(toSend);
78
+ }
79
+ async sendErrorAsync(event, _meta) {
80
+ const prepared = (0, external_finalizeIngestEvent_cjs_namespaceObject.finalizeIngestEvent)(event, {
81
+ extraSensitiveKeys: this.ingestConfig.extraSensitiveKeys,
82
+ stripSections: this.ingestConfig.stripSections
83
+ });
84
+ const r = await this.ingestConfig.beforeSend?.({
85
+ kind: "error",
86
+ event: prepared
87
+ });
88
+ if (null === r) return;
89
+ const toSend = r ?? prepared;
90
+ this.service.sendError(toSend);
91
+ }
36
92
  warn(...args) {
37
- this.service.sendLog({
93
+ this.sendLog({
38
94
  time: this.getTimeStamp(),
39
95
  level: index_cjs_namespaceObject.logLevel.WARN,
40
96
  message: this.convertArgsToString(args[0]),
41
- context: args.slice(1)
97
+ ...this.normalizedContextPayload(args.slice(1))
42
98
  });
43
99
  }
44
100
  error(...args) {
45
- this.service.sendLog({
101
+ this.sendLog({
46
102
  time: this.getTimeStamp(),
47
103
  level: index_cjs_namespaceObject.logLevel.ERROR,
48
104
  message: this.convertArgsToString(args[0]),
49
- context: args.slice(1)
105
+ ...this.normalizedContextPayload(args.slice(1))
50
106
  });
51
107
  }
52
108
  log(...args) {
53
- this.service.sendLog({
109
+ this.sendLog({
54
110
  time: this.getTimeStamp(),
55
111
  level: index_cjs_namespaceObject.logLevel.INFO,
56
112
  message: this.convertArgsToString(args[0]),
57
- context: args.slice(1)
113
+ ...this.normalizedContextPayload(args.slice(1))
58
114
  });
59
115
  }
60
116
  report(tag, level, payload) {
61
- this.service.sendLog({
117
+ this.sendLog({
62
118
  time: this.getTimeStamp(),
63
119
  level,
64
120
  message: tag,
65
- context: payload
121
+ ...void 0 !== payload ? {
122
+ context: payload
123
+ } : {}
66
124
  });
67
125
  }
68
126
  quack(tag, error) {
69
- this.service.sendError({
70
- stack: error.stack,
71
- message: tag,
72
- context: error.message
73
- });
127
+ const errorRequest = (0, external_DuckBugHelper_cjs_namespaceObject.processError)(error, tag, this.getTimeStamp());
128
+ this.sendError(errorRequest);
129
+ }
130
+ normalizedContextPayload(rest) {
131
+ if (0 === rest.length) return {};
132
+ if (1 === rest.length) {
133
+ const v = rest[0];
134
+ return {
135
+ context: v
136
+ };
137
+ }
138
+ return {
139
+ context: {
140
+ args: rest
141
+ }
142
+ };
74
143
  }
75
144
  convertArgsToString(...args) {
76
145
  return args.map((arg)=>"object" == typeof arg ? JSON.stringify(arg) : String(arg)).join(" ");
@@ -26,27 +26,168 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  DuckBugService: ()=>DuckBugService
28
28
  });
29
+ const external_parseDuckBugDsn_cjs_namespaceObject = require("./parseDuckBugDsn.cjs");
30
+ const DEFAULT_MAX_RETRIES = 2;
31
+ const DEFAULT_RETRY_DELAY_MS = 200;
32
+ const MAX_BACKEND_BATCH = 1000;
33
+ function isRetriableHttpStatus(status) {
34
+ return 408 === status || 429 === status || 500 === status || 502 === status || 503 === status || 504 === status;
35
+ }
36
+ function ingestResponseAccepted(status) {
37
+ return status >= 200 && status < 300 || 409 === status;
38
+ }
29
39
  class DuckBugService {
30
- config;
40
+ logsUrl;
41
+ errorsUrl;
42
+ logsBatchUrl;
43
+ errorsBatchUrl;
44
+ maxBatchSize;
45
+ maxRetries;
46
+ retryDelayMs;
47
+ fetchImpl;
48
+ onTransportError;
49
+ logQueue = [];
50
+ errorQueue = [];
51
+ logChain = Promise.resolve();
52
+ errorChain = Promise.resolve();
31
53
  constructor(config){
32
- this.config = config;
54
+ const parsed = (0, external_parseDuckBugDsn_cjs_namespaceObject.parseDuckBugIngestDsn)(config.dsn);
55
+ this.logsUrl = (0, external_parseDuckBugDsn_cjs_namespaceObject.ingestLogsUrl)(parsed);
56
+ this.errorsUrl = (0, external_parseDuckBugDsn_cjs_namespaceObject.ingestErrorsUrl)(parsed);
57
+ this.logsBatchUrl = (0, external_parseDuckBugDsn_cjs_namespaceObject.ingestLogsBatchUrl)(parsed);
58
+ this.errorsBatchUrl = (0, external_parseDuckBugDsn_cjs_namespaceObject.ingestErrorsBatchUrl)(parsed);
59
+ this.maxBatchSize = config.transport?.maxBatchSize ?? 1;
60
+ this.maxRetries = config.transport?.maxRetries ?? DEFAULT_MAX_RETRIES;
61
+ this.retryDelayMs = config.transport?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
62
+ this.fetchImpl = config.transport?.fetchImpl ?? globalThis.fetch.bind(globalThis);
63
+ this.onTransportError = config.onTransportError;
33
64
  }
34
65
  sendLog(logInfo) {
35
- fetch(`${this.config.dsn}/logs`, {
36
- method: "POST",
37
- headers: {
38
- "Content-Type": "application/json"
39
- },
40
- body: JSON.stringify(logInfo)
41
- });
42
- }
43
- sendError(errorInfo) {
44
- fetch(`${this.config.dsn}/errors`, {
45
- method: "POST",
46
- headers: {
47
- "Content-Type": "application/json"
48
- },
49
- body: JSON.stringify(errorInfo)
66
+ this.enqueueLogTransport(async ()=>{
67
+ this.logQueue.push(logInfo);
68
+ await this.pumpLogsAfterEnqueue();
69
+ });
70
+ }
71
+ sendError(errorRequest) {
72
+ this.enqueueErrorTransport(async ()=>{
73
+ this.errorQueue.push(errorRequest);
74
+ await this.pumpErrorsAfterEnqueue();
75
+ });
76
+ }
77
+ flush() {
78
+ return Promise.all([
79
+ this.flushLogs(),
80
+ this.flushErrors()
81
+ ]).then(()=>{});
82
+ }
83
+ flushLogs() {
84
+ return this.enqueueLogTransport(async ()=>{
85
+ while(this.logQueue.length > 0)await this.drainLogStep();
86
+ });
87
+ }
88
+ flushErrors() {
89
+ return this.enqueueErrorTransport(async ()=>{
90
+ while(this.errorQueue.length > 0)await this.drainErrorStep();
91
+ });
92
+ }
93
+ enqueueLogTransport(fn) {
94
+ const p = this.logChain.then(()=>fn());
95
+ this.logChain = p.then(()=>void 0, ()=>void 0);
96
+ return p;
97
+ }
98
+ enqueueErrorTransport(fn) {
99
+ const p = this.errorChain.then(()=>fn());
100
+ this.errorChain = p.then(()=>void 0, ()=>void 0);
101
+ return p;
102
+ }
103
+ async pumpLogsAfterEnqueue() {
104
+ if (this.maxBatchSize <= 1) {
105
+ const item = this.logQueue.shift();
106
+ if (item) await this.postJsonWithRetry(this.logsUrl, item, "log", 1);
107
+ return;
108
+ }
109
+ if (this.logQueue.length >= this.maxBatchSize) {
110
+ const n = Math.min(this.maxBatchSize, MAX_BACKEND_BATCH, this.logQueue.length);
111
+ const batch = this.logQueue.splice(0, n);
112
+ await this.postJsonWithRetry(this.logsBatchUrl, batch, "log", batch.length);
113
+ }
114
+ }
115
+ async pumpErrorsAfterEnqueue() {
116
+ if (this.maxBatchSize <= 1) {
117
+ const item = this.errorQueue.shift();
118
+ if (item) await this.postJsonWithRetry(this.errorsUrl, item, "error", 1);
119
+ return;
120
+ }
121
+ if (this.errorQueue.length >= this.maxBatchSize) {
122
+ const n = Math.min(this.maxBatchSize, MAX_BACKEND_BATCH, this.errorQueue.length);
123
+ const batch = this.errorQueue.splice(0, n);
124
+ await this.postJsonWithRetry(this.errorsBatchUrl, batch, "error", batch.length);
125
+ }
126
+ }
127
+ async drainLogStep() {
128
+ if (this.maxBatchSize <= 1) {
129
+ const item = this.logQueue.shift();
130
+ if (item) await this.postJsonWithRetry(this.logsUrl, item, "log", 1);
131
+ return;
132
+ }
133
+ const n = Math.min(this.maxBatchSize, MAX_BACKEND_BATCH, this.logQueue.length);
134
+ if (0 === n) return;
135
+ const batch = this.logQueue.splice(0, n);
136
+ await this.postJsonWithRetry(this.logsBatchUrl, batch, "log", batch.length);
137
+ }
138
+ async drainErrorStep() {
139
+ if (this.maxBatchSize <= 1) {
140
+ const item = this.errorQueue.shift();
141
+ if (item) await this.postJsonWithRetry(this.errorsUrl, item, "error", 1);
142
+ return;
143
+ }
144
+ const n = Math.min(this.maxBatchSize, MAX_BACKEND_BATCH, this.errorQueue.length);
145
+ if (0 === n) return;
146
+ const batch = this.errorQueue.splice(0, n);
147
+ await this.postJsonWithRetry(this.errorsBatchUrl, batch, "error", batch.length);
148
+ }
149
+ emitFailure(info) {
150
+ this.onTransportError?.(info);
151
+ }
152
+ async postJsonWithRetry(url, body, kind, itemCount) {
153
+ let lastErr = new Error("unknown transport failure");
154
+ const maxAttempts = this.maxRetries + 1;
155
+ for(let attempt = 0; attempt < maxAttempts; attempt++){
156
+ try {
157
+ const res = await this.fetchImpl(url, {
158
+ method: "POST",
159
+ headers: {
160
+ "Content-Type": "application/json"
161
+ },
162
+ body: JSON.stringify(body)
163
+ });
164
+ if (ingestResponseAccepted(res.status)) return;
165
+ let detail = "";
166
+ try {
167
+ const t = await res.text();
168
+ const trimmed = t.trim();
169
+ if (trimmed) {
170
+ const max = 400;
171
+ detail = trimmed.length > max ? `${trimmed.slice(0, max)}\u{2026}` : trimmed;
172
+ }
173
+ } catch {}
174
+ lastErr = new Error(detail ? `ingest HTTP ${res.status}: ${detail}` : `ingest HTTP ${res.status}`);
175
+ if (!isRetriableHttpStatus(res.status)) break;
176
+ } catch (e) {
177
+ lastErr = e;
178
+ }
179
+ if (attempt < maxAttempts - 1) {
180
+ const delay = this.retryDelayMs * 2 ** attempt;
181
+ await new Promise((r)=>setTimeout(r, delay));
182
+ }
183
+ }
184
+ const message = lastErr instanceof Error ? lastErr.message : String(lastErr);
185
+ this.emitFailure({
186
+ kind,
187
+ itemCount,
188
+ attempts: maxAttempts,
189
+ error: lastErr,
190
+ message
50
191
  });
51
192
  }
52
193
  }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ Pond: ()=>Pond
28
+ });
29
+ const Pond = {
30
+ ripple (extraSensitiveKeys = []) {
31
+ return {
32
+ extraSensitiveKeys: [
33
+ ...extraSensitiveKeys
34
+ ]
35
+ };
36
+ }
37
+ };
38
+ exports.Pond = __webpack_exports__.Pond;
39
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
40
+ "Pond"
41
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
42
+ Object.defineProperty(exports, '__esModule', {
43
+ value: true
44
+ });
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ ensureEventId: ()=>ensureEventId
28
+ });
29
+ function randomEventId() {
30
+ const c = globalThis.crypto;
31
+ if (c?.randomUUID) return c.randomUUID();
32
+ throw new Error("crypto.randomUUID is not available; use a runtime with Web Crypto or set eventId on events explicitly");
33
+ }
34
+ function ensureEventId(event) {
35
+ if (void 0 !== event.eventId && "" !== event.eventId) return event;
36
+ return {
37
+ ...event,
38
+ eventId: randomEventId()
39
+ };
40
+ }
41
+ exports.ensureEventId = __webpack_exports__.ensureEventId;
42
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
43
+ "ensureEventId"
44
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
45
+ Object.defineProperty(exports, '__esModule', {
46
+ value: true
47
+ });
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ finalizeIngestEvent: ()=>finalizeIngestEvent
28
+ });
29
+ const external_sdkIdentity_cjs_namespaceObject = require("../sdkIdentity.cjs");
30
+ const external_ensureEventId_cjs_namespaceObject = require("./ensureEventId.cjs");
31
+ const external_sanitizeIngestPayload_cjs_namespaceObject = require("./sanitizeIngestPayload.cjs");
32
+ const external_stripIngestSections_cjs_namespaceObject = require("./stripIngestSections.cjs");
33
+ function withDefaultSdk(event) {
34
+ if (void 0 !== event.sdk) return event;
35
+ return {
36
+ ...event,
37
+ sdk: {
38
+ ...external_sdkIdentity_cjs_namespaceObject.SDK_IDENTITY
39
+ }
40
+ };
41
+ }
42
+ function finalizeIngestEvent(event, options = {}) {
43
+ const withSdk = withDefaultSdk(event);
44
+ const stripped = (0, external_stripIngestSections_cjs_namespaceObject.stripIngestSections)(withSdk, options.stripSections);
45
+ const sanitized = (0, external_sanitizeIngestPayload_cjs_namespaceObject.sanitizeIngestPayload)(stripped, options.extraSensitiveKeys);
46
+ return (0, external_ensureEventId_cjs_namespaceObject.ensureEventId)(sanitized);
47
+ }
48
+ exports.finalizeIngestEvent = __webpack_exports__.finalizeIngestEvent;
49
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
50
+ "finalizeIngestEvent"
51
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
52
+ Object.defineProperty(exports, '__esModule', {
53
+ value: true
54
+ });
@@ -24,12 +24,28 @@ var __webpack_require__ = {};
24
24
  var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
- DuckBugProvider: ()=>external_DuckBugProvider_cjs_namespaceObject.DuckBugProvider
27
+ Pond: ()=>external_Pond_cjs_namespaceObject.Pond,
28
+ finalizeIngestEvent: ()=>external_finalizeIngestEvent_cjs_namespaceObject.finalizeIngestEvent,
29
+ DuckBugProvider: ()=>external_DuckBugProvider_cjs_namespaceObject.DuckBugProvider,
30
+ ensureEventId: ()=>external_ensureEventId_cjs_namespaceObject.ensureEventId,
31
+ stripIngestSections: ()=>external_stripIngestSections_cjs_namespaceObject.stripIngestSections
28
32
  });
29
33
  const external_DuckBugProvider_cjs_namespaceObject = require("./DuckBugProvider.cjs");
34
+ const external_ensureEventId_cjs_namespaceObject = require("./ensureEventId.cjs");
35
+ const external_finalizeIngestEvent_cjs_namespaceObject = require("./finalizeIngestEvent.cjs");
36
+ const external_Pond_cjs_namespaceObject = require("./Pond.cjs");
37
+ const external_stripIngestSections_cjs_namespaceObject = require("./stripIngestSections.cjs");
30
38
  exports.DuckBugProvider = __webpack_exports__.DuckBugProvider;
39
+ exports.Pond = __webpack_exports__.Pond;
40
+ exports.ensureEventId = __webpack_exports__.ensureEventId;
41
+ exports.finalizeIngestEvent = __webpack_exports__.finalizeIngestEvent;
42
+ exports.stripIngestSections = __webpack_exports__.stripIngestSections;
31
43
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
32
- "DuckBugProvider"
44
+ "DuckBugProvider",
45
+ "Pond",
46
+ "ensureEventId",
47
+ "finalizeIngestEvent",
48
+ "stripIngestSections"
33
49
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
34
50
  Object.defineProperty(exports, '__esModule', {
35
51
  value: true
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ ingestErrorsBatchUrl: ()=>ingestErrorsBatchUrl,
28
+ ingestErrorsUrl: ()=>ingestErrorsUrl,
29
+ ingestLogsBatchUrl: ()=>ingestLogsBatchUrl,
30
+ ingestLogsUrl: ()=>ingestLogsUrl,
31
+ parseDuckBugIngestDsn: ()=>parseDuckBugIngestDsn
32
+ });
33
+ function parseDuckBugIngestDsn(dsn) {
34
+ let url;
35
+ try {
36
+ url = new URL(dsn);
37
+ } catch {
38
+ throw new Error("Invalid DuckBug DSN: not a valid URL");
39
+ }
40
+ const match = url.pathname.match(/^((?:\/api)?\/ingest)\/([^/]+)$/);
41
+ if (!match) throw new Error("Invalid DuckBug DSN: path must be /ingest/{projectId}:{publicKey} or /api/ingest/{projectId}:{publicKey}");
42
+ const ingestPathPrefix = match[1];
43
+ const segment = match[2];
44
+ const colon = segment.indexOf(":");
45
+ if (colon <= 0 || colon === segment.length - 1) throw new Error("Invalid DuckBug DSN: ingest segment must be projectId:publicKey");
46
+ return {
47
+ origin: url.origin,
48
+ ingestPathPrefix,
49
+ projectId: segment.slice(0, colon),
50
+ key: segment.slice(colon + 1)
51
+ };
52
+ }
53
+ function ingestBase(parsed) {
54
+ return `${parsed.origin}${parsed.ingestPathPrefix}/${parsed.projectId}:${parsed.key}`;
55
+ }
56
+ function ingestLogsUrl(parsed) {
57
+ return `${ingestBase(parsed)}/logs`;
58
+ }
59
+ function ingestErrorsUrl(parsed) {
60
+ return `${ingestBase(parsed)}/errors`;
61
+ }
62
+ function ingestLogsBatchUrl(parsed) {
63
+ return `${ingestBase(parsed)}/logs/batch`;
64
+ }
65
+ function ingestErrorsBatchUrl(parsed) {
66
+ return `${ingestBase(parsed)}/errors/batch`;
67
+ }
68
+ exports.ingestErrorsBatchUrl = __webpack_exports__.ingestErrorsBatchUrl;
69
+ exports.ingestErrorsUrl = __webpack_exports__.ingestErrorsUrl;
70
+ exports.ingestLogsBatchUrl = __webpack_exports__.ingestLogsBatchUrl;
71
+ exports.ingestLogsUrl = __webpack_exports__.ingestLogsUrl;
72
+ exports.parseDuckBugIngestDsn = __webpack_exports__.parseDuckBugIngestDsn;
73
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
74
+ "ingestErrorsBatchUrl",
75
+ "ingestErrorsUrl",
76
+ "ingestLogsBatchUrl",
77
+ "ingestLogsUrl",
78
+ "parseDuckBugIngestDsn"
79
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
80
+ Object.defineProperty(exports, '__esModule', {
81
+ value: true
82
+ });
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ sanitizeIngestPayload: ()=>sanitizeIngestPayload
28
+ });
29
+ const DEFAULT_SENSITIVE_KEYS = new Set([
30
+ "password",
31
+ "token",
32
+ "api_key",
33
+ "authorization",
34
+ "cookie",
35
+ "session",
36
+ "secret"
37
+ ]);
38
+ const MASK = "***";
39
+ function normalizeKey(key) {
40
+ return key.trim().toLowerCase().replace(/-/g, "_").replace(/\s+/g, "_");
41
+ }
42
+ function isSensitive(key, extra) {
43
+ const n = normalizeKey(key);
44
+ if (DEFAULT_SENSITIVE_KEYS.has(n)) return true;
45
+ for (const e of extra)if (normalizeKey(e) === n) return true;
46
+ return false;
47
+ }
48
+ function cloneValue(value, extraSensitive, depth) {
49
+ if (depth > 20) return value;
50
+ if (null === value || "object" != typeof value) return value;
51
+ if (Array.isArray(value)) return value.map((v)=>cloneValue(v, extraSensitive, depth + 1));
52
+ const out = {};
53
+ for (const [k, v] of Object.entries(value))if (isSensitive(k, extraSensitive)) out[k] = MASK;
54
+ else out[k] = cloneValue(v, extraSensitive, depth + 1);
55
+ return out;
56
+ }
57
+ function sanitizeIngestPayload(payload, extraSensitiveKeys) {
58
+ const extra = new Set(extraSensitiveKeys ?? []);
59
+ return cloneValue(JSON.parse(JSON.stringify(payload)), extra, 0);
60
+ }
61
+ exports.sanitizeIngestPayload = __webpack_exports__.sanitizeIngestPayload;
62
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
63
+ "sanitizeIngestPayload"
64
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
65
+ Object.defineProperty(exports, '__esModule', {
66
+ value: true
67
+ });