@iann29/rastro 0.5.0 → 0.7.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 (80) hide show
  1. package/README.md +53 -9
  2. package/agent/integration.md +48 -19
  3. package/agent/manifest.json +13 -7
  4. package/agent/manifest.schema.json +18 -8
  5. package/dist/client/federation.d.ts +18 -8
  6. package/dist/client/federation.d.ts.map +1 -1
  7. package/dist/client/federation.js +7 -1
  8. package/dist/client/federation.js.map +1 -1
  9. package/dist/client/identity.d.ts +11 -0
  10. package/dist/client/identity.d.ts.map +1 -0
  11. package/dist/client/identity.js +123 -0
  12. package/dist/client/identity.js.map +1 -0
  13. package/dist/client/index.d.ts +257 -7
  14. package/dist/client/index.d.ts.map +1 -1
  15. package/dist/client/index.js +110 -4
  16. package/dist/client/index.js.map +1 -1
  17. package/dist/component/_generated/api.d.ts +2 -0
  18. package/dist/component/_generated/api.d.ts.map +1 -1
  19. package/dist/component/_generated/api.js.map +1 -1
  20. package/dist/component/_generated/component.d.ts +92 -0
  21. package/dist/component/_generated/component.d.ts.map +1 -1
  22. package/dist/component/ingest.d.ts.map +1 -1
  23. package/dist/component/ingest.js +37 -24
  24. package/dist/component/ingest.js.map +1 -1
  25. package/dist/component/people.d.ts +79 -0
  26. package/dist/component/people.d.ts.map +1 -0
  27. package/dist/component/people.js +249 -0
  28. package/dist/component/people.js.map +1 -0
  29. package/dist/component/reports.d.ts +13 -4
  30. package/dist/component/reports.d.ts.map +1 -1
  31. package/dist/component/reports.js +25 -10
  32. package/dist/component/reports.js.map +1 -1
  33. package/dist/component/sanitize.d.ts +3 -1
  34. package/dist/component/sanitize.d.ts.map +1 -1
  35. package/dist/component/sanitize.js +30 -1
  36. package/dist/component/sanitize.js.map +1 -1
  37. package/dist/component/schema.d.ts +42 -1
  38. package/dist/component/schema.js +30 -1
  39. package/dist/component/schema.js.map +1 -1
  40. package/dist/component/sites.d.ts +4 -0
  41. package/dist/component/sites.d.ts.map +1 -1
  42. package/dist/component/sites.js +13 -2
  43. package/dist/component/sites.js.map +1 -1
  44. package/dist/component/validators.d.ts +53 -1
  45. package/dist/component/validators.d.ts.map +1 -1
  46. package/dist/component/validators.js +28 -0
  47. package/dist/component/validators.js.map +1 -1
  48. package/dist/component/visitors.d.ts +38 -2
  49. package/dist/component/visitors.d.ts.map +1 -1
  50. package/dist/component/visitors.js +162 -42
  51. package/dist/component/visitors.js.map +1 -1
  52. package/dist/react/index.d.ts +9 -5
  53. package/dist/react/index.d.ts.map +1 -1
  54. package/dist/react/index.js +36 -5
  55. package/dist/react/index.js.map +1 -1
  56. package/dist/tracker/generated.d.ts +6 -6
  57. package/dist/tracker/generated.d.ts.map +1 -1
  58. package/dist/tracker/generated.js +6 -6
  59. package/dist/tracker/generated.js.map +1 -1
  60. package/dist/tracker/tracker.d.ts +2 -1
  61. package/dist/tracker/tracker.d.ts.map +1 -1
  62. package/dist/tracker/tracker.js +41 -2
  63. package/dist/tracker/tracker.js.map +1 -1
  64. package/dist/tracker.min.js +1 -1
  65. package/docs/federation.md +24 -0
  66. package/docs/identity.md +307 -0
  67. package/docs/upgrading.md +85 -20
  68. package/llms.txt +6 -2
  69. package/package.json +5 -3
  70. package/src/component/_generated/api.ts +2 -0
  71. package/src/component/_generated/component.ts +104 -0
  72. package/src/component/ingest.ts +54 -30
  73. package/src/component/people.ts +321 -0
  74. package/src/component/reports.ts +34 -9
  75. package/src/component/sanitize.ts +46 -1
  76. package/src/component/schema.ts +35 -0
  77. package/src/component/sites.ts +14 -1
  78. package/src/component/validators.ts +50 -0
  79. package/src/component/visitors.ts +232 -55
  80. package/src/tracker/generated.ts +6 -6
@@ -0,0 +1,249 @@
1
+ import { v } from "convex/values";
2
+ import { query, mutation } from "./_generated/server.js";
3
+ import { fail } from "./errors.js";
4
+ import { personFilterValidator, visitorProfileValidator, } from "./validators.js";
5
+ export const personDocumentValidator = visitorProfileValidator.extend({
6
+ _id: v.id("visitorProfiles"),
7
+ _creationTime: v.number(),
8
+ siteId: v.id("sites"),
9
+ });
10
+ export function profileSearchFields(name, email) {
11
+ return {
12
+ searchName: normalizeSearch(name ?? ""),
13
+ searchEmail: normalizeSearch(email ?? ""),
14
+ };
15
+ }
16
+ function normalizeSearch(value) {
17
+ return value.normalize("NFKC").trim().toLowerCase();
18
+ }
19
+ export function mergePersonAttributes(previous = {}, patch) {
20
+ const attributes = { ...previous };
21
+ for (const [key, value] of Object.entries(patch ?? {})) {
22
+ validateAttributeKey(key);
23
+ if (value === null)
24
+ delete attributes[key];
25
+ else {
26
+ validateAttributeValue(value);
27
+ attributes[key] = value;
28
+ }
29
+ }
30
+ if (Object.keys(attributes).length > 32 ||
31
+ new TextEncoder().encode(JSON.stringify(attributes)).length > 4096)
32
+ fail("INVALID_ARGUMENT", "attributes allow at most 32 keys and 4096 UTF-8 bytes");
33
+ return Object.fromEntries(Object.entries(attributes).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));
34
+ }
35
+ function validateAttributeKey(key) {
36
+ if (!/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(key) ||
37
+ ["__proto__", "constructor", "prototype"].includes(key))
38
+ fail("INVALID_ARGUMENT", "attribute keys must start with a letter and contain up to 64 ASCII letters, digits, dots, underscores or hyphens");
39
+ }
40
+ function validateAttributeValue(value) {
41
+ if ((typeof value === "string" && value.length > 512) ||
42
+ (typeof value === "number" && !Number.isFinite(value)))
43
+ fail("INVALID_ARGUMENT", "attribute values require finite numbers or strings up to 512 characters");
44
+ }
45
+ /** Index each current attribute once; ordinary reads never scan all profiles. */
46
+ export async function syncPersonAttributes(ctx, siteId, visitorId, attributes) {
47
+ const rows = await ctx.db
48
+ .query("visitorAttributes")
49
+ .withIndex("by_siteId_and_visitorId", (q) => q.eq("siteId", siteId).eq("visitorId", visitorId))
50
+ .take(33);
51
+ const present = new Set();
52
+ for (const row of rows) {
53
+ present.add(row.key);
54
+ if (!Object.hasOwn(attributes, row.key))
55
+ await ctx.db.delete("visitorAttributes", row._id);
56
+ else if (attributes[row.key] !== row.value)
57
+ await ctx.db.patch("visitorAttributes", row._id, {
58
+ value: attributes[row.key],
59
+ });
60
+ }
61
+ for (const [key, value] of Object.entries(attributes)) {
62
+ if (!present.has(key))
63
+ await ctx.db.insert("visitorAttributes", {
64
+ siteId,
65
+ visitorId,
66
+ key,
67
+ value,
68
+ });
69
+ }
70
+ }
71
+ export function publicPerson(row) {
72
+ const { searchName: _name, searchEmail: _email, ...person } = row;
73
+ return person;
74
+ }
75
+ /** An optional, bounded upgrade for profiles created before the directory. */
76
+ export const backfillSearch = mutation({
77
+ args: { siteId: v.id("sites") },
78
+ returns: v.object({ updated: v.number(), isDone: v.boolean() }),
79
+ handler: async (ctx, { siteId }) => {
80
+ if (!(await ctx.db.get("sites", siteId)))
81
+ fail("NOT_FOUND", "site not found");
82
+ const rows = await ctx.db
83
+ .query("visitorProfiles")
84
+ .withIndex("by_siteId_and_searchName_and_visitorId", (q) => q.eq("siteId", siteId).eq("searchName", undefined))
85
+ .take(65);
86
+ for (const row of rows.slice(0, 64)) {
87
+ await ctx.db.patch("visitorProfiles", row._id, profileSearchFields(row.name, row.email));
88
+ await syncPersonAttributes(ctx, siteId, row.visitorId, row.attributes ?? {});
89
+ }
90
+ return { updated: Math.min(64, rows.length), isDone: rows.length <= 64 };
91
+ },
92
+ });
93
+ /** Exclusive upper bound for a Unicode prefix, including supplementary characters. */
94
+ function afterPrefix(prefix) {
95
+ const points = Array.from(prefix);
96
+ for (let i = points.length - 1; i >= 0; i--) {
97
+ const code = points[i].codePointAt(0);
98
+ if (code < 0x10ffff)
99
+ return (points.slice(0, i).join("") +
100
+ String.fromCodePoint(code + 1 === 0xd800 ? 0xe000 : code + 1));
101
+ }
102
+ return undefined;
103
+ }
104
+ function normalizedFilter(filter) {
105
+ if (!filter)
106
+ return undefined;
107
+ if (filter.field === "attribute") {
108
+ validateAttributeKey(filter.key);
109
+ validateAttributeValue(filter.value);
110
+ return { field: "attribute", key: filter.key, value: filter.value };
111
+ }
112
+ if (filter.prefix.length > 320)
113
+ fail("INVALID_ARGUMENT", "search prefix exceeds 320 characters");
114
+ const prefix = filter.field === "visitorId"
115
+ ? filter.prefix.trim()
116
+ : normalizeSearch(filter.prefix);
117
+ return prefix ? { field: filter.field, prefix } : undefined;
118
+ }
119
+ export const list = query({
120
+ args: {
121
+ siteId: v.id("sites"),
122
+ filter: v.optional(personFilterValidator),
123
+ paginationOpts: v.object({
124
+ cursor: v.union(v.string(), v.null()),
125
+ numItems: v.number(),
126
+ }),
127
+ },
128
+ returns: v.object({
129
+ page: v.array(personDocumentValidator),
130
+ isDone: v.boolean(),
131
+ continueCursor: v.string(),
132
+ }),
133
+ handler: async (ctx, args) => {
134
+ const filter = normalizedFilter(args.filter);
135
+ const scope = JSON.stringify([args.siteId, filter ?? null]);
136
+ const limit = args.paginationOpts.numItems;
137
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 50)
138
+ fail("INVALID_ARGUMENT", "numItems must be an integer between 1 and 50");
139
+ let after;
140
+ if (args.paginationOpts.cursor !== null) {
141
+ try {
142
+ // NFKC may expand one character into several, in both scope and value.
143
+ if (args.paginationOpts.cursor.length > 16_384)
144
+ throw new Error();
145
+ const cursor = JSON.parse(args.paginationOpts.cursor);
146
+ if (cursor.v !== 1 ||
147
+ cursor.scope !== scope ||
148
+ typeof cursor.value !== "string" ||
149
+ typeof cursor.visitorId !== "string")
150
+ throw new Error();
151
+ after = { value: cursor.value, visitorId: cursor.visitorId };
152
+ if (filter &&
153
+ filter.field !== "attribute" &&
154
+ !after.value.startsWith(filter.prefix))
155
+ throw new Error();
156
+ }
157
+ catch {
158
+ fail("INVALID_ARGUMENT", "cursor does not belong to this people query");
159
+ }
160
+ }
161
+ let rows;
162
+ const take = limit + 1;
163
+ if (filter?.field === "attribute") {
164
+ const matches = await ctx.db
165
+ .query("visitorAttributes")
166
+ .withIndex("by_siteId_and_key_and_value_and_visitorId", (q) => q
167
+ .eq("siteId", args.siteId)
168
+ .eq("key", filter.key)
169
+ .eq("value", filter.value)
170
+ .gt("visitorId", after?.visitorId ?? ""))
171
+ .take(take);
172
+ rows = await Promise.all(matches.map(async (match) => {
173
+ const row = await ctx.db
174
+ .query("visitorProfiles")
175
+ .withIndex("by_siteId_and_visitorId", (q) => q.eq("siteId", args.siteId).eq("visitorId", match.visitorId))
176
+ .unique();
177
+ if (!row)
178
+ fail("NOT_FOUND", "person attribute index has no profile");
179
+ return row;
180
+ }));
181
+ }
182
+ else if (filter && filter.field !== "visitorId") {
183
+ const pending = await ctx.db
184
+ .query("visitorProfiles")
185
+ .withIndex("by_siteId_and_searchName_and_visitorId", (q) => q.eq("siteId", args.siteId).eq("searchName", undefined))
186
+ .first();
187
+ if (pending)
188
+ fail("CONFLICT", "Run backfillVisitorProfiles for this site before searching existing profiles");
189
+ const field = filter.field === "name" ? "searchName" : "searchEmail";
190
+ const index = filter.field === "name"
191
+ ? "by_siteId_and_searchName_and_visitorId"
192
+ : "by_siteId_and_searchEmail_and_visitorId";
193
+ rows = after
194
+ ? await ctx.db
195
+ .query("visitorProfiles")
196
+ .withIndex(index, (q) => q
197
+ .eq("siteId", args.siteId)
198
+ .eq(field, after.value)
199
+ .gt("visitorId", after.visitorId))
200
+ .take(take)
201
+ : [];
202
+ if (rows.length < take) {
203
+ const upper = afterPrefix(filter.prefix);
204
+ const rest = await ctx.db
205
+ .query("visitorProfiles")
206
+ .withIndex(index, (q) => {
207
+ const lower = after
208
+ ? q.eq("siteId", args.siteId).gt(field, after.value)
209
+ : q.eq("siteId", args.siteId).gte(field, filter.prefix);
210
+ return upper === undefined ? lower : lower.lt(field, upper);
211
+ })
212
+ .take(take - rows.length);
213
+ rows.push(...rest);
214
+ }
215
+ }
216
+ else {
217
+ const prefix = filter?.prefix ?? "";
218
+ const upper = afterPrefix(prefix);
219
+ rows = await ctx.db
220
+ .query("visitorProfiles")
221
+ .withIndex("by_siteId_and_visitorId", (q) => {
222
+ const lower = after
223
+ ? q.eq("siteId", args.siteId).gt("visitorId", after.visitorId)
224
+ : q.eq("siteId", args.siteId).gte("visitorId", prefix);
225
+ return upper === undefined ? lower : lower.lt("visitorId", upper);
226
+ })
227
+ .take(take);
228
+ }
229
+ const page = rows.slice(0, limit);
230
+ const last = page.at(-1);
231
+ return {
232
+ page: page.map(publicPerson),
233
+ isDone: rows.length <= limit,
234
+ continueCursor: JSON.stringify({
235
+ v: 1,
236
+ scope,
237
+ visitorId: last?.visitorId ?? after?.visitorId ?? "",
238
+ value: last
239
+ ? filter?.field === "name"
240
+ ? last.searchName
241
+ : filter?.field === "email"
242
+ ? last.searchEmail
243
+ : last.visitorId
244
+ : (after?.value ?? ""),
245
+ }),
246
+ };
247
+ },
248
+ });
249
+ //# sourceMappingURL=people.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"people.js","sourceRoot":"","sources":["../../src/component/people.ts"],"names":[],"mappings":"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"}
@@ -140,7 +140,7 @@ export declare const liveVisitors: import("convex/server").RegisteredQuery<"publ
140
140
  limit?: number | undefined;
141
141
  now: number;
142
142
  siteIds: import("convex/values").GenericId<"sites">[];
143
- }, Promise<{
143
+ }, Promise<({
144
144
  _id: import("convex/values").GenericId<"liveSessions">;
145
145
  _creationTime: number;
146
146
  siteId: import("convex/values").GenericId<"sites">;
@@ -172,7 +172,9 @@ export declare const liveVisitors: import("convex/server").RegisteredQuery<"publ
172
172
  step: number;
173
173
  steps: number;
174
174
  } | undefined;
175
- }[]>>;
175
+ } & {
176
+ profile?: import("./validators.js").VisitorProfile;
177
+ })[]>>;
176
178
  /**
177
179
  * Every route the sites served in the range and the transitions between
178
180
  * them, read from the daily route rollups newest day first. Exits and
@@ -194,6 +196,9 @@ export declare const siteMap: import("convex/server").RegisteredQuery<"public",
194
196
  from: number;
195
197
  to: number;
196
198
  } | null;
199
+ routePatterns: {
200
+ [k: string]: string[];
201
+ };
197
202
  routes: {
198
203
  route: string;
199
204
  pageviews: number;
@@ -250,7 +255,9 @@ type SessionRow = Omit<Doc<"sessions">, "geoLookupAttemptedAt" | "lastPageviewAt
250
255
  export declare const getSession: import("convex/server").RegisteredQuery<"public", {
251
256
  sessionId: string;
252
257
  siteId: import("convex/values").GenericId<"sites">;
253
- }, Promise<SessionRow | null>>;
258
+ }, Promise<(SessionRow & {
259
+ profile?: import("./validators.js").VisitorProfile;
260
+ }) | null>>;
254
261
  /** Exact commissions alongside overview's period revenue/conversion totals. */
255
262
  export declare const revenueSummary: import("convex/server").RegisteredQuery<"public", {
256
263
  from: number;
@@ -272,7 +279,9 @@ export declare const listSessions: import("convex/server").RegisteredQuery<"publ
272
279
  siteId: import("convex/values").GenericId<"sites">;
273
280
  to: number;
274
281
  }, Promise<{
275
- page: SessionRow[];
282
+ page: (SessionRow & {
283
+ profile?: import("./validators.js").VisitorProfile;
284
+ })[];
276
285
  isDone: boolean;
277
286
  continueCursor: string;
278
287
  }>>;
@@ -1 +1 @@
1
- {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/component/reports.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AAiMzD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;gBAqwEX,MAAM;mBACH,MAAM;gBACT,MAAM;sBACA,MAAM;wBACJ,MAAM;kBACZ,MAAM;kBACN,MAAM;qBACH,MAAM;sBACL,MAAM;oBACR,MAAM;2BACC,MAAM;qBACZ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAt6DX,UAAU;YACV,YAAY;YACZ,QAAQ;YACR,YAAY;YACZ,UAAU;YACV,WAAW;YACX,SAAS,EAAE,aAAa;YACxB,QAAQ,EAAE,sBAAsB;YAChC,UAAU;YACV,WAAW,EAAE,aAAa;YAC1B,YAAY;YACZ,WAAW;YACX,WAAW;;;;;;;;;;;;;;sBAsgEP,WAAW;;;;YAz/Df,aAAa,EAAE,aAAa;YAC5B,aAAa,EAAE,aAAa;YAC5B,aAAa,EAAE,aAAa;YAC5B,YAAY,EAAE,WAAW;;;GAKjC,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsEvB,CAAC;AAsBH;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA0KN,MAAM;YAAM,MAAM;eAAS,MAAM;;;QA+CvC,MAAM;QACN,WAAW;;;eAzKN,aAAa;;;wBAGN,CAAC;;;;;;;;sBAq1DP,WAAW;;;;YA/0DP,KAAK,EAAE,iBAAiB;YAAW,KAAK;;;;;;;;GAyKxD,CAAC;AA0CH,KAAK,UAAU,GAAG,IAAI,CACpB,GAAG,CAAC,UAAU,CAAC,EACf,sBAAsB,GAAG,gBAAgB,CAC1C,CAAC;AAkBF,uEAAuE;AACvE,eAAO,MAAM,UAAU;;;8BAmBrB,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,cAAc;;;;;;GAwEzB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;GAyEvB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BzB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiE1B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgDzB,CAAC;AASH,eAAO,MAAM,WAAW;;;;;;;;qBAiBH,MAAM;oBAAc,MAAM;;;;;;;;;;;;QA0DvC,KAAK;QACL,QAAQ;;;;;;;QAWR,KAAK;;;sBAwsCC,WAAW;;;;GApsCvB,CAAC;AAiBH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;QAoFhB,KAAK;QAGL,QAAQ;;;;;;;QACR,KAAK;;;sBA2lCD,WAAW;;;;;;;;;;;;;;;;KArlCvB,CAAC;AAYH,eAAO,MAAM,gBAAgB;;;;;;;;qBAqDR,MAAM;sBACL,MAAM;yBACH,MAAM;;;;;;;;;;;;;;QAkGvB,KAAK;QACL,QAAQ;;;;;;;QAaR,KAAK;;;sBAk6BC,WAAW;;;QAj6BjB,cAAc;YACZ,KAAK;YAGL,KAAK;;;GAKb,CAAC;AAWH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4HjB,KAAK,EAAE,aAAa;QACpB,QAAQ;;;;;;;QAOR,KAAK;;;sBAywBC,WAAW;;;;GArwBvB,CAAC;AAiBH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;GAmDvB,CAAC;AAykBH,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC"}
1
+ {"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/component/reports.ts"],"names":[],"mappings":"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"}
@@ -8,11 +8,12 @@ import { isLocalDayAligned, localDayStart, localDayStarts, localDayTimezone, sha
8
8
  import { compareJourneyEvents, hydrateEventContexts, loadSessionJourneyEvents, loadVisitorJourneyEvents, } from "./eventStore.js";
9
9
  import { isPlainRecord } from "./guards.js";
10
10
  import { classifyOrigin } from "./origin.js";
11
- import { externalReferrer } from "./sanitize.js";
12
- import { affiliateFieldsValidator, eventFieldsValidator, funnelFieldsValidator, goalFieldsValidator, sessionFieldsValidator, vitalMetricValidator, } from "./validators.js";
13
- import { resolveVisitorIdentities } from "./visitors.js";
11
+ import { externalReferrer, normalizeRoute } from "./sanitize.js";
12
+ import { affiliateFieldsValidator, eventFieldsValidator, funnelFieldsValidator, goalFieldsValidator, sessionFieldsValidator, vitalMetricValidator, visitorProfileValidator, } from "./validators.js";
13
+ import { resolveVisitorIdentities, withVisitorProfiles } from "./visitors.js";
14
14
  import { mergeVitalHistograms, VITAL_ALL, VITAL_METRICS, vitalHistogramPercentile, vitalRatingCounts, } from "./vitals.js";
15
15
  const sessionDocumentValidator = sessionFieldsValidator.extend({
16
+ profile: v.optional(visitorProfileValidator),
16
17
  _id: v.id("sessions"),
17
18
  _creationTime: v.number(),
18
19
  });
@@ -21,6 +22,7 @@ const eventDocumentValidator = eventFieldsValidator.extend({
21
22
  _creationTime: v.number(),
22
23
  });
23
24
  const liveSessionDocumentValidator = v.object({
25
+ profile: v.optional(visitorProfileValidator),
24
26
  _id: v.id("liveSessions"),
25
27
  _creationTime: v.number(),
26
28
  siteId: v.id("sites"),
@@ -470,7 +472,7 @@ export const liveVisitors = query({
470
472
  .order("desc")
471
473
  .take(limit)));
472
474
  }
473
- return rows
475
+ const visible = rows
474
476
  .sort((left, right) => right.lastSeenAt - left.lastSeenAt)
475
477
  .slice(0, limit)
476
478
  .map((row) => ({
@@ -504,6 +506,7 @@ export const liveVisitors = query({
504
506
  : {}),
505
507
  ...(row.funnel ? { funnel: row.funnel } : {}),
506
508
  }));
509
+ return withVisitorProfiles(ctx, visible);
507
510
  },
508
511
  });
509
512
  const siteMapRouteValidator = v.object({
@@ -547,6 +550,7 @@ export const siteMap = query({
547
550
  window: v.union(v.object({ from: v.number(), to: v.number() }), v.null()),
548
551
  routes: v.array(siteMapRouteValidator),
549
552
  transitions: v.array(siteMapTransitionValidator),
553
+ routePatterns: v.optional(v.record(v.string(), v.array(v.string()))),
550
554
  truncated: v.object({ routes: v.boolean(), transitions: v.boolean() }),
551
555
  metadata: reportMetadataValidator.extend({
552
556
  visitors: v.object({
@@ -564,6 +568,10 @@ export const siteMap = query({
564
568
  const siteIds = validateSiteIds(args.siteIds);
565
569
  validateRange(args.from, args.to, MAX_FEATURE_ROLLUP_DAYS);
566
570
  requireAlignedRange(args.from, args.to, DAY_MS, "site map");
571
+ const routePatterns = Object.fromEntries(await Promise.all(siteIds.map(async (siteId) => [
572
+ siteId,
573
+ (await ctx.db.get("sites", siteId))?.routePatterns ?? [],
574
+ ])));
567
575
  const controls = await Promise.all(siteIds.map((siteId) => ctx.db
568
576
  .query("analyticsCoverage")
569
577
  .withIndex("by_siteId", (range) => range.eq("siteId", siteId))
@@ -601,6 +609,7 @@ export const siteMap = query({
601
609
  window: null,
602
610
  routes: [],
603
611
  transitions: [],
612
+ routePatterns,
604
613
  truncated: { routes: false, transitions: false },
605
614
  metadata: metadata("unavailable"),
606
615
  };
@@ -639,7 +648,10 @@ export const siteMap = query({
639
648
  for (const row of rows) {
640
649
  if (row.bucketStart < completeFrom)
641
650
  continue;
642
- const current = totalsFor(row.route);
651
+ // Apply current patterns to retained rollups too, before merging sketches.
652
+ const patterns = routePatterns[row.siteId];
653
+ const route = normalizeRoute(row.route, patterns);
654
+ const current = totalsFor(route);
643
655
  current.pageviews += row.pageviews;
644
656
  current.entries += row.entries;
645
657
  current.continued += row.continued;
@@ -648,10 +660,11 @@ export const siteMap = query({
648
660
  current.sketch = unionVisitorSketches(current.sketch, row.visitorSketch);
649
661
  current.daily.set(row.bucketStart, (current.daily.get(row.bucketStart) ?? 0) + row.pageviews);
650
662
  for (const target of row.outgoing) {
651
- const key = `${row.route}\u0000${target.route}`;
663
+ const to = normalizeRoute(target.route, patterns);
664
+ const key = `${route}\u0000${to}`;
652
665
  const edge = edges.get(key) ?? {
653
- from: row.route,
654
- to: target.route,
666
+ from: route,
667
+ to,
655
668
  count: 0,
656
669
  };
657
670
  edge.count += target.count;
@@ -695,6 +708,7 @@ export const siteMap = query({
695
708
  from: args.from,
696
709
  to: args.to,
697
710
  window: completeFrom > args.to ? null : { from: windowFrom, to: args.to },
711
+ routePatterns,
698
712
  routes: routeRows,
699
713
  transitions: transitionRows,
700
714
  truncated: {
@@ -765,7 +779,7 @@ export const getSession = query({
765
779
  return null;
766
780
  const { geoLookupAttemptedAt: _geo, lastPageviewAt: _pageview, ...result } = session;
767
781
  const site = await ctx.db.get("sites", args.siteId);
768
- return withOrigin(result, site?.domains ?? []);
782
+ return (await withVisitorProfiles(ctx, [withOrigin(result, site?.domains ?? [])]))[0];
769
783
  },
770
784
  });
771
785
  /** Exact commissions alongside overview's period revenue/conversion totals. */
@@ -879,10 +893,11 @@ export const listSessions = query({
879
893
  }
880
894
  const site = await ctx.db.get("sites", args.siteId);
881
895
  const publicRows = rows.map(({ geoLookupAttemptedAt: _attemptedAt, lastPageviewAt: _lastPageviewAt, ...row }) => withOrigin(row, site?.domains ?? []));
882
- return keysetPaginationResult(publicRows, pagination, (row) => ({
896
+ const result = keysetPaginationResult(publicRows, pagination, (row) => ({
883
897
  timestamp: row.lastSeenAt,
884
898
  creationTime: row._creationTime,
885
899
  }));
900
+ return { ...result, page: await withVisitorProfiles(ctx, result.page) };
886
901
  },
887
902
  });
888
903
  export const sessionJourney = query({