2027-track 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,37 @@ await trackVisit({
34
34
  });
35
35
  ```
36
36
 
37
+ ## Route Filtering
38
+
39
+ **Important:** Only track public documentation routes. Exclude private endpoints to avoid leaking sensitive paths.
40
+
41
+ ### Next.js matcher (recommended)
42
+
43
+ ```ts
44
+ // middleware.ts
45
+ import { withAIAnalytics } from "2027-track/next";
46
+
47
+ export default withAIAnalytics();
48
+
49
+ export const config = {
50
+ matcher: [
51
+ // Exclude private routes, track everything else
52
+ "/((?!api|_next|app|admin|dashboard|auth|login|signup).*)",
53
+ ],
54
+ };
55
+ ```
56
+
57
+ ### Manual filtering
58
+
59
+ ```ts
60
+ import { trackVisit } from "2027-track";
61
+
62
+ // Only track if path starts with /docs
63
+ if (path.startsWith("/docs")) {
64
+ await trackVisit({ host, path, userAgent, accept });
65
+ }
66
+ ```
67
+
37
68
  ## Configuration
38
69
 
39
70
  ### Kill switch
@@ -0,0 +1,46 @@
1
+ // src/index.ts
2
+ var DEFAULT_ENDPOINT = "https://ai-docs-analytics-api.theisease.workers.dev/track";
3
+ var TIMEOUT_MS = 2500;
4
+ function getEndpoint() {
5
+ const env = typeof process !== "undefined" ? process.env.AI_ANALYTICS_ENDPOINT : void 0;
6
+ if (env === "") return null;
7
+ return env || DEFAULT_ENDPOINT;
8
+ }
9
+ function isPageView(accept) {
10
+ const a = accept.toLowerCase();
11
+ return a.includes("text/html") || a.includes("text/markdown");
12
+ }
13
+ async function trackVisit(options) {
14
+ const endpoint = getEndpoint();
15
+ if (!endpoint) {
16
+ return { ok: true, skipped: "disabled" };
17
+ }
18
+ if (!isPageView(options.accept)) {
19
+ return { ok: true, skipped: "not-page-view" };
20
+ }
21
+ const controller = new AbortController();
22
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
23
+ try {
24
+ const response = await fetch(endpoint, {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify({
28
+ host: options.host,
29
+ path: options.path,
30
+ user_agent: options.userAgent,
31
+ accept: options.accept,
32
+ country: options.country || "unknown"
33
+ }),
34
+ signal: controller.signal
35
+ });
36
+ clearTimeout(timeoutId);
37
+ return await response.json();
38
+ } catch (e) {
39
+ clearTimeout(timeoutId);
40
+ return { ok: false, error: e instanceof Error ? e.message : "unknown error" };
41
+ }
42
+ }
43
+
44
+ export {
45
+ trackVisit
46
+ };
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ function getEndpoint() {
30
30
  if (env === "") return null;
31
31
  return env || DEFAULT_ENDPOINT;
32
32
  }
33
- function shouldTrack(accept) {
33
+ function isPageView(accept) {
34
34
  const a = accept.toLowerCase();
35
35
  return a.includes("text/html") || a.includes("text/markdown");
36
36
  }
@@ -39,7 +39,7 @@ async function trackVisit(options) {
39
39
  if (!endpoint) {
40
40
  return { ok: true, skipped: "disabled" };
41
41
  }
42
- if (!shouldTrack(options.accept)) {
42
+ if (!isPageView(options.accept)) {
43
43
  return { ok: true, skipped: "not-page-view" };
44
44
  }
45
45
  const controller = new AbortController();
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  trackVisit
3
- } from "./chunk-Z3U3YF4H.mjs";
3
+ } from "./chunk-2UMSOEKA.mjs";
4
4
  export {
5
5
  trackVisit
6
6
  };
package/dist/next.js CHANGED
@@ -34,7 +34,7 @@ function getEndpoint() {
34
34
  if (env === "") return null;
35
35
  return env || DEFAULT_ENDPOINT;
36
36
  }
37
- function shouldTrack(accept) {
37
+ function isPageView(accept) {
38
38
  const a = accept.toLowerCase();
39
39
  return a.includes("text/html") || a.includes("text/markdown");
40
40
  }
@@ -43,7 +43,7 @@ async function trackVisit(options) {
43
43
  if (!endpoint) {
44
44
  return { ok: true, skipped: "disabled" };
45
45
  }
46
- if (!shouldTrack(options.accept)) {
46
+ if (!isPageView(options.accept)) {
47
47
  return { ok: true, skipped: "not-page-view" };
48
48
  }
49
49
  const controller = new AbortController();
@@ -73,14 +73,16 @@ async function trackVisit(options) {
73
73
  function withAIAnalytics(middleware) {
74
74
  return async (request, event) => {
75
75
  const response = middleware ? await middleware(request, event) : import_server.NextResponse.next();
76
- trackVisit({
77
- host: request.headers.get("host") || request.nextUrl.host,
78
- path: request.nextUrl.pathname,
79
- userAgent: request.headers.get("user-agent") || "",
80
- accept: request.headers.get("accept") || "",
81
- country: request.geo?.country || "unknown"
82
- }).catch(() => {
83
- });
76
+ event.waitUntil(
77
+ trackVisit({
78
+ host: request.headers.get("host") || request.nextUrl.host,
79
+ path: request.nextUrl.pathname,
80
+ userAgent: request.headers.get("user-agent") || "",
81
+ accept: request.headers.get("accept") || "",
82
+ country: request.geo?.country || "unknown"
83
+ }).catch(() => {
84
+ })
85
+ );
84
86
  return response;
85
87
  };
86
88
  }
package/dist/next.mjs CHANGED
@@ -1,20 +1,22 @@
1
1
  import {
2
2
  trackVisit
3
- } from "./chunk-Z3U3YF4H.mjs";
3
+ } from "./chunk-2UMSOEKA.mjs";
4
4
 
5
5
  // src/next.ts
6
6
  import { NextResponse } from "next/server";
7
7
  function withAIAnalytics(middleware) {
8
8
  return async (request, event) => {
9
9
  const response = middleware ? await middleware(request, event) : NextResponse.next();
10
- trackVisit({
11
- host: request.headers.get("host") || request.nextUrl.host,
12
- path: request.nextUrl.pathname,
13
- userAgent: request.headers.get("user-agent") || "",
14
- accept: request.headers.get("accept") || "",
15
- country: request.geo?.country || "unknown"
16
- }).catch(() => {
17
- });
10
+ event.waitUntil(
11
+ trackVisit({
12
+ host: request.headers.get("host") || request.nextUrl.host,
13
+ path: request.nextUrl.pathname,
14
+ userAgent: request.headers.get("user-agent") || "",
15
+ accept: request.headers.get("accept") || "",
16
+ country: request.geo?.country || "unknown"
17
+ }).catch(() => {
18
+ })
19
+ );
18
20
  return response;
19
21
  };
20
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "2027-track",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Track AI coding agents visiting your documentation",
5
5
  "repository": {
6
6
  "type": "git",