cursedbelt-server 4.28.0 → 4.29.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/server/metrics/metricsBuffer.d.ts +0 -2
- package/dist/server/metrics/metricsBuffer.js +5 -2
- package/dist/server/metrics/requestPlace.d.ts +8 -0
- package/dist/server/metrics/requestPlace.js +8 -0
- package/dist/server/requestLog/requestMetrics.js +1 -1
- package/dist/server/telemetry.d.ts +1 -1
- package/dist/server/telemetry.js +1 -1
- package/package.json +1 -1
- package/src/server/metrics/metricsBuffer.ts +5 -2
- package/src/server/metrics/requestPlace.ts +9 -0
- package/src/server/requestLog/requestMetrics.ts +1 -1
- package/src/server/telemetry.ts +1 -0
- package/src/server/telemetryIsWorkerSafe.spec.ts +8 -0
|
@@ -27,8 +27,6 @@ export interface MetricRow {
|
|
|
27
27
|
region?: string | null;
|
|
28
28
|
city?: string | null;
|
|
29
29
|
}
|
|
30
|
-
/** The optional place columns, in insert order. Each is written only when the table HAS it. */
|
|
31
|
-
export declare const PLACE_COLUMNS: readonly ["country", "region", "city"];
|
|
32
30
|
export interface MetricsBufferOptions {
|
|
33
31
|
db: Database;
|
|
34
32
|
/** Flush cadence in ms. Default: 1500. */
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { PLACE_COLUMNS } from './requestPlace.js';
|
|
2
|
+
// Every place column is a `MetricRow` field — a column declared in `requestPlace.ts` that this
|
|
3
|
+
// row cannot carry fails to compile here rather than inserting `undefined` for ever.
|
|
4
|
+
const _placeColumnsAreRowFields = PLACE_COLUMNS;
|
|
5
|
+
void _placeColumnsAreRowFields;
|
|
3
6
|
export function createMetricsBuffer(opts) {
|
|
4
7
|
const { db, flushIntervalMs = 1500, maxSize = 5000 } = opts;
|
|
5
8
|
let buffer = [];
|
|
@@ -30,6 +30,14 @@ export interface RequestPlace {
|
|
|
30
30
|
}
|
|
31
31
|
/** Place one request, or `null` when it cannot. Must not throw — but a throw is caught and read as `null`. */
|
|
32
32
|
export type RequestLocator = (request: Request) => RequestPlace | null;
|
|
33
|
+
/**
|
|
34
|
+
* The place columns, in insert order — the ONE declaration every reader and migration uses
|
|
35
|
+
* (`metricsBuffer` writes them, an app's reader allows them, an app's migration adds them).
|
|
36
|
+
* Exported through `cursedbelt-server/telemetry` since 4.29.0 (task 2141): until then it was
|
|
37
|
+
* private to `metricsBuffer.ts`, so flix, station and desk each declared their own copy, and a
|
|
38
|
+
* fourth column added here would have been written by the buffer and dropped by all three.
|
|
39
|
+
*/
|
|
40
|
+
export declare const PLACE_COLUMNS: readonly ["country", "region", "city"];
|
|
33
41
|
/** Each place field is capped so three of them can never crowd the 5120-byte Analytics Engine blob budget. */
|
|
34
42
|
export declare const PLACE_FIELD_MAX_CHARS = 96;
|
|
35
43
|
/**
|
|
@@ -22,6 +22,14 @@
|
|
|
22
22
|
*
|
|
23
23
|
* Worker-safe: no `bun:` import (`telemetryIsWorkerSafe.spec.ts` walks this graph).
|
|
24
24
|
*/
|
|
25
|
+
/**
|
|
26
|
+
* The place columns, in insert order — the ONE declaration every reader and migration uses
|
|
27
|
+
* (`metricsBuffer` writes them, an app's reader allows them, an app's migration adds them).
|
|
28
|
+
* Exported through `cursedbelt-server/telemetry` since 4.29.0 (task 2141): until then it was
|
|
29
|
+
* private to `metricsBuffer.ts`, so flix, station and desk each declared their own copy, and a
|
|
30
|
+
* fourth column added here would have been written by the buffer and dropped by all three.
|
|
31
|
+
*/
|
|
32
|
+
export const PLACE_COLUMNS = ['country', 'region', 'city'];
|
|
25
33
|
/** Each place field is capped so three of them can never crowd the 5120-byte Analytics Engine blob budget. */
|
|
26
34
|
export const PLACE_FIELD_MAX_CHARS = 96;
|
|
27
35
|
/** Cloudflare's "no country could be determined" code — an unknown, not a place. */
|
|
@@ -62,7 +62,7 @@ import { Database } from "bun:sqlite";
|
|
|
62
62
|
import { closeSync, existsSync, mkdirSync, openSync, readSync, renameSync, statSync } from "node:fs";
|
|
63
63
|
import { join } from "node:path";
|
|
64
64
|
import { applyCcPragmas } from "cwip/sqlite";
|
|
65
|
-
import { PLACE_COLUMNS } from "../metrics/
|
|
65
|
+
import { PLACE_COLUMNS } from "../metrics/requestPlace.js";
|
|
66
66
|
import { createTelemetrySink } from "../metrics/telemetrySink.js";
|
|
67
67
|
import { requestLogger } from "../middleware/requestLogger.js";
|
|
68
68
|
import { runMigrations } from "../migration/runner.js";
|
|
@@ -17,4 +17,4 @@
|
|
|
17
17
|
*/
|
|
18
18
|
export { type RequestLoggerOpts, requestLogger } from './middleware/requestLogger.js';
|
|
19
19
|
export { type AnalyticsEngineDataset, createTelemetrySink, TELEMETRY_POINT_VERSION, type TelemetryEvent, type TelemetrySink, type TelemetrySinkOptions, toDataPoint, } from './metrics/telemetrySink.js';
|
|
20
|
-
export { locateFromCloudflare, type RequestLocator, type RequestPlace, } from './metrics/requestPlace.js';
|
|
20
|
+
export { locateFromCloudflare, PLACE_COLUMNS, type RequestLocator, type RequestPlace, } from './metrics/requestPlace.js';
|
package/dist/server/telemetry.js
CHANGED
|
@@ -17,4 +17,4 @@
|
|
|
17
17
|
*/
|
|
18
18
|
export { requestLogger } from './middleware/requestLogger.js';
|
|
19
19
|
export { createTelemetrySink, TELEMETRY_POINT_VERSION, toDataPoint, } from './metrics/telemetrySink.js';
|
|
20
|
-
export { locateFromCloudflare, } from './metrics/requestPlace.js';
|
|
20
|
+
export { locateFromCloudflare, PLACE_COLUMNS, } from './metrics/requestPlace.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt-server",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.29.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The app-facing Bun/Hono server tier of the cursedbelt split — storage, sharing, activity, guard, sync. React-free; cursedbelt-core below it.",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Database } from 'bun:sqlite';
|
|
2
|
+
import { PLACE_COLUMNS } from './requestPlace.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* In-memory, batched writer for `request_metrics`. To keep request latency
|
|
@@ -30,8 +31,10 @@ export interface MetricRow {
|
|
|
30
31
|
city?: string | null;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
// Every place column is a `MetricRow` field — a column declared in `requestPlace.ts` that this
|
|
35
|
+
// row cannot carry fails to compile here rather than inserting `undefined` for ever.
|
|
36
|
+
const _placeColumnsAreRowFields: readonly (keyof MetricRow)[] = PLACE_COLUMNS;
|
|
37
|
+
void _placeColumnsAreRowFields;
|
|
35
38
|
|
|
36
39
|
export interface MetricsBufferOptions {
|
|
37
40
|
db: Database;
|
|
@@ -33,6 +33,15 @@ export interface RequestPlace {
|
|
|
33
33
|
/** Place one request, or `null` when it cannot. Must not throw — but a throw is caught and read as `null`. */
|
|
34
34
|
export type RequestLocator = (request: Request) => RequestPlace | null;
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* The place columns, in insert order — the ONE declaration every reader and migration uses
|
|
38
|
+
* (`metricsBuffer` writes them, an app's reader allows them, an app's migration adds them).
|
|
39
|
+
* Exported through `cursedbelt-server/telemetry` since 4.29.0 (task 2141): until then it was
|
|
40
|
+
* private to `metricsBuffer.ts`, so flix, station and desk each declared their own copy, and a
|
|
41
|
+
* fourth column added here would have been written by the buffer and dropped by all three.
|
|
42
|
+
*/
|
|
43
|
+
export const PLACE_COLUMNS = ['country', 'region', 'city'] as const;
|
|
44
|
+
|
|
36
45
|
/** Each place field is capped so three of them can never crowd the 5120-byte Analytics Engine blob budget. */
|
|
37
46
|
export const PLACE_FIELD_MAX_CHARS = 96;
|
|
38
47
|
|
|
@@ -63,7 +63,7 @@ import { closeSync, existsSync, mkdirSync, openSync, readSync, renameSync, statS
|
|
|
63
63
|
import { join } from "node:path";
|
|
64
64
|
import { applyCcPragmas } from "cwip/sqlite";
|
|
65
65
|
import type { MiddlewareHandler } from "hono";
|
|
66
|
-
import { PLACE_COLUMNS } from "../metrics/
|
|
66
|
+
import { PLACE_COLUMNS } from "../metrics/requestPlace.js";
|
|
67
67
|
import type { RequestLocator } from "../metrics/requestPlace.js";
|
|
68
68
|
import { createTelemetrySink, type TelemetrySink } from "../metrics/telemetrySink.js";
|
|
69
69
|
import { requestLogger } from "../middleware/requestLogger.js";
|
package/src/server/telemetry.ts
CHANGED
|
@@ -88,6 +88,14 @@ describe('cursedbelt-server/telemetry', () => {
|
|
|
88
88
|
const found = [..."import { Database } from 'bun:sqlite';\nimport type { X } from 'bun:sqlite';".matchAll(regex)].map((m) => m[1]);
|
|
89
89
|
expect(found).toEqual(['bun:sqlite']);
|
|
90
90
|
});
|
|
91
|
+
|
|
92
|
+
test('publishes PLACE_COLUMNS — the one declaration the buffer writes and every app reads (task 2141)', async () => {
|
|
93
|
+
const telemetry = await import('./telemetry.ts');
|
|
94
|
+
expect(telemetry.PLACE_COLUMNS).toEqual(['country', 'region', 'city']);
|
|
95
|
+
// The same array the Bun buffer inserts from, not a second copy of it.
|
|
96
|
+
const { PLACE_COLUMNS } = await import('./metrics/requestPlace.ts');
|
|
97
|
+
expect(telemetry.PLACE_COLUMNS).toBe(PLACE_COLUMNS);
|
|
98
|
+
});
|
|
91
99
|
});
|
|
92
100
|
|
|
93
101
|
describe('🔴 cursedbelt-server/engagement/d1 — a Worker mounts it (task 2096)', () => {
|