trickle-observe 0.2.118 → 0.2.119

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.
@@ -115,6 +115,18 @@ function patchFetch(environment, debugMode) {
115
115
  // Mark as patched
116
116
  globalThis.fetch.__trickle_patched = true;
117
117
  }
118
+ /**
119
+ * Replace literal IDs in URL paths with placeholders to avoid cardinality explosion.
120
+ * "/users/abc123/tasks/456" → "/users/:id/tasks/:id"
121
+ * "/items/550e8400-e29b-41d4-a716-446655440000" → "/items/:uuid"
122
+ */
123
+ function normalizePath(pathname) {
124
+ return pathname
125
+ .replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '/:uuid')
126
+ .replace(/\/[0-9a-f]{24}(?=\/|$)/gi, '/:id')
127
+ .replace(/\/[0-9a-f]{8,}(?=\/|$)/gi, '/:id')
128
+ .replace(/\/\d+(?=\/|$)/g, '/:id');
129
+ }
118
130
  /**
119
131
  * Parse a URL into a clean function name and module name.
120
132
  * "https://api.example.com/v1/users?limit=10"
@@ -123,14 +135,13 @@ function patchFetch(environment, debugMode) {
123
135
  function parseUrl(method, rawUrl) {
124
136
  try {
125
137
  const parsed = new URL(rawUrl);
126
- const pathname = parsed.pathname || '/';
138
+ const pathname = normalizePath(parsed.pathname || '/');
127
139
  return {
128
140
  functionName: `${method} ${pathname}`,
129
141
  module: parsed.hostname || 'http',
130
142
  };
131
143
  }
132
144
  catch {
133
- // Relative URL or invalid — use as-is
134
145
  return {
135
146
  functionName: `${method} ${rawUrl}`,
136
147
  module: 'http',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trickle-observe",
3
- "version": "0.2.118",
3
+ "version": "0.2.119",
4
4
  "description": "Runtime type observability for JavaScript applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -122,6 +122,19 @@ export function patchFetch(environment: string, debugMode: boolean): void {
122
122
  (globalThis.fetch as any).__trickle_patched = true;
123
123
  }
124
124
 
125
+ /**
126
+ * Replace literal IDs in URL paths with placeholders to avoid cardinality explosion.
127
+ * "/users/abc123/tasks/456" → "/users/:id/tasks/:id"
128
+ * "/items/550e8400-e29b-41d4-a716-446655440000" → "/items/:uuid"
129
+ */
130
+ function normalizePath(pathname: string): string {
131
+ return pathname
132
+ .replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '/:uuid')
133
+ .replace(/\/[0-9a-f]{24}(?=\/|$)/gi, '/:id')
134
+ .replace(/\/[0-9a-f]{8,}(?=\/|$)/gi, '/:id')
135
+ .replace(/\/\d+(?=\/|$)/g, '/:id');
136
+ }
137
+
125
138
  /**
126
139
  * Parse a URL into a clean function name and module name.
127
140
  * "https://api.example.com/v1/users?limit=10"
@@ -130,13 +143,12 @@ export function patchFetch(environment: string, debugMode: boolean): void {
130
143
  function parseUrl(method: string, rawUrl: string): { functionName: string; module: string } {
131
144
  try {
132
145
  const parsed = new URL(rawUrl);
133
- const pathname = parsed.pathname || '/';
146
+ const pathname = normalizePath(parsed.pathname || '/');
134
147
  return {
135
148
  functionName: `${method} ${pathname}`,
136
149
  module: parsed.hostname || 'http',
137
150
  };
138
151
  } catch {
139
- // Relative URL or invalid — use as-is
140
152
  return {
141
153
  functionName: `${method} ${rawUrl}`,
142
154
  module: 'http',