locallytics 0.1.9 → 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/dist/adapters/drizzle.d.mts +25 -0
- package/dist/adapters/drizzle.d.ts +25 -0
- package/dist/adapters/drizzle.js +38 -0
- package/dist/adapters/drizzle.mjs +7 -0
- package/dist/adapters/prisma.d.mts +25 -0
- package/dist/adapters/prisma.d.ts +25 -0
- package/dist/adapters/prisma.js +38 -0
- package/dist/adapters/prisma.mjs +7 -0
- package/dist/adapters.d.mts +7 -0
- package/dist/adapters.d.ts +7 -0
- package/dist/adapters.js +39 -0
- package/dist/adapters.mjs +8 -0
- package/dist/browser.d.mts +41 -0
- package/dist/browser.d.ts +41 -0
- package/dist/browser.js +79 -0
- package/dist/browser.mjs +10 -0
- package/dist/index.d.mts +59 -0
- package/dist/index.d.ts +59 -6
- package/dist/index.js +367 -7
- package/dist/index.mjs +336 -0
- package/dist/react.d.mts +48 -0
- package/dist/react.d.ts +48 -0
- package/dist/react.js +132 -0
- package/dist/react.mjs +61 -0
- package/dist/shared/chunk-8tbv1rg5.js +45 -0
- package/package.json +60 -48
- package/README.md +0 -73
- package/dist/client/LocallyticsGrabber.d.ts +0 -30
- package/dist/client/LocallyticsGrabber.d.ts.map +0 -1
- package/dist/client/LocallyticsGrabber.js +0 -71
- package/dist/client/LocallyticsGrabber.js.map +0 -1
- package/dist/client/batcher.d.ts +0 -48
- package/dist/client/batcher.d.ts.map +0 -1
- package/dist/client/batcher.js +0 -134
- package/dist/client/batcher.js.map +0 -1
- package/dist/client/tracker.d.ts +0 -18
- package/dist/client/tracker.d.ts.map +0 -1
- package/dist/client/tracker.js +0 -101
- package/dist/client/tracker.js.map +0 -1
- package/dist/db/factory.d.ts +0 -11
- package/dist/db/factory.d.ts.map +0 -1
- package/dist/db/factory.js +0 -46
- package/dist/db/factory.js.map +0 -1
- package/dist/db/mysql.d.ts +0 -17
- package/dist/db/mysql.d.ts.map +0 -1
- package/dist/db/mysql.js +0 -144
- package/dist/db/mysql.js.map +0 -1
- package/dist/db/postgres.d.ts +0 -16
- package/dist/db/postgres.d.ts.map +0 -1
- package/dist/db/postgres.js +0 -142
- package/dist/db/postgres.js.map +0 -1
- package/dist/db/sqlite.d.ts +0 -17
- package/dist/db/sqlite.d.ts.map +0 -1
- package/dist/db/sqlite.js +0 -130
- package/dist/db/sqlite.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/server/handlers.d.ts +0 -10
- package/dist/server/handlers.d.ts.map +0 -1
- package/dist/server/handlers.js +0 -96
- package/dist/server/handlers.js.map +0 -1
- package/dist/server/index.d.ts +0 -42
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -96
- package/dist/server/index.js.map +0 -1
- package/dist/server/queries.d.ts +0 -10
- package/dist/server/queries.d.ts.map +0 -1
- package/dist/server/queries.js +0 -24
- package/dist/server/queries.js.map +0 -1
- package/dist/server/validator.d.ts +0 -32
- package/dist/server/validator.d.ts.map +0 -1
- package/dist/server/validator.js +0 -129
- package/dist/server/validator.js.map +0 -1
- package/dist/types/index.d.ts +0 -135
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -24
- package/dist/types/index.js.map +0 -1
- package/dist/utils/hash.d.ts +0 -16
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/hash.js +0 -36
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/rate-limit.d.ts +0 -32
- package/dist/utils/rate-limit.d.ts.map +0 -1
- package/dist/utils/rate-limit.js +0 -73
- package/dist/utils/rate-limit.js.map +0 -1
- package/src/db/schema-mysql.sql +0 -17
- package/src/db/schema-sqlite.sql +0 -29
- package/src/db/schema.sql +0 -35
package/dist/client/batcher.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { PageviewEvent } from "../types/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* Batches events and sends them to the server
|
|
4
|
-
* Uses sendBeacon for reliable delivery on page unload
|
|
5
|
-
*/
|
|
6
|
-
export declare class EventBatcher {
|
|
7
|
-
private readonly endpoint;
|
|
8
|
-
private readonly maxSize;
|
|
9
|
-
private readonly maxWaitMs;
|
|
10
|
-
private events;
|
|
11
|
-
private flushTimeout;
|
|
12
|
-
private isFlushing;
|
|
13
|
-
constructor(endpoint: string, maxSize?: number, maxWaitMs?: number);
|
|
14
|
-
/**
|
|
15
|
-
* Add an event to the batch queue
|
|
16
|
-
*/
|
|
17
|
-
add(event: PageviewEvent): void;
|
|
18
|
-
/**
|
|
19
|
-
* Flush events to the server using fetch
|
|
20
|
-
*/
|
|
21
|
-
flush(): Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* Flush events synchronously using sendBeacon
|
|
24
|
-
* Used for beforeunload when async requests may not complete
|
|
25
|
-
*/
|
|
26
|
-
private flushSync;
|
|
27
|
-
/**
|
|
28
|
-
* Start the flush timer
|
|
29
|
-
*/
|
|
30
|
-
private startTimer;
|
|
31
|
-
/**
|
|
32
|
-
* Clear the flush timer
|
|
33
|
-
*/
|
|
34
|
-
private clearTimer;
|
|
35
|
-
/**
|
|
36
|
-
* Handle page unload - use sendBeacon for reliable delivery
|
|
37
|
-
*/
|
|
38
|
-
private handleUnload;
|
|
39
|
-
/**
|
|
40
|
-
* Handle visibility change - flush when page becomes hidden
|
|
41
|
-
*/
|
|
42
|
-
private handleVisibilityChange;
|
|
43
|
-
/**
|
|
44
|
-
* Clean up event listeners and timers
|
|
45
|
-
*/
|
|
46
|
-
destroy(): void;
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=batcher.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batcher.d.ts","sourceRoot":"","sources":["../../src/client/batcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKvD;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,UAAU,CAAkB;gBAGlC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAyB,EAClC,SAAS,GAAE,MAA4B;IAYzC;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAY/B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC5B;;;OAGG;IACH,OAAO,CAAC,SAAS;IAmBjB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAOlB;;OAEG;IACH,OAAO,CAAC,YAAY,CAElB;IAEF;;OAEG;IACH,OAAO,CAAC,sBAAsB,CAI5B;IAEF;;OAEG;IACH,OAAO,IAAI,IAAI;CAWhB"}
|
package/dist/client/batcher.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
const DEFAULT_MAX_SIZE = 10;
|
|
2
|
-
const DEFAULT_MAX_WAIT_MS = 30000;
|
|
3
|
-
/**
|
|
4
|
-
* Batches events and sends them to the server
|
|
5
|
-
* Uses sendBeacon for reliable delivery on page unload
|
|
6
|
-
*/
|
|
7
|
-
export class EventBatcher {
|
|
8
|
-
constructor(endpoint, maxSize = DEFAULT_MAX_SIZE, maxWaitMs = DEFAULT_MAX_WAIT_MS) {
|
|
9
|
-
this.events = [];
|
|
10
|
-
this.flushTimeout = null;
|
|
11
|
-
this.isFlushing = false;
|
|
12
|
-
/**
|
|
13
|
-
* Handle page unload - use sendBeacon for reliable delivery
|
|
14
|
-
*/
|
|
15
|
-
this.handleUnload = () => {
|
|
16
|
-
this.flushSync();
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* Handle visibility change - flush when page becomes hidden
|
|
20
|
-
*/
|
|
21
|
-
this.handleVisibilityChange = () => {
|
|
22
|
-
if (document.visibilityState === "hidden") {
|
|
23
|
-
this.flushSync();
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
this.endpoint = endpoint;
|
|
27
|
-
this.maxSize = maxSize;
|
|
28
|
-
this.maxWaitMs = maxWaitMs;
|
|
29
|
-
if (typeof window !== "undefined") {
|
|
30
|
-
window.addEventListener("beforeunload", this.handleUnload);
|
|
31
|
-
window.addEventListener("visibilitychange", this.handleVisibilityChange);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Add an event to the batch queue
|
|
36
|
-
*/
|
|
37
|
-
add(event) {
|
|
38
|
-
this.events.push(event);
|
|
39
|
-
if (this.events.length === 1) {
|
|
40
|
-
this.startTimer();
|
|
41
|
-
}
|
|
42
|
-
if (this.events.length >= this.maxSize) {
|
|
43
|
-
void this.flush();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Flush events to the server using fetch
|
|
48
|
-
*/
|
|
49
|
-
async flush() {
|
|
50
|
-
if (this.events.length === 0 || this.isFlushing) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
this.isFlushing = true;
|
|
54
|
-
this.clearTimer();
|
|
55
|
-
const eventsToSend = [...this.events];
|
|
56
|
-
this.events = [];
|
|
57
|
-
try {
|
|
58
|
-
const response = await fetch(this.endpoint, {
|
|
59
|
-
method: "POST",
|
|
60
|
-
headers: {
|
|
61
|
-
"Content-Type": "application/json",
|
|
62
|
-
},
|
|
63
|
-
body: JSON.stringify(eventsToSend),
|
|
64
|
-
});
|
|
65
|
-
if (!response.ok) {
|
|
66
|
-
console.error("[Locallytics] Failed to send events:", response.status);
|
|
67
|
-
this.events = [...eventsToSend, ...this.events];
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
console.error("[Locallytics] Error sending events:", error);
|
|
72
|
-
this.events = [...eventsToSend, ...this.events];
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
this.isFlushing = false;
|
|
76
|
-
// Restart timer if there are pending events
|
|
77
|
-
if (this.events.length > 0) {
|
|
78
|
-
this.startTimer();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Flush events synchronously using sendBeacon
|
|
84
|
-
* Used for beforeunload when async requests may not complete
|
|
85
|
-
*/
|
|
86
|
-
flushSync() {
|
|
87
|
-
if (this.events.length === 0) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const eventsToSend = [...this.events];
|
|
91
|
-
this.events = [];
|
|
92
|
-
this.clearTimer();
|
|
93
|
-
try {
|
|
94
|
-
const blob = new Blob([JSON.stringify(eventsToSend)], {
|
|
95
|
-
type: "application/json",
|
|
96
|
-
});
|
|
97
|
-
navigator.sendBeacon(this.endpoint, blob);
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
console.error("[Locallytics] sendBeacon failed:", error);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Start the flush timer
|
|
105
|
-
*/
|
|
106
|
-
startTimer() {
|
|
107
|
-
if (this.flushTimeout) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
this.flushTimeout = setTimeout(() => {
|
|
111
|
-
void this.flush();
|
|
112
|
-
}, this.maxWaitMs);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Clear the flush timer
|
|
116
|
-
*/
|
|
117
|
-
clearTimer() {
|
|
118
|
-
if (this.flushTimeout) {
|
|
119
|
-
clearTimeout(this.flushTimeout);
|
|
120
|
-
this.flushTimeout = null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Clean up event listeners and timers
|
|
125
|
-
*/
|
|
126
|
-
destroy() {
|
|
127
|
-
this.clearTimer();
|
|
128
|
-
if (typeof window !== "undefined") {
|
|
129
|
-
window.removeEventListener("beforeunload", this.handleUnload);
|
|
130
|
-
window.removeEventListener("visibilitychange", this.handleVisibilityChange);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
//# sourceMappingURL=batcher.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batcher.js","sourceRoot":"","sources":["../../src/client/batcher.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC;;;GAGG;AACH,MAAM,OAAO,YAAY;IAQvB,YACE,QAAgB,EAChB,UAAkB,gBAAgB,EAClC,YAAoB,mBAAmB;QAPjC,WAAM,GAAoB,EAAE,CAAC;QAC7B,iBAAY,GAAyC,IAAI,CAAC;QAC1D,eAAU,GAAY,KAAK,CAAC;QAsHpC;;WAEG;QACK,iBAAY,GAAG,GAAS,EAAE;YAChC,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC,CAAC;QAEF;;WAEG;QACK,2BAAsB,GAAG,GAAS,EAAE;YAC1C,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;gBAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,CAAC;QACH,CAAC,CAAC;QA7HA,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC3D,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,KAAoB;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAChD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,UAAU,EAAE,CAAC;QAElB,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAC1C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;aACnC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACvE,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC5D,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YAExB,4CAA4C;YAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,SAAS;QACf,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,UAAU,EAAE,CAAC;QAElB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE;gBACpD,IAAI,EAAE,kBAAkB;aACzB,CAAC,CAAC;YACH,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,UAAU;QAChB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;YAClC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACK,UAAU;QAChB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAChC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC;IAkBD;;OAEG;IACH,OAAO;QACL,IAAI,CAAC,UAAU,EAAE,CAAC;QAElB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9D,MAAM,CAAC,mBAAmB,CACxB,kBAAkB,EAClB,IAAI,CAAC,sBAAsB,CAC5B,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
package/dist/client/tracker.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Client-side tracker for pageviews
|
|
3
|
-
*/
|
|
4
|
-
export declare class Tracker {
|
|
5
|
-
private readonly batcher;
|
|
6
|
-
private readonly sessionId;
|
|
7
|
-
private dntEnabled;
|
|
8
|
-
constructor(endpoint?: string, maxWaitMs?: number);
|
|
9
|
-
/**
|
|
10
|
-
* Track the current pageview
|
|
11
|
-
*/
|
|
12
|
-
trackPageview(): void;
|
|
13
|
-
/**
|
|
14
|
-
* Clean up the tracker
|
|
15
|
-
*/
|
|
16
|
-
destroy(): void;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=tracker.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/client/tracker.ts"],"names":[],"mappings":"AAyEA;;GAEG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,UAAU,CAAU;gBAEhB,QAAQ,GAAE,MAAyB,EAAE,SAAS,CAAC,EAAE,MAAM;IAMnE;;OAEG;IACH,aAAa,IAAI,IAAI;IAsBrB;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB"}
|
package/dist/client/tracker.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { EventBatcher } from "./batcher.js";
|
|
2
|
-
const DEFAULT_ENDPOINT = "/api/analytics";
|
|
3
|
-
const STORAGE_KEY = "locallytics_sid";
|
|
4
|
-
/**
|
|
5
|
-
* Generate a unique session ID
|
|
6
|
-
*/
|
|
7
|
-
function generateSessionId() {
|
|
8
|
-
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
9
|
-
return crypto.randomUUID();
|
|
10
|
-
}
|
|
11
|
-
// Fallback for older browsers
|
|
12
|
-
return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Get or create a persistent session ID
|
|
16
|
-
*/
|
|
17
|
-
function getPersistentSessionId(dntEnabled) {
|
|
18
|
-
// DNT users get ephemeral IDs - no storage access
|
|
19
|
-
if (dntEnabled) {
|
|
20
|
-
return generateSessionId();
|
|
21
|
-
}
|
|
22
|
-
if (typeof window === "undefined") {
|
|
23
|
-
return generateSessionId();
|
|
24
|
-
}
|
|
25
|
-
try {
|
|
26
|
-
const stored = localStorage.getItem(STORAGE_KEY);
|
|
27
|
-
if (stored) {
|
|
28
|
-
return stored;
|
|
29
|
-
}
|
|
30
|
-
const newId = generateSessionId();
|
|
31
|
-
localStorage.setItem(STORAGE_KEY, newId);
|
|
32
|
-
return newId;
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
// Storage access denied (private mode, etc)
|
|
36
|
-
return generateSessionId();
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Check if Do Not Track is enabled in the browser
|
|
41
|
-
*/
|
|
42
|
-
function isDNTEnabled() {
|
|
43
|
-
if (typeof navigator === "undefined") {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
const dnt = navigator.doNotTrack;
|
|
47
|
-
if (dnt === "1" || dnt === "yes") {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Sanitize URL for tracking (extract pathname + search)
|
|
54
|
-
*/
|
|
55
|
-
function sanitizeUrl(url) {
|
|
56
|
-
try {
|
|
57
|
-
const parsed = new URL(url);
|
|
58
|
-
return parsed.pathname + parsed.search;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
return "/";
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Client-side tracker for pageviews
|
|
66
|
-
*/
|
|
67
|
-
export class Tracker {
|
|
68
|
-
constructor(endpoint = DEFAULT_ENDPOINT, maxWaitMs) {
|
|
69
|
-
this.batcher = new EventBatcher(endpoint, undefined, maxWaitMs);
|
|
70
|
-
this.dntEnabled = isDNTEnabled();
|
|
71
|
-
this.sessionId = getPersistentSessionId(this.dntEnabled);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Track the current pageview
|
|
75
|
-
*/
|
|
76
|
-
trackPageview() {
|
|
77
|
-
if (this.dntEnabled) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
if (typeof window === "undefined") {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const event = {
|
|
84
|
-
sessionId: this.sessionId,
|
|
85
|
-
pageUrl: sanitizeUrl(window.location.href),
|
|
86
|
-
referrer: document.referrer ? sanitizeUrl(document.referrer) : null,
|
|
87
|
-
userAgent: navigator.userAgent.slice(0, 512),
|
|
88
|
-
screenWidth: window.screen.width,
|
|
89
|
-
screenHeight: window.screen.height,
|
|
90
|
-
timestamp: new Date().toISOString(),
|
|
91
|
-
};
|
|
92
|
-
this.batcher.add(event);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Clean up the tracker
|
|
96
|
-
*/
|
|
97
|
-
destroy() {
|
|
98
|
-
this.batcher.destroy();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
//# sourceMappingURL=tracker.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/client/tracker.ts"],"names":[],"mappings":"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"}
|
package/dist/db/factory.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { AnalyticsDB, LocallyticsConfig } from "../types/index.js";
|
|
2
|
-
export type DatabaseType = "postgres" | "mysql" | "sqlite";
|
|
3
|
-
/**
|
|
4
|
-
* Detect database type from connection string
|
|
5
|
-
*/
|
|
6
|
-
export declare function detectDatabaseType(connectionString: string): DatabaseType;
|
|
7
|
-
/**
|
|
8
|
-
* Create the appropriate database instance based on config
|
|
9
|
-
*/
|
|
10
|
-
export declare function createDatabase(config: LocallyticsConfig): Promise<AnalyticsDB>;
|
|
11
|
-
//# sourceMappingURL=factory.d.ts.map
|
package/dist/db/factory.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/db/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAKxE,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,GAAG,YAAY,CAyBzE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAgBtB"}
|
package/dist/db/factory.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { MySQLDB } from "./mysql.js";
|
|
2
|
-
import { PostgresDB } from "./postgres.js";
|
|
3
|
-
import { SQLiteDB } from "./sqlite.js";
|
|
4
|
-
/**
|
|
5
|
-
* Detect database type from connection string
|
|
6
|
-
*/
|
|
7
|
-
export function detectDatabaseType(connectionString) {
|
|
8
|
-
const lower = connectionString.toLowerCase();
|
|
9
|
-
if (lower.startsWith("postgres://") || lower.startsWith("postgresql://")) {
|
|
10
|
-
return "postgres";
|
|
11
|
-
}
|
|
12
|
-
if (lower.startsWith("mysql://")) {
|
|
13
|
-
return "mysql";
|
|
14
|
-
}
|
|
15
|
-
// If it's a file path or sqlite:// prefix, use SQLite
|
|
16
|
-
if (lower.startsWith("sqlite://") ||
|
|
17
|
-
lower.endsWith(".db") ||
|
|
18
|
-
lower.endsWith(".sqlite") ||
|
|
19
|
-
lower.endsWith(".sqlite3") ||
|
|
20
|
-
lower.includes("/") ||
|
|
21
|
-
lower === ":memory:") {
|
|
22
|
-
return "sqlite";
|
|
23
|
-
}
|
|
24
|
-
// Default to postgres for backwards compatibility
|
|
25
|
-
return "postgres";
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Create the appropriate database instance based on config
|
|
29
|
-
*/
|
|
30
|
-
export async function createDatabase(config) {
|
|
31
|
-
const dbType = config.type ?? detectDatabaseType(config.database);
|
|
32
|
-
switch (dbType) {
|
|
33
|
-
case "sqlite": {
|
|
34
|
-
// Strip sqlite:// or file: prefix if present
|
|
35
|
-
const filePath = config.database
|
|
36
|
-
.replace(/^sqlite:\/\//, "")
|
|
37
|
-
.replace(/^file:/, "");
|
|
38
|
-
return SQLiteDB.create(filePath);
|
|
39
|
-
}
|
|
40
|
-
case "mysql":
|
|
41
|
-
return MySQLDB.create(config.database);
|
|
42
|
-
default:
|
|
43
|
-
return new PostgresDB(config.database);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
//# sourceMappingURL=factory.js.map
|
package/dist/db/factory.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/db/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,gBAAwB;IACzD,MAAM,KAAK,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;IAE7C,IAAI,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACzE,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,sDAAsD;IACtD,IACE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;QAC7B,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QACrB,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC1B,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QACnB,KAAK,KAAK,UAAU,EACpB,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,kDAAkD;IAClD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAyB;IAEzB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,IAAI,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAElE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,6CAA6C;YAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ;iBAC7B,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;iBAC3B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACzB,OAAO,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;QACD,KAAK,OAAO;YACV,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC;YACE,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
|
package/dist/db/mysql.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { AnalyticsDB, DailyStats, DateRange, PageStats, PageviewEvent } from "../types/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* MySQL implementation of the analytics database
|
|
4
|
-
*/
|
|
5
|
-
export declare class MySQLDB implements AnalyticsDB {
|
|
6
|
-
private pool;
|
|
7
|
-
private constructor();
|
|
8
|
-
static create(connectionString: string): Promise<MySQLDB>;
|
|
9
|
-
insertPageview(event: PageviewEvent, ipHash: string | null): Promise<void>;
|
|
10
|
-
getPageviews(dateRange: DateRange): Promise<number>;
|
|
11
|
-
getUniqueVisitors(dateRange: DateRange): Promise<number>;
|
|
12
|
-
getTopPages(dateRange: DateRange, limit: number): Promise<PageStats[]>;
|
|
13
|
-
getTopReferrers(dateRange: DateRange, limit: number): Promise<PageStats[]>;
|
|
14
|
-
getDailyStats(dateRange: DateRange): Promise<DailyStats[]>;
|
|
15
|
-
close(): Promise<void>;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=mysql.d.ts.map
|
package/dist/db/mysql.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.d.ts","sourceRoot":"","sources":["../../src/db/mysql.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACd,MAAM,mBAAmB,CAAC;AAgD3B;;GAEG;AACH,qBAAa,OAAQ,YAAW,WAAW;IACzC,OAAO,CAAC,IAAI,CAAO;IAEnB,OAAO;WAIM,MAAM,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzD,cAAc,CAClB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC;IAoBV,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBnD,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBxD,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAsBtE,eAAe,CACnB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,SAAS,EAAE,CAAC;IAsBjB,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAgC1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
package/dist/db/mysql.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get SQL WHERE clause parts for a date range (MySQL version)
|
|
3
|
-
*/
|
|
4
|
-
function getDateRangeFilter(dateRange) {
|
|
5
|
-
const now = new Date();
|
|
6
|
-
if (dateRange === "last24h") {
|
|
7
|
-
const start = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
8
|
-
return {
|
|
9
|
-
whereClause: "timestamp >= ?",
|
|
10
|
-
params: [start.toISOString()],
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
if (dateRange === "last7d") {
|
|
14
|
-
const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
15
|
-
return {
|
|
16
|
-
whereClause: "timestamp >= ?",
|
|
17
|
-
params: [start.toISOString()],
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
if (dateRange === "last30d") {
|
|
21
|
-
const start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
22
|
-
return {
|
|
23
|
-
whereClause: "timestamp >= ?",
|
|
24
|
-
params: [start.toISOString()],
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
// Custom date range
|
|
28
|
-
return {
|
|
29
|
-
whereClause: "timestamp >= ? AND timestamp <= ?",
|
|
30
|
-
params: [dateRange.start.toISOString(), dateRange.end.toISOString()],
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* MySQL implementation of the analytics database
|
|
35
|
-
*/
|
|
36
|
-
export class MySQLDB {
|
|
37
|
-
constructor(pool) {
|
|
38
|
-
this.pool = pool;
|
|
39
|
-
}
|
|
40
|
-
static async create(connectionString) {
|
|
41
|
-
const mysql = await import("mysql2/promise");
|
|
42
|
-
const pool = mysql.createPool({
|
|
43
|
-
uri: connectionString,
|
|
44
|
-
waitForConnections: true,
|
|
45
|
-
connectionLimit: 10,
|
|
46
|
-
});
|
|
47
|
-
return new MySQLDB(pool);
|
|
48
|
-
}
|
|
49
|
-
async insertPageview(event, ipHash) {
|
|
50
|
-
const query = `
|
|
51
|
-
INSERT INTO locallytics_pageviews (
|
|
52
|
-
session_id, page_url, referrer, user_agent,
|
|
53
|
-
screen_width, screen_height, ip_hash, timestamp
|
|
54
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
55
|
-
`;
|
|
56
|
-
await this.pool.execute(query, [
|
|
57
|
-
event.sessionId,
|
|
58
|
-
event.pageUrl,
|
|
59
|
-
event.referrer,
|
|
60
|
-
event.userAgent,
|
|
61
|
-
event.screenWidth,
|
|
62
|
-
event.screenHeight,
|
|
63
|
-
ipHash,
|
|
64
|
-
event.timestamp,
|
|
65
|
-
]);
|
|
66
|
-
}
|
|
67
|
-
async getPageviews(dateRange) {
|
|
68
|
-
const { whereClause, params } = getDateRangeFilter(dateRange);
|
|
69
|
-
const query = `
|
|
70
|
-
SELECT COUNT(*) as count
|
|
71
|
-
FROM locallytics_pageviews
|
|
72
|
-
WHERE ${whereClause}
|
|
73
|
-
`;
|
|
74
|
-
const [rows] = await this.pool.execute(query, params);
|
|
75
|
-
return rows[0]?.count ?? 0;
|
|
76
|
-
}
|
|
77
|
-
async getUniqueVisitors(dateRange) {
|
|
78
|
-
const { whereClause, params } = getDateRangeFilter(dateRange);
|
|
79
|
-
const query = `
|
|
80
|
-
SELECT COUNT(DISTINCT session_id) as count
|
|
81
|
-
FROM locallytics_pageviews
|
|
82
|
-
WHERE ${whereClause}
|
|
83
|
-
`;
|
|
84
|
-
const [rows] = await this.pool.execute(query, params);
|
|
85
|
-
return rows[0]?.count ?? 0;
|
|
86
|
-
}
|
|
87
|
-
async getTopPages(dateRange, limit) {
|
|
88
|
-
const { whereClause, params } = getDateRangeFilter(dateRange);
|
|
89
|
-
const query = `
|
|
90
|
-
SELECT page_url as pageUrl, COUNT(*) as count
|
|
91
|
-
FROM locallytics_pageviews
|
|
92
|
-
WHERE ${whereClause}
|
|
93
|
-
GROUP BY page_url
|
|
94
|
-
ORDER BY count DESC
|
|
95
|
-
LIMIT ?
|
|
96
|
-
`;
|
|
97
|
-
const [rows] = await this.pool.execute(query, [...params, limit]);
|
|
98
|
-
return rows.map((row) => ({
|
|
99
|
-
pageUrl: row.pageUrl,
|
|
100
|
-
count: Number(row.count),
|
|
101
|
-
}));
|
|
102
|
-
}
|
|
103
|
-
async getTopReferrers(dateRange, limit) {
|
|
104
|
-
const { whereClause, params } = getDateRangeFilter(dateRange);
|
|
105
|
-
const query = `
|
|
106
|
-
SELECT referrer as pageUrl, COUNT(*) as count
|
|
107
|
-
FROM locallytics_pageviews
|
|
108
|
-
WHERE ${whereClause} AND referrer IS NOT NULL
|
|
109
|
-
GROUP BY referrer
|
|
110
|
-
ORDER BY count DESC
|
|
111
|
-
LIMIT ?
|
|
112
|
-
`;
|
|
113
|
-
const [rows] = await this.pool.execute(query, [...params, limit]);
|
|
114
|
-
return rows.map((row) => ({
|
|
115
|
-
pageUrl: row.pageUrl,
|
|
116
|
-
count: Number(row.count),
|
|
117
|
-
}));
|
|
118
|
-
}
|
|
119
|
-
async getDailyStats(dateRange) {
|
|
120
|
-
const { whereClause, params } = getDateRangeFilter(dateRange);
|
|
121
|
-
const query = `
|
|
122
|
-
SELECT
|
|
123
|
-
DATE(timestamp) as date,
|
|
124
|
-
COUNT(*) as pageviews,
|
|
125
|
-
COUNT(DISTINCT session_id) as uniqueVisitors
|
|
126
|
-
FROM locallytics_pageviews
|
|
127
|
-
WHERE ${whereClause}
|
|
128
|
-
GROUP BY DATE(timestamp)
|
|
129
|
-
ORDER BY date DESC
|
|
130
|
-
`;
|
|
131
|
-
const [rows] = await this.pool.execute(query, params);
|
|
132
|
-
return rows.map((row) => ({
|
|
133
|
-
date: row.date instanceof Date
|
|
134
|
-
? (row.date.toISOString().split("T")[0] ?? "")
|
|
135
|
-
: String(row.date),
|
|
136
|
-
pageviews: Number(row.pageviews),
|
|
137
|
-
uniqueVisitors: Number(row.uniqueVisitors),
|
|
138
|
-
}));
|
|
139
|
-
}
|
|
140
|
-
async close() {
|
|
141
|
-
await this.pool.end();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
//# sourceMappingURL=mysql.js.map
|
package/dist/db/mysql.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.js","sourceRoot":"","sources":["../../src/db/mysql.ts"],"names":[],"mappings":"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"}
|
package/dist/db/postgres.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { AnalyticsDB, DailyStats, DateRange, PageStats, PageviewEvent } from "../types/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* PostgreSQL implementation of the analytics database
|
|
4
|
-
*/
|
|
5
|
-
export declare class PostgresDB implements AnalyticsDB {
|
|
6
|
-
private readonly pool;
|
|
7
|
-
constructor(connectionString: string);
|
|
8
|
-
insertPageview(event: PageviewEvent, ipHash: string | null): Promise<void>;
|
|
9
|
-
getPageviews(dateRange: DateRange): Promise<number>;
|
|
10
|
-
getUniqueVisitors(dateRange: DateRange): Promise<number>;
|
|
11
|
-
getTopPages(dateRange: DateRange, limit: number): Promise<PageStats[]>;
|
|
12
|
-
getTopReferrers(dateRange: DateRange, limit: number): Promise<PageStats[]>;
|
|
13
|
-
getDailyStats(dateRange: DateRange): Promise<DailyStats[]>;
|
|
14
|
-
close(): Promise<void>;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/db/postgres.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACd,MAAM,mBAAmB,CAAC;AA8C3B;;GAEG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC5C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAO;gBAEhB,gBAAgB,EAAE,MAAM;IAS9B,cAAc,CAClB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC;IAoBV,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAanD,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IAaxD,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAuBtE,eAAe,CACnB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,SAAS,EAAE,CAAC;IAuBjB,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA2B1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|