locallytics 0.1.8 → 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.
Files changed (88) hide show
  1. package/dist/adapters/drizzle.d.mts +25 -0
  2. package/dist/adapters/drizzle.d.ts +25 -0
  3. package/dist/adapters/drizzle.js +38 -0
  4. package/dist/adapters/drizzle.mjs +7 -0
  5. package/dist/adapters/prisma.d.mts +25 -0
  6. package/dist/adapters/prisma.d.ts +25 -0
  7. package/dist/adapters/prisma.js +38 -0
  8. package/dist/adapters/prisma.mjs +7 -0
  9. package/dist/adapters.d.mts +7 -0
  10. package/dist/adapters.d.ts +7 -0
  11. package/dist/adapters.js +39 -0
  12. package/dist/adapters.mjs +8 -0
  13. package/dist/browser.d.mts +41 -0
  14. package/dist/browser.d.ts +41 -0
  15. package/dist/browser.js +79 -0
  16. package/dist/browser.mjs +10 -0
  17. package/dist/index.d.mts +59 -0
  18. package/dist/index.d.ts +59 -7
  19. package/dist/index.js +367 -7
  20. package/dist/index.mjs +336 -0
  21. package/dist/react.d.mts +48 -0
  22. package/dist/react.d.ts +48 -0
  23. package/dist/react.js +132 -0
  24. package/dist/react.mjs +61 -0
  25. package/dist/shared/chunk-8tbv1rg5.js +45 -0
  26. package/package.json +60 -48
  27. package/README.md +0 -73
  28. package/dist/client/LocallyticsGrabber.d.ts +0 -30
  29. package/dist/client/LocallyticsGrabber.d.ts.map +0 -1
  30. package/dist/client/LocallyticsGrabber.js +0 -71
  31. package/dist/client/LocallyticsGrabber.js.map +0 -1
  32. package/dist/client/batcher.d.ts +0 -48
  33. package/dist/client/batcher.d.ts.map +0 -1
  34. package/dist/client/batcher.js +0 -139
  35. package/dist/client/batcher.js.map +0 -1
  36. package/dist/client/tracker.d.ts +0 -18
  37. package/dist/client/tracker.d.ts.map +0 -1
  38. package/dist/client/tracker.js +0 -108
  39. package/dist/client/tracker.js.map +0 -1
  40. package/dist/db/factory.d.ts +0 -11
  41. package/dist/db/factory.d.ts.map +0 -1
  42. package/dist/db/factory.js +0 -47
  43. package/dist/db/factory.js.map +0 -1
  44. package/dist/db/mysql.d.ts +0 -17
  45. package/dist/db/mysql.d.ts.map +0 -1
  46. package/dist/db/mysql.js +0 -144
  47. package/dist/db/mysql.js.map +0 -1
  48. package/dist/db/postgres.d.ts +0 -16
  49. package/dist/db/postgres.d.ts.map +0 -1
  50. package/dist/db/postgres.js +0 -143
  51. package/dist/db/postgres.js.map +0 -1
  52. package/dist/db/sqlite.d.ts +0 -17
  53. package/dist/db/sqlite.d.ts.map +0 -1
  54. package/dist/db/sqlite.js +0 -130
  55. package/dist/db/sqlite.js.map +0 -1
  56. package/dist/index.d.ts.map +0 -1
  57. package/dist/index.js.map +0 -1
  58. package/dist/server/handlers.d.ts +0 -10
  59. package/dist/server/handlers.d.ts.map +0 -1
  60. package/dist/server/handlers.js +0 -105
  61. package/dist/server/handlers.js.map +0 -1
  62. package/dist/server/index.d.ts +0 -42
  63. package/dist/server/index.d.ts.map +0 -1
  64. package/dist/server/index.js +0 -100
  65. package/dist/server/index.js.map +0 -1
  66. package/dist/server/queries.d.ts +0 -10
  67. package/dist/server/queries.d.ts.map +0 -1
  68. package/dist/server/queries.js +0 -24
  69. package/dist/server/queries.js.map +0 -1
  70. package/dist/server/validator.d.ts +0 -32
  71. package/dist/server/validator.d.ts.map +0 -1
  72. package/dist/server/validator.js +0 -144
  73. package/dist/server/validator.js.map +0 -1
  74. package/dist/types/index.d.ts +0 -135
  75. package/dist/types/index.d.ts.map +0 -1
  76. package/dist/types/index.js +0 -24
  77. package/dist/types/index.js.map +0 -1
  78. package/dist/utils/hash.d.ts +0 -16
  79. package/dist/utils/hash.d.ts.map +0 -1
  80. package/dist/utils/hash.js +0 -36
  81. package/dist/utils/hash.js.map +0 -1
  82. package/dist/utils/rate-limit.d.ts +0 -32
  83. package/dist/utils/rate-limit.d.ts.map +0 -1
  84. package/dist/utils/rate-limit.js +0 -73
  85. package/dist/utils/rate-limit.js.map +0 -1
  86. package/src/db/schema-mysql.sql +0 -17
  87. package/src/db/schema-sqlite.sql +0 -29
  88. package/src/db/schema.sql +0 -35
@@ -1,143 +0,0 @@
1
- import { Pool } from "pg";
2
- /**
3
- * Get SQL WHERE clause parts for a date range
4
- */
5
- function getDateRangeFilter(dateRange) {
6
- const now = new Date();
7
- if (dateRange === "last24h") {
8
- const start = new Date(now.getTime() - 24 * 60 * 60 * 1000);
9
- return {
10
- whereClause: "timestamp >= $1",
11
- params: [start.toISOString()],
12
- paramOffset: 1,
13
- };
14
- }
15
- if (dateRange === "last7d") {
16
- const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
17
- return {
18
- whereClause: "timestamp >= $1",
19
- params: [start.toISOString()],
20
- paramOffset: 1,
21
- };
22
- }
23
- if (dateRange === "last30d") {
24
- const start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
25
- return {
26
- whereClause: "timestamp >= $1",
27
- params: [start.toISOString()],
28
- paramOffset: 1,
29
- };
30
- }
31
- // Custom date range
32
- return {
33
- whereClause: "timestamp >= $1 AND timestamp <= $2",
34
- params: [dateRange.start.toISOString(), dateRange.end.toISOString()],
35
- paramOffset: 2,
36
- };
37
- }
38
- /**
39
- * PostgreSQL implementation of the analytics database
40
- */
41
- export class PostgresDB {
42
- constructor(connectionString) {
43
- this.pool = new Pool({
44
- connectionString,
45
- max: 10,
46
- idleTimeoutMillis: 30000,
47
- connectionTimeoutMillis: 5000,
48
- });
49
- }
50
- async insertPageview(event, ipHash) {
51
- const query = `
52
- INSERT INTO locallytics_pageviews (
53
- session_id, page_url, referrer, user_agent,
54
- screen_width, screen_height, ip_hash, timestamp
55
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
56
- `;
57
- await this.pool.query(query, [
58
- event.sessionId,
59
- event.pageUrl,
60
- event.referrer,
61
- event.userAgent,
62
- event.screenWidth,
63
- event.screenHeight,
64
- ipHash,
65
- event.timestamp,
66
- ]);
67
- }
68
- async getPageviews(dateRange) {
69
- const { whereClause, params } = getDateRangeFilter(dateRange);
70
- const query = `
71
- SELECT COUNT(*) as count
72
- FROM locallytics_pageviews
73
- WHERE ${whereClause}
74
- `;
75
- const result = await this.pool.query(query, params);
76
- return parseInt(result.rows[0]?.count ?? "0", 10);
77
- }
78
- async getUniqueVisitors(dateRange) {
79
- const { whereClause, params } = getDateRangeFilter(dateRange);
80
- const query = `
81
- SELECT COUNT(DISTINCT session_id) as count
82
- FROM locallytics_pageviews
83
- WHERE ${whereClause}
84
- `;
85
- const result = await this.pool.query(query, params);
86
- return parseInt(result.rows[0]?.count ?? "0", 10);
87
- }
88
- async getTopPages(dateRange, limit) {
89
- const { whereClause, params, paramOffset } = getDateRangeFilter(dateRange);
90
- const query = `
91
- SELECT page_url as "pageUrl", COUNT(*) as count
92
- FROM locallytics_pageviews
93
- WHERE ${whereClause}
94
- GROUP BY page_url
95
- ORDER BY count DESC
96
- LIMIT $${paramOffset + 1}
97
- `;
98
- const result = await this.pool.query(query, [...params, limit]);
99
- return result.rows.map((row) => ({
100
- pageUrl: row.pageUrl,
101
- count: parseInt(row.count, 10),
102
- }));
103
- }
104
- async getTopReferrers(dateRange, limit) {
105
- const { whereClause, params, paramOffset } = getDateRangeFilter(dateRange);
106
- const query = `
107
- SELECT referrer as "pageUrl", COUNT(*) as count
108
- FROM locallytics_pageviews
109
- WHERE ${whereClause} AND referrer IS NOT NULL
110
- GROUP BY referrer
111
- ORDER BY count DESC
112
- LIMIT $${paramOffset + 1}
113
- `;
114
- const result = await this.pool.query(query, [...params, limit]);
115
- return result.rows.map((row) => ({
116
- pageUrl: row.pageUrl,
117
- count: parseInt(row.count, 10),
118
- }));
119
- }
120
- async getDailyStats(dateRange) {
121
- const { whereClause, params } = getDateRangeFilter(dateRange);
122
- const query = `
123
- SELECT
124
- DATE(timestamp) as date,
125
- COUNT(*) as pageviews,
126
- COUNT(DISTINCT session_id) as "uniqueVisitors"
127
- FROM locallytics_pageviews
128
- WHERE ${whereClause}
129
- GROUP BY DATE(timestamp)
130
- ORDER BY date DESC
131
- `;
132
- const result = await this.pool.query(query, params);
133
- return result.rows.map((row) => ({
134
- date: row.date.toISOString().split("T")[0] ?? "",
135
- pageviews: parseInt(row.pageviews, 10),
136
- uniqueVisitors: parseInt(row.uniqueVisitors, 10),
137
- }));
138
- }
139
- async close() {
140
- await this.pool.end();
141
- }
142
- }
143
- //# sourceMappingURL=postgres.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/db/postgres.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- import type { AnalyticsDB, PageviewEvent, DateRange, PageStats, DailyStats } from "../types/index.js";
2
- /**
3
- * SQLite implementation of the analytics database
4
- */
5
- export declare class SQLiteDB implements AnalyticsDB {
6
- private db;
7
- private constructor();
8
- static create(filePath: string): Promise<SQLiteDB>;
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=sqlite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/db/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,SAAS,EACT,SAAS,EACT,UAAU,EACX,MAAM,mBAAmB,CAAC;AAuD3B;;GAEG;AACH,qBAAa,QAAS,YAAW,WAAW;IAC1C,OAAO,CAAC,EAAE,CAAW;IAErB,OAAO;WAIM,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOlD,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"}
package/dist/db/sqlite.js DELETED
@@ -1,130 +0,0 @@
1
- /**
2
- * Get SQL WHERE clause parts for a date range (SQLite 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
- * SQLite implementation of the analytics database
35
- */
36
- export class SQLiteDB {
37
- constructor(db) {
38
- this.db = db;
39
- }
40
- static async create(filePath) {
41
- const BetterSqlite3Module = await import("better-sqlite3");
42
- const BetterSqlite3 = BetterSqlite3Module.default;
43
- const db = new BetterSqlite3(filePath);
44
- return new SQLiteDB(db);
45
- }
46
- async insertPageview(event, ipHash) {
47
- const stmt = this.db.prepare(`
48
- INSERT INTO locallytics_pageviews (
49
- session_id, page_url, referrer, user_agent,
50
- screen_width, screen_height, ip_hash, timestamp
51
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
52
- `);
53
- stmt.run(event.sessionId, event.pageUrl, event.referrer, event.userAgent, event.screenWidth, event.screenHeight, ipHash, event.timestamp);
54
- }
55
- async getPageviews(dateRange) {
56
- const { whereClause, params } = getDateRangeFilter(dateRange);
57
- const stmt = this.db.prepare(`
58
- SELECT COUNT(*) as count
59
- FROM locallytics_pageviews
60
- WHERE ${whereClause}
61
- `);
62
- const result = stmt.get(...params);
63
- return result?.count ?? 0;
64
- }
65
- async getUniqueVisitors(dateRange) {
66
- const { whereClause, params } = getDateRangeFilter(dateRange);
67
- const stmt = this.db.prepare(`
68
- SELECT COUNT(DISTINCT session_id) as count
69
- FROM locallytics_pageviews
70
- WHERE ${whereClause}
71
- `);
72
- const result = stmt.get(...params);
73
- return result?.count ?? 0;
74
- }
75
- async getTopPages(dateRange, limit) {
76
- const { whereClause, params } = getDateRangeFilter(dateRange);
77
- const stmt = this.db.prepare(`
78
- SELECT page_url as pageUrl, COUNT(*) as count
79
- FROM locallytics_pageviews
80
- WHERE ${whereClause}
81
- GROUP BY page_url
82
- ORDER BY count DESC
83
- LIMIT ?
84
- `);
85
- const results = stmt.all(...params, limit);
86
- return results.map((row) => ({
87
- pageUrl: row.pageUrl,
88
- count: row.count,
89
- }));
90
- }
91
- async getTopReferrers(dateRange, limit) {
92
- const { whereClause, params } = getDateRangeFilter(dateRange);
93
- const stmt = this.db.prepare(`
94
- SELECT referrer as pageUrl, COUNT(*) as count
95
- FROM locallytics_pageviews
96
- WHERE ${whereClause} AND referrer IS NOT NULL
97
- GROUP BY referrer
98
- ORDER BY count DESC
99
- LIMIT ?
100
- `);
101
- const results = stmt.all(...params, limit);
102
- return results.map((row) => ({
103
- pageUrl: row.pageUrl,
104
- count: row.count,
105
- }));
106
- }
107
- async getDailyStats(dateRange) {
108
- const { whereClause, params } = getDateRangeFilter(dateRange);
109
- const stmt = this.db.prepare(`
110
- SELECT
111
- date(timestamp) as date,
112
- COUNT(*) as pageviews,
113
- COUNT(DISTINCT session_id) as uniqueVisitors
114
- FROM locallytics_pageviews
115
- WHERE ${whereClause}
116
- GROUP BY date(timestamp)
117
- ORDER BY date DESC
118
- `);
119
- const results = stmt.all(...params);
120
- return results.map((row) => ({
121
- date: row.date,
122
- pageviews: row.pageviews,
123
- uniqueVisitors: row.uniqueVisitors,
124
- }));
125
- }
126
- async close() {
127
- this.db.close();
128
- }
129
- }
130
- //# sourceMappingURL=sqlite.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/db/sqlite.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,SAAS,EACT,SAAS,EACT,UAAU,EACV,aAAa,EACb,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,iBAAiB;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAapE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,10 +0,0 @@
1
- import type { AnalyticsDB, LocallyticsConfig, RouteHandler } from "../types/index.js";
2
- /**
3
- * Create route handlers for analytics API
4
- *
5
- * @param db - Database instance
6
- * @param config - Locallytics configuration
7
- * @returns GET and POST handlers
8
- */
9
- export declare function createHandlers(db: AnalyticsDB, config: LocallyticsConfig): RouteHandler;
10
- //# sourceMappingURL=handlers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/server/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,YAAY,EAEb,MAAM,mBAAmB,CAAC;AAmC3B;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,iBAAiB,GACxB,YAAY,CAiGd"}
@@ -1,105 +0,0 @@
1
- import { LocallyticsError } from "../types/index.js";
2
- import { RateLimiter } from "../utils/rate-limit.js";
3
- import { hashIP, getIPFromRequest } from "../utils/hash.js";
4
- import { validatePageviewBatch, checkDNT } from "./validator.js";
5
- import { getAnalyticsData } from "./queries.js";
6
- /**
7
- * Parse date range from query string
8
- */
9
- function parseDateRange(value) {
10
- if (!value || value === "last7d") {
11
- return "last7d";
12
- }
13
- if (value === "last24h" || value === "last30d") {
14
- return value;
15
- }
16
- // Try to parse custom range (format: start,end as ISO strings)
17
- if (value.includes(",")) {
18
- const [startStr, endStr] = value.split(",");
19
- if (startStr && endStr) {
20
- const start = new Date(startStr);
21
- const end = new Date(endStr);
22
- if (!isNaN(start.getTime()) && !isNaN(end.getTime())) {
23
- return { start, end };
24
- }
25
- }
26
- }
27
- return "last7d";
28
- }
29
- /**
30
- * Create route handlers for analytics API
31
- *
32
- * @param db - Database instance
33
- * @param config - Locallytics configuration
34
- * @returns GET and POST handlers
35
- */
36
- export function createHandlers(db, config) {
37
- const rateLimiter = new RateLimiter(100, 60000);
38
- /**
39
- * POST handler - track pageview events
40
- */
41
- async function POST(request) {
42
- try {
43
- // Check DNT - respect user privacy preference
44
- if (checkDNT(request)) {
45
- return Response.json({ success: true, tracked: false });
46
- }
47
- // Rate limiting by IP
48
- const ip = getIPFromRequest(request);
49
- const rateLimitKey = ip ?? "unknown";
50
- if (!rateLimiter.check(rateLimitKey)) {
51
- const error = LocallyticsError.rateLimit();
52
- return Response.json({ error: error.message, code: error.code }, { status: error.statusCode });
53
- }
54
- // Parse and validate batch
55
- const body = await request.json();
56
- const events = validatePageviewBatch(body);
57
- // Hash IP for privacy
58
- const ipHash = ip ? hashIP(ip) : null;
59
- // Insert all events
60
- await Promise.all(events.map((event) => db.insertPageview(event, ipHash)));
61
- return Response.json({
62
- success: true,
63
- tracked: true,
64
- count: events.length,
65
- });
66
- }
67
- catch (error) {
68
- if (error instanceof LocallyticsError) {
69
- return Response.json({ error: error.message, code: error.code }, { status: error.statusCode });
70
- }
71
- // Log unexpected errors but don't expose details
72
- console.error("[Locallytics] POST error:", error);
73
- return Response.json({ error: "Internal server error", code: "INTERNAL_ERROR" }, { status: 500 });
74
- }
75
- }
76
- /**
77
- * GET handler - fetch analytics data
78
- */
79
- async function GET(request) {
80
- try {
81
- // Check API key authentication if configured
82
- if (config.apiKey) {
83
- const authHeader = request.headers.get("authorization");
84
- const providedKey = authHeader?.replace("Bearer ", "");
85
- if (providedKey !== config.apiKey) {
86
- const error = LocallyticsError.unauthorized();
87
- return Response.json({ error: error.message, code: error.code }, { status: error.statusCode });
88
- }
89
- }
90
- // Parse date range from query params
91
- const url = new URL(request.url);
92
- const dateRange = parseDateRange(url.searchParams.get("range"));
93
- // Fetch analytics data
94
- const data = await getAnalyticsData(db, dateRange);
95
- return Response.json(data);
96
- }
97
- catch (error) {
98
- // Log unexpected errors but don't expose details
99
- console.error("[Locallytics] GET error:", error);
100
- return Response.json({ error: "Internal server error", code: "INTERNAL_ERROR" }, { status: 500 });
101
- }
102
- }
103
- return { GET, POST };
104
- }
105
- //# sourceMappingURL=handlers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/server/handlers.ts"],"names":[],"mappings":"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"}
@@ -1,42 +0,0 @@
1
- import type { LocallyticsConfig, RouteHandler, AnalyticsResult, AnalyticsDataOptions } from "../types/index.js";
2
- /**
3
- * Initialize Locallytics and create route handlers
4
- *
5
- * @param config - Locallytics configuration
6
- * @returns GET and POST route handlers for Next.js App Router
7
- *
8
- * @example
9
- * ```typescript
10
- * // app/api/analytics/route.ts
11
- * import { locallytics } from 'locallytics';
12
- *
13
- * const analytics = await locallytics({
14
- * database: process.env.DATABASE_URL!,
15
- * apiKey: process.env.ANALYTICS_API_KEY,
16
- * });
17
- *
18
- * export const { GET, POST } = analytics;
19
- * ```
20
- */
21
- export declare function locallytics(config: LocallyticsConfig): Promise<RouteHandler>;
22
- /**
23
- * Server-side helper to fetch analytics data
24
- * Use in React Server Components
25
- *
26
- * @param options - Options including date range (optional)
27
- * @returns Analytics data
28
- *
29
- * @example
30
- * ```tsx
31
- * // app/dashboard/page.tsx
32
- * import { LocallyticsData } from 'locallytics';
33
- *
34
- * export default async function Dashboard() {
35
- * const data = await LocallyticsData(); // No arguments needed!
36
- *
37
- * return <div>{data.pageviews} pageviews</div>;
38
- * }
39
- * ```
40
- */
41
- export declare function LocallyticsData(options?: AnalyticsDataOptions): Promise<AnalyticsResult>;
42
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,YAAY,CAAC,CAGvB;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,eAAe,CAAC,CAiE1B"}
@@ -1,100 +0,0 @@
1
- import { createDatabase } from "../db/factory.js";
2
- import { createHandlers } from "./handlers.js";
3
- /**
4
- * Initialize Locallytics and create route handlers
5
- *
6
- * @param config - Locallytics configuration
7
- * @returns GET and POST route handlers for Next.js App Router
8
- *
9
- * @example
10
- * ```typescript
11
- * // app/api/analytics/route.ts
12
- * import { locallytics } from 'locallytics';
13
- *
14
- * const analytics = await locallytics({
15
- * database: process.env.DATABASE_URL!,
16
- * apiKey: process.env.ANALYTICS_API_KEY,
17
- * });
18
- *
19
- * export const { GET, POST } = analytics;
20
- * ```
21
- */
22
- export async function locallytics(config) {
23
- const db = await createDatabase(config);
24
- return createHandlers(db, config);
25
- }
26
- import { headers } from "next/headers";
27
- /**
28
- * Server-side helper to fetch analytics data
29
- * Use in React Server Components
30
- *
31
- * @param options - Options including date range (optional)
32
- * @returns Analytics data
33
- *
34
- * @example
35
- * ```tsx
36
- * // app/dashboard/page.tsx
37
- * import { LocallyticsData } from 'locallytics';
38
- *
39
- * export default async function Dashboard() {
40
- * const data = await LocallyticsData(); // No arguments needed!
41
- *
42
- * return <div>{data.pageviews} pageviews</div>;
43
- * }
44
- * ```
45
- */
46
- export async function LocallyticsData(options = {}) {
47
- const { dateRange = "last7d", endpoint = "/api/analytics" } = options;
48
- // Get headers to extract host for URL construction
49
- const headersList = await Promise.resolve(headers());
50
- const host = headersList.get("host") ?? "localhost:3000";
51
- const protocol = headersList.get("x-forwarded-proto") ?? "http";
52
- // Build the range query parameter
53
- let rangeParam;
54
- if (typeof dateRange === "string") {
55
- rangeParam = dateRange;
56
- }
57
- else {
58
- rangeParam = `${dateRange.start.toISOString()},${dateRange.end.toISOString()}`;
59
- }
60
- // Construct the full URL
61
- const url = `${protocol}://${host}${endpoint}?range=${encodeURIComponent(rangeParam)}`;
62
- // Forward authorization header if present
63
- const authHeader = headersList.get("authorization");
64
- const fetchHeaders = {};
65
- if (authHeader) {
66
- fetchHeaders["authorization"] = authHeader;
67
- }
68
- try {
69
- const response = await fetch(url, {
70
- headers: fetchHeaders,
71
- cache: "no-store",
72
- });
73
- if (!response.ok) {
74
- const errorData = (await response.json().catch(() => ({})));
75
- const errorMessage = errorData["message"] ??
76
- errorData["error"] ??
77
- `Failed to fetch analytics: ${response.status}`;
78
- return {
79
- pageviews: 0,
80
- uniqueVisitors: 0,
81
- topPages: [],
82
- topReferrers: [],
83
- dailyStats: [],
84
- error: errorMessage,
85
- };
86
- }
87
- return response.json();
88
- }
89
- catch (error) {
90
- return {
91
- pageviews: 0,
92
- uniqueVisitors: 0,
93
- topPages: [],
94
- topReferrers: [],
95
- dailyStats: [],
96
- error: error instanceof Error ? error.message : "Unknown error occurred",
97
- };
98
- }
99
- }
100
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import type { AnalyticsDB, AnalyticsResult, DateRange } from "../types/index.js";
2
- /**
3
- * Fetch all analytics data in parallel
4
- *
5
- * @param db - Database instance
6
- * @param dateRange - Date range for the query
7
- * @returns Complete analytics data
8
- */
9
- export declare function getAnalyticsData(db: AnalyticsDB, dateRange: DateRange): Promise<AnalyticsResult>;
10
- //# sourceMappingURL=queries.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/server/queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,SAAS,EACV,MAAM,mBAAmB,CAAC;AAE3B;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,WAAW,EACf,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,eAAe,CAAC,CAiB1B"}
@@ -1,24 +0,0 @@
1
- /**
2
- * Fetch all analytics data in parallel
3
- *
4
- * @param db - Database instance
5
- * @param dateRange - Date range for the query
6
- * @returns Complete analytics data
7
- */
8
- export async function getAnalyticsData(db, dateRange) {
9
- const [pageviews, uniqueVisitors, topPages, topReferrers, dailyStats] = await Promise.all([
10
- db.getPageviews(dateRange),
11
- db.getUniqueVisitors(dateRange),
12
- db.getTopPages(dateRange, 10),
13
- db.getTopReferrers(dateRange, 10),
14
- db.getDailyStats(dateRange),
15
- ]);
16
- return {
17
- pageviews,
18
- uniqueVisitors,
19
- topPages,
20
- topReferrers,
21
- dailyStats,
22
- };
23
- }
24
- //# sourceMappingURL=queries.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/server/queries.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAe,EACf,SAAoB;IAEpB,MAAM,CAAC,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,GACnE,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC;QAC1B,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;QAC/B,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;QAC7B,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,CAAC;QACjC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC;KAC5B,CAAC,CAAC;IAEL,OAAO;QACL,SAAS;QACT,cAAc;QACd,QAAQ;QACR,YAAY;QACZ,UAAU;KACX,CAAC;AACJ,CAAC"}