@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
package/dist/env.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Connection settings for the OSS DuckDB store, read from the environment
3
+ * (ADR 0020).
4
+ *
5
+ * Names mirror `.env.example`. Everything has a local-dev default so the package
6
+ * is usable out of the box (a single persisted `.duckdb` file).
7
+ */
8
+ import { existsSync } from "node:fs";
9
+ import { dirname, join } from "node:path";
10
+ function bool(value, fallback) {
11
+ if (value == null)
12
+ return fallback;
13
+ return value === "1" || value.toLowerCase() === "true";
14
+ }
15
+ /**
16
+ * Walk up from `start` until a directory containing `pnpm-workspace.yaml` is
17
+ * found, i.e. the monorepo root. Returns `undefined` if none exists.
18
+ */
19
+ function findRepoRoot(start) {
20
+ let dir = start;
21
+ for (;;) {
22
+ if (existsSync(join(dir, "pnpm-workspace.yaml")))
23
+ return dir;
24
+ const parent = dirname(dir);
25
+ if (parent === dir)
26
+ return undefined;
27
+ dir = parent;
28
+ }
29
+ }
30
+ /**
31
+ * The default DuckDB file location when `DUCKDB_PATH` is unset.
32
+ *
33
+ * Resolved against the **repo root** (not the process cwd) so every tool — the
34
+ * collector server, the migrate/seed/new-project CLIs — converges on one
35
+ * canonical store no matter which package directory it runs from. Falls back to
36
+ * the cwd-relative path only when the repo root can't be located (e.g. when the
37
+ * package is consumed outside the monorepo).
38
+ */
39
+ function defaultDuckdbPath() {
40
+ const root = findRepoRoot(process.cwd());
41
+ return root ? join(root, "data", "uptimizr.duckdb") : "./data/uptimizr.duckdb";
42
+ }
43
+ /**
44
+ * Build {@link DbSettings} from an env-like record (defaults to `process.env`).
45
+ * Passing an explicit record keeps this pure and testable.
46
+ */
47
+ export function readDbSettings(env = process.env) {
48
+ return {
49
+ duckdb: {
50
+ path: env.DUCKDB_PATH ?? defaultDuckdbPath(),
51
+ },
52
+ enableRawSessionRetention: bool(env.ENABLE_RAW_SESSION_RETENTION, false),
53
+ };
54
+ }
55
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAgB1C,SAAS,IAAI,CAAC,KAAyB,EAAE,QAAiB;IACxD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,QAAQ,CAAC;IACnC,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAW,OAAO,CAAC,GAAG;IACnD,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,GAAG,CAAC,WAAW,IAAI,iBAAiB,EAAE;SAC7C;QACD,yBAAyB,EAAE,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC;KACzE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Engine-neutral event-row mapping (ADR 0020).
3
+ *
4
+ * `toEventRow` flattens a validated event into the wide column set both storage
5
+ * engines share — DuckDB (OSS) and the single-tenant ClickHouse adapter (scale
6
+ * tier). Keeping it here, free of any engine client, lets both stores
7
+ * reuse one mapping and lets OSS carry zero ClickHouse references.
8
+ */
9
+ import { type AnyEvent, type Device, type NodeTransformEvent, type SceneMeta, type SessionUser } from "@uptimizr/schema";
10
+ /** Flat row matching the wide `events` table columns (engine-independent). */
11
+ export interface EventRow {
12
+ project_id: string;
13
+ session_id: string;
14
+ visitor_id: string;
15
+ event_type: string;
16
+ ts: string;
17
+ sdk_version: string;
18
+ url: string;
19
+ scene_id: string;
20
+ source: string;
21
+ handedness: string;
22
+ source_id: string;
23
+ ray_origin: number[];
24
+ ray_direction: number[];
25
+ position: number[];
26
+ direction: number[];
27
+ hit_point: number[];
28
+ screen: number[];
29
+ mesh: string;
30
+ fps: number;
31
+ visible_ms: number;
32
+ centered_ms: number;
33
+ screen_fraction: number;
34
+ texture_bytes: number;
35
+ geometry_bytes: number;
36
+ triangles: number;
37
+ vertices: number;
38
+ js_heap_bytes: number;
39
+ cap_from: string;
40
+ cap_to: string;
41
+ frame_time_ms: number;
42
+ frame_time_p95_ms: number;
43
+ long_frames: number;
44
+ dpr: number;
45
+ render_scale: number;
46
+ name: string;
47
+ payload: string;
48
+ }
49
+ /**
50
+ * Format an epoch-millisecond timestamp as a naive-UTC `YYYY-MM-DD HH:MM:SS.mmm`
51
+ * literal. This is the timestamp form both engines accept (ClickHouse
52
+ * `DateTime64(3)` and DuckDB `TIMESTAMP`), avoiding seconds/millis ambiguity.
53
+ */
54
+ export declare function formatUtcTimestamp(epochMs: number): string;
55
+ /**
56
+ * Map a validated event into a flat row. Hot, queryable fields are promoted into
57
+ * dedicated columns for aggregation; the full event is preserved in `payload`
58
+ * (JSON) so reads remain replay-complete regardless of extraction.
59
+ */
60
+ export declare function toEventRow(event: AnyEvent): EventRow;
61
+ /** Per-session descriptor extracted from the session's `session_start` event. */
62
+ export interface SessionMeta {
63
+ sessionId: string;
64
+ /** Session start time as a naive-UTC `YYYY-MM-DD HH:MM:SS.mmm` string, if known. */
65
+ startedAt: string | undefined;
66
+ device: Device | undefined;
67
+ scene: SceneMeta | undefined;
68
+ user: SessionUser | undefined;
69
+ }
70
+ /**
71
+ * Flat row matching the dedicated `node_samples` table (ADR 0027 §9). The
72
+ * `node_transform` event is split out of the wide `events` table: it is the
73
+ * highest-cardinality signal in the system, so it gets its own transform-shaped
74
+ * storage instead of padding `events` with quaternion/bone columns that are null
75
+ * for every other type. `bone_id` is `''` for the Tier-1 node/root tier; `scale`
76
+ * is `[]` when the sample omitted it (unchanged from identity / last sample).
77
+ * `child_path` (ADR 0033) is `''` for the declared root and for bone rows; it is
78
+ * the descendant's path relative to `node_id` for a Tier-1 subtree child.
79
+ */
80
+ export interface NodeSampleRow {
81
+ project_id: string;
82
+ session_id: string;
83
+ ts: string;
84
+ sdk_version: string;
85
+ scene_id: string;
86
+ node_id: string;
87
+ bone_id: string;
88
+ child_path: string;
89
+ position: number[];
90
+ rotation: number[];
91
+ scale: number[];
92
+ }
93
+ /** Map a validated `node_transform` event into a flat {@link NodeSampleRow}. */
94
+ export declare function toNodeSampleRow(event: NodeTransformEvent): NodeSampleRow;
95
+ /**
96
+ * Reconstruct a replay-complete `node_transform` event from a stored
97
+ * {@link NodeSampleRow}. The dedicated table keeps only the transform-shaped
98
+ * columns, so this rehydrates the schema event for the replay merge (ADR 0027
99
+ * §8). `tsEpochMs` is the row's `ts` already converted back to epoch ms by the
100
+ * caller (engine-specific timestamp decoding stays in the store).
101
+ */
102
+ export declare function nodeSampleRowToEvent(row: Pick<NodeSampleRow, "project_id" | "session_id" | "sdk_version" | "scene_id" | "node_id" | "bone_id" | "child_path"> & {
103
+ position: number[];
104
+ rotation: number[];
105
+ scale: number[];
106
+ }, tsEpochMs: number): NodeTransformEvent;
107
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
package/dist/events.js ADDED
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Engine-neutral event-row mapping (ADR 0020).
3
+ *
4
+ * `toEventRow` flattens a validated event into the wide column set both storage
5
+ * engines share — DuckDB (OSS) and the single-tenant ClickHouse adapter (scale
6
+ * tier). Keeping it here, free of any engine client, lets both stores
7
+ * reuse one mapping and lets OSS carry zero ClickHouse references.
8
+ */
9
+ import { DEFAULT_SCENE_ID, } from "@uptimizr/schema";
10
+ /**
11
+ * Format an epoch-millisecond timestamp as a naive-UTC `YYYY-MM-DD HH:MM:SS.mmm`
12
+ * literal. This is the timestamp form both engines accept (ClickHouse
13
+ * `DateTime64(3)` and DuckDB `TIMESTAMP`), avoiding seconds/millis ambiguity.
14
+ */
15
+ export function formatUtcTimestamp(epochMs) {
16
+ const d = new Date(epochMs);
17
+ const p = (n, w = 2) => String(n).padStart(w, "0");
18
+ return (`${d.getUTCFullYear()}-${p(d.getUTCMonth() + 1)}-${p(d.getUTCDate())} ` +
19
+ `${p(d.getUTCHours())}:${p(d.getUTCMinutes())}:${p(d.getUTCSeconds())}.${p(d.getUTCMilliseconds(), 3)}`);
20
+ }
21
+ function vec(value) {
22
+ return Array.isArray(value) && value.every((n) => typeof n === "number")
23
+ ? value
24
+ : [];
25
+ }
26
+ /**
27
+ * Map a validated event into a flat row. Hot, queryable fields are promoted into
28
+ * dedicated columns for aggregation; the full event is preserved in `payload`
29
+ * (JSON) so reads remain replay-complete regardless of extraction.
30
+ */
31
+ export function toEventRow(event) {
32
+ // The discriminated union widens awkwardly across payload variants; read
33
+ // optional fields through a permissive view without losing the validated input.
34
+ const e = event;
35
+ const hitPoint = vec(e.hitPoint).length ? vec(e.hitPoint) : vec(e.point);
36
+ const mesh = typeof e.mesh === "string" ? e.mesh : typeof e.hitMesh === "string" ? e.hitMesh : "";
37
+ // `name` carries the custom-event name / asset name, and is reused as the coarse
38
+ // `phase` label for compile_stall (#42) and the `kind` label for
39
+ // capability_change (#49) so those rollups can group without a dedicated column.
40
+ const name = typeof e.name === "string"
41
+ ? e.name
42
+ : typeof e.phase === "string"
43
+ ? e.phase
44
+ : typeof e.kind === "string"
45
+ ? e.kind
46
+ : "";
47
+ const ray = (e.ray ?? {});
48
+ return {
49
+ project_id: event.projectId,
50
+ session_id: event.sessionId,
51
+ visitor_id: event.visitorId ?? "",
52
+ event_type: event.type,
53
+ ts: formatUtcTimestamp(event.ts),
54
+ sdk_version: event.sdkVersion,
55
+ url: event.url ?? "",
56
+ scene_id: typeof e.sceneId === "string" && e.sceneId.length > 0 ? e.sceneId : DEFAULT_SCENE_ID,
57
+ source: typeof e.source === "string" && e.source.length > 0 ? e.source : "mouse",
58
+ handedness: typeof e.handedness === "string" ? e.handedness : "",
59
+ source_id: typeof e.sourceId === "string" ? e.sourceId : "",
60
+ ray_origin: vec(ray.origin),
61
+ ray_direction: vec(ray.direction),
62
+ position: vec(e.position),
63
+ direction: vec(e.direction),
64
+ hit_point: hitPoint,
65
+ screen: vec(e.screen),
66
+ mesh,
67
+ fps: typeof e.fps === "number" ? e.fps : 0,
68
+ // mesh_visibility dwell metrics (#37): promoted for the object-attention
69
+ // aggregation; 0 on every other event type (the full event stays in payload).
70
+ // hover_dwell (#48) reuses this column for its `dwellMs` duration, and
71
+ // compile_stall (#42) reuses it for its `durationMs` — all are millisecond
72
+ // durations, so no extra column/migration is needed.
73
+ visible_ms: typeof e.visibleMs === "number"
74
+ ? e.visibleMs
75
+ : typeof e.dwellMs === "number"
76
+ ? e.dwellMs
77
+ : typeof e.durationMs === "number"
78
+ ? e.durationMs
79
+ : 0,
80
+ centered_ms: typeof e.centeredMs === "number" ? e.centeredMs : 0,
81
+ screen_fraction: typeof e.maxScreenFraction === "number" ? e.maxScreenFraction : 0,
82
+ // resource_sample (#44) GPU / memory footprint metrics; 0 on other event
83
+ // types (the full event stays in payload). Every field is optional on the
84
+ // event, so undefined maps to 0 (NULL-equivalent for SUM/AVG/MAX).
85
+ texture_bytes: typeof e.textureBytes === "number" ? e.textureBytes : 0,
86
+ geometry_bytes: typeof e.geometryBytes === "number" ? e.geometryBytes : 0,
87
+ triangles: typeof e.triangles === "number" ? e.triangles : 0,
88
+ vertices: typeof e.vertices === "number" ? e.vertices : 0,
89
+ js_heap_bytes: typeof e.jsHeapBytes === "number" ? e.jsHeapBytes : 0,
90
+ // capability_change (#49) transition tokens; '' on other event types (the
91
+ // full event, including `reason`, stays in payload). `kind` lives in `name`.
92
+ cap_from: typeof e.from === "string" ? e.from : "",
93
+ cap_to: typeof e.to === "string" ? e.to : "",
94
+ // frame_perf (#80) percentile/jank/resolution detail; 0 on other event types
95
+ // (the full event stays in payload). All are optional on the event, so an
96
+ // absent field maps to 0 — perf queries filter `event_type = 'frame_perf'`
97
+ // and use `nullIf(...)` where 0 is not a meaningful sample (dpr/renderScale).
98
+ frame_time_ms: typeof e.frameTimeMs === "number" ? e.frameTimeMs : 0,
99
+ frame_time_p95_ms: typeof e.frameTimeP95Ms === "number" ? e.frameTimeP95Ms : 0,
100
+ long_frames: typeof e.longFrames === "number" ? e.longFrames : 0,
101
+ dpr: typeof e.dpr === "number" ? e.dpr : 0,
102
+ render_scale: typeof e.renderScale === "number" ? e.renderScale : 0,
103
+ name,
104
+ payload: JSON.stringify(event),
105
+ };
106
+ }
107
+ /** Map a validated `node_transform` event into a flat {@link NodeSampleRow}. */
108
+ export function toNodeSampleRow(event) {
109
+ return {
110
+ project_id: event.projectId,
111
+ session_id: event.sessionId,
112
+ ts: formatUtcTimestamp(event.ts),
113
+ sdk_version: event.sdkVersion,
114
+ scene_id: typeof event.sceneId === "string" && event.sceneId.length > 0
115
+ ? event.sceneId
116
+ : DEFAULT_SCENE_ID,
117
+ node_id: event.nodeId,
118
+ bone_id: event.boneId ?? "",
119
+ child_path: event.childPath ?? "",
120
+ position: [...event.position],
121
+ rotation: [...event.rotation],
122
+ scale: event.scale ? [...event.scale] : [],
123
+ };
124
+ }
125
+ /**
126
+ * Reconstruct a replay-complete `node_transform` event from a stored
127
+ * {@link NodeSampleRow}. The dedicated table keeps only the transform-shaped
128
+ * columns, so this rehydrates the schema event for the replay merge (ADR 0027
129
+ * §8). `tsEpochMs` is the row's `ts` already converted back to epoch ms by the
130
+ * caller (engine-specific timestamp decoding stays in the store).
131
+ */
132
+ export function nodeSampleRowToEvent(row, tsEpochMs) {
133
+ const event = {
134
+ type: "node_transform",
135
+ projectId: row.project_id,
136
+ sessionId: row.session_id,
137
+ ts: tsEpochMs,
138
+ sdkVersion: row.sdk_version,
139
+ nodeId: row.node_id,
140
+ position: row.position,
141
+ rotation: row.rotation,
142
+ };
143
+ if (row.scene_id && row.scene_id !== DEFAULT_SCENE_ID)
144
+ event.sceneId = row.scene_id;
145
+ if (row.bone_id)
146
+ event.boneId = row.bone_id;
147
+ if (row.child_path)
148
+ event.childPath = row.child_path;
149
+ if (row.scale.length === 3)
150
+ event.scale = row.scale;
151
+ return event;
152
+ }
153
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `@uptimizr/db` — the OSS storage contracts and the single-file DuckDB store
3
+ * (ADR 0020).
4
+ *
5
+ * Ships the dialect-agnostic query layer, engine-neutral event-row mapping and
6
+ * metadata types, and a fully-functional DuckDB store (events + metadata in one
7
+ * file). It carries no ClickHouse/Postgres dependency — an optional,
8
+ * separately-licensed scale store composes these contracts.
9
+ *
10
+ * Server/Node only — no DOM imports. Aggregations are query-time in v1.
11
+ */
12
+ export { readDbSettings } from "./env.js";
13
+ export type { DbSettings, DuckdbSettings } from "./env.js";
14
+ export { toEventRow, formatUtcTimestamp } from "./events.js";
15
+ export type { EventRow, SessionMeta } from "./events.js";
16
+ export { toNodeSampleRow, nodeSampleRowToEvent } from "./events.js";
17
+ export type { NodeSampleRow } from "./events.js";
18
+ export { hashApiKey, apiKeyPrefix, generateApiKey } from "./metadata.js";
19
+ export type { Project, ApiKeyRecord, ApiKeyCapability, ResolvedApiKey, SceneRepresentation, SceneRepresentationKind, SceneRepresentationSummary, } from "./metadata.js";
20
+ export type { Dialect, ParamType } from "./query/dialect.js";
21
+ export { duckdbDialect, toDuckdbTimestamp } from "./query/duckdbDialect.js";
22
+ export { buildListSessions, buildPointerHeatmap, buildWorldHeatmap, buildGazeHeatmap, buildCameraDirectionHeatmap, buildCameraPositionHeatmap, buildSessionTrajectory, buildClickGazeRay, buildFlowHeatmap, buildTopMeshes, buildMeshDwell, buildDeadClicks, buildRageClicks, buildHoverDwell, buildCompileStalls, buildResourceSummary, buildCapabilityChanges, buildCameraGestures, buildPerfSummary, buildPerfDistribution, buildFpsHistogram, buildFrameTimePercentiles, buildJankRate, buildPerfByDevice, buildPerfByScene, buildResourcePercentiles, buildStabilityCounts, buildPerfDaily, buildEventsDaily, buildDistinctScenes, buildTimeseries, buildEventTypeCounts, buildSceneCoverage, buildCameraDistance, buildNavigationStats, buildXrRotationRate, buildXrSourceUsage, buildXrAbandonment, buildInteractionsBySource, } from "./query/aggregations.js";
23
+ export type { QuerySpec, RangeOptions, SceneOptions, SourceOptions, SessionOptions, CameraModeOptions, TimeseriesOptions, SessionSummaryRow, HeatmapBinRow, WorldHeatmapBinRow, PositionBinRow, TrajectoryPointRow, DirectionBinRow, ClickGazeRayRow, FlowLinkRow, MeshCountRow, MeshDwellRow, DeadClickRow, RageClickRow, HoverDwellRow, CompileStallRow, ResourceSummaryRow, CapabilityChangeRow, CameraGestureRow, PerfSummaryRow, PerfDistributionRow, FpsHistogramRow, FrameTimePercentileRow, JankRateRow, PerfByDeviceRow, PerfBySceneRow, ResourcePercentileRow, StabilityCountRow, PerfDailyRow, EventsDailyRow, SceneRow, TimeseriesBucketRow, EventTypeCountRow, CoverageVoxelRow, CameraDistanceBucketRow, NavigationStatsRow, XrRotationRateRow, XrSourceUsageRow, XrAbandonmentRow, InteractionSourceRow, } from "./query/types.js";
24
+ export { createDuckdbClient, convertValue } from "./duckdb/client.js";
25
+ export type { DuckdbClient, DuckdbRow } from "./duckdb/client.js";
26
+ export { DUCKDB_MIGRATIONS, migrateDuckdb } from "./duckdb/migrations.js";
27
+ export { runDuckdbQuery } from "./duckdb/queries.js";
28
+ export { insertEvents as duckdbInsertEvents, getSessionEvents as duckdbGetSessionEvents, streamSessionEvents as duckdbStreamSessionEvents, getSessionMeta as duckdbGetSessionMeta, } from "./duckdb/events.js";
29
+ export { createProject as duckdbCreateProject, getProject as duckdbGetProject, createApiKey as duckdbCreateApiKey, resolveApiKey as duckdbResolveApiKey, } from "./duckdb/projects.js";
30
+ export { upsertSceneProxy as duckdbUpsertSceneProxy, getSceneRepresentation as duckdbGetSceneRepresentation, listSceneRepresentations as duckdbListSceneRepresentations, } from "./duckdb/sceneRegistry.js";
31
+ export { PARITY_PROJECT_ID, PARITY_T0, PARITY_RANGE, PARITY_DAY_RANGE, PARITY_DAY, PARITY_EVENTS, } from "./parity/fixtures.js";
32
+ export { PARITY_ABS_TOLERANCE, PARITY_REL_TOLERANCE, diffParity } from "./parity/compare.js";
33
+ export type { ParityRow, ParityCompareOptions } from "./parity/compare.js";
34
+ export { PARITY_CASES } from "./parity/cases.js";
35
+ export type { ParityCase } from "./parity/cases.js";
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `@uptimizr/db` — the OSS storage contracts and the single-file DuckDB store
3
+ * (ADR 0020).
4
+ *
5
+ * Ships the dialect-agnostic query layer, engine-neutral event-row mapping and
6
+ * metadata types, and a fully-functional DuckDB store (events + metadata in one
7
+ * file). It carries no ClickHouse/Postgres dependency — an optional,
8
+ * separately-licensed scale store composes these contracts.
9
+ *
10
+ * Server/Node only — no DOM imports. Aggregations are query-time in v1.
11
+ */
12
+ export { readDbSettings } from "./env.js";
13
+ // --- Engine-neutral event-row mapping (ADR 0020) ---
14
+ export { toEventRow, formatUtcTimestamp } from "./events.js";
15
+ // --- Scene-actor transform mapping (node_transform → node_samples, ADR 0027) ---
16
+ export { toNodeSampleRow, nodeSampleRowToEvent } from "./events.js";
17
+ // --- Engine-neutral metadata helpers and types (ADR 0020) ---
18
+ export { hashApiKey, apiKeyPrefix, generateApiKey } from "./metadata.js";
19
+ export { duckdbDialect, toDuckdbTimestamp } from "./query/duckdbDialect.js";
20
+ export { buildListSessions, buildPointerHeatmap, buildWorldHeatmap, buildGazeHeatmap, buildCameraDirectionHeatmap, buildCameraPositionHeatmap, buildSessionTrajectory, buildClickGazeRay, buildFlowHeatmap, buildTopMeshes, buildMeshDwell, buildDeadClicks, buildRageClicks, buildHoverDwell, buildCompileStalls, buildResourceSummary, buildCapabilityChanges, buildCameraGestures, buildPerfSummary, buildPerfDistribution, buildFpsHistogram, buildFrameTimePercentiles, buildJankRate, buildPerfByDevice, buildPerfByScene, buildResourcePercentiles, buildStabilityCounts, buildPerfDaily, buildEventsDaily, buildDistinctScenes, buildTimeseries, buildEventTypeCounts, buildSceneCoverage, buildCameraDistance, buildNavigationStats, buildXrRotationRate, buildXrSourceUsage, buildXrAbandonment, buildInteractionsBySource, } from "./query/aggregations.js";
21
+ // --- DuckDB (OSS single-file store, ADR 0020) ---
22
+ export { createDuckdbClient, convertValue } from "./duckdb/client.js";
23
+ export { DUCKDB_MIGRATIONS, migrateDuckdb } from "./duckdb/migrations.js";
24
+ export { runDuckdbQuery } from "./duckdb/queries.js";
25
+ export { insertEvents as duckdbInsertEvents, getSessionEvents as duckdbGetSessionEvents, streamSessionEvents as duckdbStreamSessionEvents, getSessionMeta as duckdbGetSessionMeta, } from "./duckdb/events.js";
26
+ export { createProject as duckdbCreateProject, getProject as duckdbGetProject, createApiKey as duckdbCreateApiKey, resolveApiKey as duckdbResolveApiKey, } from "./duckdb/projects.js";
27
+ export { upsertSceneProxy as duckdbUpsertSceneProxy, getSceneRepresentation as duckdbGetSceneRepresentation, listSceneRepresentations as duckdbListSceneRepresentations, } from "./duckdb/sceneRegistry.js";
28
+ // --- Cross-engine parity harness (ADR 0020) ---
29
+ // Shared fixtures, golden expectations, and a tolerance-aware comparator. OSS
30
+ // runs DuckDB-vs-golden; the scale tier reuses these to run DuckDB-vs-ClickHouse.
31
+ export { PARITY_PROJECT_ID, PARITY_T0, PARITY_RANGE, PARITY_DAY_RANGE, PARITY_DAY, PARITY_EVENTS, } from "./parity/fixtures.js";
32
+ export { PARITY_ABS_TOLERANCE, PARITY_REL_TOLERANCE, diffParity } from "./parity/compare.js";
33
+ export { PARITY_CASES } from "./parity/cases.js";
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG1C,sDAAsD;AACtD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG7D,kFAAkF;AAClF,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGpE,+DAA+D;AAC/D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAgBzE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,2BAA2B,EAC3B,0BAA0B,EAC1B,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAiDjC,mDAAmD;AACnD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,YAAY,IAAI,kBAAkB,EAClC,gBAAgB,IAAI,sBAAsB,EAC1C,mBAAmB,IAAI,yBAAyB,EAChD,cAAc,IAAI,oBAAoB,GACvC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,aAAa,IAAI,mBAAmB,EACpC,UAAU,IAAI,gBAAgB,EAC9B,YAAY,IAAI,kBAAkB,EAClC,aAAa,IAAI,mBAAmB,GACrC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,gBAAgB,IAAI,sBAAsB,EAC1C,sBAAsB,IAAI,4BAA4B,EACtD,wBAAwB,IAAI,8BAA8B,GAC3D,MAAM,2BAA2B,CAAC;AAEnC,iDAAiD;AACjD,8EAA8E;AAC9E,kFAAkF;AAClF,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE7F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Engine-neutral metadata helpers and types (ADR 0020).
3
+ *
4
+ * API-key hashing/generation are pure crypto and the project / API-key / scene
5
+ * representation shapes are storage-independent. Both the OSS DuckDB store and
6
+ * the scale-tier Postgres metadata clients reuse these, so the type contracts live
7
+ * once and OSS carries no Postgres dependency.
8
+ */
9
+ import type { Aabb, SceneProxy } from "@uptimizr/schema";
10
+ /** SHA-256 hash of an API key. Only the hash is ever stored (never plaintext). */
11
+ export declare function hashApiKey(plaintext: string): string;
12
+ /** Display prefix used to identify a key without revealing it. */
13
+ export declare function apiKeyPrefix(plaintext: string): string;
14
+ /** Generate a new opaque API key (`utk_` + 32 random bytes, base64url). */
15
+ export declare function generateApiKey(): string;
16
+ export interface Project {
17
+ id: string;
18
+ name: string;
19
+ /** Owning organization (scale tier). `null` for single-tenant/OSS projects. */
20
+ orgId: string | null;
21
+ createdAt: Date;
22
+ }
23
+ /**
24
+ * What a project API key is allowed to do. `query` keys may read the analytics
25
+ * API (the default — public ingestion is keyless, so issued keys are for
26
+ * reads); `ingest` keys are reserved for server-side write paths.
27
+ */
28
+ export type ApiKeyCapability = "ingest" | "query";
29
+ export interface ApiKeyRecord {
30
+ id: string;
31
+ projectId: string;
32
+ keyPrefix: string;
33
+ createdAt: Date;
34
+ revokedAt: Date | null;
35
+ /** What this key is allowed to do. Defaults to `query`. */
36
+ capability: ApiKeyCapability;
37
+ }
38
+ /**
39
+ * The result of resolving a plaintext API key: the project it authenticates and
40
+ * the capability that scopes what it may do at the request boundary.
41
+ */
42
+ export interface ResolvedApiKey {
43
+ projectId: string;
44
+ capability: ApiKeyCapability;
45
+ }
46
+ /**
47
+ * One representation per `(projectId, sceneId)`. Gives world-space heatmaps a
48
+ * backdrop — an engine-agnostic {@link SceneProxy} captured from a live scene, a
49
+ * URL to an external display asset, or `"none"` (registered, label only).
50
+ */
51
+ export type SceneRepresentationKind = "none" | "proxy" | "asset";
52
+ export interface SceneRepresentation {
53
+ projectId: string;
54
+ sceneId: string;
55
+ /** Human-friendly label for the scene (developer-supplied). */
56
+ label: string | null;
57
+ kind: SceneRepresentationKind;
58
+ upAxis: "y" | "z";
59
+ unitScale: number;
60
+ /** Overall world bounds `[minX,minY,minZ,maxX,maxY,maxZ]`, when known. */
61
+ bounds: Aabb | null;
62
+ /** Full proxy geometry when `kind === "proxy"`. */
63
+ proxy: SceneProxy | null;
64
+ /** External asset URL when `kind === "asset"`. */
65
+ assetUrl: string | null;
66
+ /** Content digest of the proxy/asset for cache validation. */
67
+ contentHash: string | null;
68
+ /** Proxy wire-format version, when a proxy is stored. */
69
+ proxyVersion: number | null;
70
+ /** When the geometry was captured (epoch-based; `null` for `"none"`). */
71
+ capturedAt: Date | null;
72
+ updatedAt: Date;
73
+ }
74
+ /** Lightweight registry listing row (omits the heavy `proxy` blob). */
75
+ export interface SceneRepresentationSummary {
76
+ sceneId: string;
77
+ label: string | null;
78
+ kind: SceneRepresentationKind;
79
+ bounds: Aabb | null;
80
+ contentHash: string | null;
81
+ capturedAt: Date | null;
82
+ updatedAt: Date;
83
+ }
84
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIzD,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAID,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,2DAA2D;IAC3D,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAID;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,mDAAmD;IACnD,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,yEAAyE;IACzE,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,uEAAuE;AACvE,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;CACjB"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Engine-neutral metadata helpers and types (ADR 0020).
3
+ *
4
+ * API-key hashing/generation are pure crypto and the project / API-key / scene
5
+ * representation shapes are storage-independent. Both the OSS DuckDB store and
6
+ * the scale-tier Postgres metadata clients reuse these, so the type contracts live
7
+ * once and OSS carries no Postgres dependency.
8
+ */
9
+ import { createHash, randomBytes } from "node:crypto";
10
+ // --- API keys (pure crypto) ---
11
+ /** SHA-256 hash of an API key. Only the hash is ever stored (never plaintext). */
12
+ export function hashApiKey(plaintext) {
13
+ return createHash("sha256").update(plaintext).digest("hex");
14
+ }
15
+ /** Display prefix used to identify a key without revealing it. */
16
+ export function apiKeyPrefix(plaintext) {
17
+ return plaintext.slice(0, 12);
18
+ }
19
+ /** Generate a new opaque API key (`utk_` + 32 random bytes, base64url). */
20
+ export function generateApiKey() {
21
+ return `utk_${randomBytes(32).toString("base64url")}`;
22
+ }
23
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGtD,iCAAiC;AAEjC,kFAAkF;AAClF,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;AACxD,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Cross-engine parity cases (Phase C, ADR 0020).
3
+ *
4
+ * Each case pairs one dialect-agnostic aggregation builder with the
5
+ * engine-independent golden output it must produce for {@link PARITY_EVENTS}.
6
+ * The golden is authored as truth (hand-verified from the fixtures) so that any
7
+ * engine — DuckDB in OSS, ClickHouse in the scale tier — can be checked against
8
+ * the same expectations. Two engines that both match the golden are, by
9
+ * transitivity, in parity with each other.
10
+ *
11
+ * Comparison uses the tolerance rules in {@link diffParity}: order-insensitive,
12
+ * float-tolerant on continuous columns, integer-exact on bin indices, and
13
+ * temporal projection columns excluded.
14
+ */
15
+ import type { Dialect } from "../query/dialect.js";
16
+ import type { QuerySpec } from "../query/types.js";
17
+ import type { ParityRow } from "./compare.js";
18
+ export interface ParityCase {
19
+ /** Stable identifier (also the test name). */
20
+ readonly name: string;
21
+ /** Render the aggregation for a given engine dialect. */
22
+ build(dialect: Dialect): QuerySpec;
23
+ /** Columns that together order a row for multiset comparison. */
24
+ readonly sortKeys: readonly string[];
25
+ /** Engine-specific temporal columns excluded from comparison. */
26
+ readonly ignoreColumns?: readonly string[];
27
+ /** Engine-independent expected output. */
28
+ readonly golden: readonly ParityRow[];
29
+ }
30
+ export declare const PARITY_CASES: readonly ParityCase[];
31
+ //# sourceMappingURL=cases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cases.d.ts","sourceRoot":"","sources":["../../src/parity/cases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA2CH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAS9C,MAAM,WAAW,UAAU;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iEAAiE;IACjE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;CACvC;AAID,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EA2f7C,CAAC"}