@rootcat/node 0.0.0-stage → 0.2.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/CHANGELOG.md +83 -0
  2. package/LICENSE +202 -0
  3. package/README.md +294 -2
  4. package/dist/attach.d.ts +1 -0
  5. package/dist/attach.js +24 -0
  6. package/dist/attach.js.map +1 -0
  7. package/dist/callsite.d.ts +109 -0
  8. package/dist/callsite.js +565 -0
  9. package/dist/callsite.js.map +1 -0
  10. package/dist/coexist.d.ts +183 -0
  11. package/dist/coexist.js +587 -0
  12. package/dist/coexist.js.map +1 -0
  13. package/dist/config.d.ts +75 -0
  14. package/dist/config.js +182 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/drizzle.d.ts +21 -0
  17. package/dist/drizzle.js +127 -0
  18. package/dist/drizzle.js.map +1 -0
  19. package/dist/esm.mjs +57 -0
  20. package/dist/esmhook.d.ts +52 -0
  21. package/dist/esmhook.js +158 -0
  22. package/dist/esmhook.js.map +1 -0
  23. package/dist/iitm-hook.mjs +83 -0
  24. package/dist/index.d.ts +12 -0
  25. package/dist/index.js +52 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/intake.d.ts +40 -0
  28. package/dist/intake.js +164 -0
  29. package/dist/intake.js.map +1 -0
  30. package/dist/keys.d.ts +20 -0
  31. package/dist/keys.js +33 -0
  32. package/dist/keys.js.map +1 -0
  33. package/dist/notices.d.ts +2 -0
  34. package/dist/notices.js +21 -0
  35. package/dist/notices.js.map +1 -0
  36. package/dist/otlp.d.ts +75 -0
  37. package/dist/otlp.js +449 -0
  38. package/dist/otlp.js.map +1 -0
  39. package/dist/pg.d.ts +16 -0
  40. package/dist/pg.js +170 -0
  41. package/dist/pg.js.map +1 -0
  42. package/dist/pgpool.d.ts +20 -0
  43. package/dist/pgpool.js +99 -0
  44. package/dist/pgpool.js.map +1 -0
  45. package/dist/postgresjs.d.ts +60 -0
  46. package/dist/postgresjs.js +400 -0
  47. package/dist/postgresjs.js.map +1 -0
  48. package/dist/privacy.d.ts +38 -0
  49. package/dist/privacy.js +161 -0
  50. package/dist/privacy.js.map +1 -0
  51. package/dist/processor.d.ts +197 -0
  52. package/dist/processor.js +494 -0
  53. package/dist/processor.js.map +1 -0
  54. package/dist/register.d.ts +1 -0
  55. package/dist/register.js +12 -0
  56. package/dist/register.js.map +1 -0
  57. package/dist/sampler.d.ts +30 -0
  58. package/dist/sampler.js +101 -0
  59. package/dist/sampler.js.map +1 -0
  60. package/dist/sdk.d.ts +129 -0
  61. package/dist/sdk.js +606 -0
  62. package/dist/sdk.js.map +1 -0
  63. package/package.json +72 -4
@@ -0,0 +1,400 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresJsInstrumentation = void 0;
4
+ // postgres.js (the `postgres` package) has no upstream instrumentation.
5
+ // Its Query is a lazy promise: nothing runs until .then, .execute or
6
+ // .forEach calls handle(). An awaited Query is a Promise subclass, so the
7
+ // await calls then() from a job of its own, where no application frame
8
+ // is on the stack. The driver itself keeps a short stack per tagged
9
+ // template (query.origin, four frames, cached per template), which is
10
+ // where the span's call site comes from: parsed once per template.
11
+ // The span starts in handle() on the first execution and ends when the
12
+ // query resolves or rejects. The statement text is what the driver built
13
+ // (query.statement.string, with $1 placeholders); the span never touches
14
+ // query.args.
15
+ //
16
+ // The Query class is internal to the module, so the module's default
17
+ // export (the postgres() factory) is wrapped: the first sql function it
18
+ // returns yields the class through an unexecuted query, and handle() is
19
+ // patched on that prototype once. The same wrapper serves the CommonJS
20
+ // and the ES module builds.
21
+ const api_1 = require("@opentelemetry/api");
22
+ const instrumentation_1 = require("@opentelemetry/instrumentation");
23
+ const callsite_js_1 = require("./callsite.js");
24
+ const keys_js_1 = require("./keys.js");
25
+ const privacy_js_1 = require("./privacy.js");
26
+ const processor_js_1 = require("./processor.js");
27
+ /** Bounds. */
28
+ const maxStatementBytes = 4096;
29
+ const supportedVersions = ['>=3.0.0 <4'];
30
+ const rootcatSpan = Symbol('rootcat.span');
31
+ const rootcatWrapped = Symbol('rootcat.wrapped');
32
+ const rootcatOptions = Symbol('rootcat.options');
33
+ /** ownFactories are the package's wrappers of the postgres() factory. */
34
+ const ownFactories = new WeakSet();
35
+ /** probe is a template that is never executed; it only yields the class. */
36
+ const probe = Object.freeze(Object.assign(['select 1'], { raw: Object.freeze(['select 1']) }));
37
+ class PostgresJsInstrumentation extends instrumentation_1.InstrumentationBase {
38
+ patched = new WeakSet();
39
+ /** origins remembers the parsed call site per template, null for none. */
40
+ origins = new WeakMap();
41
+ /** recording maps a sql function to its site-recording proxy (spans false). */
42
+ recording = new WeakMap();
43
+ /** templateSites remembers the captured call site per template (spans false). */
44
+ templateSites = new WeakMap();
45
+ /** querySites holds the call site captured for a query until it is handled (spans false). */
46
+ querySites = new WeakMap();
47
+ constructor(options) {
48
+ super('@rootcat/node/postgres-js', '0.2.0', options);
49
+ }
50
+ init() {
51
+ return new instrumentation_1.InstrumentationNodeModuleDefinition('postgres', supportedVersions, (moduleExports) => this.patchModule(moduleExports), (moduleExports) => this.unpatchModule(moduleExports));
52
+ }
53
+ /**
54
+ * patchModule wraps the factory. CommonJS exports the function itself
55
+ * (the wrapper is returned in its place); an ES module namespace has it
56
+ * as default (replaced in place).
57
+ */
58
+ patchModule(moduleExports) {
59
+ const ns = moduleExports;
60
+ if (typeof ns === 'function') {
61
+ return this.wrapFactory(ns);
62
+ }
63
+ if (ns && typeof ns.default === 'function') {
64
+ try {
65
+ ns.default = this.wrapFactory(ns.default);
66
+ }
67
+ catch {
68
+ // a frozen namespace: no postgres.js spans
69
+ }
70
+ }
71
+ return moduleExports;
72
+ }
73
+ unpatchModule(moduleExports) {
74
+ const ns = moduleExports;
75
+ const wrapped = typeof ns === 'function' ? ns : ns?.default;
76
+ // Only the package's own wrapper is taken off: another SDK's wrapper
77
+ // of it (Sentry's Proxy forwards the symbol below) stays, and the
78
+ // package's inside it passes through once disabled.
79
+ if (!ownFactories.has(wrapped)) {
80
+ return;
81
+ }
82
+ const original = wrapped?.[rootcatWrapped];
83
+ if (original && typeof ns !== 'function' && ns) {
84
+ ns.default = original;
85
+ }
86
+ }
87
+ wrapFactory(original) {
88
+ const marked = original;
89
+ if (marked[rootcatWrapped]) {
90
+ return original;
91
+ }
92
+ const instrumentation = this;
93
+ const wrapper = function postgres(...args) {
94
+ const sql = original.apply(this, args);
95
+ if (!instrumentation.isEnabled()) {
96
+ return sql;
97
+ }
98
+ try {
99
+ instrumentation.patchQueryClass(sql);
100
+ if (instrumentation.getConfig().spans === false) {
101
+ return instrumentation.siteRecording(sql);
102
+ }
103
+ }
104
+ catch {
105
+ // the driver works untraced
106
+ }
107
+ return sql;
108
+ };
109
+ Object.assign(wrapper, original);
110
+ Object.setPrototypeOf(wrapper, Object.getPrototypeOf(original));
111
+ wrapper[rootcatWrapped] = original;
112
+ ownFactories.add(wrapper);
113
+ return wrapper;
114
+ }
115
+ /**
116
+ * siteRecording is the sql function as the application gets it when
117
+ * another SDK (Sentry) spans the queries: the driver's own origin then
118
+ * cannot name the application, as it keeps four frames and Sentry's
119
+ * wrapper of the sql function takes the last one. The call site is
120
+ * captured here instead, where the application calls: once per tagged
121
+ * template (a template is one place in the source, as the driver's own
122
+ * origin cache assumes), and per unsafe() call unless an outer layer
123
+ * (Drizzle) already carries one; queries inside sql.begin() get the
124
+ * same treatment through the transaction's sql function.
125
+ */
126
+ siteRecording(sql) {
127
+ const instrumentation = this;
128
+ const known = this.recording.get(sql);
129
+ if (known) {
130
+ return known;
131
+ }
132
+ const unsafe = function unsafe(...args) {
133
+ const query = sql.unsafe(...args);
134
+ try {
135
+ const config = instrumentation.getConfig();
136
+ if (query && typeof query === 'object' && api_1.context.active().getValue(keys_js_1.callSiteContextKey) === undefined && config.sampling.take()) {
137
+ const site = (0, callsite_js_1.captureCallSite)(callsite_js_1.defaultDepth, callsite_js_1.isAppFile, unsafe);
138
+ if (site) {
139
+ instrumentation.querySites.set(query, site);
140
+ }
141
+ }
142
+ }
143
+ catch {
144
+ // the query runs without a site
145
+ }
146
+ return query;
147
+ };
148
+ const begin = function begin(...args) {
149
+ const last = args.length - 1;
150
+ const callback = args[last];
151
+ if (typeof callback === 'function') {
152
+ args[last] = function (scoped) {
153
+ return callback.call(this, typeof scoped === 'function' ? instrumentation.siteRecording(scoped) : scoped);
154
+ };
155
+ }
156
+ return sql.begin(...args);
157
+ };
158
+ const handler = {
159
+ // The trap is the frame a capture starts below.
160
+ apply: function apply(target, thisArg, args) {
161
+ const query = Reflect.apply(target, thisArg, args);
162
+ if (!instrumentation.isEnabled()) {
163
+ return query;
164
+ }
165
+ try {
166
+ const strings = args[0];
167
+ if (query && typeof query === 'object' && Array.isArray(strings) && Array.isArray(strings.raw)) {
168
+ let site = instrumentation.templateSites.get(strings);
169
+ if (site === undefined && instrumentation.getConfig().sampling.on) {
170
+ site = (0, callsite_js_1.captureCallSite)(callsite_js_1.defaultDepth, callsite_js_1.isAppFile, handler.apply) ?? null;
171
+ instrumentation.templateSites.set(strings, site);
172
+ }
173
+ if (site) {
174
+ instrumentation.querySites.set(query, site);
175
+ }
176
+ }
177
+ }
178
+ catch {
179
+ // the query runs without a site
180
+ }
181
+ return query;
182
+ },
183
+ get(target, property, receiver) {
184
+ if (property === 'unsafe' && typeof target.unsafe === 'function') {
185
+ return unsafe;
186
+ }
187
+ if (property === 'begin' && typeof target.begin === 'function') {
188
+ return begin;
189
+ }
190
+ return Reflect.get(target, property, receiver);
191
+ },
192
+ };
193
+ const proxy = new Proxy(sql, handler);
194
+ this.recording.set(sql, proxy);
195
+ return proxy;
196
+ }
197
+ /** patchQueryClass finds Query.prototype through an unexecuted query. */
198
+ patchQueryClass(sql) {
199
+ if (typeof sql !== 'function') {
200
+ return;
201
+ }
202
+ const query = sql(probe);
203
+ if (!query || typeof query !== 'object') {
204
+ return;
205
+ }
206
+ const proto = Object.getPrototypeOf(query);
207
+ if (!proto || typeof proto.handle !== 'function') {
208
+ return;
209
+ }
210
+ // The connection options live on the sql function; the queries of
211
+ // this instance reach them through their handler.
212
+ if (typeof query.handler === 'function' && sql.options && typeof sql.options === 'object') {
213
+ query.handler[rootcatOptions] = sql.options;
214
+ }
215
+ if (this.patched.has(proto)) {
216
+ return;
217
+ }
218
+ this.patched.add(proto);
219
+ if ((0, instrumentation_1.isWrapped)(proto.handle) && (0, keys_js_1.mine)(proto.handle)) {
220
+ this._unwrap(proto, 'handle');
221
+ }
222
+ const before = proto.handle;
223
+ this._wrap(proto, 'handle', this.wrapHandle);
224
+ if (proto.handle !== before) {
225
+ (0, keys_js_1.marked)(proto.handle); // not when a guard kept another SDK's wrapper
226
+ }
227
+ }
228
+ wrapHandle = (original) => {
229
+ const instrumentation = this;
230
+ return function handle(...args) {
231
+ if (this.executed || this[rootcatSpan] || !instrumentation.isEnabled()) {
232
+ return original.apply(this, args);
233
+ }
234
+ if (typeof this.canceller !== 'function') {
235
+ // The driver's own queries on a new connection (the array type
236
+ // lookup, the read-only check) have no canceller: they are part
237
+ // of connecting, like the handshake, and are not traced (they
238
+ // would show as a second span for the query that opened it).
239
+ return original.apply(this, args);
240
+ }
241
+ const config = instrumentation.getConfig();
242
+ if (config.spans === false) {
243
+ try {
244
+ const site = instrumentation.querySites.get(this) ?? (config.sampling.on ? instrumentation.originSite(this) : undefined);
245
+ if (site) {
246
+ config.onSite?.(site);
247
+ }
248
+ }
249
+ catch {
250
+ // the query runs without a site
251
+ }
252
+ return original.apply(this, args);
253
+ }
254
+ let span;
255
+ try {
256
+ span = instrumentation.startQuerySpan(this);
257
+ }
258
+ catch {
259
+ span = undefined;
260
+ }
261
+ if (!span) {
262
+ return original.apply(this, args);
263
+ }
264
+ this[rootcatSpan] = span;
265
+ const resolve = this.resolve;
266
+ const reject = this.reject;
267
+ const query = this;
268
+ if (typeof resolve === 'function') {
269
+ this.resolve = function (value) {
270
+ instrumentation.endQuerySpan(query, span, undefined);
271
+ return resolve.call(this, value);
272
+ };
273
+ }
274
+ if (typeof reject === 'function') {
275
+ this.reject = function (reason) {
276
+ instrumentation.endQuerySpan(query, span, reason);
277
+ return reject.call(this, reason);
278
+ };
279
+ }
280
+ return original.apply(this, args);
281
+ };
282
+ };
283
+ /**
284
+ * originSite is the application frame of the driver's own origin stack
285
+ * for a tagged query, parsed once per template; undefined for unsafe()
286
+ * and file() queries, which hold no origin.
287
+ */
288
+ originSite(query) {
289
+ const strings = query.strings;
290
+ if (!query.tagged || !strings || typeof strings !== 'object') {
291
+ return undefined;
292
+ }
293
+ const known = this.origins.get(strings);
294
+ if (known !== undefined) {
295
+ return known ?? undefined;
296
+ }
297
+ let site;
298
+ try {
299
+ const origin = query.origin;
300
+ site = typeof origin === 'string' ? (0, callsite_js_1.parseStack)(origin) : undefined;
301
+ }
302
+ catch {
303
+ site = undefined;
304
+ }
305
+ this.origins.set(strings, site ?? null);
306
+ return site;
307
+ }
308
+ startQuerySpan(query) {
309
+ // The template's own origin (free: parsed once per template) wins over
310
+ // a site carried from outside, as a query written in the continuation
311
+ // of another is its own; unsafe() queries keep what an ORM carried.
312
+ const ctx = this.getConfig().sampling.carry(() => this.originSite(query), true) ?? api_1.context.active();
313
+ if ((0, processor_js_1.unsampled)(ctx)) {
314
+ return undefined; // not recorded: the query runs untouched
315
+ }
316
+ const options = query.handler?.[rootcatOptions];
317
+ const keyword = (0, privacy_js_1.statementKeyword)(leadingText(query));
318
+ const attributes = { 'db.system.name': 'postgresql' };
319
+ if (keyword !== '') {
320
+ attributes['db.operation.name'] = keyword;
321
+ }
322
+ if (options) {
323
+ if (typeof options.database === 'string') {
324
+ attributes['db.namespace'] = options.database;
325
+ }
326
+ const host = Array.isArray(options.host) ? options.host[0] : options.host;
327
+ if (typeof host === 'string') {
328
+ attributes['server.address'] = host;
329
+ }
330
+ const port = Array.isArray(options.port) ? options.port[0] : options.port;
331
+ if (typeof port === 'number') {
332
+ attributes['server.port'] = port;
333
+ }
334
+ }
335
+ const name = keyword === '' ? 'postgres.query' : `postgres.query:${keyword}`;
336
+ return this.tracer.startSpan(name, { kind: api_1.SpanKind.CLIENT, attributes }, ctx);
337
+ }
338
+ endQuerySpan(query, span, reason) {
339
+ try {
340
+ // Literals are masked (or the text reduced to its keyword) by the
341
+ // processor's statement rule as the span ends.
342
+ const statement = finalStatement(query);
343
+ if (statement !== '') {
344
+ span.setAttribute('db.query.text', statement);
345
+ }
346
+ if (reason !== undefined) {
347
+ // The server's message can quote the input that failed ("invalid
348
+ // input syntax for type integer: ..."), so, as the pg
349
+ // instrumentation does, only the error's class and SQLSTATE travel.
350
+ const error = reason;
351
+ const name = typeof error?.name === 'string' ? error.name.slice(0, 64) : 'Error';
352
+ const code = typeof error?.code === 'string' ? error.code.slice(0, 16) : '';
353
+ const message = code === '' ? `${name} from postgres.js` : `${name} from postgres.js (code: ${code})`;
354
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
355
+ span.addEvent('exception', { 'exception.type': name, 'exception.message': message });
356
+ span.setAttribute('error.type', name);
357
+ if (code !== '') {
358
+ span.setAttribute('db.response.status_code', code);
359
+ }
360
+ }
361
+ }
362
+ catch {
363
+ // the span still ends
364
+ }
365
+ finally {
366
+ span.end();
367
+ delete query[rootcatSpan];
368
+ }
369
+ }
370
+ }
371
+ exports.PostgresJsInstrumentation = PostgresJsInstrumentation;
372
+ /** leadingText is the first template part, before any parameter. */
373
+ function leadingText(query) {
374
+ const strings = query.strings;
375
+ if (Array.isArray(strings) && typeof strings[0] === 'string') {
376
+ return strings[0].slice(0, 256);
377
+ }
378
+ return '';
379
+ }
380
+ /**
381
+ * finalStatement is the statement the driver sent: query.statement.string
382
+ * once built, else the template joined with placeholders for a query the
383
+ * driver answered without building (an error before the build).
384
+ */
385
+ function finalStatement(query) {
386
+ const built = query.statement?.string;
387
+ if (typeof built === 'string') {
388
+ return built.slice(0, maxStatementBytes);
389
+ }
390
+ const strings = query.strings;
391
+ if (Array.isArray(strings) && strings.every((part) => typeof part === 'string')) {
392
+ let text = strings[0] ?? '';
393
+ for (let i = 1; i < strings.length; i++) {
394
+ text += '$' + i + strings[i];
395
+ }
396
+ return text.slice(0, maxStatementBytes);
397
+ }
398
+ return '';
399
+ }
400
+ //# sourceMappingURL=postgresjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresjs.js","sourceRoot":"","sources":["../src/postgresjs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Attributes } from '@opentelemetry/api';
2
+ /** StatementMode is what query text keeps: its shape with literals masked, or its first keyword. */
3
+ export type StatementMode = 'masked' | 'off';
4
+ /** urlKeys hold a URL or path whose query, fragment and opaque segments are cut. */
5
+ export declare const urlKeys: readonly ["http.url", "url.full", "http.target", "url.path", "url"];
6
+ /** clearedKeys hold a query string, a connection string, a client's address or a user agent; they are emptied. */
7
+ export declare const clearedKeys: readonly ["url.query", "url.fragment", "http.query", "db.connection_string", "http.client_ip", "client.address", "net.peer.ip", "net.sock.peer.addr", "network.peer.address", "user_agent.original", "http.user_agent"];
8
+ /** maxStatementLength bounds the text the masker reads. */
9
+ export declare const maxStatementLength = 4096;
10
+ /** statementKeys hold query text. */
11
+ export declare const statementKeys: readonly ["db.statement", "db.query.text"];
12
+ /**
13
+ * framesOnly keeps the frame lines of a stack trace (" at ...") and
14
+ * drops the message line(s) before them, which can quote input.
15
+ */
16
+ export declare function framesOnly(stack: string): string;
17
+ /** stripQuery cuts a URL at its query or fragment. */
18
+ export declare function stripQuery(url: string): string;
19
+ /**
20
+ * maskPath cuts the query and fragment and replaces every segment that
21
+ * could hold an identifier or a token (numbers, UUIDs, JWTs, reset
22
+ * tokens, emails, file names) with {id}; the scheme and host of a full
23
+ * URL are kept.
24
+ */
25
+ export declare function maskPath(url: string): string;
26
+ /** statementKeyword keeps the first word of a statement, upper-cased. */
27
+ export declare function statementKeyword(statement: string): string;
28
+ /**
29
+ * maskLiterals replaces every literal in a SQL statement with ?, keeps
30
+ * identifiers, keywords and placeholders, and drops comments (which
31
+ * sqlcommenter fills with values).
32
+ */
33
+ export declare function maskLiterals(statement: string): string;
34
+ /**
35
+ * scrubbed returns the attribute changes privacy requires for the given
36
+ * attributes, or undefined when nothing needs changing.
37
+ */
38
+ export declare function scrubbed(attributes: Attributes, statement: StatementMode): Attributes | undefined;
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.statementKeys = exports.maxStatementLength = exports.clearedKeys = exports.urlKeys = void 0;
4
+ exports.framesOnly = framesOnly;
5
+ exports.stripQuery = stripQuery;
6
+ exports.maskPath = maskPath;
7
+ exports.statementKeyword = statementKeyword;
8
+ exports.maskLiterals = maskLiterals;
9
+ exports.scrubbed = scrubbed;
10
+ /** urlKeys hold a URL or path whose query, fragment and opaque segments are cut. */
11
+ exports.urlKeys = ['http.url', 'url.full', 'http.target', 'url.path', 'url'];
12
+ /** clearedKeys hold a query string, a connection string, a client's address or a user agent; they are emptied. */
13
+ exports.clearedKeys = [
14
+ 'url.query',
15
+ 'url.fragment',
16
+ 'http.query',
17
+ 'db.connection_string',
18
+ 'http.client_ip',
19
+ 'client.address',
20
+ 'net.peer.ip',
21
+ 'net.sock.peer.addr',
22
+ 'network.peer.address',
23
+ 'user_agent.original',
24
+ 'http.user_agent',
25
+ ];
26
+ /** maxStatementLength bounds the text the masker reads. */
27
+ exports.maxStatementLength = 4096;
28
+ /** statementKeys hold query text. */
29
+ exports.statementKeys = ['db.statement', 'db.query.text'];
30
+ /**
31
+ * framesOnly keeps the frame lines of a stack trace (" at ...") and
32
+ * drops the message line(s) before them, which can quote input.
33
+ */
34
+ function framesOnly(stack) {
35
+ const lines = stack.split('\n');
36
+ const first = lines.findIndex((line) => /^\s+at\s/.test(line));
37
+ if (first <= 0) {
38
+ return first === 0 ? stack : '';
39
+ }
40
+ return lines.slice(first).join('\n');
41
+ }
42
+ /** stripQuery cuts a URL at its query or fragment. */
43
+ function stripQuery(url) {
44
+ const cut = url.search(/[?#]/);
45
+ return cut < 0 ? url : url.slice(0, cut);
46
+ }
47
+ /**
48
+ * keptSegment reports whether a path segment can hold no secret: a name
49
+ * of letters, hyphens and underscores up to 32 bytes that is not a
50
+ * mixed-case run of twelve or more (a base62 token without digits), or a
51
+ * version (v1, api2). The agent's request capture keeps the same.
52
+ */
53
+ function keptSegment(segment) {
54
+ if (/^[A-Za-z]{1,4}\d{1,3}$/.test(segment)) {
55
+ return true;
56
+ }
57
+ if (!/^[A-Za-z_-]{1,32}$/.test(segment)) {
58
+ return false;
59
+ }
60
+ return !(segment.length >= 12 && /[a-z]/.test(segment) && /[A-Z]/.test(segment));
61
+ }
62
+ /**
63
+ * maskPath cuts the query and fragment and replaces every segment that
64
+ * could hold an identifier or a token (numbers, UUIDs, JWTs, reset
65
+ * tokens, emails, file names) with {id}; the scheme and host of a full
66
+ * URL are kept.
67
+ */
68
+ function maskPath(url) {
69
+ const bare = stripQuery(url);
70
+ const origin = /^[a-z][a-z0-9+.-]*:\/\/[^/]*/i.exec(bare);
71
+ const prefix = origin ? origin[0] : '';
72
+ const rest = bare.slice(prefix.length);
73
+ const masked = rest
74
+ .split('/')
75
+ .map((segment) => (segment === '' || keptSegment(segment) ? segment : '{id}'))
76
+ .join('/');
77
+ return prefix + masked;
78
+ }
79
+ /** statementKeyword keeps the first word of a statement, upper-cased. */
80
+ function statementKeyword(statement) {
81
+ const match = /^\s*(?:\/\*.*?\*\/\s*)*([A-Za-z]+)/.exec(statement);
82
+ return match ? match[1].toUpperCase() : '';
83
+ }
84
+ // One pass over the text: quoted identifiers are kept, comments dropped,
85
+ // string, dollar-quoted and numeric literals masked. $1-style
86
+ // placeholders are kept (a dollar quote's tag cannot start with a digit,
87
+ // and a number right after $ is not a literal).
88
+ // A string or dollar quote left open (a statement cut at its bound) is
89
+ // masked to the end.
90
+ // An E'' string's E must start a word (in LIKE'%x%' the E ends a keyword).
91
+ // Numbers: decimal with or without digits on either side of the point
92
+ // (1, 1.5, 1., .5), with an exponent, or hexadecimal (0xDEAD).
93
+ const sqlTokens = /("(?:[^"]|"")*"|`(?:[^`]|``)*`)|(--[^\n]*|\/\*[\s\S]*?\*\/)|((?<!\w)[Ee]'(?:[^'\\]|\\.|'')*'|'(?:[^']|'')*'|\$([A-Za-z_][A-Za-z0-9_]*)?\$[\s\S]*?\$\4\$|(?<!\w)[Ee]'[\s\S]*$|'[\s\S]*$|\$(?:[A-Za-z_][A-Za-z0-9_]*)?\$[\s\S]*$)|((?<![\w$.])(?:0[xX][0-9a-fA-F]+|(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)(?![\w.]))/g;
94
+ /**
95
+ * maskLiterals replaces every literal in a SQL statement with ?, keeps
96
+ * identifiers, keywords and placeholders, and drops comments (which
97
+ * sqlcommenter fills with values).
98
+ */
99
+ function maskLiterals(statement) {
100
+ return statement
101
+ .replace(sqlTokens, (_match, identifier, comment) => {
102
+ if (identifier !== undefined) {
103
+ return identifier;
104
+ }
105
+ if (comment !== undefined) {
106
+ return '';
107
+ }
108
+ return '?';
109
+ })
110
+ .trim();
111
+ }
112
+ /**
113
+ * scrubbed returns the attribute changes privacy requires for the given
114
+ * attributes, or undefined when nothing needs changing.
115
+ */
116
+ function scrubbed(attributes, statement) {
117
+ let changes;
118
+ const set = (key, value) => {
119
+ (changes ??= {})[key] = value;
120
+ };
121
+ for (const key of exports.urlKeys) {
122
+ const value = attributes[key];
123
+ if (typeof value === 'string' && value !== '') {
124
+ const masked = maskPath(value);
125
+ if (masked !== value) {
126
+ set(key, masked);
127
+ }
128
+ }
129
+ }
130
+ for (const key of exports.clearedKeys) {
131
+ const value = attributes[key];
132
+ if (typeof value === 'string' && value !== '') {
133
+ set(key, '');
134
+ }
135
+ }
136
+ const redis = attributes['db.system'] === 'redis' || attributes['db.system.name'] === 'redis';
137
+ for (const key of exports.statementKeys) {
138
+ const value = attributes[key];
139
+ if (typeof value === 'string' && value !== '' && redis) {
140
+ // A Redis statement is its command and the argument count (the
141
+ // package's own serializer); one written by another SDK (Sentry's
142
+ // "get user:42:session") keeps only the command: keys name users.
143
+ const kept = /^\S+( \[\d+ args\])?$/.test(value) ? value : value.split(' ', 1)[0].slice(0, 64);
144
+ if (kept !== value) {
145
+ set(key, kept);
146
+ }
147
+ continue;
148
+ }
149
+ if (typeof value === 'string' && value !== '') {
150
+ // The span limits bound attribute values; the masker never runs over
151
+ // more than that, whatever set the attribute.
152
+ const bounded = value.length > exports.maxStatementLength ? value.slice(0, exports.maxStatementLength) : value;
153
+ const kept = statement === 'off' ? statementKeyword(bounded) : maskLiterals(bounded);
154
+ if (kept !== value) {
155
+ set(key, kept);
156
+ }
157
+ }
158
+ }
159
+ return changes;
160
+ }
161
+ //# sourceMappingURL=privacy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privacy.js","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"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"}