@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.
package/dist/query.js ADDED
@@ -0,0 +1,471 @@
1
+ import { getClient } from "./client.js";
2
+ function buildWhere(options) {
3
+ return {
4
+ siteId: options.siteId,
5
+ timestamp: {
6
+ gte: options.startDate,
7
+ lte: options.endDate,
8
+ },
9
+ isBot: false, // Exclude bots by default
10
+ };
11
+ }
12
+ export async function getStats(options) {
13
+ const db = getClient();
14
+ const where = buildWhere(options);
15
+ // Get page views count
16
+ const pageViews = await db.pageView.count({ where });
17
+ // Get unique visitors
18
+ const visitorsResult = await db.pageView.groupBy({
19
+ by: ["visitorHash"],
20
+ where,
21
+ });
22
+ const visitors = visitorsResult.length;
23
+ // Get unique sessions
24
+ const sessionsResult = await db.pageView.groupBy({
25
+ by: ["sessionId"],
26
+ where,
27
+ });
28
+ const sessions = sessionsResult.length;
29
+ // Calculate bounce rate (sessions with only 1 page view)
30
+ const sessionPageCounts = await db.pageView.groupBy({
31
+ by: ["sessionId"],
32
+ where,
33
+ _count: { id: true },
34
+ });
35
+ const bouncedSessions = sessionPageCounts.filter((s) => s._count.id === 1).length;
36
+ const bounceRate = sessions > 0 ? (bouncedSessions / sessions) * 100 : 0;
37
+ return {
38
+ pageViews,
39
+ visitors,
40
+ sessions,
41
+ bounceRate: Math.round(bounceRate * 100) / 100,
42
+ };
43
+ }
44
+ export async function getTopPages(options) {
45
+ const db = getClient();
46
+ const where = buildWhere(options);
47
+ const limit = options.limit ?? 10;
48
+ // Group by pathname and count
49
+ const results = await db.pageView.groupBy({
50
+ by: ["pathname"],
51
+ where,
52
+ _count: { id: true },
53
+ });
54
+ // Get unique visitors per page (need separate query)
55
+ const pageVisitors = await Promise.all(results.map(async (r) => {
56
+ const uniqueVisitors = await db.pageView.groupBy({
57
+ by: ["visitorHash"],
58
+ where: { ...where, pathname: r.pathname },
59
+ });
60
+ return {
61
+ pathname: r.pathname,
62
+ pageViews: r._count.id,
63
+ visitors: uniqueVisitors.length,
64
+ };
65
+ }));
66
+ // Sort by page views and limit
67
+ return pageVisitors
68
+ .sort((a, b) => b.pageViews - a.pageViews)
69
+ .slice(0, limit);
70
+ }
71
+ export async function getLocations(options) {
72
+ const db = getClient();
73
+ const where = buildWhere(options);
74
+ const limit = options.limit ?? 20;
75
+ // Group by country and city
76
+ const results = await db.pageView.groupBy({
77
+ by: ["country", "countryCode", "city"],
78
+ where,
79
+ _count: { id: true },
80
+ });
81
+ // Get unique visitors per location
82
+ const locationData = await Promise.all(results.map(async (r) => {
83
+ const uniqueVisitors = await db.pageView.groupBy({
84
+ by: ["visitorHash"],
85
+ where: {
86
+ ...where,
87
+ country: r.country,
88
+ city: r.city,
89
+ },
90
+ });
91
+ return {
92
+ country: r.country,
93
+ countryCode: r.countryCode,
94
+ city: r.city,
95
+ pageViews: r._count.id,
96
+ visitors: uniqueVisitors.length,
97
+ };
98
+ }));
99
+ // Sort by page views and limit
100
+ return locationData
101
+ .sort((a, b) => b.pageViews - a.pageViews)
102
+ .slice(0, limit);
103
+ }
104
+ export async function getReferrers(options) {
105
+ const db = getClient();
106
+ const where = buildWhere(options);
107
+ const limit = options.limit ?? 10;
108
+ // Group by referrer
109
+ const results = await db.pageView.groupBy({
110
+ by: ["referrer"],
111
+ where,
112
+ _count: { id: true },
113
+ });
114
+ // Get unique visitors per referrer
115
+ const referrerData = await Promise.all(results.map(async (r) => {
116
+ const uniqueVisitors = await db.pageView.groupBy({
117
+ by: ["visitorHash"],
118
+ where: { ...where, referrer: r.referrer },
119
+ });
120
+ return {
121
+ referrer: r.referrer,
122
+ pageViews: r._count.id,
123
+ visitors: uniqueVisitors.length,
124
+ };
125
+ }));
126
+ // Sort by page views and limit
127
+ return referrerData
128
+ .sort((a, b) => b.pageViews - a.pageViews)
129
+ .slice(0, limit);
130
+ }
131
+ export async function getDevices(options) {
132
+ const db = getClient();
133
+ const where = buildWhere(options);
134
+ const limit = options.limit ?? 10;
135
+ // Group by device, browser, os
136
+ const results = await db.pageView.groupBy({
137
+ by: ["device", "browser", "os"],
138
+ where,
139
+ _count: { id: true },
140
+ });
141
+ // Get unique visitors per device combo
142
+ const deviceData = await Promise.all(results.map(async (r) => {
143
+ const uniqueVisitors = await db.pageView.groupBy({
144
+ by: ["visitorHash"],
145
+ where: {
146
+ ...where,
147
+ device: r.device,
148
+ browser: r.browser,
149
+ os: r.os,
150
+ },
151
+ });
152
+ return {
153
+ device: r.device,
154
+ browser: r.browser,
155
+ os: r.os,
156
+ pageViews: r._count.id,
157
+ visitors: uniqueVisitors.length,
158
+ };
159
+ }));
160
+ // Sort by page views and limit
161
+ return deviceData
162
+ .sort((a, b) => b.pageViews - a.pageViews)
163
+ .slice(0, limit);
164
+ }
165
+ export async function getTimeSeries(options) {
166
+ const db = getClient();
167
+ const where = buildWhere(options);
168
+ const interval = options.interval ?? "day";
169
+ // Get all page views in range
170
+ const pageViews = await db.pageView.findMany({
171
+ where,
172
+ select: { timestamp: true, visitorHash: true },
173
+ orderBy: { timestamp: "asc" },
174
+ });
175
+ // Group by interval
176
+ const groups = new Map();
177
+ for (const pv of pageViews) {
178
+ const key = formatDateKey(pv.timestamp, interval);
179
+ const group = groups.get(key) ?? { views: 0, visitors: new Set() };
180
+ group.views++;
181
+ group.visitors.add(pv.visitorHash);
182
+ groups.set(key, group);
183
+ }
184
+ // Convert to array
185
+ return Array.from(groups.entries()).map(([date, data]) => ({
186
+ date,
187
+ pageViews: data.views,
188
+ visitors: data.visitors.size,
189
+ }));
190
+ }
191
+ function formatDateKey(date, interval) {
192
+ const d = new Date(date);
193
+ switch (interval) {
194
+ case "hour":
195
+ return d.toISOString().slice(0, 13) + ":00";
196
+ case "day":
197
+ return d.toISOString().slice(0, 10);
198
+ case "week": {
199
+ // Get start of week (Sunday)
200
+ const day = d.getDay();
201
+ d.setDate(d.getDate() - day);
202
+ return d.toISOString().slice(0, 10);
203
+ }
204
+ case "month":
205
+ return d.toISOString().slice(0, 7);
206
+ }
207
+ }
208
+ // ============================================
209
+ // Session Analytics Functions
210
+ // ============================================
211
+ /**
212
+ * Get aggregate session statistics
213
+ */
214
+ export async function getSessionStats(options) {
215
+ const db = getClient();
216
+ const where = buildWhere(options);
217
+ // Get all page views grouped by session
218
+ const pageViews = await db.pageView.findMany({
219
+ where,
220
+ select: { sessionId: true, timestamp: true },
221
+ orderBy: { timestamp: "asc" },
222
+ });
223
+ // Group page views by session
224
+ const sessions = new Map();
225
+ for (const pv of pageViews) {
226
+ const timestamps = sessions.get(pv.sessionId) ?? [];
227
+ timestamps.push(pv.timestamp);
228
+ sessions.set(pv.sessionId, timestamps);
229
+ }
230
+ const totalSessions = sessions.size;
231
+ if (totalSessions === 0) {
232
+ return {
233
+ totalSessions: 0,
234
+ avgDuration: 0,
235
+ avgPagesPerSession: 0,
236
+ bounceRate: 0,
237
+ };
238
+ }
239
+ let totalDuration = 0;
240
+ let totalPageCount = 0;
241
+ let bounceCount = 0;
242
+ for (const timestamps of sessions.values()) {
243
+ const pageCount = timestamps.length;
244
+ totalPageCount += pageCount;
245
+ if (pageCount === 1) {
246
+ bounceCount++;
247
+ // Single page view = 0 duration
248
+ }
249
+ else {
250
+ // Duration = last timestamp - first timestamp
251
+ const sorted = timestamps.sort((a, b) => a.getTime() - b.getTime());
252
+ const firstTimestamp = sorted[0];
253
+ const lastTimestamp = sorted[sorted.length - 1];
254
+ if (firstTimestamp && lastTimestamp) {
255
+ const duration = (lastTimestamp.getTime() - firstTimestamp.getTime()) / 1000;
256
+ totalDuration += duration;
257
+ }
258
+ }
259
+ }
260
+ return {
261
+ totalSessions,
262
+ avgDuration: Math.round(totalDuration / totalSessions),
263
+ avgPagesPerSession: Math.round((totalPageCount / totalSessions) * 100) / 100,
264
+ bounceRate: Math.round((bounceCount / totalSessions) * 100 * 100) / 100,
265
+ };
266
+ }
267
+ /**
268
+ * Get entry pages (first page of each session)
269
+ */
270
+ export async function getEntryPages(options) {
271
+ const db = getClient();
272
+ const where = buildWhere(options);
273
+ const limit = options.limit ?? 10;
274
+ // Get all page views with session info
275
+ const pageViews = await db.pageView.findMany({
276
+ where,
277
+ select: { sessionId: true, pathname: true, timestamp: true },
278
+ orderBy: { timestamp: "asc" },
279
+ });
280
+ // Find first page view per session
281
+ const sessionFirstPages = new Map();
282
+ for (const pv of pageViews) {
283
+ if (!sessionFirstPages.has(pv.sessionId)) {
284
+ sessionFirstPages.set(pv.sessionId, pv.pathname);
285
+ }
286
+ }
287
+ // Count entry pages
288
+ const entryPageCounts = new Map();
289
+ for (const pathname of sessionFirstPages.values()) {
290
+ entryPageCounts.set(pathname, (entryPageCounts.get(pathname) ?? 0) + 1);
291
+ }
292
+ const totalSessions = sessionFirstPages.size;
293
+ // Convert to array and sort
294
+ return Array.from(entryPageCounts.entries())
295
+ .map(([pathname, count]) => ({
296
+ pathname,
297
+ count,
298
+ percentage: Math.round((count / totalSessions) * 100 * 100) / 100,
299
+ }))
300
+ .sort((a, b) => b.count - a.count)
301
+ .slice(0, limit);
302
+ }
303
+ /**
304
+ * Get exit pages (last page of each session)
305
+ */
306
+ export async function getExitPages(options) {
307
+ const db = getClient();
308
+ const where = buildWhere(options);
309
+ const limit = options.limit ?? 10;
310
+ // Get all page views with session info
311
+ const pageViews = await db.pageView.findMany({
312
+ where,
313
+ select: { sessionId: true, pathname: true, timestamp: true },
314
+ orderBy: { timestamp: "desc" }, // Descending to get last pages first
315
+ });
316
+ // Find last page view per session
317
+ const sessionLastPages = new Map();
318
+ for (const pv of pageViews) {
319
+ if (!sessionLastPages.has(pv.sessionId)) {
320
+ sessionLastPages.set(pv.sessionId, pv.pathname);
321
+ }
322
+ }
323
+ // Count exit pages
324
+ const exitPageCounts = new Map();
325
+ for (const pathname of sessionLastPages.values()) {
326
+ exitPageCounts.set(pathname, (exitPageCounts.get(pathname) ?? 0) + 1);
327
+ }
328
+ const totalSessions = sessionLastPages.size;
329
+ // Convert to array and sort
330
+ return Array.from(exitPageCounts.entries())
331
+ .map(([pathname, count]) => ({
332
+ pathname,
333
+ count,
334
+ percentage: Math.round((count / totalSessions) * 100 * 100) / 100,
335
+ }))
336
+ .sort((a, b) => b.count - a.count)
337
+ .slice(0, limit);
338
+ }
339
+ /**
340
+ * Get common page flow paths (sequence of pages in sessions)
341
+ */
342
+ export async function getPageFlows(options) {
343
+ const db = getClient();
344
+ const where = buildWhere(options);
345
+ const limit = options.limit ?? 10;
346
+ const maxPathLength = options.maxPathLength ?? 5;
347
+ // Get all page views with session info
348
+ const pageViews = await db.pageView.findMany({
349
+ where,
350
+ select: { sessionId: true, pathname: true, timestamp: true },
351
+ orderBy: { timestamp: "asc" },
352
+ });
353
+ // Build paths per session
354
+ const sessionPaths = new Map();
355
+ for (const pv of pageViews) {
356
+ const path = sessionPaths.get(pv.sessionId) ?? [];
357
+ // Only add if different from last (avoid duplicates from refreshes)
358
+ if (path.length === 0 || path[path.length - 1] !== pv.pathname) {
359
+ path.push(pv.pathname);
360
+ }
361
+ sessionPaths.set(pv.sessionId, path);
362
+ }
363
+ // Truncate paths and count
364
+ const pathCounts = new Map();
365
+ for (const path of sessionPaths.values()) {
366
+ const truncated = path.slice(0, maxPathLength);
367
+ const key = JSON.stringify(truncated);
368
+ pathCounts.set(key, (pathCounts.get(key) ?? 0) + 1);
369
+ }
370
+ const totalSessions = sessionPaths.size;
371
+ // Convert to array and sort
372
+ return Array.from(pathCounts.entries())
373
+ .map(([key, count]) => ({
374
+ path: JSON.parse(key),
375
+ count,
376
+ percentage: Math.round((count / totalSessions) * 100 * 100) / 100,
377
+ }))
378
+ .sort((a, b) => b.count - a.count)
379
+ .slice(0, limit);
380
+ }
381
+ /**
382
+ * Get individual session data (for debugging/analysis)
383
+ */
384
+ export async function getSessions(options) {
385
+ const db = getClient();
386
+ const where = buildWhere(options);
387
+ const limit = options.limit ?? 50;
388
+ const offset = options.offset ?? 0;
389
+ // Get all page views
390
+ const pageViews = await db.pageView.findMany({
391
+ where,
392
+ select: {
393
+ sessionId: true,
394
+ visitorHash: true,
395
+ pathname: true,
396
+ timestamp: true,
397
+ country: true,
398
+ device: true,
399
+ browser: true,
400
+ },
401
+ orderBy: { timestamp: "asc" },
402
+ });
403
+ // Group by session
404
+ const sessionMap = new Map();
405
+ for (const pv of pageViews) {
406
+ const existing = sessionMap.get(pv.sessionId);
407
+ if (existing) {
408
+ existing.pages.push({ pathname: pv.pathname, timestamp: pv.timestamp });
409
+ }
410
+ else {
411
+ sessionMap.set(pv.sessionId, {
412
+ visitorHash: pv.visitorHash,
413
+ pages: [{ pathname: pv.pathname, timestamp: pv.timestamp }],
414
+ country: pv.country,
415
+ device: pv.device,
416
+ browser: pv.browser,
417
+ });
418
+ }
419
+ }
420
+ // Convert to SessionData array
421
+ const sessions = [];
422
+ for (const [sessionId, data] of sessionMap.entries()) {
423
+ const sortedPages = data.pages.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
424
+ const firstPage = sortedPages[0];
425
+ const lastPage = sortedPages[sortedPages.length - 1];
426
+ // Skip if somehow we have no pages (shouldn't happen)
427
+ if (!firstPage || !lastPage)
428
+ continue;
429
+ const startTime = firstPage.timestamp;
430
+ const endTime = lastPage.timestamp;
431
+ const duration = Math.round((endTime.getTime() - startTime.getTime()) / 1000);
432
+ sessions.push({
433
+ sessionId,
434
+ visitorHash: data.visitorHash,
435
+ startTime,
436
+ endTime,
437
+ duration,
438
+ pageCount: sortedPages.length,
439
+ entryPage: firstPage.pathname,
440
+ exitPage: lastPage.pathname,
441
+ isBounce: sortedPages.length === 1,
442
+ country: data.country,
443
+ device: data.device,
444
+ browser: data.browser,
445
+ });
446
+ }
447
+ // Sort by startTime descending (most recent first) and paginate
448
+ return sessions
449
+ .sort((a, b) => b.startTime.getTime() - a.startTime.getTime())
450
+ .slice(offset, offset + limit);
451
+ }
452
+ // Get or create a site
453
+ export async function getOrCreateSite(domain, name) {
454
+ const db = getClient();
455
+ let site = await db.site.findUnique({ where: { domain } });
456
+ if (!site) {
457
+ site = await db.site.create({
458
+ data: {
459
+ domain,
460
+ name: name ?? domain,
461
+ },
462
+ });
463
+ }
464
+ return site;
465
+ }
466
+ // List all sites
467
+ export async function listSites() {
468
+ const db = getClient();
469
+ return db.site.findMany({ orderBy: { name: "asc" } });
470
+ }
471
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { TrackPageViewOptions, TrackEventOptions } from "./types.js";
2
+ export declare function trackPageView(options: TrackPageViewOptions): Promise<void>;
3
+ export declare function trackEvent(options: TrackEventOptions): Promise<void>;
4
+ //# sourceMappingURL=track.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE1E,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAkEf;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB1E"}
package/dist/track.js ADDED
@@ -0,0 +1,74 @@
1
+ import { getClient } from "./client.js";
2
+ import { parseUserAgent } from "./ua.js";
3
+ import { isBot, getVisitorInfo, extractPathname } from "./utils.js";
4
+ export async function trackPageView(options) {
5
+ const { siteId, url, referrer, ip, userAgent, userId,
6
+ // Geo data passed directly (e.g., from Vercel headers)
7
+ country, countryCode, region, city, } = options;
8
+ // Normalize undefined to null
9
+ const ipNorm = ip ?? null;
10
+ const uaNorm = userAgent ?? null;
11
+ // Get visitor info (hashes for privacy)
12
+ const { visitorHash, sessionId } = await getVisitorInfo(ipNorm, uaNorm);
13
+ // Parse user agent
14
+ const ua = parseUserAgent(uaNorm);
15
+ // Detect bots
16
+ const isBotRequest = isBot(uaNorm);
17
+ // Extract pathname from URL
18
+ const pathname = extractPathname(url);
19
+ // Clean referrer (remove query params for privacy)
20
+ let cleanReferrer = referrer ?? null;
21
+ if (cleanReferrer) {
22
+ try {
23
+ const refUrl = new URL(cleanReferrer);
24
+ // Only keep the domain for external referrers
25
+ cleanReferrer = refUrl.origin + refUrl.pathname;
26
+ }
27
+ catch {
28
+ // Keep as-is if not a valid URL
29
+ }
30
+ }
31
+ const db = getClient();
32
+ await db.pageView.create({
33
+ data: {
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,
50
+ isBot: isBotRequest,
51
+ },
52
+ });
53
+ }
54
+ export async function trackEvent(options) {
55
+ const { siteId, name, properties, url, ip, userAgent, userId } = options;
56
+ // Normalize undefined to null
57
+ const ipNorm = ip ?? null;
58
+ const uaNorm = userAgent ?? null;
59
+ // Get visitor info (hashes for privacy)
60
+ const { visitorHash, sessionId } = await getVisitorInfo(ipNorm, uaNorm);
61
+ const db = getClient();
62
+ await db.event.create({
63
+ data: {
64
+ siteId,
65
+ name,
66
+ properties: properties,
67
+ url,
68
+ visitorHash,
69
+ sessionId,
70
+ userId,
71
+ },
72
+ });
73
+ }
74
+ //# sourceMappingURL=track.js.map
@@ -0,0 +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,QAAQ,CAAC,MAAM,CAAC;QACvB,IAAI,EAAE;YACJ,MAAM;YACN,GAAG;YACH,QAAQ;YACR,QAAQ,EAAE,aAAa;YACvB,WAAW;YACX,SAAS;YACT,OAAO,EAAE,OAAO,IAAI,IAAI;YACxB,WAAW,EAAE,WAAW,IAAI,IAAI;YAChC,MAAM,EAAE,MAAM,IAAI,IAAI;YACtB,IAAI,EAAE,IAAI,IAAI,IAAI;YAClB,OAAO,EAAE,EAAE,CAAC,OAAO;YACnB,UAAU,EAAE,EAAE,CAAC,UAAU;YACzB,EAAE,EAAE,EAAE,CAAC,EAAE;YACT,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,MAAM;YACN,KAAK,EAAE,YAAY;SACpB;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAEzE,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,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAEvB,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE;YACJ,MAAM;YACN,IAAI;YACJ,UAAU,EAAE,UAAgC;YAC5C,GAAG;YACH,WAAW;YACX,SAAS;YACT,MAAM;SACP;KACF,CAAC,CAAC;AACL,CAAC"}