@polishd/next 0.2.1 → 0.2.2-dev.1
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/CHANGELOG.md +57 -0
- package/DATABASE.md +8 -1
- package/README.md +52 -0
- package/dist/ai/actions.d.ts +10 -1
- package/dist/ai/actions.d.ts.map +1 -1
- package/dist/ai/actions.js +21 -0
- package/dist/ai/actions.js.map +1 -1
- package/dist/ai/ignored.d.ts +26 -0
- package/dist/ai/ignored.d.ts.map +1 -0
- package/dist/ai/ignored.js +134 -0
- package/dist/ai/ignored.js.map +1 -0
- package/dist/ai/summary.d.ts +8 -1
- package/dist/ai/summary.d.ts.map +1 -1
- package/dist/ai/summary.js +59 -22
- package/dist/ai/summary.js.map +1 -1
- package/dist/ai/types.d.ts +31 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/client/dom.d.ts +23 -0
- package/dist/client/dom.d.ts.map +1 -0
- package/dist/client/dom.js +71 -0
- package/dist/client/dom.js.map +1 -0
- package/dist/client/init.d.ts.map +1 -1
- package/dist/client/init.js +3 -62
- package/dist/client/init.js.map +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +16 -10
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/summary.d.ts.map +1 -1
- package/dist/dashboard/summary.js +64 -4
- package/dist/dashboard/summary.js.map +1 -1
- package/dist/dashboard/telemetry-consent.d.ts +3 -0
- package/dist/dashboard/telemetry-consent.d.ts.map +1 -0
- package/dist/dashboard/telemetry-consent.js +20 -0
- package/dist/dashboard/telemetry-consent.js.map +1 -0
- package/dist/dashboard/telemetry.d.ts +21 -0
- package/dist/dashboard/telemetry.d.ts.map +1 -0
- package/dist/dashboard/telemetry.js +212 -0
- package/dist/dashboard/telemetry.js.map +1 -0
- package/dist/dashboard.css +52 -0
- package/dist/server/ingest.d.ts +20 -0
- package/dist/server/ingest.d.ts.map +1 -1
- package/dist/server/ingest.js +49 -0
- package/dist/server/ingest.js.map +1 -1
- package/dist/server/store.d.ts +6 -2
- package/dist/server/store.d.ts.map +1 -1
- package/dist/server/store.js +34 -13
- package/dist/server/store.js.map +1 -1
- package/dist/server/telemetry.d.ts +28 -0
- package/dist/server/telemetry.d.ts.map +1 -0
- package/dist/server/telemetry.js +83 -0
- package/dist/server/telemetry.js.map +1 -0
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/telemetry.d.ts +43 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +81 -0
- package/dist/telemetry.js.map +1 -0
- package/package.json +5 -1
package/dist/server/ingest.js
CHANGED
|
@@ -136,4 +136,53 @@ export async function ingest(body, cookieValue, config = {}) {
|
|
|
136
136
|
const stored = await insertEvents(sessionId, events);
|
|
137
137
|
return { ok: true, stored };
|
|
138
138
|
}
|
|
139
|
+
// ── Cross-install telemetry ingest ───────────────────────────────────────────
|
|
140
|
+
/**
|
|
141
|
+
* The shape both client-minted ids must satisfy. Loose enough for a UUID or a
|
|
142
|
+
* short hash, tight enough that the column can never hold markup, whitespace,
|
|
143
|
+
* or anything long enough to be a payload.
|
|
144
|
+
*/
|
|
145
|
+
const TELEMETRY_ID_RE = /^[A-Za-z0-9._-]{6,64}$/;
|
|
146
|
+
/**
|
|
147
|
+
* Ingest a telemetry batch from a *remote* polishd installation.
|
|
148
|
+
*
|
|
149
|
+
* This differs from first-party {@link ingest} in exactly three ways, each a
|
|
150
|
+
* consequence of the request crossing origins:
|
|
151
|
+
*
|
|
152
|
+
* 1. Identity travels in the body. The session cookie is httpOnly and
|
|
153
|
+
* first-party, so it never arrives here; the emitter mints an anonymous
|
|
154
|
+
* session id itself and sends it alongside a stable `installId`. Both are
|
|
155
|
+
* validated by shape only — there is nothing to verify them against, and
|
|
156
|
+
* the worst a forger achieves is polluting telemetry, same as any public
|
|
157
|
+
* ingest endpoint.
|
|
158
|
+
* 2. Every stored row is tagged with the `installId`, so one shared database
|
|
159
|
+
* can tell installations apart.
|
|
160
|
+
* 3. Dashboard paths are NOT dropped. Recording how the dashboard itself is
|
|
161
|
+
* used is the entire point of this channel; the emitter is expected to
|
|
162
|
+
* namespace its paths so they can't collide with the receiving site's own
|
|
163
|
+
* first-party events.
|
|
164
|
+
*/
|
|
165
|
+
export async function ingestTelemetry(body, config = {}) {
|
|
166
|
+
const cfg = { ...defaultPolishdConfig, ...config };
|
|
167
|
+
if (!cfg.enabled)
|
|
168
|
+
return { ok: true, stored: 0, reason: "disabled" };
|
|
169
|
+
const b = body;
|
|
170
|
+
const installId = typeof b?.installId === "string" && TELEMETRY_ID_RE.test(b.installId)
|
|
171
|
+
? b.installId
|
|
172
|
+
: null;
|
|
173
|
+
const sessionId = typeof b?.sessionId === "string" && TELEMETRY_ID_RE.test(b.sessionId)
|
|
174
|
+
? b.sessionId
|
|
175
|
+
: null;
|
|
176
|
+
if (!installId || !sessionId)
|
|
177
|
+
return { ok: false, stored: 0, reason: "bad_identity" };
|
|
178
|
+
const rawEvents = b?.events;
|
|
179
|
+
if (!Array.isArray(rawEvents))
|
|
180
|
+
return { ok: false, stored: 0, reason: "no_events" };
|
|
181
|
+
const events = rawEvents
|
|
182
|
+
.slice(0, MAX_EVENTS_PER_BATCH)
|
|
183
|
+
.map(sanitize)
|
|
184
|
+
.filter((e) => e !== null);
|
|
185
|
+
const stored = await insertEvents(sessionId, events, installId);
|
|
186
|
+
return { ok: true, stored };
|
|
187
|
+
}
|
|
139
188
|
//# sourceMappingURL=ingest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/server/ingest.ts"],"names":[],"mappings":"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"}
|
package/dist/server/store.d.ts
CHANGED
|
@@ -6,8 +6,12 @@ import type { PolishdEvent, PolishdEventRow } from "../shared/types";
|
|
|
6
6
|
type Row = Record<string, unknown>;
|
|
7
7
|
/** True when events are actually being persisted (used by the dashboard). */
|
|
8
8
|
export declare function storeReady(): Promise<boolean>;
|
|
9
|
-
/**
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Persist a batch of events for one session. Silently drops if no store.
|
|
11
|
+
* `installId` is only ever set on the telemetry path — first-party ingest
|
|
12
|
+
* leaves it undefined and the column null.
|
|
13
|
+
*/
|
|
14
|
+
export declare function insertEvents(sessionId: string, events: PolishdEvent[], installId?: string): Promise<number>;
|
|
11
15
|
/**
|
|
12
16
|
* Run a portable read query, or return `[]` in no-op mode. Use `?` placeholders;
|
|
13
17
|
* each backend rewrites them to its own dialect. The aggregation layer (and the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErE;;;GAGG;AACH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAErE;;;GAGG;AACH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAmTnC,6EAA6E;AAC7E,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAEnD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EAAE,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAY/E;AAQD,sEAAsE;AACtE,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIjE;AAED,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB1E;AAED,mEAAmE;AACnE,wBAAsB,OAAO,CAAC,KAAK,SAAO,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAGtE;AAmBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAW/D"}
|
package/dist/server/store.js
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { defaultPolishdConfig } from "../config";
|
|
22
22
|
/** The columns every backend inserts, in a fixed order, for one event. */
|
|
23
|
-
const INSERT_COLS = "session_id, type, ts, path, selector, component, text, value, meta, received_at";
|
|
23
|
+
const INSERT_COLS = "session_id, type, ts, path, selector, component, text, value, meta, received_at, install_id";
|
|
24
24
|
/** Turn one event into its positional values, matching `INSERT_COLS`. */
|
|
25
|
-
function eventValues(sessionId, e, now) {
|
|
25
|
+
function eventValues(sessionId, e, now, installId) {
|
|
26
26
|
return [
|
|
27
27
|
sessionId,
|
|
28
28
|
e.type,
|
|
@@ -34,6 +34,7 @@ function eventValues(sessionId, e, now) {
|
|
|
34
34
|
e.value ?? null,
|
|
35
35
|
e.meta ? JSON.stringify(e.meta) : null,
|
|
36
36
|
now,
|
|
37
|
+
installId ?? null,
|
|
37
38
|
];
|
|
38
39
|
}
|
|
39
40
|
// ── Legacy metadata migration ────────────────────────────────────────────────
|
|
@@ -93,7 +94,8 @@ async function openSqlite() {
|
|
|
93
94
|
text TEXT,
|
|
94
95
|
value REAL,
|
|
95
96
|
meta TEXT,
|
|
96
|
-
received_at INTEGER NOT NULL
|
|
97
|
+
received_at INTEGER NOT NULL,
|
|
98
|
+
install_id TEXT
|
|
97
99
|
);
|
|
98
100
|
CREATE INDEX IF NOT EXISTS idx_events_path ON events(path);
|
|
99
101
|
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
@@ -105,20 +107,30 @@ async function openSqlite() {
|
|
|
105
107
|
updated_at INTEGER NOT NULL
|
|
106
108
|
);
|
|
107
109
|
`);
|
|
110
|
+
// Databases created before install_id existed lack the column; SQLite has no
|
|
111
|
+
// ADD COLUMN IF NOT EXISTS, so the raise on an up-to-date table is the
|
|
112
|
+
// expected path. The index only lands once the column is guaranteed present.
|
|
113
|
+
try {
|
|
114
|
+
db.exec(`ALTER TABLE events ADD COLUMN install_id TEXT`);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Column already there — fresh table or already-migrated database.
|
|
118
|
+
}
|
|
119
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_events_install ON events(install_id)`);
|
|
108
120
|
migrateLegacyMeta((sql) => db.exec(sql), `INSERT OR IGNORE INTO polishd_meta (key, value, updated_at)
|
|
109
121
|
SELECT key, value, updated_at FROM buffd_meta`);
|
|
110
122
|
return {
|
|
111
|
-
async insert(sessionId, events) {
|
|
123
|
+
async insert(sessionId, events, installId) {
|
|
112
124
|
if (events.length === 0)
|
|
113
125
|
return 0;
|
|
114
126
|
const now = Date.now();
|
|
115
|
-
const stmt = db.prepare(`INSERT INTO events (${INSERT_COLS}) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
127
|
+
const stmt = db.prepare(`INSERT INTO events (${INSERT_COLS}) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
116
128
|
let written = 0;
|
|
117
129
|
// node:sqlite has no .transaction() helper; wrap manually for batch speed.
|
|
118
130
|
db.exec("BEGIN");
|
|
119
131
|
try {
|
|
120
132
|
for (const e of events) {
|
|
121
|
-
stmt.run(...eventValues(sessionId, e, now));
|
|
133
|
+
stmt.run(...eventValues(sessionId, e, now, installId));
|
|
122
134
|
written++;
|
|
123
135
|
}
|
|
124
136
|
db.exec("COMMIT");
|
|
@@ -176,11 +188,15 @@ function openPostgres(url) {
|
|
|
176
188
|
text TEXT,
|
|
177
189
|
value DOUBLE PRECISION,
|
|
178
190
|
meta JSONB,
|
|
179
|
-
received_at BIGINT NOT NULL
|
|
191
|
+
received_at BIGINT NOT NULL,
|
|
192
|
+
install_id TEXT
|
|
180
193
|
);
|
|
194
|
+
-- Migrates tables created before install_id existed; no-op otherwise.
|
|
195
|
+
ALTER TABLE events ADD COLUMN IF NOT EXISTS install_id TEXT;
|
|
181
196
|
CREATE INDEX IF NOT EXISTS idx_events_path ON events(path);
|
|
182
197
|
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
183
198
|
CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
|
|
199
|
+
CREATE INDEX IF NOT EXISTS idx_events_install ON events(install_id);
|
|
184
200
|
|
|
185
201
|
CREATE TABLE IF NOT EXISTS polishd_meta (
|
|
186
202
|
key TEXT PRIMARY KEY,
|
|
@@ -193,12 +209,12 @@ function openPostgres(url) {
|
|
|
193
209
|
ON CONFLICT (key) DO NOTHING`);
|
|
194
210
|
});
|
|
195
211
|
return {
|
|
196
|
-
async insert(sessionId, events) {
|
|
212
|
+
async insert(sessionId, events, installId) {
|
|
197
213
|
if (events.length === 0)
|
|
198
214
|
return 0;
|
|
199
215
|
await ready;
|
|
200
216
|
const now = Date.now();
|
|
201
|
-
const cols =
|
|
217
|
+
const cols = 11; // must match INSERT_COLS / eventValues
|
|
202
218
|
const params = [];
|
|
203
219
|
const tuples = [];
|
|
204
220
|
events.forEach((e, row) => {
|
|
@@ -206,7 +222,7 @@ function openPostgres(url) {
|
|
|
206
222
|
// meta is the 9th column (index 8) — cast its text param to jsonb.
|
|
207
223
|
const ph = Array.from({ length: cols }, (_, c) => c === 8 ? `$${base + c + 1}::jsonb` : `$${base + c + 1}`);
|
|
208
224
|
tuples.push(`(${ph.join(", ")})`);
|
|
209
|
-
params.push(...eventValues(sessionId, e, now));
|
|
225
|
+
params.push(...eventValues(sessionId, e, now, installId));
|
|
210
226
|
});
|
|
211
227
|
const res = await pool.query(`INSERT INTO events (${INSERT_COLS}) VALUES ${tuples.join(", ")}`, params);
|
|
212
228
|
return res.rowCount ?? 0;
|
|
@@ -261,13 +277,17 @@ async function getBackend() {
|
|
|
261
277
|
export async function storeReady() {
|
|
262
278
|
return (await getBackend()) !== null;
|
|
263
279
|
}
|
|
264
|
-
/**
|
|
265
|
-
|
|
280
|
+
/**
|
|
281
|
+
* Persist a batch of events for one session. Silently drops if no store.
|
|
282
|
+
* `installId` is only ever set on the telemetry path — first-party ingest
|
|
283
|
+
* leaves it undefined and the column null.
|
|
284
|
+
*/
|
|
285
|
+
export async function insertEvents(sessionId, events, installId) {
|
|
266
286
|
const b = await getBackend();
|
|
267
287
|
if (!b || events.length === 0)
|
|
268
288
|
return 0;
|
|
269
289
|
try {
|
|
270
|
-
return await b.insert(sessionId, events);
|
|
290
|
+
return await b.insert(sessionId, events, installId);
|
|
271
291
|
}
|
|
272
292
|
catch (err) {
|
|
273
293
|
console.warn("[polishd] insert failed, dropping batch:", err instanceof Error ? err.message : err);
|
|
@@ -335,6 +355,7 @@ function deserialize(row) {
|
|
|
335
355
|
value: row.value == null ? undefined : Number(row.value),
|
|
336
356
|
meta: parseMeta(row.meta),
|
|
337
357
|
received_at: Number(row.received_at),
|
|
358
|
+
install_id: row.install_id ?? undefined,
|
|
338
359
|
};
|
|
339
360
|
}
|
|
340
361
|
/**
|
package/dist/server/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAkBjD,0EAA0E;AAC1E,MAAM,WAAW,GACf,
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where telemetry lands: the polishd landing site's own installation. One
|
|
3
|
+
* constant on purpose — when the site moves to a real domain, this is the
|
|
4
|
+
* single line to change.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_TELEMETRY_ENDPOINT = "https://polishd-lac.vercel.app/api/polishd-telemetry";
|
|
7
|
+
export type PolishdTelemetryStatus =
|
|
8
|
+
/** Owner said yes; the emitter runs. */
|
|
9
|
+
"granted"
|
|
10
|
+
/** Owner said no; nothing runs, nothing asks again. */
|
|
11
|
+
| "denied"
|
|
12
|
+
/** Never asked — the dashboard shows the consent prompt. */
|
|
13
|
+
| "unset"
|
|
14
|
+
/** Env kill switch, or no writable store to keep consent in. */
|
|
15
|
+
| "disabled";
|
|
16
|
+
export interface PolishdTelemetryState {
|
|
17
|
+
status: PolishdTelemetryStatus;
|
|
18
|
+
/** Set only when status is "granted" — the emitter needs it, nobody else. */
|
|
19
|
+
installId: string | null;
|
|
20
|
+
endpoint: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function telemetryDisabledByEnv(): boolean;
|
|
23
|
+
export declare function resolveTelemetryEndpoint(): string;
|
|
24
|
+
/** Record the owner's decision. Overwrites any previous one. */
|
|
25
|
+
export declare function saveTelemetryConsent(granted: boolean): Promise<void>;
|
|
26
|
+
/** What the dashboard should do about telemetry on this render. */
|
|
27
|
+
export declare function loadPolishdTelemetryState(): Promise<PolishdTelemetryState>;
|
|
28
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/server/telemetry.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,yDACiB,CAAC;AAKzD,MAAM,MAAM,sBAAsB;AAChC,wCAAwC;AACtC,SAAS;AACX,uDAAuD;GACrD,QAAQ;AACV,4DAA4D;GAC1D,OAAO;AACT,gEAAgE;GAC9D,UAAU,CAAC;AAEf,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,6EAA6E;IAC7E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAGhD;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAcD,gEAAgE;AAChE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1E;AAED,mEAAmE;AACnE,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAuBhF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polishd — dogfood telemetry state (server only).
|
|
3
|
+
*
|
|
4
|
+
* Polishd can report anonymous usage of its *own dashboard* back to the
|
|
5
|
+
* polishd project, so the dashboard is improved by the same signals it
|
|
6
|
+
* preaches. This module owns everything about whether that happens:
|
|
7
|
+
*
|
|
8
|
+
* • Consent, stored in `polishd_meta` — asked once on the dashboard, opt-in,
|
|
9
|
+
* nothing is ever sent before the owner says yes.
|
|
10
|
+
* • The install id — a random UUID minted on first grant, meaning nothing
|
|
11
|
+
* and stable per installation, so the collecting side can tell
|
|
12
|
+
* installations apart without identifying anyone.
|
|
13
|
+
* • The endpoint — the polishd site's `@polishd/next/telemetry` route,
|
|
14
|
+
* overridable for testing via `POLISHD_TELEMETRY_ENDPOINT`.
|
|
15
|
+
* • The kill switch — `POLISHD_TELEMETRY=off` (or 0/false/no) disables the
|
|
16
|
+
* whole feature, banner included, regardless of stored consent.
|
|
17
|
+
*
|
|
18
|
+
* What gets sent is decided by the emitter (`dashboard/telemetry.tsx`), and is
|
|
19
|
+
* only ever dashboard interaction — never the host site's analytics, never
|
|
20
|
+
* its visitors' events.
|
|
21
|
+
*/
|
|
22
|
+
import { getMeta, setMeta, storeReady } from "./store";
|
|
23
|
+
/**
|
|
24
|
+
* Where telemetry lands: the polishd landing site's own installation. One
|
|
25
|
+
* constant on purpose — when the site moves to a real domain, this is the
|
|
26
|
+
* single line to change.
|
|
27
|
+
*/
|
|
28
|
+
export const DEFAULT_TELEMETRY_ENDPOINT = "https://polishd-lac.vercel.app/api/polishd-telemetry";
|
|
29
|
+
const CONSENT_KEY = "telemetry_consent";
|
|
30
|
+
const INSTALL_ID_KEY = "install_id";
|
|
31
|
+
export function telemetryDisabledByEnv() {
|
|
32
|
+
const v = process.env.POLISHD_TELEMETRY;
|
|
33
|
+
return v !== undefined && /^(0|false|off|no)$/i.test(v.trim());
|
|
34
|
+
}
|
|
35
|
+
export function resolveTelemetryEndpoint() {
|
|
36
|
+
return process.env.POLISHD_TELEMETRY_ENDPOINT || DEFAULT_TELEMETRY_ENDPOINT;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The stable anonymous id of this installation, minted on first use. Returns
|
|
40
|
+
* null when the store can't persist it — an id that changes every restart
|
|
41
|
+
* would be worse than none, inflating the install count on the other end.
|
|
42
|
+
*/
|
|
43
|
+
async function getInstallId() {
|
|
44
|
+
const existing = await getMeta(INSTALL_ID_KEY);
|
|
45
|
+
if (existing)
|
|
46
|
+
return existing;
|
|
47
|
+
const id = crypto.randomUUID();
|
|
48
|
+
return (await setMeta(INSTALL_ID_KEY, id)) ? id : null;
|
|
49
|
+
}
|
|
50
|
+
/** Record the owner's decision. Overwrites any previous one. */
|
|
51
|
+
export async function saveTelemetryConsent(granted) {
|
|
52
|
+
await setMeta(CONSENT_KEY, JSON.stringify({ status: granted ? "granted" : "denied", at: Date.now() }));
|
|
53
|
+
}
|
|
54
|
+
/** What the dashboard should do about telemetry on this render. */
|
|
55
|
+
export async function loadPolishdTelemetryState() {
|
|
56
|
+
const endpoint = resolveTelemetryEndpoint();
|
|
57
|
+
const off = { status: "disabled", installId: null, endpoint };
|
|
58
|
+
if (telemetryDisabledByEnv())
|
|
59
|
+
return off;
|
|
60
|
+
// Without a writable store there is nowhere to keep the answer, so asking
|
|
61
|
+
// would mean asking on every single render. Stay quiet instead.
|
|
62
|
+
if (!(await storeReady()))
|
|
63
|
+
return off;
|
|
64
|
+
const raw = await getMeta(CONSENT_KEY);
|
|
65
|
+
if (!raw)
|
|
66
|
+
return { status: "unset", installId: null, endpoint };
|
|
67
|
+
try {
|
|
68
|
+
const parsed = JSON.parse(raw);
|
|
69
|
+
if (parsed.status === "granted") {
|
|
70
|
+
const installId = await getInstallId();
|
|
71
|
+
return installId
|
|
72
|
+
? { status: "granted", installId, endpoint }
|
|
73
|
+
: off;
|
|
74
|
+
}
|
|
75
|
+
if (parsed.status === "denied")
|
|
76
|
+
return { status: "denied", installId: null, endpoint };
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Unreadable record — treat as never asked rather than silently sending.
|
|
80
|
+
}
|
|
81
|
+
return { status: "unset", installId: null, endpoint };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/server/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,sDAAsD,CAAC;AAEzD,MAAM,WAAW,GAAG,mBAAmB,CAAC;AACxC,MAAM,cAAc,GAAG,YAAY,CAAC;AAmBpC,MAAM,UAAU,sBAAsB;IACpC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACxC,OAAO,CAAC,KAAK,SAAS,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,0BAA0B,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY;IACzB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAC/B,OAAO,CAAC,MAAM,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC;AAED,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAgB;IACzD,MAAM,OAAO,CACX,WAAW,EACX,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAC3E,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,MAAM,QAAQ,GAAG,wBAAwB,EAAE,CAAC;IAC5C,MAAM,GAAG,GAA0B,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrF,IAAI,sBAAsB,EAAE;QAAE,OAAO,GAAG,CAAC;IACzC,0EAA0E;IAC1E,gEAAgE;IAChE,IAAI,CAAC,CAAC,MAAM,UAAU,EAAE,CAAC;QAAE,OAAO,GAAG,CAAC;IAEtC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAChE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACvD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;YACvC,OAAO,SAAS;gBACd,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE;gBAC5C,CAAC,CAAC,GAAG,CAAC;QACV,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;IAC3E,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACxD,CAAC"}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -44,12 +44,28 @@ export interface PolishdIngestBody {
|
|
|
44
44
|
/** Page that produced this batch, for sanity/debugging. */
|
|
45
45
|
page?: string;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* What a telemetry emitter POSTs to a `@polishd/next/telemetry` route.
|
|
49
|
+
*
|
|
50
|
+
* Unlike first-party ingest, identity travels in the body: the session cookie
|
|
51
|
+
* is httpOnly and first-party, so a cross-origin POST arrives without it. Both
|
|
52
|
+
* ids are anonymous and client-minted; the receiving end validates their shape
|
|
53
|
+
* but has no way (and no need) to tie them to anything.
|
|
54
|
+
*/
|
|
55
|
+
export interface PolishdTelemetryBody extends PolishdIngestBody {
|
|
56
|
+
/** Stable, anonymous id of the installation the events came from. */
|
|
57
|
+
installId: string;
|
|
58
|
+
/** Anonymous session id minted by the emitter (no cookie crosses origins). */
|
|
59
|
+
sessionId: string;
|
|
60
|
+
}
|
|
47
61
|
/** A stored event row, as it comes back from the database. */
|
|
48
62
|
export interface PolishdEventRow extends PolishdEvent {
|
|
49
63
|
id: number;
|
|
50
64
|
session_id: string;
|
|
51
65
|
/** Server receive time, ms since epoch — authoritative for retention. */
|
|
52
66
|
received_at: number;
|
|
67
|
+
/** Which installation sent this event. Only set on telemetry-ingested rows. */
|
|
68
|
+
install_id?: string;
|
|
53
69
|
}
|
|
54
70
|
/** The set of event types the client is allowed to send. */
|
|
55
71
|
export declare const CLIENT_EVENT_TYPES: ReadonlySet<PolishdEventType>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,OAAO,GACP,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,UAAU,GACV,UAAU,GACV,WAAW,GACX,OAAO,GACP,gBAAgB,GAChB,OAAO,GACP,aAAa,GACb,aAAa,CAAC;AAElB;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CACzD;AAED,iDAAiD;AACjD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,8DAA8D;AAC9D,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,gBAAgB,CAc3D,CAAC;AASH,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC/E,mBAAmB;AACnB,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAChD,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACjD,yBAAyB;AACzB,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,wBAAwB;IACvC,8BAA8B;IAC9B,CAAC,EAAE,CAAC,CAAC;IACL,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,sDAAsD;IACtD,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,kEAAkE;IAClE,EAAE,EAAE,gBAAgB,EAAE,CAAC;IACvB,mDAAmD;IACnD,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,uDAAuD;IACvD,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,gEAAgE;IAChE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,kEAAkE;IAClE,GAAG,EAAE,cAAc,EAAE,CAAC;CACvB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,OAAO,GACP,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,UAAU,GACV,UAAU,GACV,WAAW,GACX,OAAO,GACP,gBAAgB,GAChB,OAAO,GACP,aAAa,GACb,aAAa,CAAC;AAElB;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CACzD;AAED,iDAAiD;AACjD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8DAA8D;AAC9D,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,gBAAgB,CAc3D,CAAC;AASH,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC/E,mBAAmB;AACnB,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAChD,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACjD,yBAAyB;AACzB,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,wBAAwB;IACvC,8BAA8B;IAC9B,CAAC,EAAE,CAAC,CAAC;IACL,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,sDAAsD;IACtD,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,kEAAkE;IAClE,EAAE,EAAE,gBAAgB,EAAE,CAAC;IACvB,mDAAmD;IACnD,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,uDAAuD;IACvD,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,gEAAgE;IAChE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,kEAAkE;IAClE,GAAG,EAAE,cAAc,EAAE,CAAC;CACvB"}
|
package/dist/shared/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA8EH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAkC,IAAI,GAAG,CAAmB;IACzF,WAAW;IACX,OAAO;IACP,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,UAAU;IACV,UAAU;IACV,WAAW;IACX,OAAO;IACP,gBAAgB;IAChB,OAAO;IACP,aAAa;IACb,aAAa;CACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @polishd/next/telemetry — the cross-install ingest endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Mount this in the app that *collects* telemetry from other polishd
|
|
5
|
+
* installations (for polishd itself, the landing site). It differs from the
|
|
6
|
+
* first-party `@polishd/next/route` in that it accepts POSTs from any origin:
|
|
7
|
+
* remote dashboards live on other people's domains, so the endpoint answers
|
|
8
|
+
* CORS preflights and takes identity from the request body instead of the
|
|
9
|
+
* first-party session cookie (see `ingestTelemetry` for the full contrast).
|
|
10
|
+
*
|
|
11
|
+
* Consumers wire it up with a one-line re-export:
|
|
12
|
+
*
|
|
13
|
+
* // src/app/api/polishd-telemetry/route.ts
|
|
14
|
+
* export { POST, OPTIONS, runtime, dynamic } from "@polishd/next/telemetry";
|
|
15
|
+
*
|
|
16
|
+
* Or build a configured handler:
|
|
17
|
+
*
|
|
18
|
+
* const { POST, OPTIONS } = createPolishdTelemetryRoute({
|
|
19
|
+
* allowedOrigins: ["https://example.com"],
|
|
20
|
+
* });
|
|
21
|
+
*/
|
|
22
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
23
|
+
import { type PolishdConfig } from "./config";
|
|
24
|
+
export declare const runtime = "nodejs";
|
|
25
|
+
export declare const dynamic = "force-dynamic";
|
|
26
|
+
export interface PolishdTelemetryRouteOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Origins allowed to POST telemetry. Omit to accept any origin — the right
|
|
29
|
+
* default here, since dashboards report in from domains that can't be known
|
|
30
|
+
* in advance. The endpoint never uses cookies or credentialed CORS, so a
|
|
31
|
+
* wildcard exposes nothing; an allowlist merely narrows who may write.
|
|
32
|
+
*/
|
|
33
|
+
allowedOrigins?: string[];
|
|
34
|
+
/** Host-app config overrides (only `enabled` matters to this route). */
|
|
35
|
+
config?: Partial<PolishdConfig>;
|
|
36
|
+
}
|
|
37
|
+
export declare function createPolishdTelemetryRoute(options?: PolishdTelemetryRouteOptions): {
|
|
38
|
+
POST: (req: NextRequest) => Promise<NextResponse<import("./server").IngestResult>>;
|
|
39
|
+
OPTIONS: (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
40
|
+
};
|
|
41
|
+
/** Default handlers — used by the one-line re-export. */
|
|
42
|
+
export declare const POST: (req: NextRequest) => Promise<NextResponse<import("./server").IngestResult>>, OPTIONS: (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
43
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAIpE,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,MAAM,WAAW,4BAA4B;IAC3C;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC;AAmBD,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,4BAAiC;gBAmB3D,WAAW;mBAdR,WAAW;EAsCxC;AAED,yDAAyD;AACzD,eAAO,MAAQ,IAAI,QA3BQ,WAAW,6DA2BjB,OAAO,QAzCE,WAAW,mCAyCqB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @polishd/next/telemetry — the cross-install ingest endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Mount this in the app that *collects* telemetry from other polishd
|
|
5
|
+
* installations (for polishd itself, the landing site). It differs from the
|
|
6
|
+
* first-party `@polishd/next/route` in that it accepts POSTs from any origin:
|
|
7
|
+
* remote dashboards live on other people's domains, so the endpoint answers
|
|
8
|
+
* CORS preflights and takes identity from the request body instead of the
|
|
9
|
+
* first-party session cookie (see `ingestTelemetry` for the full contrast).
|
|
10
|
+
*
|
|
11
|
+
* Consumers wire it up with a one-line re-export:
|
|
12
|
+
*
|
|
13
|
+
* // src/app/api/polishd-telemetry/route.ts
|
|
14
|
+
* export { POST, OPTIONS, runtime, dynamic } from "@polishd/next/telemetry";
|
|
15
|
+
*
|
|
16
|
+
* Or build a configured handler:
|
|
17
|
+
*
|
|
18
|
+
* const { POST, OPTIONS } = createPolishdTelemetryRoute({
|
|
19
|
+
* allowedOrigins: ["https://example.com"],
|
|
20
|
+
* });
|
|
21
|
+
*/
|
|
22
|
+
import { NextResponse } from "next/server";
|
|
23
|
+
import { defaultPolishdConfig } from "./config";
|
|
24
|
+
import { ingestTelemetry } from "./server/ingest";
|
|
25
|
+
// node:sqlite / pg need the Node runtime — never the Edge runtime.
|
|
26
|
+
export const runtime = "nodejs";
|
|
27
|
+
// This route mutates per-request; it must never be statically cached.
|
|
28
|
+
export const dynamic = "force-dynamic";
|
|
29
|
+
/**
|
|
30
|
+
* CORS response headers for this request, or null when the origin is
|
|
31
|
+
* disallowed. A request with no Origin header (same-origin, server-to-server)
|
|
32
|
+
* is outside CORS entirely and passes with no headers added.
|
|
33
|
+
*/
|
|
34
|
+
function corsHeaders(origin, allowedOrigins) {
|
|
35
|
+
if (!origin)
|
|
36
|
+
return {};
|
|
37
|
+
if (!allowedOrigins)
|
|
38
|
+
return { "Access-Control-Allow-Origin": "*" };
|
|
39
|
+
if (allowedOrigins.includes(origin)) {
|
|
40
|
+
return { "Access-Control-Allow-Origin": origin, Vary: "Origin" };
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
export function createPolishdTelemetryRoute(options = {}) {
|
|
45
|
+
const { allowedOrigins } = options;
|
|
46
|
+
const cfg = { ...defaultPolishdConfig, ...options.config };
|
|
47
|
+
/** Answers the browser's CORS preflight for the cross-origin POST. */
|
|
48
|
+
async function OPTIONS(req) {
|
|
49
|
+
const cors = corsHeaders(req.headers.get("origin"), allowedOrigins);
|
|
50
|
+
if (!cors)
|
|
51
|
+
return new NextResponse(null, { status: 403 });
|
|
52
|
+
return new NextResponse(null, {
|
|
53
|
+
status: 204,
|
|
54
|
+
headers: {
|
|
55
|
+
...cors,
|
|
56
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
57
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
58
|
+
"Access-Control-Max-Age": "86400",
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function POST(req) {
|
|
63
|
+
const cors = corsHeaders(req.headers.get("origin"), allowedOrigins);
|
|
64
|
+
if (!cors) {
|
|
65
|
+
return NextResponse.json({ ok: false, stored: 0, reason: "origin_not_allowed" }, { status: 403 });
|
|
66
|
+
}
|
|
67
|
+
let body;
|
|
68
|
+
try {
|
|
69
|
+
body = await req.json();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return NextResponse.json({ ok: false, stored: 0, reason: "bad_json" }, { status: 400, headers: cors });
|
|
73
|
+
}
|
|
74
|
+
const result = await ingestTelemetry(body, cfg);
|
|
75
|
+
return NextResponse.json(result, { status: result.ok ? 200 : 400, headers: cors });
|
|
76
|
+
}
|
|
77
|
+
return { POST, OPTIONS };
|
|
78
|
+
}
|
|
79
|
+
/** Default handlers — used by the one-line re-export. */
|
|
80
|
+
export const { POST, OPTIONS } = createPolishdTelemetryRoute();
|
|
81
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polishd/next",
|
|
3
|
-
"version": "0.2.1",
|
|
3
|
+
"version": "0.2.2-dev.1",
|
|
4
4
|
"description": "Drop-in product analytics for Next.js — capture real user behavioral signals (rage/dead clicks, scroll depth, errors, web vitals) and explore them on a built-in dashboard. What gets measured gets improved.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
"types": "./dist/route.d.ts",
|
|
58
58
|
"default": "./dist/route.js"
|
|
59
59
|
},
|
|
60
|
+
"./telemetry": {
|
|
61
|
+
"types": "./dist/telemetry.d.ts",
|
|
62
|
+
"default": "./dist/telemetry.js"
|
|
63
|
+
},
|
|
60
64
|
"./proxy": {
|
|
61
65
|
"types": "./dist/proxy.d.ts",
|
|
62
66
|
"default": "./dist/proxy.js"
|