@seneris/nosework 0.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.
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Client-side error capture for nosework
3
+ *
4
+ * This is a lightweight (~2KB) script that captures unhandled errors
5
+ * and sends them to your tracking endpoint.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { initErrorTracking } from '@seneris/nosework/client/errors'
10
+ *
11
+ * initErrorTracking({
12
+ * endpoint: '/api/analytics/error',
13
+ * siteId: process.env.NEXT_PUBLIC_ANALYTICS_SITE_ID!,
14
+ * })
15
+ * ```
16
+ */
17
+ let config = null;
18
+ let errorCount = 0;
19
+ let lastResetTime = Date.now();
20
+ /**
21
+ * Reset rate limiter every minute
22
+ */
23
+ function checkRateLimit() {
24
+ const now = Date.now();
25
+ if (now - lastResetTime > 60000) {
26
+ errorCount = 0;
27
+ lastResetTime = now;
28
+ }
29
+ const limit = config?.rateLimit ?? 10;
30
+ if (errorCount >= limit) {
31
+ return false;
32
+ }
33
+ errorCount++;
34
+ return true;
35
+ }
36
+ /**
37
+ * Send error to the tracking endpoint
38
+ */
39
+ async function sendError(payload) {
40
+ if (!config)
41
+ return;
42
+ try {
43
+ await fetch(config.endpoint, {
44
+ method: "POST",
45
+ headers: { "Content-Type": "application/json" },
46
+ body: JSON.stringify(payload),
47
+ // Don't wait for response, fire and forget
48
+ keepalive: true,
49
+ });
50
+ }
51
+ catch {
52
+ // Silently fail - we don't want error tracking to cause more errors
53
+ }
54
+ }
55
+ /**
56
+ * Process and send an error
57
+ */
58
+ function handleError(captured) {
59
+ if (!config)
60
+ return;
61
+ // Apply filter if provided
62
+ if (config.filter && !config.filter(captured)) {
63
+ return;
64
+ }
65
+ // Check rate limit
66
+ if (!checkRateLimit()) {
67
+ return;
68
+ }
69
+ const payload = {
70
+ siteId: config.siteId,
71
+ message: captured.message,
72
+ stack: captured.stack,
73
+ url: captured.url,
74
+ metadata: {
75
+ ...config.metadata,
76
+ errorType: captured.type,
77
+ },
78
+ };
79
+ sendError(payload);
80
+ }
81
+ /**
82
+ * Handler for window.onerror events
83
+ */
84
+ function errorHandler(event) {
85
+ handleError({
86
+ message: event.message || "Unknown error",
87
+ stack: event.error?.stack,
88
+ url: window.location.href,
89
+ type: "error",
90
+ });
91
+ }
92
+ /**
93
+ * Handler for unhandled promise rejections
94
+ */
95
+ function rejectionHandler(event) {
96
+ let message = "Unhandled promise rejection";
97
+ let stack;
98
+ if (event.reason instanceof Error) {
99
+ message = event.reason.message;
100
+ stack = event.reason.stack;
101
+ }
102
+ else if (typeof event.reason === "string") {
103
+ message = event.reason;
104
+ }
105
+ else if (event.reason && typeof event.reason === "object") {
106
+ message = JSON.stringify(event.reason);
107
+ }
108
+ handleError({
109
+ message,
110
+ stack,
111
+ url: window.location.href,
112
+ type: "unhandledrejection",
113
+ });
114
+ }
115
+ /**
116
+ * Initialize error tracking
117
+ * Call this once when your app starts
118
+ */
119
+ export function initErrorTracking(options) {
120
+ if (typeof window === "undefined") {
121
+ // SSR - do nothing
122
+ return;
123
+ }
124
+ config = options;
125
+ // Add event listeners
126
+ window.addEventListener("error", errorHandler);
127
+ window.addEventListener("unhandledrejection", rejectionHandler);
128
+ }
129
+ /**
130
+ * Stop error tracking and remove event listeners
131
+ */
132
+ export function stopErrorTracking() {
133
+ if (typeof window === "undefined")
134
+ return;
135
+ window.removeEventListener("error", errorHandler);
136
+ window.removeEventListener("unhandledrejection", rejectionHandler);
137
+ config = null;
138
+ }
139
+ /**
140
+ * Manually track an error
141
+ * Useful for caught exceptions you still want to track
142
+ */
143
+ export function captureError(error, metadata) {
144
+ if (!config)
145
+ return;
146
+ const captured = {
147
+ message: typeof error === "string" ? error : error.message,
148
+ stack: typeof error === "string" ? undefined : error.stack,
149
+ url: typeof window !== "undefined" ? window.location.href : "",
150
+ type: "error",
151
+ };
152
+ // Apply filter
153
+ if (config.filter && !config.filter(captured)) {
154
+ return;
155
+ }
156
+ // Check rate limit
157
+ if (!checkRateLimit()) {
158
+ return;
159
+ }
160
+ const payload = {
161
+ siteId: config.siteId,
162
+ message: captured.message,
163
+ stack: captured.stack,
164
+ url: captured.url,
165
+ metadata: {
166
+ ...config.metadata,
167
+ ...metadata,
168
+ errorType: "manual",
169
+ },
170
+ };
171
+ sendError(payload);
172
+ }
173
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/client/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { PrismaClient } from "@prisma/client";
2
+ declare global {
3
+ var __noseworkPrisma: PrismaClient | undefined;
4
+ }
5
+ export declare function getClient(): PrismaClient;
6
+ export declare function disconnect(): Promise<void>;
7
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,gBAAgB,EAAE,YAAY,GAAG,SAAS,CAAC;CAChD;AAID,wBAAgB,SAAS,IAAI,YAAY,CAoBxC;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhD"}
package/dist/client.js ADDED
@@ -0,0 +1,29 @@
1
+ import { PrismaClient } from "@prisma/client";
2
+ let prismaClient = null;
3
+ export function getClient() {
4
+ if (prismaClient) {
5
+ return prismaClient;
6
+ }
7
+ // In development, use global to preserve client across hot reloads
8
+ if (process.env.NODE_ENV === "development") {
9
+ if (!global.__noseworkPrisma) {
10
+ global.__noseworkPrisma = new PrismaClient({
11
+ datasourceUrl: process.env.ANALYTICS_DATABASE_URL,
12
+ });
13
+ }
14
+ prismaClient = global.__noseworkPrisma;
15
+ }
16
+ else {
17
+ prismaClient = new PrismaClient({
18
+ datasourceUrl: process.env.ANALYTICS_DATABASE_URL,
19
+ });
20
+ }
21
+ return prismaClient;
22
+ }
23
+ export async function disconnect() {
24
+ if (prismaClient) {
25
+ await prismaClient.$disconnect();
26
+ prismaClient = null;
27
+ }
28
+ }
29
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9C,IAAI,YAAY,GAAwB,IAAI,CAAC;AAE7C,MAAM,UAAU,SAAS;IACvB,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,mEAAmE;IACnE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC7B,MAAM,CAAC,gBAAgB,GAAG,IAAI,YAAY,CAAC;gBACzC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;aAClD,CAAC,CAAC;QACL,CAAC;QACD,YAAY,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,IAAI,YAAY,CAAC;YAC9B,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;SAClD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,YAAY,CAAC,WAAW,EAAE,CAAC;QACjC,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;AACH,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { TrackErrorOptions, ErrorStats, ErrorGroupData, ErrorInstance, ErrorGroupStatus } from "./types.js";
2
+ /**
3
+ * Track a JavaScript error
4
+ */
5
+ export declare function trackError(options: TrackErrorOptions): Promise<void>;
6
+ /**
7
+ * Get error statistics
8
+ */
9
+ export declare function getErrorStats(siteId: string, options?: {
10
+ startDate?: Date;
11
+ endDate?: Date;
12
+ }): Promise<ErrorStats>;
13
+ /**
14
+ * Get error groups (aggregated errors by fingerprint)
15
+ */
16
+ export declare function getErrorGroups(siteId: string, options?: {
17
+ status?: ErrorGroupStatus;
18
+ limit?: number;
19
+ offset?: number;
20
+ }): Promise<ErrorGroupData[]>;
21
+ /**
22
+ * Get individual error instances for a specific error group
23
+ */
24
+ export declare function getErrorInstances(siteId: string, fingerprint: string, options?: {
25
+ limit?: number;
26
+ offset?: number;
27
+ }): Promise<ErrorInstance[]>;
28
+ /**
29
+ * Update error group status
30
+ */
31
+ export declare function updateErrorGroupStatus(siteId: string, fingerprint: string, status: ErrorGroupStatus): Promise<void>;
32
+ /**
33
+ * Delete errors older than a certain date
34
+ * Useful for manual cleanup
35
+ */
36
+ export declare function deleteOldErrors(siteId: string, olderThan: Date): Promise<{
37
+ deletedErrors: number;
38
+ deletedGroups: number;
39
+ }>;
40
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAgDpB;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD1E;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,IAAI,CAAA;CAAE,GAC7C,OAAO,CAAC,UAAU,CAAC,CA2CrB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,OAAO,CAAC,cAAc,EAAE,CAAC,CAyB3B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C,OAAO,CAAC,aAAa,EAAE,CAAC,CA4B1B;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,IAAI,GACd,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,CAwC3D"}
package/dist/error.js ADDED
@@ -0,0 +1,248 @@
1
+ import { getClient } from "./client.js";
2
+ import { createHash } from "crypto";
3
+ /**
4
+ * Create a fingerprint for grouping similar errors
5
+ * Normalizes variable parts to group similar errors together
6
+ */
7
+ function createFingerprint(message, stack) {
8
+ // Normalize message (remove variable parts)
9
+ const normalizedMessage = message
10
+ .replace(/\d+/g, "N") // Numbers → N
11
+ .replace(/'[^']*'/g, "'S'") // Single-quoted strings → 'S'
12
+ .replace(/"[^"]*"/g, '"S"') // Double-quoted strings → "S"
13
+ .replace(/`[^`]*`/g, "`S`") // Template strings → `S`
14
+ .replace(/0x[a-fA-F0-9]+/g, "0xHEX"); // Hex addresses → 0xHEX
15
+ // Extract top stack frame (most relevant for grouping)
16
+ let topFrame = "";
17
+ if (stack) {
18
+ const lines = stack.split("\n");
19
+ // Find first line that looks like a stack frame (starts with "at " or similar)
20
+ for (const line of lines.slice(1)) {
21
+ const trimmed = line.trim();
22
+ if (trimmed.startsWith("at ") || trimmed.match(/^\w+@/)) {
23
+ // Normalize file paths and line numbers
24
+ topFrame = trimmed
25
+ .replace(/:\d+:\d+/g, ":L:C") // Line:column → L:C
26
+ .replace(/\?.*/g, ""); // Remove query strings
27
+ break;
28
+ }
29
+ }
30
+ }
31
+ const hash = createHash("sha256");
32
+ hash.update(normalizedMessage + topFrame);
33
+ return hash.digest("hex").slice(0, 16);
34
+ }
35
+ /**
36
+ * Extract pathname from URL
37
+ */
38
+ function extractPathname(url) {
39
+ try {
40
+ return new URL(url).pathname;
41
+ }
42
+ catch {
43
+ return url;
44
+ }
45
+ }
46
+ /**
47
+ * Track a JavaScript error
48
+ */
49
+ export async function trackError(options) {
50
+ const db = getClient();
51
+ const fingerprint = createFingerprint(options.message, options.stack);
52
+ const pathname = extractPathname(options.url);
53
+ const now = new Date();
54
+ // Create the error record
55
+ await db.error.create({
56
+ data: {
57
+ siteId: options.siteId,
58
+ message: options.message,
59
+ stack: options.stack,
60
+ fingerprint,
61
+ url: options.url,
62
+ pathname,
63
+ visitorHash: options.visitorHash,
64
+ sessionId: options.sessionId,
65
+ userId: options.userId,
66
+ browser: options.browser,
67
+ browserVer: options.browserVer,
68
+ os: options.os,
69
+ device: options.device,
70
+ metadata: options.metadata ?? undefined,
71
+ },
72
+ });
73
+ // Upsert the error group
74
+ await db.errorGroup.upsert({
75
+ where: {
76
+ siteId_fingerprint: {
77
+ siteId: options.siteId,
78
+ fingerprint,
79
+ },
80
+ },
81
+ create: {
82
+ siteId: options.siteId,
83
+ fingerprint,
84
+ message: options.message,
85
+ stack: options.stack,
86
+ count: 1,
87
+ firstSeen: now,
88
+ lastSeen: now,
89
+ status: "open",
90
+ },
91
+ update: {
92
+ count: { increment: 1 },
93
+ lastSeen: now,
94
+ // Update message/stack if this is a clearer example
95
+ ...(options.stack && { stack: options.stack }),
96
+ },
97
+ });
98
+ }
99
+ /**
100
+ * Get error statistics
101
+ */
102
+ export async function getErrorStats(siteId, options) {
103
+ const db = getClient();
104
+ const where = {
105
+ siteId,
106
+ ...(options?.startDate || options?.endDate
107
+ ? {
108
+ timestamp: {
109
+ ...(options?.startDate && { gte: options.startDate }),
110
+ ...(options?.endDate && { lte: options.endDate }),
111
+ },
112
+ }
113
+ : {}),
114
+ };
115
+ const totalErrors = await db.error.count({ where });
116
+ const uniqueResult = await db.error.groupBy({
117
+ by: ["fingerprint"],
118
+ where,
119
+ });
120
+ const uniqueErrors = uniqueResult.length;
121
+ // Errors in last 24 hours
122
+ const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
123
+ const errorsToday = await db.error.count({
124
+ where: {
125
+ siteId,
126
+ timestamp: { gte: oneDayAgo },
127
+ },
128
+ });
129
+ // Open error groups
130
+ const openGroups = await db.errorGroup.count({
131
+ where: { siteId, status: "open" },
132
+ });
133
+ return {
134
+ totalErrors,
135
+ uniqueErrors,
136
+ errorsToday,
137
+ openGroups,
138
+ };
139
+ }
140
+ /**
141
+ * Get error groups (aggregated errors by fingerprint)
142
+ */
143
+ export async function getErrorGroups(siteId, options) {
144
+ const db = getClient();
145
+ const limit = options?.limit ?? 50;
146
+ const offset = options?.offset ?? 0;
147
+ const groups = await db.errorGroup.findMany({
148
+ where: {
149
+ siteId,
150
+ ...(options?.status && { status: options.status }),
151
+ },
152
+ orderBy: { lastSeen: "desc" },
153
+ take: limit,
154
+ skip: offset,
155
+ });
156
+ return groups.map((g) => ({
157
+ id: g.id,
158
+ fingerprint: g.fingerprint,
159
+ message: g.message,
160
+ stack: g.stack,
161
+ count: g.count,
162
+ firstSeen: g.firstSeen,
163
+ lastSeen: g.lastSeen,
164
+ status: g.status,
165
+ }));
166
+ }
167
+ /**
168
+ * Get individual error instances for a specific error group
169
+ */
170
+ export async function getErrorInstances(siteId, fingerprint, options) {
171
+ const db = getClient();
172
+ const limit = options?.limit ?? 50;
173
+ const offset = options?.offset ?? 0;
174
+ const errors = await db.error.findMany({
175
+ where: { siteId, fingerprint },
176
+ orderBy: { timestamp: "desc" },
177
+ take: limit,
178
+ skip: offset,
179
+ });
180
+ return errors.map((e) => ({
181
+ id: e.id,
182
+ message: e.message,
183
+ stack: e.stack,
184
+ url: e.url,
185
+ pathname: e.pathname,
186
+ visitorHash: e.visitorHash,
187
+ sessionId: e.sessionId,
188
+ userId: e.userId,
189
+ browser: e.browser,
190
+ browserVer: e.browserVer,
191
+ os: e.os,
192
+ device: e.device,
193
+ metadata: e.metadata,
194
+ timestamp: e.timestamp,
195
+ }));
196
+ }
197
+ /**
198
+ * Update error group status
199
+ */
200
+ export async function updateErrorGroupStatus(siteId, fingerprint, status) {
201
+ const db = getClient();
202
+ await db.errorGroup.update({
203
+ where: {
204
+ siteId_fingerprint: { siteId, fingerprint },
205
+ },
206
+ data: { status },
207
+ });
208
+ }
209
+ /**
210
+ * Delete errors older than a certain date
211
+ * Useful for manual cleanup
212
+ */
213
+ export async function deleteOldErrors(siteId, olderThan) {
214
+ const db = getClient();
215
+ // Delete old error instances
216
+ const deletedErrors = await db.error.deleteMany({
217
+ where: {
218
+ siteId,
219
+ timestamp: { lt: olderThan },
220
+ },
221
+ });
222
+ // Delete error groups with no remaining errors
223
+ // First, get fingerprints that still have errors
224
+ const remainingFingerprints = await db.error.groupBy({
225
+ by: ["fingerprint"],
226
+ where: { siteId },
227
+ });
228
+ const activeFingerprints = new Set(remainingFingerprints.map((r) => r.fingerprint));
229
+ // Delete groups not in active fingerprints
230
+ const allGroups = await db.errorGroup.findMany({
231
+ where: { siteId },
232
+ select: { fingerprint: true },
233
+ });
234
+ const groupsToDelete = allGroups
235
+ .filter((g) => !activeFingerprints.has(g.fingerprint))
236
+ .map((g) => g.fingerprint);
237
+ const deletedGroups = await db.errorGroup.deleteMany({
238
+ where: {
239
+ siteId,
240
+ fingerprint: { in: groupsToDelete },
241
+ },
242
+ });
243
+ return {
244
+ deletedErrors: deletedErrors.count,
245
+ deletedGroups: deletedGroups.count,
246
+ };
247
+ }
248
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { trackPageView, trackEvent } from "./track.js";
2
+ export { trackError, getErrorStats, getErrorGroups, getErrorInstances, updateErrorGroupStatus, deleteOldErrors, } from "./error.js";
3
+ export { getStats, getTopPages, getLocations, getReferrers, getDevices, getTimeSeries, getOrCreateSite, listSites, getSessionStats, getEntryPages, getExitPages, getPageFlows, getSessions, } from "./query.js";
4
+ export { getClient, disconnect } from "./client.js";
5
+ export { isBot, cleanupOldSalts } from "./utils.js";
6
+ export { parseUserAgent } from "./ua.js";
7
+ export type { TrackPageViewOptions, TrackEventOptions, DateRange, QueryOptions, PaginatedQueryOptions, Stats, TopPage, LocationData, ReferrerData, DeviceData, GeoLocation, ParsedUserAgent, VisitorInfo, SessionStats, SessionData, EntryExitPage, PageFlow, TrackErrorOptions, ErrorStats, ErrorGroupStatus, ErrorGroupData, ErrorInstance, } from "./types.js";
8
+ export type { TimeSeriesDataPoint } from "./query.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGvD,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS,EAET,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,qBAAqB,EACrB,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EACf,WAAW,EAEX,YAAY,EACZ,WAAW,EACX,aAAa,EACb,QAAQ,EAER,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ // Main exports for nosework analytics package
2
+ // Tracking functions
3
+ export { trackPageView, trackEvent } from "./track.js";
4
+ // Error tracking functions
5
+ export { trackError, getErrorStats, getErrorGroups, getErrorInstances, updateErrorGroupStatus, deleteOldErrors, } from "./error.js";
6
+ // Query functions
7
+ export { getStats, getTopPages, getLocations, getReferrers, getDevices, getTimeSeries, getOrCreateSite, listSites,
8
+ // Session analytics
9
+ getSessionStats, getEntryPages, getExitPages, getPageFlows, getSessions, } from "./query.js";
10
+ // Client utilities
11
+ export { getClient, disconnect } from "./client.js";
12
+ // Utility functions
13
+ export { isBot, cleanupOldSalts } from "./utils.js";
14
+ // User-Agent parsing (for advanced use cases)
15
+ export { parseUserAgent } from "./ua.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,qBAAqB;AACrB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvD,2BAA2B;AAC3B,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,kBAAkB;AAClB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS;AACT,oBAAoB;AACpB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,mBAAmB;AACnB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpD,oBAAoB;AACpB,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEpD,8CAA8C;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,48 @@
1
+ import type { QueryOptions, PaginatedQueryOptions, Stats, TopPage, LocationData, ReferrerData, DeviceData, SessionStats, SessionData, EntryExitPage, PageFlow } from "./types.js";
2
+ export declare function getStats(options: QueryOptions): Promise<Stats>;
3
+ export declare function getTopPages(options: PaginatedQueryOptions): Promise<TopPage[]>;
4
+ export declare function getLocations(options: PaginatedQueryOptions): Promise<LocationData[]>;
5
+ export declare function getReferrers(options: PaginatedQueryOptions): Promise<ReferrerData[]>;
6
+ export declare function getDevices(options: PaginatedQueryOptions): Promise<DeviceData[]>;
7
+ export interface TimeSeriesDataPoint {
8
+ date: string;
9
+ pageViews: number;
10
+ visitors: number;
11
+ }
12
+ export declare function getTimeSeries(options: QueryOptions & {
13
+ interval?: "hour" | "day" | "week" | "month";
14
+ }): Promise<TimeSeriesDataPoint[]>;
15
+ /**
16
+ * Get aggregate session statistics
17
+ */
18
+ export declare function getSessionStats(options: QueryOptions): Promise<SessionStats>;
19
+ /**
20
+ * Get entry pages (first page of each session)
21
+ */
22
+ export declare function getEntryPages(options: PaginatedQueryOptions): Promise<EntryExitPage[]>;
23
+ /**
24
+ * Get exit pages (last page of each session)
25
+ */
26
+ export declare function getExitPages(options: PaginatedQueryOptions): Promise<EntryExitPage[]>;
27
+ /**
28
+ * Get common page flow paths (sequence of pages in sessions)
29
+ */
30
+ export declare function getPageFlows(options: PaginatedQueryOptions & {
31
+ maxPathLength?: number;
32
+ }): Promise<PageFlow[]>;
33
+ /**
34
+ * Get individual session data (for debugging/analysis)
35
+ */
36
+ export declare function getSessions(options: PaginatedQueryOptions): Promise<SessionData[]>;
37
+ export declare function getOrCreateSite(domain: string, name?: string): Promise<{
38
+ id: string;
39
+ name: string;
40
+ domain: string;
41
+ }>;
42
+ export declare function listSites(): Promise<{
43
+ id: string;
44
+ name: string;
45
+ domain: string;
46
+ createdAt: Date;
47
+ }[]>;
48
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,qBAAqB,EACrB,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,aAAa,EACb,QAAQ,EACT,MAAM,YAAY,CAAC;AAmBpB,wBAAsB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CAuCpE;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,OAAO,EAAE,CAAC,CA+BpB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,YAAY,EAAE,CAAC,CAqCzB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,YAAY,EAAE,CAAC,CA+BzB;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,UAAU,EAAE,CAAC,CAsCvB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,YAAY,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,GACvE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA6BhC;AA4BD;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,YAAY,CAAC,CA0DvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC,CAqC1B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC,CAqC1B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1D,OAAO,CAAC,QAAQ,EAAE,CAAC,CA2CrB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,CAoFxB;AAGD,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAevD;AAGD,wBAAsB,SAAS,IAAI,OAAO,CACxC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,EAAE,CAChE,CAGA"}