@faststats/nitro 0.6.0 → 0.8.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.
@@ -1,6 +1,3 @@
1
- import { createRequire } from "node:module";
2
- import { readFileSync } from "node:fs";
3
- import { version } from "node:os";
4
1
  //#region src/options.ts
5
2
  const DEFAULT_ENDPOINT = "https://metrics.faststats.dev/v1/error";
6
3
  const envInt = (key, fallback) => {
@@ -23,18 +20,9 @@ function resolveFaststatsNitroOptions(overrides = {}) {
23
20
  };
24
21
  }
25
22
  const SDK_NAME = "@faststats/nitro";
26
- const SDK_VERSION = "0.6.0";
23
+ const SDK_VERSION = "0.8.0";
27
24
  //#endregion
28
25
  //#region src/context.ts
29
- function readPackageVersion(name) {
30
- try {
31
- const raw = readFileSync(createRequire(import.meta.url).resolve(`${name}/package.json`), "utf8");
32
- const pkg = JSON.parse(raw);
33
- return typeof pkg.version === "string" ? pkg.version : void 0;
34
- } catch {
35
- return;
36
- }
37
- }
38
26
  function detectRuntime() {
39
27
  if (typeof Bun !== "undefined" && Bun.version !== void 0) return {
40
28
  runtime: "bun",
@@ -67,15 +55,11 @@ function buildServerReportContext(extra = {}) {
67
55
  return {
68
56
  source: "@faststats/nitro",
69
57
  ...extra,
70
- nitroVersion: readPackageVersion("nitropack") ?? readPackageVersion("nitro"),
71
58
  nitroPreset: process?.env?.NITRO_PRESET,
72
59
  runtime,
73
60
  runtimeVersion,
74
- os: process?.release?.name ?? "unknown",
75
- osVersion: version() || "unknown",
76
61
  platform: process?.platform ?? "unknown",
77
- arch: process?.arch ?? "unknown",
78
- ...process?.cwd?.() ? { cwd: process.cwd() } : {}
62
+ arch: process?.arch ?? "unknown"
79
63
  };
80
64
  }
81
65
  //#endregion
@@ -97,39 +81,19 @@ function serializeCause(cause) {
97
81
  message: cause
98
82
  };
99
83
  }
100
- function causeFingerprint(cause) {
101
- if (!cause) return "";
102
- return `${cause.error}\0${cause.message ?? ""}\0${causeFingerprint(cause.cause)}`;
103
- }
104
- function hashMessage(message, cause) {
105
- const key = [
106
- "error",
107
- message,
108
- "",
109
- "",
110
- causeFingerprint(cause)
111
- ].join("\0");
112
- let a = 2166136261;
113
- let b = 3598710387;
114
- for (let i = 0; i < key.length; i++) {
115
- const c = key.charCodeAt(i);
116
- a = Math.imul(a ^ c, 16777619);
117
- b = Math.imul(b ^ c, 2246822519);
118
- }
119
- return `err_${(a >>> 0).toString(16).padStart(8, "0")}${(b >>> 0).toString(16).padStart(8, "0")}`;
120
- }
121
- function hashServerError(error) {
84
+ function normalizeServerError(error) {
122
85
  const err = error instanceof Error ? error : new Error(String(error));
123
86
  const name = err.name?.trim() || "Error";
124
87
  const cause = serializeCause(err.cause);
88
+ const entry = {
89
+ error: name,
90
+ message: err.message,
91
+ stack: parseStack(err.stack),
92
+ ...cause ? { cause } : {}
93
+ };
125
94
  return {
126
- hash: hashMessage(err.message, cause),
127
- entry: {
128
- error: name,
129
- message: err.message,
130
- stack: parseStack(err.stack),
131
- ...cause ? { cause } : {}
132
- }
95
+ key: JSON.stringify(entry),
96
+ entry
133
97
  };
134
98
  }
135
99
  //#endregion
@@ -139,7 +103,6 @@ const defaultRuntime = {
139
103
  setTimeout: (callback, delay) => setTimeout(callback, delay),
140
104
  clearTimeout: (timer) => clearTimeout(timer),
141
105
  now: () => Date.now(),
142
- randomUUID: () => crypto.randomUUID?.() ?? `sess-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`,
143
106
  warn: (...args) => console.warn(...args)
144
107
  };
145
108
  function definedStrings(context) {
@@ -147,8 +110,6 @@ function definedStrings(context) {
147
110
  }
148
111
  function mergeBucket(target, incoming) {
149
112
  target.count += incoming.count;
150
- if (incoming.path !== void 0) target.path = incoming.path;
151
- if (incoming.tags.length > 0) target.tags = incoming.tags;
152
113
  }
153
114
  function mergeBuckets(target, incoming) {
154
115
  for (const [hash, bucket] of incoming) {
@@ -157,39 +118,25 @@ function mergeBuckets(target, incoming) {
157
118
  else target.set(hash, { ...bucket });
158
119
  }
159
120
  }
160
- function buildPayload(buckets, options, sessionId) {
121
+ function buildPayload(buckets, options) {
161
122
  const errors = [];
162
- const tags = /* @__PURE__ */ new Set();
163
- let route;
164
- let routeCount = -1;
165
- const custom = {};
166
- for (const [hash, bucket] of buckets) {
167
- errors.push({
168
- ...bucket.entry,
169
- hash,
170
- count: bucket.count
171
- });
172
- for (const tag of bucket.tags) tags.add(tag);
173
- if (bucket.path !== void 0 && bucket.count > routeCount) {
174
- routeCount = bucket.count;
175
- route = bucket.path;
123
+ for (const bucket of buckets.values()) errors.push({
124
+ ...bucket.entry,
125
+ count: bucket.count,
126
+ context: {
127
+ ...bucket.path ? { route: bucket.path } : {},
128
+ ...bucket.tags.length ? { tags: bucket.tags.join(",") } : {},
129
+ ...bucket.custom
176
130
  }
177
- for (const [key, value] of Object.entries(bucket.custom)) if (!(key in custom)) custom[key] = value;
178
- }
131
+ });
179
132
  return {
180
133
  errors,
181
- sessionId,
134
+ language: "javascript",
135
+ ...options.sessionId ? { sessionId: options.sessionId } : {},
182
136
  ...options.buildId ? { buildId: options.buildId } : {},
183
137
  sdkName: SDK_NAME,
184
138
  sdkVersion: SDK_VERSION,
185
- context: {
186
- ...definedStrings(buildServerReportContext({
187
- route,
188
- plugin: options.pluginId,
189
- tags: tags.size > 0 ? [...tags].join(",") : void 0
190
- })),
191
- ...custom
192
- }
139
+ context: definedStrings(buildServerReportContext({ plugin: options.pluginId }))
193
140
  };
194
141
  }
195
142
  function createNitroErrorReporter(options, runtime) {
@@ -198,11 +145,6 @@ function createNitroErrorReporter(options, runtime) {
198
145
  let flushing = false;
199
146
  let consecutiveFailures = 0;
200
147
  let pausedUntil = 0;
201
- let sessionId = options.sessionId;
202
- const getSessionId = () => {
203
- sessionId ??= runtime.randomUUID();
204
- return sessionId;
205
- };
206
148
  const clearTimer = () => {
207
149
  if (timer === null) return;
208
150
  runtime.clearTimeout(timer);
@@ -223,7 +165,7 @@ function createNitroErrorReporter(options, runtime) {
223
165
  "Content-Type": "application/json",
224
166
  Authorization: `Bearer ${options.token}`
225
167
  },
226
- body: JSON.stringify(buildPayload(snapshot, options, getSessionId()))
168
+ body: JSON.stringify(buildPayload(snapshot, options))
227
169
  });
228
170
  if (response.ok) return true;
229
171
  if (options.debug) runtime.warn("[faststats nitro] report failed", response.status, await response.text());
@@ -264,32 +206,30 @@ function createNitroErrorReporter(options, runtime) {
264
206
  if (options.debug) runtime.warn("[faststats nitro] FASTSTATS_TOKEN not set; skipping error report");
265
207
  return;
266
208
  }
267
- if (runtime.now() < pausedUntil) return;
268
- const { hash, entry } = hashServerError(error);
269
- const existing = buckets.get(hash);
270
- if (existing) mergeBucket(existing, {
209
+ const { key, entry } = normalizeServerError(error);
210
+ let custom = {};
211
+ if (options.getContext) try {
212
+ custom = await options.getContext({
213
+ error,
214
+ ...args
215
+ }) ?? {};
216
+ } catch {}
217
+ let customKey = "";
218
+ try {
219
+ customKey = JSON.stringify(custom);
220
+ } catch {
221
+ custom = {};
222
+ }
223
+ const bucketKey = `${key}\0${args.path ?? ""}\0${args.tags.join("\0")}\0${customKey}`;
224
+ const existing = buckets.get(bucketKey);
225
+ if (existing) mergeBucket(existing, { count: 1 });
226
+ else buckets.set(bucketKey, {
227
+ entry,
271
228
  count: 1,
272
229
  path: args.path,
273
- tags: args.tags
230
+ tags: args.tags,
231
+ custom
274
232
  });
275
- else {
276
- let custom = {};
277
- if (options.getContext) try {
278
- custom = await options.getContext({
279
- error,
280
- ...args
281
- }) ?? {};
282
- } catch {
283
- custom = {};
284
- }
285
- buckets.set(hash, {
286
- entry,
287
- count: 1,
288
- path: args.path,
289
- tags: args.tags,
290
- custom
291
- });
292
- }
293
233
  if (buckets.size >= options.maxBatchHashes) {
294
234
  clearTimer();
295
235
  await flush();
@@ -303,16 +243,20 @@ function createNitroErrorReporter(options, runtime) {
303
243
  function extractPath(event) {
304
244
  if (!event || typeof event !== "object") return void 0;
305
245
  const e = event;
306
- if (e.path) return e.path;
307
- const url = e.node?.req?.url;
308
- return url === void 0 ? void 0 : String(url);
246
+ const value = e.path ?? e.node?.req?.url;
247
+ if (value === void 0) return void 0;
248
+ try {
249
+ return new URL(String(value), "http://faststats.local").pathname;
250
+ } catch {
251
+ return String(value).split(/[?#]/, 1)[0];
252
+ }
309
253
  }
310
254
  function createNitroErrorHook(resolved) {
311
255
  const reporter = createNitroErrorReporter(resolved, defaultRuntime);
312
256
  return (error, context) => {
313
257
  reporter.report(error, {
314
258
  path: extractPath(context.event),
315
- tags: Array.isArray(context.tags) ? context.tags : []
259
+ tags: Array.isArray(context.tags) ? context.tags.filter((tag) => typeof tag === "string") : []
316
260
  });
317
261
  };
318
262
  }
package/dist/v2.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { t as FaststatsNitroOptions } from "./options-D8H8Cnje.mjs";
2
-
3
2
  //#region src/v2.d.ts
4
3
  declare function createFaststatsNitroPluginV2(options?: FaststatsNitroOptions): import("nitropack").NitroAppPlugin;
5
4
  declare const _default: import("nitropack").NitroAppPlugin;
package/dist/v2.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as resolveFaststatsNitroOptions, t as createNitroErrorHook } from "./plugin-hook-TnJ41MN2.mjs";
1
+ import { n as resolveFaststatsNitroOptions, t as createNitroErrorHook } from "./plugin-hook-BNTf2s_P.mjs";
2
2
  import { defineNitroPlugin } from "nitropack/runtime";
3
3
  //#region src/v2.ts
4
4
  function createFaststatsNitroPluginV2(options) {
package/dist/v3.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { t as FaststatsNitroOptions } from "./options-D8H8Cnje.mjs";
2
-
3
2
  //#region src/v3.d.ts
4
3
  declare function createFaststatsNitroPluginV3(options?: FaststatsNitroOptions): import("nitro/types").NitroAppPlugin;
5
4
  declare const _default: import("nitro/types").NitroAppPlugin;
package/dist/v3.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as resolveFaststatsNitroOptions, t as createNitroErrorHook } from "./plugin-hook-TnJ41MN2.mjs";
1
+ import { n as resolveFaststatsNitroOptions, t as createNitroErrorHook } from "./plugin-hook-BNTf2s_P.mjs";
2
2
  import { definePlugin } from "nitro";
3
3
  //#region src/v3.ts
4
4
  function createFaststatsNitroPluginV3(options) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/faststats-dev/faststats-javascript.git"
6
6
  },
7
- "version": "0.6.0",
7
+ "version": "0.8.0",
8
8
  "type": "module",
9
9
  "main": "./dist/v2.mjs",
10
10
  "module": "./dist/v2.mjs",
@@ -32,9 +32,9 @@
32
32
  "nitro": "3.0.260311-beta"
33
33
  },
34
34
  "devDependencies": {
35
- "nitropack": "2.13.1",
36
- "nitro": "3.0.260311-beta",
37
- "tsdown": "^0.22.3",
35
+ "nitropack": "2.13.4",
36
+ "nitro": "3.0.260610-beta",
37
+ "tsdown": "^0.22.14",
38
38
  "typescript": "^6.0.3"
39
39
  },
40
40
  "peerDependenciesMeta": {