@camstack/system 1.2.443 → 1.2.445

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 (160) hide show
  1. package/assets/record-entries/icon.svg +8 -0
  2. package/dist/addon-runner.js +81 -42
  3. package/dist/addon-runner.mjs +82 -43
  4. package/dist/{agent-https-DlpTMDqA.js → agent-https-CiOW0-sj.js} +810 -12
  5. package/dist/{agent-https-U0d4uvn2.mjs → agent-https-D4Q8iFNd.mjs} +697 -13
  6. package/dist/auth/admin-token-manager.d.ts +9 -3
  7. package/dist/auth/api-key-manager.d.ts +9 -3
  8. package/dist/auth/auth-audit-log.d.ts +9 -3
  9. package/dist/auth/device-credential-manager.d.ts +5 -1
  10. package/dist/auth/external-identity-manager.d.ts +8 -21
  11. package/dist/auth/login-session-manager.d.ts +11 -3
  12. package/dist/auth/scoped-token-manager.d.ts +8 -52
  13. package/dist/auth/totp-manager.d.ts +11 -3
  14. package/dist/auth/user-manager.d.ts +10 -17
  15. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  16. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  17. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  18. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  19. package/dist/builtins/alerts/alert-store.d.ts +32 -0
  20. package/dist/builtins/alerts/alerts.addon.d.ts +19 -4
  21. package/dist/builtins/alerts/alerts.addon.js +331 -159
  22. package/dist/builtins/alerts/alerts.addon.mjs +330 -159
  23. package/dist/builtins/alerts/record-kinds.d.ts +15 -0
  24. package/dist/builtins/autotrack/index.js +1 -1
  25. package/dist/builtins/autotrack/index.mjs +1 -1
  26. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +1 -0
  27. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +134 -193
  28. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +134 -193
  29. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +4 -2
  30. package/dist/builtins/backup-orchestrator/encryption-key-store.d.ts +4 -2
  31. package/dist/builtins/backup-orchestrator/record-kinds.d.ts +58 -0
  32. package/dist/builtins/backup-orchestrator/schedule-store.d.ts +4 -2
  33. package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +4 -2
  34. package/dist/builtins/calendars/calendar-prefs-store.d.ts +13 -5
  35. package/dist/builtins/calendars/calendars.addon.d.ts +2 -2
  36. package/dist/builtins/calendars/calendars.addon.js +67 -64
  37. package/dist/builtins/calendars/calendars.addon.mjs +59 -64
  38. package/dist/builtins/calendars/record-kinds.d.ts +18 -0
  39. package/dist/builtins/camera-grid/index.js +1 -1
  40. package/dist/builtins/camera-grid/index.mjs +1 -1
  41. package/dist/builtins/cluster-agent/record-kinds.d.ts +36 -0
  42. package/dist/builtins/composer/composer.addon.js +2 -2
  43. package/dist/builtins/composer/composer.addon.mjs +2 -2
  44. package/dist/builtins/console-logging/index.js +1 -1
  45. package/dist/builtins/console-logging/index.mjs +1 -1
  46. package/dist/builtins/core-blocks/block-settings-store.d.ts +8 -4
  47. package/dist/builtins/core-blocks/core-block-store.d.ts +8 -16
  48. package/dist/builtins/core-blocks/core-blocks.addon.js +85 -112
  49. package/dist/builtins/core-blocks/core-blocks.addon.mjs +86 -113
  50. package/dist/builtins/core-blocks/index.mjs +1 -1
  51. package/dist/builtins/core-blocks/record-kinds.d.ts +26 -0
  52. package/dist/builtins/device-manager/device-manager.addon.js +111 -187
  53. package/dist/builtins/device-manager/device-manager.addon.mjs +110 -187
  54. package/dist/builtins/device-manager/device-tombstone-store.d.ts +9 -48
  55. package/dist/builtins/device-manager/record-kinds.d.ts +14 -0
  56. package/dist/builtins/hub-forwarder/index.js +1 -1
  57. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  58. package/dist/builtins/keychain/index.js +152 -22
  59. package/dist/builtins/keychain/index.mjs +152 -22
  60. package/dist/builtins/keychain/keychain-service.d.ts +3 -2
  61. package/dist/builtins/keychain/keychain-store.d.ts +13 -2
  62. package/dist/builtins/keychain/record-kinds.d.ts +16 -0
  63. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  64. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  65. package/dist/builtins/local-auth/auth-schema.d.ts +3 -1
  66. package/dist/builtins/local-auth/local-auth.addon.js +2903 -2123
  67. package/dist/builtins/local-auth/local-auth.addon.mjs +2904 -2124
  68. package/dist/builtins/local-auth/oauth-session-manager.d.ts +8 -48
  69. package/dist/builtins/local-auth/record-kinds.d.ts +141 -0
  70. package/dist/builtins/local-network/local-network.addon.js +2 -2
  71. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  72. package/dist/builtins/loki-logging/index.js +1 -1
  73. package/dist/builtins/loki-logging/index.mjs +1 -1
  74. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  75. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  76. package/dist/builtins/platform-probe/index.js +1 -1
  77. package/dist/builtins/platform-probe/index.mjs +1 -1
  78. package/dist/builtins/record-entries/entries-service.d.ts +42 -0
  79. package/dist/builtins/record-entries/index.d.ts +1 -0
  80. package/dist/builtins/record-entries/index.js +142 -0
  81. package/dist/builtins/record-entries/index.mjs +136 -0
  82. package/dist/builtins/record-entries/record-entries.addon.d.ts +13 -0
  83. package/dist/builtins/records/legacy-table-row-count.d.ts +5 -0
  84. package/dist/builtins/records/phase6-declare-gate.d.ts +28 -0
  85. package/dist/builtins/records-isolated.d.ts +10 -0
  86. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  87. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  88. package/dist/builtins/snapshot/index.js +1 -1
  89. package/dist/builtins/snapshot/index.mjs +1 -1
  90. package/dist/builtins/sqlite-storage/file-host-client.d.ts +2 -0
  91. package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +4 -0
  92. package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +7 -1
  93. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  94. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  95. package/dist/builtins/sqlite-storage/index.js +1 -1
  96. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  97. package/dist/builtins/sqlite-storage/integration-record-kinds.d.ts +30 -0
  98. package/dist/builtins/sqlite-storage/integration-registry.d.ts +10 -16
  99. package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +7 -0
  100. package/dist/builtins/sqlite-storage/placement-router.d.ts +5 -0
  101. package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +5 -0
  102. package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +6 -0
  103. package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +29 -0
  104. package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +51 -0
  105. package/dist/builtins/sqlite-storage/records/records-engine.d.ts +94 -0
  106. package/dist/builtins/sqlite-storage/records/records-explain.d.ts +18 -0
  107. package/dist/builtins/sqlite-storage/records/records-plan.d.ts +90 -0
  108. package/dist/builtins/sqlite-storage/records/records-probe.d.ts +33 -0
  109. package/dist/builtins/sqlite-storage/records/records-provider.d.ts +63 -0
  110. package/dist/builtins/sqlite-storage/records/records-rows.d.ts +46 -0
  111. package/dist/builtins/sqlite-storage/records/records-sql.d.ts +41 -0
  112. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +17 -10
  113. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -0
  114. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +446 -5
  115. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +446 -5
  116. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +15 -1
  117. package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +5 -2
  118. package/dist/builtins/storage-orchestrator/location-store.d.ts +7 -2
  119. package/dist/builtins/storage-orchestrator/record-kinds.d.ts +38 -0
  120. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -0
  121. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +196 -5
  122. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +195 -6
  123. package/dist/builtins/system-config/record-kinds.d.ts +32 -0
  124. package/dist/builtins/system-config/system-config.addon.js +53 -618
  125. package/dist/builtins/system-config/system-config.addon.mjs +29 -577
  126. package/dist/builtins/winston-logging/index.js +1 -1
  127. package/dist/builtins/winston-logging/index.mjs +1 -1
  128. package/dist/{composition-sources-C8tUG2uL.mjs → composition-sources-BMt5cFYb.mjs} +1 -1
  129. package/dist/{composition-sources-BUXX1e8j.js → composition-sources-D3fi9Xns.js} +1 -1
  130. package/dist/{constants-CGwVaAV3.mjs → constants-BMHCxRzb.mjs} +1 -1
  131. package/dist/{constants-DWmm7_of.js → constants-Br879Axi.js} +1 -1
  132. package/dist/{device-ca-DGayRmC0.js → device-ca-CnJ_va7i.js} +1 -1
  133. package/dist/{device-ca-DBfiJ_SB.mjs → device-ca-T8osSMos.mjs} +1 -1
  134. package/dist/{dist-Bxt_S-9a.mjs → dist-BNunRyXT.mjs} +1133 -93
  135. package/dist/{dist-D9qT3jHr.js → dist-DgOG8flk.js} +1354 -92
  136. package/dist/file-host-worker.js +11 -1
  137. package/dist/file-host-worker.mjs +11 -1
  138. package/dist/{hub-mdns-ciao-B-wk9nzx.js → hub-mdns-ciao-BIkTHq-n.js} +2 -2
  139. package/dist/{hub-mdns-ciao-DpPcQDg-.mjs → hub-mdns-ciao-D16oRQ9K.mjs} +2 -2
  140. package/dist/index.d.ts +7 -0
  141. package/dist/index.js +3111 -2806
  142. package/dist/index.mjs +3083 -2795
  143. package/dist/kernel/index.d.ts +2 -0
  144. package/dist/kernel/moleculer/event-bus.d.ts +3 -1
  145. package/dist/kernel/moleculer/mesh-mtls/mesh-certificate-registry.d.ts +5 -1
  146. package/dist/kernel/moleculer/records-api-transport.d.ts +9 -0
  147. package/dist/kernel/moleculer/remote-logger.d.ts +2 -2
  148. package/dist/kernel/settings-view-types.d.ts +0 -7
  149. package/dist/kernel/transport/cap-route-resolver.d.ts +9 -38
  150. package/dist/phase6-declare-gate-Ci1-8uUn.js +98 -0
  151. package/dist/phase6-declare-gate-tkKOEitw.mjs +93 -0
  152. package/dist/read-all-rows-CVoO1ONM.js +29 -0
  153. package/dist/read-all-rows-TaPqdWNF.mjs +25 -0
  154. package/dist/records/read-all-rows.d.ts +6 -0
  155. package/dist/{restore-archive-9CGgeBzD.mjs → restore-archive-DR9MtO7J.mjs} +339 -9
  156. package/dist/{restore-archive-BMNXwWWD.js → restore-archive-DjJnCgap.js} +353 -5
  157. package/dist/tls/agent-https-names.d.ts +9 -13
  158. package/dist/{wal-maintenance-cRHR4rUY.js → wal-maintenance-CODGqhKY.js} +0 -0
  159. package/dist/{wal-maintenance-sIB32ONp.mjs → wal-maintenance-CfvgtQ7C.mjs} +0 -0
  160. package/package.json +22 -1
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Bounds for hub `record-kinds` modules under emit-isolated-dts (TS9010).
3
+ *
4
+ * Annotate with `: IsolatedZodSchema` / `: IsolatedRecordKinds` erases inference
5
+ * (`z.infer` → `unknown`, string index → `| undefined`). Use `satisfies` instead.
6
+ */
7
+ import type { DefinedRecordKind } from "@camstack/types";
8
+ import type { z } from "zod";
9
+ export type IsolatedZodSchema = z.ZodTypeAny;
10
+ export type IsolatedRecordKinds = Readonly<Record<string, DefinedRecordKind>>;
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D9qT3jHr.js");
6
+ const require_dist = require("../../dist-DgOG8flk.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { Ei as EventCategory, jr as BaseAddon } from "../../dist-Bxt_S-9a.mjs";
1
+ import { Rr as BaseAddon, la as EventCategory } from "../../dist-BNunRyXT.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D9qT3jHr.js");
6
+ const require_dist = require("../../dist-DgOG8flk.js");
7
7
  const require_snapshot_courtesy = require("../../snapshot-courtesy-D_C5-nC0.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- import { Ar as errMsg, Dr as DeviceFeature, Ei as EventCategory, Pt as deriveBatteryPresence, Qn as snapshotCapability, dt as batteryCapability, jr as BaseAddon, kr as DeviceType, or as streamQualityLabel, s as BatteryStatusSchema, ui as nodePin, ut as bareAddonId, xn as memoizePinnedFfmpeg } from "../../dist-Bxt_S-9a.mjs";
1
+ import { En as memoizePinnedFfmpeg, Hi as nodePin, Ir as DeviceType, Lr as errMsg, Pr as DeviceFeature, Rr as BaseAddon, ar as snapshotCapability, gt as batteryCapability, ht as bareAddonId, la as EventCategory, pr as streamQualityLabel, s as BatteryStatusSchema, zt as deriveBatteryPresence } from "../../dist-BNunRyXT.mjs";
2
2
  import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-CyFs1M3I.mjs";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
@@ -1,5 +1,6 @@
1
1
  import type { IScopedLogger } from "@camstack/types";
2
2
  import { type ControlOp, type ControlOps, type DataStoreInput, type DataStoreOp, type DataStoreOutput, type FileHostWorkerData, type OwnedSqliteFileSpec, type VectorInput, type VectorOp, type VectorOutput } from "./file-host-protocol.js";
3
+ import type { RecordsInput, RecordsOp, RecordsOutput } from "./records/records-engine-types.js";
3
4
  /** The members of a `Worker` this class touches — structural, so a spec can substitute. */
4
5
  export interface FileHostThread {
5
6
  on(event: "message", listener: (message: unknown) => void): unknown;
@@ -48,6 +49,7 @@ export declare class FileHostClient {
48
49
  noteDeclared(table: string): void;
49
50
  data<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
50
51
  vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
52
+ records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
51
53
  control<K extends ControlOp>(op: K, input: ControlOps[K]["input"]): Promise<ControlOps[K]["output"]>;
52
54
  /** Ask the thread to close its connection, then end it. */
53
55
  stop(): Promise<void>;
@@ -6,12 +6,16 @@
6
6
  */
7
7
  import type { IVectorStoreProvider } from "@camstack/types";
8
8
  import { type ControlOp, type ControlOps, type DataStoreInput, type DataStoreOp, type DataStoreOutput, type VectorInput, type VectorOp, type VectorOutput } from "./file-host-protocol.js";
9
+ import type { RecordsEngineOps, RecordsInput, RecordsOp, RecordsOutput } from "./records/records-engine-types.js";
9
10
  import type { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
10
11
  /** The data surface as a mapped type — what lets `target[op](input)` type-check for a generic `op`. */
11
12
  export type DataTarget = { readonly [K in DataStoreOp]: (input: DataStoreInput<K>) => Promise<DataStoreOutput<K>> };
12
13
  export type VectorTarget = { readonly [K in VectorOp]: (input: VectorInput<K>) => Promise<VectorOutput<K>> };
13
14
  export declare function callData<K extends DataStoreOp>(target: DataTarget, op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
14
15
  export declare function callVector<K extends VectorOp>(target: IVectorStoreProvider, op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
16
+ /** The records surface as a mapped type, for the same reason. */
17
+ export type RecordsTarget = { readonly [K in RecordsOp]: (input: RecordsInput<K>) => Promise<RecordsOutput<K>> };
18
+ export declare function callRecords<K extends RecordsOp>(target: RecordsEngineOps, op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
15
19
  /** The control surface as a mapped type, for the same reason. */
16
20
  type ControlTarget = { readonly [K in ControlOp]: (input: ControlOps[K]["input"]) => ControlOps[K]["output"] };
17
21
  /**
@@ -9,7 +9,7 @@
9
9
  * result }` or `{ id, ok: false, error }`. `kind` is `data` (the
10
10
  * `data-store-provider` surface), `vector` (the `vector-store` surface) or
11
11
  * `control` (what the placement router needs to ask a file that no cap
12
- * method covers). Errors cross by NAME (`placement-errors.ts`).
12
+ * method covers), or `records` (the `records` surface, D881). Errors cross by NAME (`placement-errors.ts`).
13
13
  *
14
14
  * ## The type boundary
15
15
  *
@@ -22,6 +22,7 @@
22
22
  import type { IDataStoreProvider, IVectorStoreProvider } from "@camstack/types";
23
23
  import type { DataStoreDatabase, LogTags } from "@camstack/types";
24
24
  import type { SerializedError } from "./placement-errors.js";
25
+ import { type RecordsOp } from "./records/records-engine-types.js";
25
26
  /** Every `data-store-provider` method a file serves (all but self-description). */
26
27
  export type DataStoreMethods = Omit<IDataStoreProvider, "getEngineInfo">;
27
28
  export type DataStoreOp = keyof DataStoreMethods;
@@ -86,6 +87,11 @@ export type FileHostRequest = {
86
87
  readonly kind: "vector";
87
88
  readonly op: VectorOp;
88
89
  readonly input: unknown;
90
+ } | {
91
+ readonly id: number;
92
+ readonly kind: "records";
93
+ readonly op: RecordsOp;
94
+ readonly input: unknown;
89
95
  } | {
90
96
  readonly id: number;
91
97
  readonly kind: "control";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-D9qT3jHr.js");
6
+ const require_dist = require("../../dist-DgOG8flk.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Yt as filesystemBrowseCapability, ir as storageProviderCapability, jr as BaseAddon } from "../../dist-Bxt_S-9a.mjs";
1
+ import { Rr as BaseAddon, dr as storageProviderCapability, en as filesystemBrowseCapability } from "../../dist-BNunRyXT.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -4,7 +4,7 @@ Object.defineProperties(exports, {
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
6
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./filesystem-storage.addon.js");
7
- const require_wal_maintenance = require("../../wal-maintenance-cRHR4rUY.js");
7
+ const require_wal_maintenance = require("../../wal-maintenance-CODGqhKY.js");
8
8
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./sqlite-settings.addon.js");
9
9
  //#region src/builtins/sqlite-storage/config-store.ts
10
10
  var ConfigStore = class {
@@ -1,5 +1,5 @@
1
1
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./filesystem-storage.addon.mjs";
2
- import { A as SQLITE_PAGE_CACHE_FLOOR_KIB, D as SQLITE_MMAP_CEILING_BYTES, E as SQLITE_JOURNAL_SIZE_LIMIT_BYTES, F as SQLITE_PROFILE_REPORT_INTERVAL_MS, I as SQLITE_PROFILE_TOP_N, L as SQLITE_SLOW_CALL_MS, M as sqlitePageCacheKibFor, N as SQLITE_ENGINE_STORM_WALL_SHARE, O as SQLITE_MMAP_FLOOR_BYTES, P as SQLITE_PROFILE_REPORT_FLOOR_MS, R as SqliteOpProfiler, a as WalMaintenance, c as SqliteSettingsBackend, i as WAL_MAINTENANCE_INTERVAL_MS, j as sqliteMmapSizeFor, k as SQLITE_PAGE_CACHE_CEILING_KIB, n as WAL_HIGH_WATER_BYTES, r as WAL_IDLE_QUIET_MS, t as WAL_CHECKPOINT_BUSY_TIMEOUT_MS, z as sqliteEngineStorm } from "../../wal-maintenance-sIB32ONp.mjs";
2
+ import { A as SQLITE_MMAP_FLOOR_BYTES, B as SqliteOpProfiler, F as SQLITE_ENGINE_STORM_WALL_SHARE, I as SQLITE_PROFILE_REPORT_FLOOR_MS, L as SQLITE_PROFILE_REPORT_INTERVAL_MS, M as SQLITE_PAGE_CACHE_FLOOR_KIB, N as sqliteMmapSizeFor, O as SQLITE_JOURNAL_SIZE_LIMIT_BYTES, P as sqlitePageCacheKibFor, R as SQLITE_PROFILE_TOP_N, V as sqliteEngineStorm, a as WalMaintenance, c as SqliteSettingsBackend, i as WAL_MAINTENANCE_INTERVAL_MS, j as SQLITE_PAGE_CACHE_CEILING_KIB, k as SQLITE_MMAP_CEILING_BYTES, n as WAL_HIGH_WATER_BYTES, r as WAL_IDLE_QUIET_MS, t as WAL_CHECKPOINT_BUSY_TIMEOUT_MS, z as SQLITE_SLOW_CALL_MS } from "../../wal-maintenance-CfvgtQ7C.mjs";
3
3
  import { SqliteSettingsAddon } from "./sqlite-settings.addon.mjs";
4
4
  //#region src/builtins/sqlite-storage/config-store.ts
5
5
  var ConfigStore = class {
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Record kinds owned by integration-registry (phase 4).
3
+ */
4
+ import { type DefinedRecordKind } from "@camstack/types";
5
+ import { z } from "zod";
6
+ export declare const INTEGRATIONS_LEGACY = "integrations";
7
+ export declare const INTEGRATION_SETTINGS_LEGACY = "integration_settings";
8
+ export type IntegrationBody = {
9
+ readonly addonId: string;
10
+ readonly name: string;
11
+ readonly enabled: boolean;
12
+ readonly info: Record<string, unknown>;
13
+ readonly createdAt: number;
14
+ readonly updatedAt: number;
15
+ };
16
+ export declare const IntegrationBodySchema: z.ZodType<IntegrationBody>;
17
+ export type IntegrationSettingBody = {
18
+ readonly integrationId: string;
19
+ readonly key: string;
20
+ readonly value: string;
21
+ readonly valueType: string;
22
+ };
23
+ export declare const IntegrationSettingBodySchema: z.ZodType<IntegrationSettingBody>;
24
+ export type IntegrationRegistryRecordKindsMap = {
25
+ readonly integrations: DefinedRecordKind<z.ZodType<IntegrationBody>>;
26
+ readonly "integration-settings": DefinedRecordKind<z.ZodType<IntegrationSettingBody>>;
27
+ };
28
+ export declare const integrationRegistryRecordKinds: IntegrationRegistryRecordKindsMap;
29
+ export declare const integrationsRecordKind: DefinedRecordKind<z.ZodType<IntegrationBody>>;
30
+ export declare const integrationSettingsRecordKind: DefinedRecordKind<z.ZodType<IntegrationSettingBody>>;
@@ -1,22 +1,16 @@
1
- import type { CreateIntegrationInput, IIntegrationRegistry, Integration, ISettingsStoreProvider } from "@camstack/types";
2
- /**
3
- * The persisted INTEGRATIONS — one row per provider instance an operator (or a
4
- * declaring addon) added, plus that instance's settings.
5
- *
6
- * It had a device half once: `devices` + `device_settings_kv`, `dev_NNNN` ids,
7
- * `createDevice` / `listCameras` / `setDeviceSetting`. It was removed on
8
- * 2026-08-19 with both tables ([D183](../../../../../docs/decisions/adr-0183-code-that-is-deleted-takes-its-tables-with-it.md)):
9
- * measured on the reference hub it held 0 rows against 974 live devices, no
10
- * production caller ever reached it, and its id-space could not be reconciled
11
- * with the numeric ids every track, rule and binding in the system uses. The
12
- * fleet is `device-manager:devices`. Do not add a device method here — the
13
- * device authority is the device-manager, and a second one that agrees with
14
- * nothing is how this half came to exist.
15
- */
1
+ import type { CreateIntegrationInput, IIntegrationRegistry, Integration, ISettingsStoreProvider, RecordKindHandle, RecordsAccess } from "@camstack/types";
2
+ import { type IntegrationBody, type IntegrationSettingBody } from "./integration-record-kinds.js";
3
+ export interface IntegrationRecordStores {
4
+ readonly integrations: RecordKindHandle<IntegrationBody>;
5
+ readonly settings: RecordKindHandle<IntegrationSettingBody>;
6
+ }
16
7
  export declare class IntegrationRegistry implements IIntegrationRegistry {
17
8
  private readonly store;
18
- constructor(backend: ISettingsStoreProvider);
9
+ private readonly recordStores;
10
+ constructor(backend: ISettingsStoreProvider, recordStores?: IntegrationRecordStores);
11
+ static recordStoresOf(records: Pick<RecordsAccess, "kind">): IntegrationRecordStores;
19
12
  initialize(): Promise<void>;
13
+ private resumeCounter;
20
14
  createIntegration(input: CreateIntegrationInput): Promise<Integration>;
21
15
  getIntegration(id: string): Promise<Integration | null>;
22
16
  getIntegrationByAddonId(addonId: string): Promise<Integration | null>;
@@ -13,6 +13,7 @@
13
13
  * package knows a file path.
14
14
  */
15
15
  import type { DatabaseSnapshotResult, DataStoreDatabase, IScopedLogger } from "@camstack/types";
16
+ import type { RecordsInput, RecordsOp, RecordsOutput } from "./records/records-engine-types.js";
16
17
  import { type FileHostThreadFactory } from "./file-host-client.js";
17
18
  import type { DataStoreInput, DataStoreOp, DataStoreOutput, OwnedSqliteFileSpec, VectorInput, VectorOp, VectorOutput } from "./file-host-protocol.js";
18
19
  import { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
@@ -26,6 +27,8 @@ export interface OwnedSqliteFile {
26
27
  readonly databaseId: DataStoreDatabase;
27
28
  readonly livePath: string;
28
29
  call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
30
+ /** `records` calls (D881). */
31
+ records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
29
32
  /** `vector-store` calls; refused on a file that does not load sqlite-vec. */
30
33
  vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
31
34
  /** The collections this file's own `_collection_declarations` names. */
@@ -85,6 +88,7 @@ declare abstract class OwnedFileBase implements OwnedSqliteFile {
85
88
  constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
86
89
  abstract call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
87
90
  abstract vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
91
+ abstract records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
88
92
  abstract declaredCollections(): ReadonlySet<string>;
89
93
  abstract hasTable(name: string): Promise<boolean>;
90
94
  abstract dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
@@ -106,10 +110,12 @@ export declare class InlineOwnedFile extends OwnedFileBase {
106
110
  private vectorIndex;
107
111
  private vectorProvider;
108
112
  private maintenance;
113
+ private recordsEngine;
109
114
  constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
110
115
  open(): Promise<void>;
111
116
  getVectorIndex(): SqliteVecVectorIndex | null;
112
117
  call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
118
+ records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
113
119
  vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
114
120
  declaredCollections(): ReadonlySet<string>;
115
121
  hasTable(name: string): Promise<boolean>;
@@ -125,6 +131,7 @@ export declare class WorkerOwnedFile extends OwnedFileBase {
125
131
  open(): Promise<void>;
126
132
  call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
127
133
  vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
134
+ records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
128
135
  declaredCollections(): ReadonlySet<string>;
129
136
  hasTable(name: string): Promise<boolean>;
130
137
  dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
@@ -55,6 +55,11 @@ export declare class PlacementRouter implements IDataStoreProvider {
55
55
  private fileOf;
56
56
  /** The database a table is served from. */
57
57
  databaseOf(table: string): DataStoreDatabase;
58
+ /**
59
+ * The file that hosts records of `databaseId`, created by the first
60
+ * declaration that names it (`events`). `history` never hosts records.
61
+ */
62
+ recordsFileFor(databaseId: DataStoreDatabase): Promise<OwnedSqliteFile>;
58
63
  /** The files currently open, settings first. */
59
64
  openFiles(): readonly OwnedSqliteFile[];
60
65
  private openFile;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Boot guard (B3): addon-settings array fields block adoption until copied.
3
+ */
4
+ import type { PlacementRouter } from "../placement-router.js";
5
+ export declare function countSettingsArrayLegacy(router: PlacementRouter, addonId: string, settingsKey: string): Promise<number>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boot guard (B2): brokers still in addon-settings block adoption until
3
+ * `records-adopt` copies them into the entry kind.
4
+ */
5
+ import type { PlacementRouter } from "../placement-router.js";
6
+ export declare function countSettingsBrokersLegacy(router: PlacementRouter, addonId: string): Promise<number>;
@@ -0,0 +1,29 @@
1
+ import type Database from "better-sqlite3";
2
+ import { type DeclareKindResult, type RecordKindDeclaration } from "@camstack/types";
3
+ /** One kind as the engine holds it. */
4
+ export interface KindRow {
5
+ readonly kindId: number;
6
+ readonly owner: string;
7
+ readonly kind: string;
8
+ readonly database: "settings" | "events";
9
+ readonly hash: string;
10
+ readonly state: "declared" | "orphaned" | "dropped";
11
+ readonly declaration: RecordKindDeclaration;
12
+ /** When `adoptRecords` finished copying the legacy table into this kind; the boot guard reads it. */
13
+ readonly adoptedAt: number | null;
14
+ }
15
+ /** The hash a declaration is known by; two spellings of the same declaration agree. */
16
+ export declare function declarationHash(decl: RecordKindDeclaration): string;
17
+ /** Create the shared tables of a file. Idempotent. */
18
+ export declare function ensureRecordsSchema(db: Database.Database): void;
19
+ /** Every kind this file's catalog holds. */
20
+ export declare function loadKinds(db: Database.Database): readonly KindRow[];
21
+ export interface DeclareOutcome {
22
+ readonly row: KindRow;
23
+ readonly result: DeclareKindResult;
24
+ }
25
+ /**
26
+ * Reconcile one kind: insert its catalog row and create the declared indexes,
27
+ * or confirm it is unchanged, or apply an additive change. One transaction.
28
+ */
29
+ export declare function declareKind(db: Database.Database, owner: string, kind: string, declaration: RecordKindDeclaration, prior: KindRow | undefined): DeclareOutcome;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The ops one database file serves for `records` (D881): the `records` cap's
3
+ * methods with an explicit `owner` (the transport-stamped caller, decided by
4
+ * the router) plus the engine's own housekeeping. Pure types: the worker bundle
5
+ * and the main thread both import this.
6
+ */
7
+ import type { IRecordsProvider, StorageKind } from "@camstack/types";
8
+ /** A `records` cap method's input with the owner the router resolved. */
9
+ export type OwnedInput<M extends keyof IRecordsProvider> = Parameters<IRecordsProvider[M]>[0] & {
10
+ readonly owner: string;
11
+ };
12
+ type OwnedOps = { readonly [M in keyof IRecordsProvider]: (input: OwnedInput<M>) => Promise<Awaited<ReturnType<IRecordsProvider[M]>>> };
13
+ export interface RecordsEngineOps extends OwnedOps {
14
+ /** Every kind this file holds, with rows and a size estimate (System -> Data). */
15
+ listKinds(input: {
16
+ readonly owner?: string | undefined;
17
+ }): Promise<readonly StorageKind[]>;
18
+ /** Delete rows past `expires_at`, in batches. */
19
+ sweepExpired(input: {
20
+ readonly batch?: number;
21
+ }): Promise<{
22
+ readonly deleted: number;
23
+ }>;
24
+ /** Rows of a legacy table in THIS file; `null` when the table is not there. */
25
+ legacyRowCount(input: {
26
+ readonly table: string;
27
+ }): Promise<number | null>;
28
+ /** Has `adoptRecords` finished copying the legacy table into this kind? (the boot guard) */
29
+ adoptionState(input: {
30
+ readonly owner: string;
31
+ readonly kind: string;
32
+ }): Promise<{
33
+ readonly adoptedAt: number | null;
34
+ }>;
35
+ /** Record that the copy is complete. Idempotent. */
36
+ markAdopted(input: {
37
+ readonly owner: string;
38
+ readonly kind: string;
39
+ }): Promise<void>;
40
+ /** Undo a false `complete` when the legacy table still holds rows. */
41
+ revokeAdopted(input: {
42
+ readonly owner: string;
43
+ readonly kind: string;
44
+ }): Promise<void>;
45
+ }
46
+ export type RecordsOp = keyof RecordsEngineOps;
47
+ export type RecordsInput<K extends RecordsOp> = Parameters<RecordsEngineOps[K]>[0];
48
+ export type RecordsOutput<K extends RecordsOp> = Awaited<ReturnType<RecordsEngineOps[K]>>;
49
+ export declare const RECORDS_OPS: readonly RecordsOp[];
50
+ export declare function isRecordsOp(op: string): op is RecordsOp;
51
+ export {};
@@ -0,0 +1,94 @@
1
+ /**
2
+ * The records engine of ONE database file (D881): the operations behind
3
+ * `ctx.records`, over the same connection the file's collections use.
4
+ *
5
+ * Everything here is synchronous SQLite inside a method that returns a promise,
6
+ * so a big delete can YIELD between batches and the serving thread is not held.
7
+ * One thread per file (D851) serialises every statement, so each op is atomic
8
+ * and a read-modify-write goes through `ifRev`.
9
+ *
10
+ * Every statement is compiled with `kind_id = <literal>` first (records-sql.ts),
11
+ * no op exists without an (owner, kind), and an owner reaches only its own
12
+ * kinds: another addon's kind is indistinguishable from one that does not exist.
13
+ */
14
+ import type Database from "better-sqlite3";
15
+ import { type DataStoreDatabase, type IScopedLogger, type StorageKind } from "@camstack/types";
16
+ import { type KindRow } from "./records-catalog.js";
17
+ import type { OwnedInput, RecordsEngineOps, RecordsOutput } from "./records-engine-types.js";
18
+ export interface RecordsEngineOptions {
19
+ readonly databaseId: DataStoreDatabase;
20
+ readonly logger: IScopedLogger;
21
+ readonly now?: () => number;
22
+ }
23
+ export declare class RecordsEngine implements RecordsEngineOps {
24
+ private readonly db;
25
+ private readonly options;
26
+ private readonly kinds;
27
+ private readonly now;
28
+ private readonly writesSinceTrim;
29
+ constructor(db: Database.Database, options: RecordsEngineOptions);
30
+ private schemaReady;
31
+ private kindOf;
32
+ declareKinds(input: OwnedInput<"declareKinds">): Promise<RecordsOutput<"declareKinds">>;
33
+ private timed;
34
+ private static readonly ROW_SELECT;
35
+ get(input: OwnedInput<"get">): Promise<RecordsOutput<"get">>;
36
+ getMany(input: OwnedInput<"getMany">): Promise<RecordsOutput<"getMany">>;
37
+ secretRefs(input: OwnedInput<"secretRefs">): Promise<RecordsOutput<"secretRefs">>;
38
+ query(input: OwnedInput<"query">): Promise<RecordsOutput<"query">>;
39
+ count(input: OwnedInput<"count">): Promise<RecordsOutput<"count">>;
40
+ histogram(input: OwnedInput<"histogram">): Promise<RecordsOutput<"histogram">>;
41
+ aggregate(input: OwnedInput<"aggregate">): Promise<RecordsOutput<"aggregate">>;
42
+ private storedRow;
43
+ private upsertSql;
44
+ private wrapWrite;
45
+ /** One row, inside the caller's transaction. */
46
+ private writeRecord;
47
+ put(input: OwnedInput<"put">): Promise<RecordsOutput<"put">>;
48
+ putMany(input: OwnedInput<"putMany">): Promise<RecordsOutput<"putMany">>;
49
+ patch(input: OwnedInput<"patch">): Promise<RecordsOutput<"patch">>;
50
+ private refsOfRows;
51
+ delete(input: OwnedInput<"delete">): Promise<RecordsOutput<"delete">>;
52
+ deleteMany(input: OwnedInput<"deleteMany">): Promise<RecordsOutput<"deleteMany">>;
53
+ /** Delete the rows `selectSql` names, in batches, yielding between them. */
54
+ private deleteBatched;
55
+ deleteWhere(input: OwnedInput<"deleteWhere">): Promise<RecordsOutput<"deleteWhere">>;
56
+ deleteDevice(input: OwnedInput<"deleteDevice">): Promise<RecordsOutput<"deleteDevice">>;
57
+ allocateId(input: OwnedInput<"allocateId">): Promise<RecordsOutput<"allocateId">>;
58
+ /**
59
+ * Trim a ring after a write. Counting a big ring on every write would be the
60
+ * cost the bound exists to avoid, so a ring of more than TRIM_SLACK rows is
61
+ * trimmed once per (bound / TRIM_SLACK) writes: the bound holds within 1 %.
62
+ */
63
+ private afterWrite;
64
+ private trimScope;
65
+ sweepExpired(input: {
66
+ readonly batch?: number;
67
+ }): Promise<{
68
+ readonly deleted: number;
69
+ }>;
70
+ listKinds(input: {
71
+ readonly owner?: string | undefined;
72
+ readonly counts?: boolean | undefined;
73
+ }): Promise<readonly StorageKind[]>;
74
+ private countRows;
75
+ /** The declarations this file holds, for the router's placement map and the entries service. */
76
+ declarations(): readonly KindRow[];
77
+ legacyRowCount(input: {
78
+ readonly table: string;
79
+ }): Promise<number | null>;
80
+ adoptionState(input: {
81
+ readonly owner: string;
82
+ readonly kind: string;
83
+ }): Promise<{
84
+ readonly adoptedAt: number | null;
85
+ }>;
86
+ markAdopted(input: {
87
+ readonly owner: string;
88
+ readonly kind: string;
89
+ }): Promise<void>;
90
+ revokeAdopted(input: {
91
+ readonly owner: string;
92
+ readonly kind: string;
93
+ }): Promise<void>;
94
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Reading a SQLite plan for the D447 proof (D881).
3
+ *
4
+ * `EXPLAIN QUERY PLAN` prints `USING INDEX` whether or not the table row is
5
+ * read behind that index entry, so it cannot prove an aggregate is served from
6
+ * the index alone. The VDBE program can: a statement that never reads the
7
+ * table has no `Column` opcode on the table's cursor. Both readers live here
8
+ * because the specs and the `check-records-index-served` guard must agree.
9
+ */
10
+ import type Database from "better-sqlite3";
11
+ export interface ExplainedStatement {
12
+ readonly sql: string;
13
+ readonly params: readonly unknown[];
14
+ }
15
+ /** The `EXPLAIN QUERY PLAN` detail lines of a statement. */
16
+ export declare function planOf(db: Database.Database, s: ExplainedStatement): readonly string[];
17
+ /** How many `Column` opcodes read the `records` TABLE (not an index) in this statement. */
18
+ export declare function tableColumnReads(db: Database.Database, s: ExplainedStatement): number;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Statement planning for `records` (D881): turn a request into SQL that is
3
+ * served by an index BY CONSTRUCTION, or refuse it.
4
+ *
5
+ * - `where` accepts declared index fields only: the equality fields must be the
6
+ * LEADING fields of one declared index (any order), with at most one range on
7
+ * the field right after them. Anything else throws {@link UnindexedFilterError}
8
+ * - an unindexed filter does not compile.
9
+ * - Every index path is named with `INDEXED BY`: if SQLite cannot use that index
10
+ * for the statement it ERRORS instead of quietly scanning.
11
+ * - Pagination is keyset (`(key..., rid) > cursor`); there is no offset.
12
+ *
13
+ * Pure: no database in here, so the statements are testable (and EXPLAINed) on
14
+ * their own.
15
+ */
16
+ import { type RecordKindDeclaration, type RecordWhere } from "@camstack/types";
17
+ type Bindable = string | number | null;
18
+ /** A declared index and what a `where` leaves for ordering. */
19
+ export interface WherePlan {
20
+ readonly index: RecordKindDeclaration["indexes"][number];
21
+ readonly clauses: readonly string[];
22
+ readonly params: readonly Bindable[];
23
+ /** The index fields after the equality prefix: the order a `where` query returns in. */
24
+ readonly orderFields: readonly string[];
25
+ }
26
+ /**
27
+ * Find the declared index that serves `where` (plus any `extraFields` the
28
+ * statement reads: an aggregate's value and group columns), or throw.
29
+ */
30
+ export declare function planWhere(kind: string, decl: RecordKindDeclaration, where: RecordWhere | undefined, opts: {
31
+ readonly allowIn: boolean;
32
+ readonly extraFields?: readonly string[];
33
+ }): WherePlan | null;
34
+ /** The built-in filters shared by every statement. */
35
+ export interface WindowFilter {
36
+ readonly deviceId?: number | undefined;
37
+ readonly atFrom?: number | undefined;
38
+ readonly atTo?: number | undefined;
39
+ }
40
+ /** The built-in index that serves a device/time window. */
41
+ export declare function windowIndex(w: WindowFilter): string;
42
+ export interface PlannedStatement {
43
+ readonly sql: string;
44
+ readonly params: readonly Bindable[];
45
+ }
46
+ export interface PlannedQuery extends PlannedStatement {
47
+ /** Names the access path; a cursor is valid only for the plan that issued it. */
48
+ readonly tag: string;
49
+ /** How many `_k<i>` cursor-key columns the statement selects (before `rid`). */
50
+ readonly keyCount: number;
51
+ }
52
+ export interface QueryRequest extends WindowFilter {
53
+ readonly where?: RecordWhere | undefined;
54
+ readonly order?: "at" | "id" | undefined;
55
+ readonly desc?: boolean | undefined;
56
+ readonly limit: number;
57
+ /** A decoded cursor: the tag of the plan that issued it, and its key values. */
58
+ readonly cursor?: {
59
+ readonly tag: string;
60
+ readonly values: readonly Bindable[];
61
+ } | undefined;
62
+ }
63
+ export declare function planQuery(kind: string, kindId: number, decl: RecordKindDeclaration, q: QueryRequest): PlannedQuery;
64
+ export interface CountRequest extends WindowFilter {
65
+ readonly where?: RecordWhere | undefined;
66
+ }
67
+ export declare function planCount(kind: string, kindId: number, decl: RecordKindDeclaration, q: CountRequest): PlannedStatement;
68
+ export interface HistogramRequest {
69
+ readonly deviceId?: number | undefined;
70
+ readonly from: number;
71
+ readonly to: number;
72
+ readonly bucketMs: number;
73
+ }
74
+ /** Buckets one answer may carry: a histogram is a chart, not an export. */
75
+ export declare const HISTOGRAM_MAX_BUCKETS = 1e4;
76
+ export declare function planHistogram(kind: string, kindId: number, decl: RecordKindDeclaration, q: HistogramRequest): PlannedStatement;
77
+ export interface AggregateRequest {
78
+ readonly op: "sum" | "min" | "max" | "count";
79
+ readonly field?: string | undefined;
80
+ readonly groupBy?: string | undefined;
81
+ readonly where?: RecordWhere | undefined;
82
+ }
83
+ export declare function planAggregate(kind: string, kindId: number, decl: RecordKindDeclaration, q: AggregateRequest): PlannedStatement;
84
+ export interface DeleteWhereRequest extends WindowFilter {
85
+ readonly atBefore?: number | undefined;
86
+ readonly where?: RecordWhere | undefined;
87
+ }
88
+ /** The subselect that names up to `limit` rows to delete. */
89
+ export declare function planDeleteWhere(kind: string, kindId: number, decl: RecordKindDeclaration, q: DeleteWhereRequest, limit: number): PlannedStatement;
90
+ export {};
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The index-served proof of a record kind (D881, D447), run on the statements
3
+ * the engine REALLY prepares.
4
+ *
5
+ * A kind is declared with its indexes; this builds an in-memory engine, declares
6
+ * the kind, runs every operation the kind's declaration promises (by device and
7
+ * time, by id, by each declared index at each prefix length, the counts, the
8
+ * histogram, the aggregates over indexed fields, the bounded deletes) with a
9
+ * spy on `prepare`, and then EXPLAINs each captured statement:
10
+ *
11
+ * - no plan may be a table SCAN, and none may sort (`TEMP B-TREE FOR ORDER BY`);
12
+ * - every statement names `kind_id` as a literal (the partial indexes need it);
13
+ * - a count and an aggregate must not read the table row - checked on the
14
+ * opcodes, because `EXPLAIN QUERY PLAN` says `USING INDEX` either way.
15
+ *
16
+ * It is what `scripts/check-records-index-served.ts` runs over every declared
17
+ * kind, and what its spec runs over a deliberately broken one.
18
+ */
19
+ import Database from "better-sqlite3";
20
+ import type { DefinedRecordKind } from "@camstack/types";
21
+ export interface ProbeProblem {
22
+ readonly kind: string;
23
+ readonly op: string;
24
+ readonly problem: string;
25
+ }
26
+ export interface Captured {
27
+ readonly sql: string;
28
+ readonly params: readonly unknown[];
29
+ }
30
+ /** Judge one prepared statement. Exported so a spec can plant a bad one and watch it fail. */
31
+ export declare function judgeStatement(db: Database.Database, kind: string, op: string, statement: Captured): readonly ProbeProblem[];
32
+ /** Probe one kind. An empty answer means every promised operation is served from an index. */
33
+ export declare function probeKind(def: DefinedRecordKind): Promise<readonly ProbeProblem[]>;