@seneris/nosework 0.1.0 → 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.
- package/README.md +28 -44
- package/dist/client.d.ts +9 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +26 -17
- package/dist/client.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +123 -117
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/query.d.ts +0 -11
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +173 -212
- package/dist/query.js.map +1 -1
- package/dist/schema.d.ts +979 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +101 -0
- package/dist/schema.js.map +1 -0
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +27 -30
- package/dist/track.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +31 -22
- package/dist/utils.js.map +1 -1
- package/package.json +4 -9
- package/prisma/schema.prisma +0 -145
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCrB,CAAC;AAGF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqBlB,CAAC;AAGF,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGrB,CAAC;AAGH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoC3B,CAAC;AAGF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBvB,CAAC;AAGF,MAAM,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC,YAAY,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,OAAO,SAAS,CAAC,YAAY,CAAC;AACxD,MAAM,MAAM,KAAK,GAAG,OAAO,MAAM,CAAC,YAAY,CAAC;AAC/C,MAAM,MAAM,QAAQ,GAAG,OAAO,MAAM,CAAC,YAAY,CAAC;AAClD,MAAM,MAAM,SAAS,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AACjE,MAAM,MAAM,iBAAiB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,OAAO,WAAW,CAAC,YAAY,CAAC"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { pgTable, text, timestamp, boolean, integer, json, date, index, unique, } from "drizzle-orm/pg-core";
|
|
2
|
+
// Page view events
|
|
3
|
+
export const pageViews = pgTable("page_views", {
|
|
4
|
+
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
5
|
+
siteId: text("siteId").notNull(),
|
|
6
|
+
// Page info
|
|
7
|
+
url: text("url").notNull(),
|
|
8
|
+
pathname: text("pathname").notNull(),
|
|
9
|
+
referrer: text("referrer"),
|
|
10
|
+
// Visitor (cookieless identification)
|
|
11
|
+
visitorHash: text("visitorHash").notNull(),
|
|
12
|
+
sessionId: text("sessionId").notNull(),
|
|
13
|
+
// Location (from Vercel geo headers)
|
|
14
|
+
country: text("country"),
|
|
15
|
+
countryCode: text("countryCode"),
|
|
16
|
+
region: text("region"),
|
|
17
|
+
city: text("city"),
|
|
18
|
+
// Device (parsed from User-Agent)
|
|
19
|
+
browser: text("browser"),
|
|
20
|
+
browserVer: text("browserVer"),
|
|
21
|
+
os: text("os"),
|
|
22
|
+
osVer: text("osVer"),
|
|
23
|
+
device: text("device"),
|
|
24
|
+
// Optional user link
|
|
25
|
+
userId: text("userId"),
|
|
26
|
+
isBot: boolean("isBot").default(false).notNull(),
|
|
27
|
+
timestamp: timestamp("timestamp").defaultNow().notNull(),
|
|
28
|
+
}, (table) => [
|
|
29
|
+
index("page_views_site_timestamp_idx").on(table.siteId, table.timestamp),
|
|
30
|
+
index("page_views_site_pathname_idx").on(table.siteId, table.pathname),
|
|
31
|
+
index("page_views_session_idx").on(table.sessionId),
|
|
32
|
+
index("page_views_user_idx").on(table.userId),
|
|
33
|
+
]);
|
|
34
|
+
// Custom events
|
|
35
|
+
export const events = pgTable("events", {
|
|
36
|
+
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
37
|
+
siteId: text("siteId").notNull(),
|
|
38
|
+
name: text("name").notNull(),
|
|
39
|
+
properties: json("properties"),
|
|
40
|
+
visitorHash: text("visitorHash").notNull(),
|
|
41
|
+
sessionId: text("sessionId").notNull(),
|
|
42
|
+
userId: text("userId"),
|
|
43
|
+
url: text("url"),
|
|
44
|
+
timestamp: timestamp("timestamp").defaultNow().notNull(),
|
|
45
|
+
}, (table) => [
|
|
46
|
+
index("events_site_name_timestamp_idx").on(table.siteId, table.name, table.timestamp),
|
|
47
|
+
index("events_site_timestamp_idx").on(table.siteId, table.timestamp),
|
|
48
|
+
index("events_user_idx").on(table.userId),
|
|
49
|
+
]);
|
|
50
|
+
// Daily salt for visitor hashing (privacy - rotates daily)
|
|
51
|
+
export const dailySalts = pgTable("daily_salts", {
|
|
52
|
+
date: date("date").primaryKey(),
|
|
53
|
+
salt: text("salt").notNull(),
|
|
54
|
+
});
|
|
55
|
+
// Error tracking - individual occurrences
|
|
56
|
+
export const analyticsErrors = pgTable("analytics_errors", {
|
|
57
|
+
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
58
|
+
siteId: text("siteId").notNull(),
|
|
59
|
+
// Error details
|
|
60
|
+
message: text("message").notNull(),
|
|
61
|
+
stack: text("stack"),
|
|
62
|
+
fingerprint: text("fingerprint").notNull(),
|
|
63
|
+
// Context
|
|
64
|
+
url: text("url").notNull(),
|
|
65
|
+
pathname: text("pathname").notNull(),
|
|
66
|
+
// Visitor context
|
|
67
|
+
visitorHash: text("visitorHash"),
|
|
68
|
+
sessionId: text("sessionId"),
|
|
69
|
+
userId: text("userId"),
|
|
70
|
+
// Browser context
|
|
71
|
+
browser: text("browser"),
|
|
72
|
+
browserVer: text("browserVer"),
|
|
73
|
+
os: text("os"),
|
|
74
|
+
device: text("device"),
|
|
75
|
+
// Metadata
|
|
76
|
+
metadata: json("metadata"),
|
|
77
|
+
timestamp: timestamp("timestamp").defaultNow().notNull(),
|
|
78
|
+
}, (table) => [
|
|
79
|
+
index("errors_site_timestamp_idx").on(table.siteId, table.timestamp),
|
|
80
|
+
index("errors_site_fingerprint_idx").on(table.siteId, table.fingerprint),
|
|
81
|
+
index("errors_user_idx").on(table.userId),
|
|
82
|
+
]);
|
|
83
|
+
// Error groups - aggregated by fingerprint
|
|
84
|
+
export const errorGroups = pgTable("error_groups", {
|
|
85
|
+
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
86
|
+
siteId: text("siteId").notNull(),
|
|
87
|
+
fingerprint: text("fingerprint").notNull(),
|
|
88
|
+
// Representative error
|
|
89
|
+
message: text("message").notNull(),
|
|
90
|
+
stack: text("stack"),
|
|
91
|
+
// Counts
|
|
92
|
+
count: integer("count").default(1).notNull(),
|
|
93
|
+
lastSeen: timestamp("lastSeen").notNull(),
|
|
94
|
+
firstSeen: timestamp("firstSeen").notNull(),
|
|
95
|
+
// Status: open, resolved, ignored
|
|
96
|
+
status: text("status").default("open").notNull(),
|
|
97
|
+
}, (table) => [
|
|
98
|
+
unique("error_groups_site_fingerprint_unique").on(table.siteId, table.fingerprint),
|
|
99
|
+
index("error_groups_site_status_lastseen_idx").on(table.siteId, table.status, table.lastSeen),
|
|
100
|
+
]);
|
|
101
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/track.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE1E,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgEf;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB1E"}
|
package/dist/track.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getClient } from "./client.js";
|
|
2
|
+
import { pageViews, events } from "./schema.js";
|
|
2
3
|
import { parseUserAgent } from "./ua.js";
|
|
3
4
|
import { isBot, getVisitorInfo, extractPathname } from "./utils.js";
|
|
4
5
|
export async function trackPageView(options) {
|
|
@@ -29,26 +30,24 @@ export async function trackPageView(options) {
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
const db = getClient();
|
|
32
|
-
await db.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
isBot: isBotRequest,
|
|
51
|
-
},
|
|
33
|
+
await db.insert(pageViews).values({
|
|
34
|
+
siteId,
|
|
35
|
+
url,
|
|
36
|
+
pathname,
|
|
37
|
+
referrer: cleanReferrer,
|
|
38
|
+
visitorHash,
|
|
39
|
+
sessionId,
|
|
40
|
+
country: country ?? null,
|
|
41
|
+
countryCode: countryCode ?? null,
|
|
42
|
+
region: region ?? null,
|
|
43
|
+
city: city ?? null,
|
|
44
|
+
browser: ua.browser,
|
|
45
|
+
browserVer: ua.browserVer,
|
|
46
|
+
os: ua.os,
|
|
47
|
+
osVer: ua.osVer,
|
|
48
|
+
device: ua.device,
|
|
49
|
+
userId: userId ?? null,
|
|
50
|
+
isBot: isBotRequest,
|
|
52
51
|
});
|
|
53
52
|
}
|
|
54
53
|
export async function trackEvent(options) {
|
|
@@ -59,16 +58,14 @@ export async function trackEvent(options) {
|
|
|
59
58
|
// Get visitor info (hashes for privacy)
|
|
60
59
|
const { visitorHash, sessionId } = await getVisitorInfo(ipNorm, uaNorm);
|
|
61
60
|
const db = getClient();
|
|
62
|
-
await db.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
userId,
|
|
71
|
-
},
|
|
61
|
+
await db.insert(events).values({
|
|
62
|
+
siteId,
|
|
63
|
+
name,
|
|
64
|
+
properties: properties ?? null,
|
|
65
|
+
url: url ?? null,
|
|
66
|
+
visitorHash,
|
|
67
|
+
sessionId,
|
|
68
|
+
userId: userId ?? null,
|
|
72
69
|
});
|
|
73
70
|
}
|
|
74
71
|
//# sourceMappingURL=track.js.map
|
package/dist/track.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track.js","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGpE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAA6B;IAE7B,MAAM,EACJ,MAAM,EACN,GAAG,EACH,QAAQ,EACR,EAAE,EACF,SAAS,EACT,MAAM;IACN,uDAAuD;IACvD,OAAO,EACP,WAAW,EACX,MAAM,EACN,IAAI,GACL,GAAG,OAAO,CAAC;IAEZ,8BAA8B;IAC9B,MAAM,MAAM,GAAG,EAAE,IAAI,IAAI,CAAC;IAC1B,MAAM,MAAM,GAAG,SAAS,IAAI,IAAI,CAAC;IAEjC,wCAAwC;IACxC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExE,mBAAmB;IACnB,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAElC,cAAc;IACd,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAEnC,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEtC,mDAAmD;IACnD,IAAI,aAAa,GAAG,QAAQ,IAAI,IAAI,CAAC;IACrC,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;YACtC,8CAA8C;YAC9C,aAAa,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAEvB,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"track.js","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA6C9C,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAIvD;AAsCD,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,GAAG,IAAI,EACjB,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,OAAO,CAAC,WAAW,CAAC,CAgBtB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASnD;AAGD,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAYvD"}
|
package/dist/utils.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash, randomBytes } from "crypto";
|
|
2
2
|
import { getClient } from "./client.js";
|
|
3
|
+
import { dailySalts } from "./schema.js";
|
|
4
|
+
import { eq, lt } from "drizzle-orm";
|
|
3
5
|
// Bot patterns to detect
|
|
4
6
|
const BOT_PATTERNS = [
|
|
5
7
|
/bot/i,
|
|
@@ -52,27 +54,32 @@ function hash(input) {
|
|
|
52
54
|
}
|
|
53
55
|
async function getDailySalt(date) {
|
|
54
56
|
const db = getClient();
|
|
55
|
-
|
|
57
|
+
// Format date as YYYY-MM-DD string for the date column
|
|
58
|
+
const dateStr = date.toISOString().split("T")[0];
|
|
56
59
|
// Try to get existing salt
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
const [existingSalt] = await db
|
|
61
|
+
.select()
|
|
62
|
+
.from(dailySalts)
|
|
63
|
+
.where(eq(dailySalts.date, dateStr))
|
|
64
|
+
.limit(1);
|
|
65
|
+
if (existingSalt) {
|
|
66
|
+
return existingSalt.salt;
|
|
67
|
+
}
|
|
60
68
|
// Create if doesn't exist
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
const salt = randomBytes(32).toString("hex");
|
|
70
|
+
try {
|
|
71
|
+
await db.insert(dailySalts).values({ date: dateStr, salt });
|
|
72
|
+
return salt;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Race condition - another request created it, try to fetch again
|
|
76
|
+
const [retry] = await db
|
|
77
|
+
.select()
|
|
78
|
+
.from(dailySalts)
|
|
79
|
+
.where(eq(dailySalts.date, dateStr))
|
|
80
|
+
.limit(1);
|
|
81
|
+
return retry?.salt ?? salt;
|
|
74
82
|
}
|
|
75
|
-
return dailySalt?.salt ?? randomBytes(32).toString("hex");
|
|
76
83
|
}
|
|
77
84
|
export async function getVisitorInfo(ip, userAgent) {
|
|
78
85
|
const now = new Date();
|
|
@@ -104,9 +111,11 @@ export async function cleanupOldSalts() {
|
|
|
104
111
|
const db = getClient();
|
|
105
112
|
const sevenDaysAgo = new Date();
|
|
106
113
|
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
const dateStr = sevenDaysAgo.toISOString().split("T")[0];
|
|
115
|
+
const deleted = await db
|
|
116
|
+
.delete(dailySalts)
|
|
117
|
+
.where(lt(dailySalts.date, dateStr))
|
|
118
|
+
.returning({ date: dailySalts.date });
|
|
119
|
+
return deleted.length;
|
|
111
120
|
}
|
|
112
121
|
//# sourceMappingURL=utils.js.map
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seneris/nosework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Privacy-focused, self-hosted analytics for your app suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,16 +17,11 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
|
-
"dist"
|
|
21
|
-
"prisma"
|
|
20
|
+
"dist"
|
|
22
21
|
],
|
|
23
22
|
"scripts": {
|
|
24
23
|
"build": "tsc",
|
|
25
24
|
"dev": "tsc --watch",
|
|
26
|
-
"db:generate": "prisma generate",
|
|
27
|
-
"db:migrate": "prisma migrate dev",
|
|
28
|
-
"db:push": "prisma db push",
|
|
29
|
-
"postinstall": "prisma generate",
|
|
30
25
|
"prepublishOnly": "bun run build"
|
|
31
26
|
},
|
|
32
27
|
"keywords": [
|
|
@@ -39,13 +34,13 @@
|
|
|
39
34
|
"author": "",
|
|
40
35
|
"license": "MIT",
|
|
41
36
|
"dependencies": {
|
|
42
|
-
"
|
|
37
|
+
"drizzle-orm": "^0.38.3",
|
|
38
|
+
"postgres": "^3.4.5",
|
|
43
39
|
"ua-parser-js": "^2.0.1"
|
|
44
40
|
},
|
|
45
41
|
"devDependencies": {
|
|
46
42
|
"@types/bun": "^1.3.5",
|
|
47
43
|
"@types/ua-parser-js": "^0.7.39",
|
|
48
|
-
"prisma": "^6.2.1",
|
|
49
44
|
"typescript": "^5.7.3"
|
|
50
45
|
},
|
|
51
46
|
"peerDependencies": {
|
package/prisma/schema.prisma
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
generator client {
|
|
2
|
-
provider = "prisma-client-js"
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
datasource db {
|
|
6
|
-
provider = "postgresql"
|
|
7
|
-
url = env("ANALYTICS_DATABASE_URL")
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
model Site {
|
|
11
|
-
id String @id @default(cuid())
|
|
12
|
-
name String
|
|
13
|
-
domain String @unique
|
|
14
|
-
createdAt DateTime @default(now())
|
|
15
|
-
|
|
16
|
-
pageViews PageView[]
|
|
17
|
-
events Event[]
|
|
18
|
-
errors Error[]
|
|
19
|
-
errorGroups ErrorGroup[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
model PageView {
|
|
23
|
-
id String @id @default(cuid())
|
|
24
|
-
siteId String
|
|
25
|
-
site Site @relation(fields: [siteId], references: [id], onDelete: Cascade)
|
|
26
|
-
|
|
27
|
-
// Page info
|
|
28
|
-
url String
|
|
29
|
-
pathname String
|
|
30
|
-
referrer String?
|
|
31
|
-
|
|
32
|
-
// Visitor (cookieless)
|
|
33
|
-
visitorHash String // Hash of IP + UA + daily salt
|
|
34
|
-
sessionId String // Hash with shorter rotation (30 min)
|
|
35
|
-
|
|
36
|
-
// Location (from GeoIP)
|
|
37
|
-
country String?
|
|
38
|
-
countryCode String?
|
|
39
|
-
region String?
|
|
40
|
-
city String?
|
|
41
|
-
|
|
42
|
-
// Device (from User-Agent)
|
|
43
|
-
browser String?
|
|
44
|
-
browserVer String?
|
|
45
|
-
os String?
|
|
46
|
-
osVer String?
|
|
47
|
-
device String? // desktop, mobile, tablet
|
|
48
|
-
|
|
49
|
-
// User context (optional, from your OAuth)
|
|
50
|
-
userId String?
|
|
51
|
-
|
|
52
|
-
// Bot detection
|
|
53
|
-
isBot Boolean @default(false)
|
|
54
|
-
|
|
55
|
-
timestamp DateTime @default(now())
|
|
56
|
-
|
|
57
|
-
@@index([siteId, timestamp])
|
|
58
|
-
@@index([siteId, pathname])
|
|
59
|
-
@@index([siteId, country])
|
|
60
|
-
@@index([visitorHash, timestamp])
|
|
61
|
-
@@index([sessionId])
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
model Event {
|
|
65
|
-
id String @id @default(cuid())
|
|
66
|
-
siteId String
|
|
67
|
-
site Site @relation(fields: [siteId], references: [id], onDelete: Cascade)
|
|
68
|
-
|
|
69
|
-
name String // e.g., "signup", "purchase", "button_click"
|
|
70
|
-
properties Json? // Flexible event data
|
|
71
|
-
|
|
72
|
-
visitorHash String
|
|
73
|
-
sessionId String
|
|
74
|
-
userId String?
|
|
75
|
-
|
|
76
|
-
url String?
|
|
77
|
-
|
|
78
|
-
timestamp DateTime @default(now())
|
|
79
|
-
|
|
80
|
-
@@index([siteId, name, timestamp])
|
|
81
|
-
@@index([siteId, timestamp])
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Daily salt for visitor hashing (privacy - rotates daily)
|
|
85
|
-
model DailySalt {
|
|
86
|
-
date DateTime @id @db.Date
|
|
87
|
-
salt String
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Error tracking
|
|
91
|
-
model Error {
|
|
92
|
-
id String @id @default(cuid())
|
|
93
|
-
siteId String
|
|
94
|
-
site Site @relation(fields: [siteId], references: [id], onDelete: Cascade)
|
|
95
|
-
|
|
96
|
-
// Error details
|
|
97
|
-
message String
|
|
98
|
-
stack String? @db.Text
|
|
99
|
-
fingerprint String // Hash for grouping similar errors
|
|
100
|
-
|
|
101
|
-
// Context
|
|
102
|
-
url String
|
|
103
|
-
pathname String
|
|
104
|
-
|
|
105
|
-
// Visitor context (reuse existing pattern)
|
|
106
|
-
visitorHash String?
|
|
107
|
-
sessionId String?
|
|
108
|
-
userId String?
|
|
109
|
-
|
|
110
|
-
// Browser context
|
|
111
|
-
browser String?
|
|
112
|
-
browserVer String?
|
|
113
|
-
os String?
|
|
114
|
-
device String?
|
|
115
|
-
|
|
116
|
-
// Metadata
|
|
117
|
-
metadata Json? // Custom context from app
|
|
118
|
-
|
|
119
|
-
timestamp DateTime @default(now())
|
|
120
|
-
|
|
121
|
-
@@index([siteId, timestamp])
|
|
122
|
-
@@index([siteId, fingerprint])
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
model ErrorGroup {
|
|
126
|
-
id String @id @default(cuid())
|
|
127
|
-
siteId String
|
|
128
|
-
site Site @relation(fields: [siteId], references: [id], onDelete: Cascade)
|
|
129
|
-
fingerprint String
|
|
130
|
-
|
|
131
|
-
// Representative error
|
|
132
|
-
message String
|
|
133
|
-
stack String? @db.Text
|
|
134
|
-
|
|
135
|
-
// Counts
|
|
136
|
-
count Int @default(1)
|
|
137
|
-
lastSeen DateTime
|
|
138
|
-
firstSeen DateTime
|
|
139
|
-
|
|
140
|
-
// Status: open, resolved, ignored
|
|
141
|
-
status String @default("open")
|
|
142
|
-
|
|
143
|
-
@@unique([siteId, fingerprint])
|
|
144
|
-
@@index([siteId, status, lastSeen])
|
|
145
|
-
}
|