@uptimizr/db 0.1.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 (93) hide show
  1. package/AGENTS.md +109 -0
  2. package/LICENSE +201 -0
  3. package/README.md +89 -0
  4. package/dist/cli/createProject.d.ts +3 -0
  5. package/dist/cli/createProject.d.ts.map +1 -0
  6. package/dist/cli/createProject.js +41 -0
  7. package/dist/cli/createProject.js.map +1 -0
  8. package/dist/cli/migrate.d.ts +3 -0
  9. package/dist/cli/migrate.d.ts.map +1 -0
  10. package/dist/cli/migrate.js +21 -0
  11. package/dist/cli/migrate.js.map +1 -0
  12. package/dist/cli/seed.d.ts +2 -0
  13. package/dist/cli/seed.d.ts.map +1 -0
  14. package/dist/cli/seed.js +175 -0
  15. package/dist/cli/seed.js.map +1 -0
  16. package/dist/duckdb/client.d.ts +42 -0
  17. package/dist/duckdb/client.d.ts.map +1 -0
  18. package/dist/duckdb/client.js +93 -0
  19. package/dist/duckdb/client.js.map +1 -0
  20. package/dist/duckdb/events.d.ts +44 -0
  21. package/dist/duckdb/events.d.ts.map +1 -0
  22. package/dist/duckdb/events.js +225 -0
  23. package/dist/duckdb/events.js.map +1 -0
  24. package/dist/duckdb/migrations.d.ts +20 -0
  25. package/dist/duckdb/migrations.d.ts.map +1 -0
  26. package/dist/duckdb/migrations.js +323 -0
  27. package/dist/duckdb/migrations.js.map +1 -0
  28. package/dist/duckdb/projects.d.ts +23 -0
  29. package/dist/duckdb/projects.d.ts.map +1 -0
  30. package/dist/duckdb/projects.js +55 -0
  31. package/dist/duckdb/projects.js.map +1 -0
  32. package/dist/duckdb/queries.d.ts +10 -0
  33. package/dist/duckdb/queries.d.ts.map +1 -0
  34. package/dist/duckdb/queries.js +10 -0
  35. package/dist/duckdb/queries.js.map +1 -0
  36. package/dist/duckdb/sceneRegistry.d.ts +15 -0
  37. package/dist/duckdb/sceneRegistry.d.ts.map +1 -0
  38. package/dist/duckdb/sceneRegistry.js +98 -0
  39. package/dist/duckdb/sceneRegistry.js.map +1 -0
  40. package/dist/env.d.ts +25 -0
  41. package/dist/env.d.ts.map +1 -0
  42. package/dist/env.js +55 -0
  43. package/dist/env.js.map +1 -0
  44. package/dist/events.d.ts +107 -0
  45. package/dist/events.d.ts.map +1 -0
  46. package/dist/events.js +153 -0
  47. package/dist/events.js.map +1 -0
  48. package/dist/index.d.ts +36 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +34 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/metadata.d.ts +84 -0
  53. package/dist/metadata.d.ts.map +1 -0
  54. package/dist/metadata.js +23 -0
  55. package/dist/metadata.js.map +1 -0
  56. package/dist/parity/cases.d.ts +31 -0
  57. package/dist/parity/cases.d.ts.map +1 -0
  58. package/dist/parity/cases.js +524 -0
  59. package/dist/parity/cases.js.map +1 -0
  60. package/dist/parity/compare.d.ts +47 -0
  61. package/dist/parity/compare.d.ts.map +1 -0
  62. package/dist/parity/compare.js +90 -0
  63. package/dist/parity/compare.js.map +1 -0
  64. package/dist/parity/fixtures.d.ts +45 -0
  65. package/dist/parity/fixtures.d.ts.map +1 -0
  66. package/dist/parity/fixtures.js +157 -0
  67. package/dist/parity/fixtures.js.map +1 -0
  68. package/dist/parity/index.d.ts +12 -0
  69. package/dist/parity/index.d.ts.map +1 -0
  70. package/dist/parity/index.js +12 -0
  71. package/dist/parity/index.js.map +1 -0
  72. package/dist/query/aggregations.d.ts +393 -0
  73. package/dist/query/aggregations.d.ts.map +1 -0
  74. package/dist/query/aggregations.js +1412 -0
  75. package/dist/query/aggregations.js.map +1 -0
  76. package/dist/query/dialect.d.ts +100 -0
  77. package/dist/query/dialect.d.ts.map +1 -0
  78. package/dist/query/dialect.js +88 -0
  79. package/dist/query/dialect.js.map +1 -0
  80. package/dist/query/duckdbDialect.d.ts +27 -0
  81. package/dist/query/duckdbDialect.d.ts.map +1 -0
  82. package/dist/query/duckdbDialect.js +83 -0
  83. package/dist/query/duckdbDialect.js.map +1 -0
  84. package/dist/query/index.d.ts +22 -0
  85. package/dist/query/index.d.ts.map +1 -0
  86. package/dist/query/index.js +30 -0
  87. package/dist/query/index.js.map +1 -0
  88. package/dist/query/types.d.ts +388 -0
  89. package/dist/query/types.d.ts.map +1 -0
  90. package/dist/query/types.js +11 -0
  91. package/dist/query/types.js.map +1 -0
  92. package/llms.txt +21 -0
  93. package/package.json +71 -0
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Tolerance-aware row comparison for cross-engine parity (Phase C, ADR 0020).
3
+ *
4
+ * Two SQL engines (DuckDB for OSS, ClickHouse for the scale tier)
5
+ * implement the same dialect-agnostic aggregations. Their numeric output can
6
+ * differ in the last bits of floating-point arithmetic and their row order is
7
+ * only as stable as the query's `ORDER BY`. This module encodes the tolerance
8
+ * rules that let "equal analytics" be asserted despite those differences.
9
+ *
10
+ * ## Tolerance rules
11
+ *
12
+ * 1. **Order-insensitive.** Rows are compared as a multiset: both sides are
13
+ * sorted by the case's `sortKeys` before comparison. SQL guarantees no row
14
+ * order beyond an explicit `ORDER BY`, and ties under `ORDER BY count` are
15
+ * unstable across engines.
16
+ * 2. **Float tolerance.** Numeric columns (averages, quantiles, ASOF ray
17
+ * origins/hits) match when their absolute difference is within
18
+ * {@link PARITY_ABS_TOLERANCE} or their relative difference is within
19
+ * {@link PARITY_REL_TOLERANCE}. Counts and bin indices are integers and so
20
+ * compare exactly under the same rule (difference 0).
21
+ * 3. **Bin indices are integer-exact.** Heatmap bin columns come from
22
+ * `floor(...)` and are deterministic within an engine; they are integers and
23
+ * compared exactly. Inputs are chosen to avoid landing exactly on a bin
24
+ * boundary, where a sub-ulp difference could flip the floor across engines.
25
+ * 4. **Temporal projections are excluded.** Wall-clock `TIMESTAMP` columns
26
+ * (e.g. `started_at`, `ended_at`, `last_seen`) are presentation metadata, not
27
+ * analytics, and their string rendering differs by engine; list them in a
28
+ * case's `ignoreColumns`. Date-granular `day` strings (`YYYY-MM-DD`) render
29
+ * identically in both engines and are compared.
30
+ */
31
+ /** Absolute tolerance for floating-point column comparison. */
32
+ export const PARITY_ABS_TOLERANCE = 1e-6;
33
+ /** Relative tolerance for floating-point column comparison. */
34
+ export const PARITY_REL_TOLERANCE = 1e-9;
35
+ function numbersClose(a, b) {
36
+ const diff = Math.abs(a - b);
37
+ if (diff <= PARITY_ABS_TOLERANCE)
38
+ return true;
39
+ const scale = Math.max(Math.abs(a), Math.abs(b));
40
+ return diff <= scale * PARITY_REL_TOLERANCE;
41
+ }
42
+ function sortKey(row, keys) {
43
+ return JSON.stringify(keys.map((k) => row[k] ?? null));
44
+ }
45
+ function sortRows(rows, keys) {
46
+ return [...rows].sort((a, b) => {
47
+ const ka = sortKey(a, keys);
48
+ const kb = sortKey(b, keys);
49
+ return ka < kb ? -1 : ka > kb ? 1 : 0;
50
+ });
51
+ }
52
+ function cellsEqual(actual, expected) {
53
+ if (typeof expected === "number" && typeof actual === "number") {
54
+ return numbersClose(actual, expected);
55
+ }
56
+ // DuckDB returns numerics as JS numbers; guard against string/number drift.
57
+ if (typeof expected === "number" && typeof actual === "string") {
58
+ const n = Number(actual);
59
+ return !Number.isNaN(n) && numbersClose(n, expected);
60
+ }
61
+ return Object.is(actual, expected);
62
+ }
63
+ /**
64
+ * Compare engine output against golden rows under the tolerance rules above.
65
+ * Returns a list of human-readable differences; an empty list means parity.
66
+ */
67
+ export function diffParity(actual, golden, options) {
68
+ const errors = [];
69
+ const ignore = new Set(options.ignoreColumns ?? []);
70
+ if (actual.length !== golden.length) {
71
+ errors.push(`row count: expected ${golden.length}, got ${actual.length}`);
72
+ return errors;
73
+ }
74
+ const sortedActual = sortRows(actual, options.sortKeys);
75
+ const sortedGolden = sortRows(golden, options.sortKeys);
76
+ for (let i = 0; i < sortedGolden.length; i++) {
77
+ const exp = sortedGolden[i];
78
+ const act = sortedActual[i];
79
+ for (const col of Object.keys(exp)) {
80
+ if (ignore.has(col))
81
+ continue;
82
+ if (!cellsEqual(act[col], exp[col])) {
83
+ errors.push(`row ${i} column "${col}": expected ${JSON.stringify(exp[col])}, ` +
84
+ `got ${JSON.stringify(act[col])}`);
85
+ }
86
+ }
87
+ }
88
+ return errors;
89
+ }
90
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/parity/compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Shared cross-engine parity fixtures (Phase C, ADR 0020).
3
+ *
4
+ * A single deterministic event set that exercises every analytics aggregation —
5
+ * 2D/3D heatmaps, the camera-direction (gaze) heatmap, the ASOF click↔gaze ray
6
+ * and flow joins, quantile-based perf, the daily rollups, and the scene/session
7
+ * dimensions. The same fixtures and golden outputs are reused by:
8
+ *
9
+ * - the OSS DuckDB-vs-golden suite (`src/__tests__/duckdbParity.test.ts`), and
10
+ * - the DuckDB-vs-ClickHouse cross-engine suite (per ADR 0020, the
11
+ * cross-engine half lives in the separately-licensed scale tier).
12
+ *
13
+ * Values are chosen so each aggregation produces more than one group and the
14
+ * arithmetic is hand-verifiable (see the golden in `cases.ts`).
15
+ */
16
+ import type { AnyEvent } from "@uptimizr/schema";
17
+ /** Project all parity fixtures belong to. */
18
+ export declare const PARITY_PROJECT_ID = "parity-project";
19
+ /** Base timestamp: a whole-minute boundary so the 60 s time bucket is exact. */
20
+ export declare const PARITY_T0: number;
21
+ /** Tight window covering every fixture event (spans T0 .. T0 + 14 s). */
22
+ export declare const PARITY_RANGE: {
23
+ since: number;
24
+ until: number;
25
+ };
26
+ /**
27
+ * Day-granular window for the daily rollups. The upper bound is exclusive at
28
+ * date granularity in both engines, so span a full day on either side.
29
+ */
30
+ export declare const PARITY_DAY_RANGE: {
31
+ since: number;
32
+ until: number;
33
+ };
34
+ /** The calendar day every fixture event lands on (UTC). */
35
+ export declare const PARITY_DAY = "2024-06-16";
36
+ /**
37
+ * Two sessions across two scenes.
38
+ *
39
+ * Session `s1` (scene `lobby`): two camera samples and two clicks that ASOF-join
40
+ * to distinct preceding samples, plus two perf samples.
41
+ * Session `s2` (scene `arena`): one camera sample, a move + click on the same
42
+ * mesh, and one perf sample.
43
+ */
44
+ export declare const PARITY_EVENTS: AnyEvent[];
45
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/parity/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,6CAA6C;AAC7C,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAElD,gFAAgF;AAChF,eAAO,MAAM,SAAS,QAAkC,CAAC;AAEzD,yEAAyE;AACzE,eAAO,MAAM,YAAY;;;CAGxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;CAG5B,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,UAAU,eAAe,CAAC;AAcvC;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,QAAQ,EAuGnC,CAAC"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Shared cross-engine parity fixtures (Phase C, ADR 0020).
3
+ *
4
+ * A single deterministic event set that exercises every analytics aggregation —
5
+ * 2D/3D heatmaps, the camera-direction (gaze) heatmap, the ASOF click↔gaze ray
6
+ * and flow joins, quantile-based perf, the daily rollups, and the scene/session
7
+ * dimensions. The same fixtures and golden outputs are reused by:
8
+ *
9
+ * - the OSS DuckDB-vs-golden suite (`src/__tests__/duckdbParity.test.ts`), and
10
+ * - the DuckDB-vs-ClickHouse cross-engine suite (per ADR 0020, the
11
+ * cross-engine half lives in the separately-licensed scale tier).
12
+ *
13
+ * Values are chosen so each aggregation produces more than one group and the
14
+ * arithmetic is hand-verifiable (see the golden in `cases.ts`).
15
+ */
16
+ /** Project all parity fixtures belong to. */
17
+ export const PARITY_PROJECT_ID = "parity-project";
18
+ /** Base timestamp: a whole-minute boundary so the 60 s time bucket is exact. */
19
+ export const PARITY_T0 = Date.UTC(2024, 5, 16, 10, 0, 0);
20
+ /** Tight window covering every fixture event (spans T0 .. T0 + 14 s). */
21
+ export const PARITY_RANGE = {
22
+ since: PARITY_T0 - 60_000,
23
+ until: PARITY_T0 + 60_000,
24
+ };
25
+ /**
26
+ * Day-granular window for the daily rollups. The upper bound is exclusive at
27
+ * date granularity in both engines, so span a full day on either side.
28
+ */
29
+ export const PARITY_DAY_RANGE = {
30
+ since: PARITY_T0 - 86_400_000,
31
+ until: PARITY_T0 + 86_400_000,
32
+ };
33
+ /** The calendar day every fixture event lands on (UTC). */
34
+ export const PARITY_DAY = "2024-06-16";
35
+ function ev(type, ts, extra = {}) {
36
+ return {
37
+ type,
38
+ projectId: PARITY_PROJECT_ID,
39
+ sessionId: "s1",
40
+ ts,
41
+ sdkVersion: "0.1.0",
42
+ sceneId: "lobby",
43
+ ...extra,
44
+ };
45
+ }
46
+ /**
47
+ * Two sessions across two scenes.
48
+ *
49
+ * Session `s1` (scene `lobby`): two camera samples and two clicks that ASOF-join
50
+ * to distinct preceding samples, plus two perf samples.
51
+ * Session `s2` (scene `arena`): one camera sample, a move + click on the same
52
+ * mesh, and one perf sample.
53
+ */
54
+ export const PARITY_EVENTS = [
55
+ // --- session s1 / scene lobby ---
56
+ ev("session_start", PARITY_T0, {
57
+ scene: { cameraType: "arc-rotate", cameraName: "cam", meshCount: 3 },
58
+ user: { id: "anon-1" },
59
+ device: { engine: "webgpu" },
60
+ }),
61
+ ev("camera_sample", PARITY_T0 + 1_000, {
62
+ position: [0, 0, 0],
63
+ direction: [2, 1, 2],
64
+ hitPoint: [0.2, 0.2, 0.2],
65
+ }),
66
+ ev("pointer_click", PARITY_T0 + 2_000, {
67
+ screen: [0.15, 0.15],
68
+ hitPoint: [0.2, 0.2, 0.2],
69
+ hitMesh: "box",
70
+ button: 0,
71
+ source: "mouse",
72
+ }),
73
+ ev("camera_sample", PARITY_T0 + 3_000, {
74
+ position: [10, 0, 0],
75
+ direction: [1, 3, -2],
76
+ hitPoint: [5, 5, 5],
77
+ }),
78
+ ev("pointer_click", PARITY_T0 + 4_000, {
79
+ screen: [0.95, 0.95],
80
+ hitPoint: [5, 5, 5],
81
+ hitMesh: "sphere",
82
+ button: 0,
83
+ source: "mouse",
84
+ }),
85
+ ev("frame_perf", PARITY_T0 + 5_000, {
86
+ fps: 60,
87
+ frameTimeMs: 16,
88
+ frameTimeP95Ms: 20,
89
+ longFrames: 1,
90
+ dpr: 2,
91
+ renderScale: 1,
92
+ }),
93
+ ev("frame_perf", PARITY_T0 + 6_000, {
94
+ fps: 30,
95
+ frameTimeMs: 33,
96
+ frameTimeP95Ms: 40,
97
+ longFrames: 5,
98
+ dpr: 2,
99
+ renderScale: 0.8,
100
+ }),
101
+ // Two bucketed mesh_visibility summaries (#37): dwell on "box" and "sphere".
102
+ ev("mesh_visibility", PARITY_T0 + 7_000, {
103
+ mesh: "box",
104
+ visibleMs: 4000,
105
+ centeredMs: 1500,
106
+ maxScreenFraction: 0.4,
107
+ }),
108
+ ev("mesh_visibility", PARITY_T0 + 8_000, {
109
+ mesh: "sphere",
110
+ visibleMs: 2000,
111
+ centeredMs: 800,
112
+ maxScreenFraction: 0.7,
113
+ }),
114
+ // --- session s2 / scene arena ---
115
+ ev("session_start", PARITY_T0 + 10_000, {
116
+ sessionId: "s2",
117
+ sceneId: "arena",
118
+ scene: { cameraType: "free", cameraName: "cam2", meshCount: 5 },
119
+ user: { id: "anon-2" },
120
+ device: { engine: "webgl2" },
121
+ }),
122
+ ev("camera_sample", PARITY_T0 + 11_000, {
123
+ sessionId: "s2",
124
+ sceneId: "arena",
125
+ position: [0, 0, 0],
126
+ direction: [-2, -1, 1],
127
+ hitPoint: [1, 1, 1],
128
+ }),
129
+ ev("pointer_move", PARITY_T0 + 12_000, {
130
+ sessionId: "s2",
131
+ sceneId: "arena",
132
+ screen: [0.55, 0.55],
133
+ hitPoint: [1, 1, 1],
134
+ hitMesh: "floor",
135
+ source: "mouse",
136
+ }),
137
+ ev("pointer_click", PARITY_T0 + 13_000, {
138
+ sessionId: "s2",
139
+ sceneId: "arena",
140
+ screen: [0.55, 0.55],
141
+ hitPoint: [1, 1, 1],
142
+ hitMesh: "floor",
143
+ button: 2,
144
+ source: "mouse",
145
+ }),
146
+ ev("frame_perf", PARITY_T0 + 14_000, {
147
+ sessionId: "s2",
148
+ sceneId: "arena",
149
+ fps: 45,
150
+ frameTimeMs: 22,
151
+ frameTimeP95Ms: 28,
152
+ longFrames: 2,
153
+ dpr: 1,
154
+ renderScale: 1,
155
+ }),
156
+ ];
157
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/parity/fixtures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Cross-engine analytics parity harness (Phase C, ADR 0020).
3
+ *
4
+ * Shared fixtures, golden expectations, and a tolerance-aware comparator so the
5
+ * same aggregation builders can be proven equal across SQL engines. The OSS
6
+ * package ships the DuckDB-vs-golden suite; the scale-tier side reuses these exports
7
+ * to run DuckDB-vs-ClickHouse.
8
+ */
9
+ export * from "./fixtures.js";
10
+ export * from "./compare.js";
11
+ export * from "./cases.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parity/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Cross-engine analytics parity harness (Phase C, ADR 0020).
3
+ *
4
+ * Shared fixtures, golden expectations, and a tolerance-aware comparator so the
5
+ * same aggregation builders can be proven equal across SQL engines. The OSS
6
+ * package ships the DuckDB-vs-golden suite; the scale-tier side reuses these exports
7
+ * to run DuckDB-vs-ClickHouse.
8
+ */
9
+ export * from "./fixtures.js";
10
+ export * from "./compare.js";
11
+ export * from "./cases.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parity/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}