@camstack/system 1.2.423 → 1.2.425
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-databases.d.ts +51 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +13 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +248 -17
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +248 -17
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +23 -3
- package/dist/builtins/backup-orchestrator/run-queue.d.ts +3 -0
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +7 -1
- package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +34 -0
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/database-snapshot-provider.d.ts +18 -0
- package/dist/builtins/sqlite-storage/file-host-client.d.ts +59 -0
- package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +23 -0
- package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +151 -0
- package/dist/builtins/sqlite-storage/file-host-worker.d.ts +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +21 -20
- package/dist/builtins/sqlite-storage/index.mjs +2 -1
- package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +136 -0
- package/dist/builtins/sqlite-storage/placement-errors.d.ts +60 -0
- package/dist/builtins/sqlite-storage/placement-router.d.ts +80 -0
- package/dist/builtins/sqlite-storage/retired-collections.d.ts +7 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +68 -8
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +23 -26
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/sqlite-storage/vector-provider.d.ts +24 -0
- package/dist/builtins/sqlite-storage/wal-maintenance.d.ts +17 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +3 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +3 -1
- package/dist/builtins/system-backup/system-backup.service.d.ts +48 -15
- package/dist/builtins/system-config/system-config.addon.js +2 -2
- package/dist/builtins/system-config/system-config.addon.mjs +2 -2
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-CgiAeG-2.js → composition-sources-197keifF.js} +1 -1
- package/dist/{composition-sources-BXDchWFn.mjs → composition-sources-DmzTSy26.mjs} +1 -1
- package/dist/{constants-1_7QtPNo.js → constants-B5Jd8Zch.js} +1 -1
- package/dist/{constants-C2dhkIuF.mjs → constants-CkNLi-XW.mjs} +1 -1
- package/dist/{dist-DimotS8e.mjs → dist-DMWeqeTF.mjs} +863 -750
- package/dist/{dist-VIIxVsBW.js → dist-DnALrQF-.js} +866 -747
- package/dist/file-host-worker.js +144 -0
- package/dist/file-host-worker.mjs +144 -0
- package/dist/index.js +9 -8
- package/dist/index.mjs +6 -5
- package/dist/{jwt-signing-key-C8nMdNYW.mjs → jwt-signing-key-CCHXAtrs.mjs} +1 -1
- package/dist/{jwt-signing-key-C8s9syVg.js → jwt-signing-key-DeqG7LD9.js} +1 -1
- package/dist/{restore-archive-DjppfrIB.js → restore-archive-C4UhQOsg.js} +156 -65
- package/dist/{restore-archive-bOMZwY0D.mjs → restore-archive-GevpOHw8.mjs} +151 -66
- package/dist/{retired-settings-keys-_muTvNyh.js → retired-settings-keys-0FOsnzIE.js} +1 -1
- package/dist/{retired-settings-keys-BYnjMBE-.mjs → retired-settings-keys-CdVFl7m2.mjs} +1 -1
- package/dist/sqlite-snapshot-worker.js +1 -1
- package/dist/sqlite-snapshot-worker.mjs +1 -1
- package/dist/wal-checkpoint-worker.js +1 -1
- package/dist/wal-checkpoint-worker.mjs +1 -1
- package/dist/wal-maintenance-BtfyfuT5.mjs +0 -0
- package/dist/wal-maintenance-DJV1rde2.js +0 -0
- package/package.json +1 -1
|
@@ -10880,6 +10880,568 @@ var authProviderCapability = {
|
|
|
10880
10880
|
mount: { kind: "skip" }
|
|
10881
10881
|
};
|
|
10882
10882
|
/**
|
|
10883
|
+
* Query filter for settings-store collections.
|
|
10884
|
+
*/
|
|
10885
|
+
var QueryFilterSchema = zod.z.object({
|
|
10886
|
+
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
10887
|
+
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
10888
|
+
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
10889
|
+
/** NULL-safe exclusion: matches rows whose field is NULL OR != the value. */
|
|
10890
|
+
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
10891
|
+
/** NULL-safe exclusion of a SET — `whereNot` for more than one value. An
|
|
10892
|
+
* empty list excludes nothing. See `QueryFilter.whereNotIn`. */
|
|
10893
|
+
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
10894
|
+
orderBy: zod.z.object({
|
|
10895
|
+
field: zod.z.string(),
|
|
10896
|
+
direction: zod.z.enum(["asc", "desc"])
|
|
10897
|
+
}).optional(),
|
|
10898
|
+
limit: zod.z.number().optional(),
|
|
10899
|
+
offset: zod.z.number().optional()
|
|
10900
|
+
});
|
|
10901
|
+
/**
|
|
10902
|
+
* The predicate half of a filter, for BULK MUTATIONS.
|
|
10903
|
+
*
|
|
10904
|
+
* Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
|
|
10905
|
+
* meaning for a statement that rewrites a set, and accepting them would invite
|
|
10906
|
+
* a caller to believe `limit` bounds the damage. Every field is optional here
|
|
10907
|
+
* only so the shape stays composable — the implementation REJECTS a filter
|
|
10908
|
+
* that compiles to no predicate, because that is the whole collection.
|
|
10909
|
+
*/
|
|
10910
|
+
var MutationFilterSchema = zod.z.object({
|
|
10911
|
+
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
10912
|
+
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
10913
|
+
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
10914
|
+
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
10915
|
+
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional()
|
|
10916
|
+
});
|
|
10917
|
+
/**
|
|
10918
|
+
* One scalar an {@link settingsStoreCapability.methods.aggregate} call asks for.
|
|
10919
|
+
*
|
|
10920
|
+
* `as` names the slot in the result, so the SAME column may be asked twice with
|
|
10921
|
+
* two operations (`MIN(startMs)` and `MAX(startMs)` in one round trip) — which
|
|
10922
|
+
* a `Record<column, op>` shape could not express.
|
|
10923
|
+
*/
|
|
10924
|
+
var AggregateFieldSchema = zod.z.object({
|
|
10925
|
+
/** Result key. */
|
|
10926
|
+
as: zod.z.string().min(1),
|
|
10927
|
+
/** Column to aggregate. Must be a real column of a declared collection. */
|
|
10928
|
+
field: zod.z.string().min(1),
|
|
10929
|
+
op: zod.z.enum([
|
|
10930
|
+
"sum",
|
|
10931
|
+
"min",
|
|
10932
|
+
"max"
|
|
10933
|
+
])
|
|
10934
|
+
});
|
|
10935
|
+
/**
|
|
10936
|
+
* `COUNT(*)` plus one number per requested field.
|
|
10937
|
+
*
|
|
10938
|
+
* `null` means NO ROW MATCHED, never zero: a `SUM` over an empty set and a sum
|
|
10939
|
+
* that really is 0 are different facts, and an accounting caller that renders
|
|
10940
|
+
* "0 bytes, oldest = 0" for "nothing here" reports a lie about a disk.
|
|
10941
|
+
*/
|
|
10942
|
+
var AggregateResultSchema = zod.z.object({
|
|
10943
|
+
count: zod.z.number().int(),
|
|
10944
|
+
values: zod.z.record(zod.z.string(), zod.z.number().nullable())
|
|
10945
|
+
});
|
|
10946
|
+
/** A single stored record: `{ id, data }`. */
|
|
10947
|
+
var SettingsRecordSchema = zod.z.object({
|
|
10948
|
+
id: zod.z.string(),
|
|
10949
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
10950
|
+
});
|
|
10951
|
+
/**
|
|
10952
|
+
* One record of a BULK insert — {@link SettingsRecordSchema} with the id made
|
|
10953
|
+
* optional.
|
|
10954
|
+
*
|
|
10955
|
+
* A separate schema rather than loosening the shared one: every other method
|
|
10956
|
+
* on this cap addresses a row BY its id, and making that field optional
|
|
10957
|
+
* everywhere would turn a forgotten key into a silently generated one on
|
|
10958
|
+
* `update` and `delete` as well.
|
|
10959
|
+
*/
|
|
10960
|
+
var BulkRecordSchema = zod.z.object({
|
|
10961
|
+
id: zod.z.string().optional(),
|
|
10962
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
10963
|
+
});
|
|
10964
|
+
/**
|
|
10965
|
+
* The database FILES one `sqlite-settings` engine process owns (D851).
|
|
10966
|
+
* Closed on purpose: a file is a thing the engine opens, backs up and gives a
|
|
10967
|
+
* serving thread, so a new one is a code change, never a string a caller
|
|
10968
|
+
* invents. `settings` is `camstack.db` and the default for every collection
|
|
10969
|
+
* that names no file.
|
|
10970
|
+
*/
|
|
10971
|
+
var DataStoreDatabaseSchema = zod.z.enum([
|
|
10972
|
+
"settings",
|
|
10973
|
+
"events",
|
|
10974
|
+
"history"
|
|
10975
|
+
]);
|
|
10976
|
+
/** Every database file, in a stable order (settings first). */
|
|
10977
|
+
var DATA_STORE_DATABASES = DataStoreDatabaseSchema.options;
|
|
10978
|
+
/**
|
|
10979
|
+
* One write inside a {@link settingsStoreCapability.methods.transact} call.
|
|
10980
|
+
* The three that a "replace this set, bump that revision" write needs, plus
|
|
10981
|
+
* the batched upsert a rollup writer needs.
|
|
10982
|
+
*/
|
|
10983
|
+
var TransactOpSchema = zod.z.discriminatedUnion("op", [
|
|
10984
|
+
zod.z.object({
|
|
10985
|
+
op: zod.z.literal("deleteWhere"),
|
|
10986
|
+
collection: zod.z.string(),
|
|
10987
|
+
filter: MutationFilterSchema
|
|
10988
|
+
}),
|
|
10989
|
+
zod.z.object({
|
|
10990
|
+
op: zod.z.literal("insertMany"),
|
|
10991
|
+
collection: zod.z.string(),
|
|
10992
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
10993
|
+
}),
|
|
10994
|
+
zod.z.object({
|
|
10995
|
+
op: zod.z.literal("update"),
|
|
10996
|
+
collection: zod.z.string(),
|
|
10997
|
+
id: zod.z.string(),
|
|
10998
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
10999
|
+
}),
|
|
11000
|
+
zod.z.object({
|
|
11001
|
+
op: zod.z.literal("upsertMany"),
|
|
11002
|
+
collection: zod.z.string(),
|
|
11003
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
11004
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
11005
|
+
})
|
|
11006
|
+
]);
|
|
11007
|
+
/**
|
|
11008
|
+
* The precondition of a transaction: the row `key` of `collection` must hold
|
|
11009
|
+
* `equals` in `column`, read INSIDE the transaction.
|
|
11010
|
+
*/
|
|
11011
|
+
var TransactGuardSchema = zod.z.object({
|
|
11012
|
+
collection: zod.z.string(),
|
|
11013
|
+
key: zod.z.string(),
|
|
11014
|
+
column: zod.z.string(),
|
|
11015
|
+
equals: zod.z.unknown()
|
|
11016
|
+
});
|
|
11017
|
+
/**
|
|
11018
|
+
* Column declaration for a structured (SQL-backed) collection.
|
|
11019
|
+
*
|
|
11020
|
+
* Logical types — the backend translates each to the matching SQLite
|
|
11021
|
+
* storage class and handles per-type marshaling:
|
|
11022
|
+
* - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
|
|
11023
|
+
* - `JSON` — TEXT under the hood; serialised on write, parsed on read
|
|
11024
|
+
* - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
|
|
11025
|
+
*/
|
|
11026
|
+
var CollectionColumnSchema = zod.z.object({
|
|
11027
|
+
name: zod.z.string(),
|
|
11028
|
+
type: zod.z.enum([
|
|
11029
|
+
"TEXT",
|
|
11030
|
+
"INTEGER",
|
|
11031
|
+
"REAL",
|
|
11032
|
+
"JSON",
|
|
11033
|
+
"BOOLEAN"
|
|
11034
|
+
]),
|
|
11035
|
+
primaryKey: zod.z.boolean().optional(),
|
|
11036
|
+
notNull: zod.z.boolean().optional(),
|
|
11037
|
+
unique: zod.z.boolean().optional(),
|
|
11038
|
+
/**
|
|
11039
|
+
* Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
|
|
11040
|
+
* columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
|
|
11041
|
+
* collection surface simply cannot express their existing tables — which is
|
|
11042
|
+
* why they were still on the uncapped `table*` API.
|
|
11043
|
+
*/
|
|
11044
|
+
defaultValue: zod.z.union([
|
|
11045
|
+
zod.z.string(),
|
|
11046
|
+
zod.z.number(),
|
|
11047
|
+
zod.z.boolean()
|
|
11048
|
+
]).optional()
|
|
11049
|
+
});
|
|
11050
|
+
var CollectionIndexSchema = zod.z.object({
|
|
11051
|
+
name: zod.z.string(),
|
|
11052
|
+
columns: zod.z.array(zod.z.string()).readonly(),
|
|
11053
|
+
unique: zod.z.boolean().optional()
|
|
11054
|
+
});
|
|
11055
|
+
/**
|
|
11056
|
+
* The input of `declareCollection` — ONE schema for the door and for the
|
|
11057
|
+
* engine behind it, so the two surfaces cannot drift (the dispatcher forwards
|
|
11058
|
+
* the payload untouched).
|
|
11059
|
+
*
|
|
11060
|
+
* - `database` — the file the collection lives in (D851). Absent means
|
|
11061
|
+
* `settings`. A declaration naming a file other than the one the table is
|
|
11062
|
+
* already in is REFUSED by the engine, never moved.
|
|
11063
|
+
* - `primaryKey` — a COMPOSITE key, as column names. A single name is the same
|
|
11064
|
+
* as `primaryKey: true` on that column. A composite-keyed collection has no
|
|
11065
|
+
* `id`: it is written with `insertMany` / `upsertMany` / `transact` and read
|
|
11066
|
+
* with `query` / `count` / `aggregate` / `deleteWhere`; the calls that
|
|
11067
|
+
* address one row by id are refused.
|
|
11068
|
+
* - `withoutRowid` — emit `WITHOUT ROWID`. Requires a primary key.
|
|
11069
|
+
*/
|
|
11070
|
+
var DeclareCollectionInputSchema = zod.z.object({
|
|
11071
|
+
namespace: zod.z.string().optional(),
|
|
11072
|
+
collection: zod.z.string(),
|
|
11073
|
+
columns: zod.z.array(CollectionColumnSchema).readonly(),
|
|
11074
|
+
indexes: zod.z.array(CollectionIndexSchema).readonly().optional(),
|
|
11075
|
+
database: DataStoreDatabaseSchema.optional(),
|
|
11076
|
+
primaryKey: zod.z.array(zod.z.string()).readonly().optional(),
|
|
11077
|
+
withoutRowid: zod.z.boolean().optional()
|
|
11078
|
+
});
|
|
11079
|
+
/**
|
|
11080
|
+
* settings-store — singleton capability for addon-scoped persistence.
|
|
11081
|
+
*
|
|
11082
|
+
* Every method operates within a `collection`. An optional `namespace`
|
|
11083
|
+
* field provides access to additional data spaces beyond the default
|
|
11084
|
+
* addon settings — useful for business data (events, tracks, faces, etc.).
|
|
11085
|
+
*
|
|
11086
|
+
* **Scoping is the CALLER's, and it is opt-in.** The table is
|
|
11087
|
+
* `namespace ? `${namespace}:${collection}` : collection` — nothing
|
|
11088
|
+
* consults the identity of the caller. An earlier version of this comment
|
|
11089
|
+
* claimed the implementation prefixes every collection with the calling
|
|
11090
|
+
* addon's ID and that "addons never see each other's data"; that was never
|
|
11091
|
+
* true, and this same file contradicted it under `declareCollection`. What
|
|
11092
|
+
* exists is `addon-context-factory`, which passes `namespace: addonId` ON
|
|
11093
|
+
* THE ADDON'S BEHALF for the `addon-settings` / `addon-devices` paths only.
|
|
11094
|
+
* Business collections use bare names, and any caller may name any
|
|
11095
|
+
* namespace, or none. Making the door enforce it is tracked separately —
|
|
11096
|
+
* it renames tables, so it needs a migration.
|
|
11097
|
+
*
|
|
11098
|
+
* **So every method is `auth: 'admin'` (D634).** Because nothing scopes a
|
|
11099
|
+
* call to its caller, a `protected` method here was a raw, unredacted read
|
|
11100
|
+
* (and write) of every addon's collections for any role holding
|
|
11101
|
+
* `category:system` — which is every role: a `viewer` could read every
|
|
11102
|
+
* notifier token in plaintext from `notifiers:notification-targets`. No
|
|
11103
|
+
* browser or app client calls this cap. Addons are not affected: an
|
|
11104
|
+
* addon's `ctx.api` cap call is resolved to the provider directly and never
|
|
11105
|
+
* enters the tRPC router (so the tier gates sessions and tokens, never
|
|
11106
|
+
* addons), and the hub itself calls it through the capability registry.
|
|
11107
|
+
*
|
|
11108
|
+
* - `{ collection: 'addon-settings' }` → table `addon-settings`
|
|
11109
|
+
* - `{ namespace: 'my-addon', collection: 'addon-settings' }` →
|
|
11110
|
+
* table `my-addon:addon-settings`
|
|
11111
|
+
*
|
|
11112
|
+
* Served by the **storage-orchestrator** builtin, which dispatches to the
|
|
11113
|
+
* `data-store-provider` engine registered for the collection
|
|
11114
|
+
* (`sqlite-settings`, a SQLite WAL backend, today). One addon owns the
|
|
11115
|
+
* data door; engines sit behind it
|
|
11116
|
+
* ([D44](../../../../docs/decisions/adr-0044.md)).
|
|
11117
|
+
* Addons access it via `ctx.api.settingsStore.*`.
|
|
11118
|
+
*/
|
|
11119
|
+
var settingsStoreCapability = {
|
|
11120
|
+
name: "settings-store",
|
|
11121
|
+
scope: "system",
|
|
11122
|
+
mode: "singleton",
|
|
11123
|
+
methods: {
|
|
11124
|
+
/** Get a single value by key from a collection. */
|
|
11125
|
+
get: method(zod.z.object({
|
|
11126
|
+
namespace: zod.z.string().optional(),
|
|
11127
|
+
collection: zod.z.string(),
|
|
11128
|
+
key: zod.z.string()
|
|
11129
|
+
}), zod.z.unknown(), { auth: "admin" }),
|
|
11130
|
+
/** Set a value by key in a collection (upsert). */
|
|
11131
|
+
set: method(zod.z.object({
|
|
11132
|
+
namespace: zod.z.string().optional(),
|
|
11133
|
+
collection: zod.z.string(),
|
|
11134
|
+
key: zod.z.string(),
|
|
11135
|
+
value: zod.z.unknown()
|
|
11136
|
+
}), zod.z.void(), {
|
|
11137
|
+
kind: "mutation",
|
|
11138
|
+
auth: "admin"
|
|
11139
|
+
}),
|
|
11140
|
+
/**
|
|
11141
|
+
* Rows matching a filter.
|
|
11142
|
+
*
|
|
11143
|
+
* `columns` is a SQL-level projection: the engine SELECTs only those
|
|
11144
|
+
* columns (plus the primary key) instead of the whole row. It is the only
|
|
11145
|
+
* way to stop paying disk for a column that is discarded — a heavy JSON
|
|
11146
|
+
* column dominates the row, and dropping it in JS after the read pays every
|
|
11147
|
+
* byte first. Measured on the live `pipeline-analytics:tracks` table: a
|
|
11148
|
+
* 501-row page is 4.6 MB whole and 0.11 MB projected, same index, same
|
|
11149
|
+
* plan.
|
|
11150
|
+
*
|
|
11151
|
+
* The engine REFUSES a column it cannot serve rather than omitting it —
|
|
11152
|
+
* see `SettingsQueryInput.columns` for why a projection may not be
|
|
11153
|
+
* forgiving the way a predicate is.
|
|
11154
|
+
*/
|
|
11155
|
+
query: method(zod.z.object({
|
|
11156
|
+
namespace: zod.z.string().optional(),
|
|
11157
|
+
collection: zod.z.string(),
|
|
11158
|
+
filter: QueryFilterSchema.optional(),
|
|
11159
|
+
columns: zod.z.array(zod.z.string()).readonly().optional()
|
|
11160
|
+
}), zod.z.array(SettingsRecordSchema).readonly(), { auth: "admin" }),
|
|
11161
|
+
/**
|
|
11162
|
+
* Make a SLOT hold this row — insert it, or update whatever already
|
|
11163
|
+
* occupies the slot — and answer with the id the row HAS.
|
|
11164
|
+
*
|
|
11165
|
+
* ## Why the store needed this
|
|
11166
|
+
*
|
|
11167
|
+
* {@link set} is already an upsert, but its slot is the PRIMARY KEY: the
|
|
11168
|
+
* caller has to know the id to address the row. That is exactly what a
|
|
11169
|
+
* collection keyed by an `INTEGER` rowid alias cannot do — SQLite assigns
|
|
11170
|
+
* the id, so a writer whose uniqueness rule is "one row per
|
|
11171
|
+
* `(ownerKind, ownerId, kind, slot)`" has no id to name and no way to
|
|
11172
|
+
* express the rule. {@link insert} can express it (a UNIQUE index
|
|
11173
|
+
* arbitrates) but only by THROWING at the loser of a race, and the loser
|
|
11174
|
+
* here is a legitimate re-capture, not an error.
|
|
11175
|
+
*
|
|
11176
|
+
* Getting there without this method means read-then-write: query the slot,
|
|
11177
|
+
* then `insert` or `update`. Two statements instead of one, a race between
|
|
11178
|
+
* them, and a recovery path that has to recognise a UNIQUE violation by its
|
|
11179
|
+
* MESSAGE — across a process boundary, because the store lives behind an
|
|
11180
|
+
* RPC door. A string match would be the whole gate, and a store that
|
|
11181
|
+
* rephrased its error would lose the row silently. One statement has no
|
|
11182
|
+
* such gate (D482).
|
|
11183
|
+
*
|
|
11184
|
+
* ## The contract
|
|
11185
|
+
*
|
|
11186
|
+
* `conflict` names the DECLARED columns that identify the slot. They must
|
|
11187
|
+
* be covered by a UNIQUE index on the collection — SQLite resolves an
|
|
11188
|
+
* `ON CONFLICT` target against its indexes and REFUSES the statement when
|
|
11189
|
+
* none matches, so a wrong list is a loud error on the first write, never a
|
|
11190
|
+
* silently duplicated row. An empty list is refused rather than passed on:
|
|
11191
|
+
* `ON CONFLICT()` is not valid SQL, and the intent it would most likely
|
|
11192
|
+
* encode ("no slot, just insert") is {@link insert}.
|
|
11193
|
+
*
|
|
11194
|
+
* Row shape is {@link insert}'s: `record.id` is used when the collection
|
|
11195
|
+
* needs a supplied key and IGNORED when the primary key is an `INTEGER`
|
|
11196
|
+
* rowid alias — exactly as `insert` and `insertMany` already treat it.
|
|
11197
|
+
*
|
|
11198
|
+
* Returns the id either way: the one SQLite assigned on an insert, or the
|
|
11199
|
+
* one the row it updated already had. A caller cannot tell which happened,
|
|
11200
|
+
* and deliberately — every caller wants the slot's id, and one that needed
|
|
11201
|
+
* to distinguish creation from replacement would have to read first anyway.
|
|
11202
|
+
*/
|
|
11203
|
+
upsert: method(zod.z.object({
|
|
11204
|
+
namespace: zod.z.string().optional(),
|
|
11205
|
+
collection: zod.z.string(),
|
|
11206
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
11207
|
+
* index on the collection. Never empty. */
|
|
11208
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
11209
|
+
record: BulkRecordSchema
|
|
11210
|
+
}), zod.z.object({
|
|
11211
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
11212
|
+
* row's own id on an update. */
|
|
11213
|
+
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
11214
|
+
kind: "mutation",
|
|
11215
|
+
auth: "admin"
|
|
11216
|
+
}),
|
|
11217
|
+
/**
|
|
11218
|
+
* {@link upsert} for a BATCH, in ONE transaction on ONE prepared statement.
|
|
11219
|
+
*
|
|
11220
|
+
* The write-side twin of {@link insertMany} for rows that may already
|
|
11221
|
+
* exist: a rollup writer recomputes a bucket and must overwrite it, and
|
|
11222
|
+
* N round trips with N COMMITs is the cost {@link insertMany} was added to
|
|
11223
|
+
* avoid. `conflict` has the meaning it has on {@link upsert} (declared
|
|
11224
|
+
* columns covered by a UNIQUE index or the primary key, never empty).
|
|
11225
|
+
*
|
|
11226
|
+
* Every record of a batch must carry the SAME set of declared columns and
|
|
11227
|
+
* every `conflict` column: one batch is one statement shape, and a record
|
|
11228
|
+
* that silently bound NULL over a column it did not mention would erase
|
|
11229
|
+
* it. A heterogeneous batch is refused whole. **All or nothing.**
|
|
11230
|
+
*/
|
|
11231
|
+
upsertMany: method(zod.z.object({
|
|
11232
|
+
namespace: zod.z.string().optional(),
|
|
11233
|
+
collection: zod.z.string(),
|
|
11234
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
11235
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
11236
|
+
}), zod.z.object({ upserted: zod.z.number().int() }), {
|
|
11237
|
+
kind: "mutation",
|
|
11238
|
+
auth: "admin"
|
|
11239
|
+
}),
|
|
11240
|
+
/** Insert a new record. */
|
|
11241
|
+
insert: method(zod.z.object({
|
|
11242
|
+
namespace: zod.z.string().optional(),
|
|
11243
|
+
collection: zod.z.string(),
|
|
11244
|
+
record: zod.z.object({
|
|
11245
|
+
id: zod.z.string().optional(),
|
|
11246
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
11247
|
+
})
|
|
11248
|
+
}), zod.z.object({
|
|
11249
|
+
/**
|
|
11250
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
11251
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
11252
|
+
* primary key — which is the only place an auto key is knowable.
|
|
11253
|
+
*/
|
|
11254
|
+
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
11255
|
+
kind: "mutation",
|
|
11256
|
+
auth: "admin"
|
|
11257
|
+
}),
|
|
11258
|
+
/**
|
|
11259
|
+
* Insert MANY records in ONE transaction, returning how many landed.
|
|
11260
|
+
*
|
|
11261
|
+
* The write-side twin of {@link deleteWhere}, and it exists for the same
|
|
11262
|
+
* reason: without it, appending a batch is N round trips and N COMMITs on
|
|
11263
|
+
* the single shared connection that also serves every cluster-wide
|
|
11264
|
+
* configuration read. The durable load series writes one process row per
|
|
11265
|
+
* process per sample — 76 rows every 10 s on the live fleet — and the
|
|
11266
|
+
* operator's rule for it is *one transaction per sample, never one per
|
|
11267
|
+
* row*. `insert` cannot express that; nothing else could.
|
|
11268
|
+
*
|
|
11269
|
+
* **All or nothing.** A batch that fails on its fifth row leaves none of
|
|
11270
|
+
* the five behind. A half-written sample is worse than a missing one: the
|
|
11271
|
+
* missing one reads as "nobody reported", which is true, while the half
|
|
11272
|
+
* one reads as "these were the only processes running", which is not.
|
|
11273
|
+
*
|
|
11274
|
+
* `id` is OPTIONAL per record, and that is the difference from
|
|
11275
|
+
* {@link insert}. A collection whose primary key is an `INTEGER` rowid
|
|
11276
|
+
* alias has no id to supply — SQLite assigns it, for free, and inventing a
|
|
11277
|
+
* `randomUUID()` for such a column would write a 36-character string into
|
|
11278
|
+
* an integer key. Omitted on a TEXT key, a uuid is generated exactly as
|
|
11279
|
+
* `insert` does.
|
|
11280
|
+
*/
|
|
11281
|
+
insertMany: method(zod.z.object({
|
|
11282
|
+
namespace: zod.z.string().optional(),
|
|
11283
|
+
collection: zod.z.string(),
|
|
11284
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
11285
|
+
}), zod.z.object({ inserted: zod.z.number().int() }), {
|
|
11286
|
+
kind: "mutation",
|
|
11287
|
+
auth: "admin"
|
|
11288
|
+
}),
|
|
11289
|
+
/**
|
|
11290
|
+
* Several writes, ONE transaction, behind an optional precondition.
|
|
11291
|
+
*
|
|
11292
|
+
* The multi-collection twin of {@link insertMany}: a write that has to move
|
|
11293
|
+
* a set of rows in one collection AND a revision in another cannot be
|
|
11294
|
+
* expressed as separate calls without a window in which a reader (or a
|
|
11295
|
+
* crash) sees half of it. The retrain annotation save replaces a frame's
|
|
11296
|
+
* rows, its dismissed set and its revision this way.
|
|
11297
|
+
*
|
|
11298
|
+
* `guard`, when given, is read inside the transaction: if the row is
|
|
11299
|
+
* missing or its column differs from `equals`, NOTHING is written and the
|
|
11300
|
+
* answer is `{ applied: false, current }` with what was found — the
|
|
11301
|
+
* compare-and-set a revisioned write needs, with no second reader able to
|
|
11302
|
+
* slip between the check and the writes.
|
|
11303
|
+
*
|
|
11304
|
+
* **All or nothing**, like {@link insertMany}: a throw in any op rolls the
|
|
11305
|
+
* whole call back. Ops run in the order given (delete before insert to
|
|
11306
|
+
* replace a set). `namespace` applies to every collection named.
|
|
11307
|
+
*/
|
|
11308
|
+
transact: method(zod.z.object({
|
|
11309
|
+
namespace: zod.z.string().optional(),
|
|
11310
|
+
guard: TransactGuardSchema.optional(),
|
|
11311
|
+
ops: zod.z.array(TransactOpSchema).readonly()
|
|
11312
|
+
}), zod.z.object({
|
|
11313
|
+
applied: zod.z.boolean(),
|
|
11314
|
+
current: zod.z.unknown().optional()
|
|
11315
|
+
}), {
|
|
11316
|
+
kind: "mutation",
|
|
11317
|
+
auth: "admin"
|
|
11318
|
+
}),
|
|
11319
|
+
/** Update an existing record by ID. */
|
|
11320
|
+
update: method(zod.z.object({
|
|
11321
|
+
namespace: zod.z.string().optional(),
|
|
11322
|
+
collection: zod.z.string(),
|
|
11323
|
+
id: zod.z.string(),
|
|
11324
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
11325
|
+
}), zod.z.void(), {
|
|
11326
|
+
kind: "mutation",
|
|
11327
|
+
auth: "admin"
|
|
11328
|
+
}),
|
|
11329
|
+
/** Delete a record by key/ID. */
|
|
11330
|
+
delete: method(zod.z.object({
|
|
11331
|
+
namespace: zod.z.string().optional(),
|
|
11332
|
+
collection: zod.z.string(),
|
|
11333
|
+
key: zod.z.string()
|
|
11334
|
+
}), zod.z.void(), {
|
|
11335
|
+
kind: "mutation",
|
|
11336
|
+
auth: "admin"
|
|
11337
|
+
}),
|
|
11338
|
+
/**
|
|
11339
|
+
* Delete every record matching `filter`, in ONE statement, returning how
|
|
11340
|
+
* many rows went. This exists because its absence made every retention
|
|
11341
|
+
* path in the system an N+1 drain loop: `delete` takes a key, so a sweep
|
|
11342
|
+
* had to SELECT a page of full rows — every column, including the fat
|
|
11343
|
+
* ones — purely to learn their ids, then issue one call per row.
|
|
11344
|
+
*
|
|
11345
|
+
* **The filter is required and must resolve.** A predicate naming
|
|
11346
|
+
* something the collection cannot express is an ERROR here, not a
|
|
11347
|
+
* widening as it is on `query`, and a filter with no predicates is an
|
|
11348
|
+
* error rather than "every row". Deleting a whole collection is a
|
|
11349
|
+
* legitimate intent, but it must be asked for by name — not reached by
|
|
11350
|
+
* an empty object.
|
|
11351
|
+
*/
|
|
11352
|
+
deleteWhere: method(zod.z.object({
|
|
11353
|
+
namespace: zod.z.string().optional(),
|
|
11354
|
+
collection: zod.z.string(),
|
|
11355
|
+
filter: MutationFilterSchema
|
|
11356
|
+
}), zod.z.object({ deleted: zod.z.number().int() }), {
|
|
11357
|
+
kind: "mutation",
|
|
11358
|
+
auth: "admin"
|
|
11359
|
+
}),
|
|
11360
|
+
/**
|
|
11361
|
+
* Apply `data` to every record matching `filter`, in one statement,
|
|
11362
|
+
* returning how many rows changed. Same filter contract as
|
|
11363
|
+
* {@link deleteWhere} — an unresolvable predicate is an error.
|
|
11364
|
+
*/
|
|
11365
|
+
updateWhere: method(zod.z.object({
|
|
11366
|
+
namespace: zod.z.string().optional(),
|
|
11367
|
+
collection: zod.z.string(),
|
|
11368
|
+
filter: MutationFilterSchema,
|
|
11369
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
11370
|
+
}), zod.z.object({ updated: zod.z.number().int() }), {
|
|
11371
|
+
kind: "mutation",
|
|
11372
|
+
auth: "admin"
|
|
11373
|
+
}),
|
|
11374
|
+
/** Count entries in a collection, optionally filtered. */
|
|
11375
|
+
count: method(zod.z.object({
|
|
11376
|
+
namespace: zod.z.string().optional(),
|
|
11377
|
+
collection: zod.z.string(),
|
|
11378
|
+
filter: QueryFilterSchema.optional()
|
|
11379
|
+
}), zod.z.number(), { auth: "admin" }),
|
|
11380
|
+
/**
|
|
11381
|
+
* `COUNT(*)` and one `SUM` / `MIN` / `MAX` per requested field, in ONE
|
|
11382
|
+
* statement, over the rows `filter` selects.
|
|
11383
|
+
*
|
|
11384
|
+
* Exists because "how much is there" was being answered by materialising
|
|
11385
|
+
* "what is there". The recorder's storage-pressure sweep asked its in-RAM
|
|
11386
|
+
* footage index for bytes/count/oldest/newest across a set of storage
|
|
11387
|
+
* locations twice a minute, and the only way to answer that from a map is
|
|
11388
|
+
* to visit every row — 7.1 M of them on the live hub, ~15 M row visits a
|
|
11389
|
+
* minute on the main thread, which is also why the whole archive had to
|
|
11390
|
+
* stay resident to be visited. The question is a sum; nothing needs to be
|
|
11391
|
+
* materialised to answer it.
|
|
11392
|
+
*
|
|
11393
|
+
* **The engine REFUSES a field it cannot serve**, exactly as
|
|
11394
|
+
* `query.columns` does and unlike a PREDICATE, which is skipped when
|
|
11395
|
+
* unresolvable. A dropped predicate over-matches and the caller sees extra
|
|
11396
|
+
* rows; a dropped aggregate returns a NUMBER that is wrong and looks
|
|
11397
|
+
* exactly like a real one. That asymmetry is what this repo has already
|
|
11398
|
+
* paid for once in `count`.
|
|
11399
|
+
*/
|
|
11400
|
+
aggregate: method(zod.z.object({
|
|
11401
|
+
namespace: zod.z.string().optional(),
|
|
11402
|
+
collection: zod.z.string(),
|
|
11403
|
+
fields: zod.z.array(AggregateFieldSchema).readonly(),
|
|
11404
|
+
filter: QueryFilterSchema.optional()
|
|
11405
|
+
}), AggregateResultSchema, { auth: "admin" }),
|
|
11406
|
+
/** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
|
|
11407
|
+
histogram: method(zod.z.object({
|
|
11408
|
+
namespace: zod.z.string().optional(),
|
|
11409
|
+
collection: zod.z.string(),
|
|
11410
|
+
field: zod.z.string(),
|
|
11411
|
+
bucketSize: zod.z.number().int().positive(),
|
|
11412
|
+
origin: zod.z.number().int(),
|
|
11413
|
+
filter: QueryFilterSchema.optional()
|
|
11414
|
+
}), zod.z.array(zod.z.object({
|
|
11415
|
+
bucket: zod.z.number().int(),
|
|
11416
|
+
count: zod.z.number().int()
|
|
11417
|
+
})).readonly(), { auth: "admin" }),
|
|
11418
|
+
/** Check if a collection is empty. */
|
|
11419
|
+
isEmpty: method(zod.z.object({
|
|
11420
|
+
namespace: zod.z.string().optional(),
|
|
11421
|
+
collection: zod.z.string()
|
|
11422
|
+
}), zod.z.boolean(), { auth: "admin" }),
|
|
11423
|
+
/**
|
|
11424
|
+
* Declare a typed (SQL-backed) collection with explicit columns +
|
|
11425
|
+
* indexes. Idempotent: re-declaring an existing collection with the
|
|
11426
|
+
* same shape is a no-op; shape changes (new columns, new indexes)
|
|
11427
|
+
* are applied additively. Subsequent `insert` / `update` / `delete`
|
|
11428
|
+
* / `query` calls on this collection use typed columns instead of
|
|
11429
|
+
* JSON-blob storage — `record.data` fields are spread across
|
|
11430
|
+
* columns, `query.filter.where` matches real columns (no
|
|
11431
|
+
* `json_extract` overhead), `orderBy` uses column indexes.
|
|
11432
|
+
*
|
|
11433
|
+
* Addons call this in `onInitialize` before their first read/write.
|
|
11434
|
+
* Collection names should be namespaced by addon (e.g.
|
|
11435
|
+
* `pipeline-analytics:object-events`) to avoid cross-addon
|
|
11436
|
+
* clashes — no automatic prefix is added.
|
|
11437
|
+
*/
|
|
11438
|
+
declareCollection: method(DeclareCollectionInputSchema, zod.z.void(), {
|
|
11439
|
+
kind: "mutation",
|
|
11440
|
+
auth: "admin"
|
|
11441
|
+
})
|
|
11442
|
+
}
|
|
11443
|
+
};
|
|
11444
|
+
/**
|
|
10883
11445
|
* The suffix of a verified snapshot, written next to the live database it
|
|
10884
11446
|
* copies: `<db>.backup-snapshot`. A restore promotes it back over `<db>`
|
|
10885
11447
|
* (`server/backend/src/sqlite-restore.ts` spells the same string — the
|
|
@@ -10906,7 +11468,11 @@ var DATABASE_SNAPSHOT_TIMEOUT_MS = 30 * 6e4;
|
|
|
10906
11468
|
* database has no sidecars and is just as owned). Paths are absolute on the
|
|
10907
11469
|
* owner's host.
|
|
10908
11470
|
*/
|
|
10909
|
-
var DatabaseSnapshotTargetsSchema = zod.z.object({ databases: zod.z.array(zod.z.object({
|
|
11471
|
+
var DatabaseSnapshotTargetsSchema = zod.z.object({ databases: zod.z.array(zod.z.object({
|
|
11472
|
+
/** Which owned file this is — the handle `writeSnapshot` takes. */
|
|
11473
|
+
databaseId: DataStoreDatabaseSchema,
|
|
11474
|
+
livePath: zod.z.string()
|
|
11475
|
+
})) });
|
|
10910
11476
|
/** One b-tree table of the snapshot and the rows it holds. */
|
|
10911
11477
|
var DatabaseSnapshotTableSchema = zod.z.object({
|
|
10912
11478
|
name: zod.z.string(),
|
|
@@ -10939,6 +11505,10 @@ var DatabaseSnapshotResultSchema = zod.z.object({
|
|
|
10939
11505
|
/** When the pinned read transaction began (ms epoch) — the snapshot's instant. */
|
|
10940
11506
|
takenAt: zod.z.number()
|
|
10941
11507
|
});
|
|
11508
|
+
/** A snapshot the owner wrote, with the file it belongs to. */
|
|
11509
|
+
var DatabaseSnapshotWrittenSchema = DatabaseSnapshotResultSchema.extend({ databaseId: DataStoreDatabaseSchema });
|
|
11510
|
+
/** Which database `writeSnapshot` copies. Required: an unstated ask is not guessed. */
|
|
11511
|
+
var DatabaseSnapshotRequestSchema = zod.z.object({ databaseId: DataStoreDatabaseSchema });
|
|
10942
11512
|
/**
|
|
10943
11513
|
* A snapshot as an ARCHIVE records it (`ArchiveManifest.sqliteSnapshots`):
|
|
10944
11514
|
* the same facts, with both paths relative to the archive root (the node's
|
|
@@ -10948,7 +11518,9 @@ var ArchiveSqliteSnapshotSchema = DatabaseSnapshotResultSchema.extend({
|
|
|
10948
11518
|
/** Archive-relative path of the live database the archive does NOT carry. */
|
|
10949
11519
|
livePath: zod.z.string(),
|
|
10950
11520
|
/** Archive-relative path of the verified copy it carries in its place. */
|
|
10951
|
-
snapshotPath: zod.z.string()
|
|
11521
|
+
snapshotPath: zod.z.string(),
|
|
11522
|
+
/** Absent on an archive made before several files were owned: that was `settings`. */
|
|
11523
|
+
databaseId: DataStoreDatabaseSchema.optional()
|
|
10952
11524
|
});
|
|
10953
11525
|
/**
|
|
10954
11526
|
* database-snapshot — the OWNER of a live SQLite database writes a consistent,
|
|
@@ -10973,17 +11545,21 @@ var databaseSnapshotCapability = {
|
|
|
10973
11545
|
internal: true,
|
|
10974
11546
|
methods: {
|
|
10975
11547
|
/**
|
|
10976
|
-
*
|
|
10977
|
-
* touched — so a backup can ask it before deciding
|
|
11548
|
+
* EVERY database file this owner has open, with its id. Answered from
|
|
11549
|
+
* memory — no file is touched — so a backup can ask it before deciding
|
|
11550
|
+
* anything. A file created at runtime is listed from the moment it opens,
|
|
11551
|
+
* so no backup can leave it out (D693).
|
|
10978
11552
|
*/
|
|
10979
11553
|
listDatabases: method(zod.z.object({}), DatabaseSnapshotTargetsSchema, { auth: "admin" }),
|
|
10980
11554
|
/**
|
|
10981
|
-
* Write `<db>.backup-snapshot` and return what it holds.
|
|
10982
|
-
* leaves no file under the final name — when the copy fails
|
|
10983
|
-
* `integrity_check` or its row counts differ from the pinned source's
|
|
10984
|
-
* A second call
|
|
11555
|
+
* Write `<db>.backup-snapshot` for ONE database and return what it holds.
|
|
11556
|
+
* Throws — and leaves no file under the final name — when the copy fails
|
|
11557
|
+
* `integrity_check` or its row counts differ from the pinned source's, or
|
|
11558
|
+
* when the database is not open. A second call for the SAME database while
|
|
11559
|
+
* one is running joins it; different databases run one after the other
|
|
11560
|
+
* (the disk reserve check is per copy).
|
|
10985
11561
|
*/
|
|
10986
|
-
writeSnapshot: method(
|
|
11562
|
+
writeSnapshot: method(DatabaseSnapshotRequestSchema, DatabaseSnapshotWrittenSchema, {
|
|
10987
11563
|
kind: "mutation",
|
|
10988
11564
|
auth: "admin",
|
|
10989
11565
|
timeoutMs: DATABASE_SNAPSHOT_TIMEOUT_MS
|
|
@@ -11106,7 +11682,12 @@ var BackupArchiveEntrySchema = zod.z.object({
|
|
|
11106
11682
|
/** Top-level locations included in the archive (db, addons, tls, …). */
|
|
11107
11683
|
locations: zod.z.array(zod.z.string()).readonly(),
|
|
11108
11684
|
/** Present when the archive is encrypted; restore then needs that key. */
|
|
11109
|
-
encryption: BackupArchiveEncryptionSchema.optional()
|
|
11685
|
+
encryption: BackupArchiveEncryptionSchema.optional(),
|
|
11686
|
+
/**
|
|
11687
|
+
* The databases the run asked to carry (its retention class). Absent on an
|
|
11688
|
+
* archive made before several files were owned: that was `['settings']`.
|
|
11689
|
+
*/
|
|
11690
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly().optional()
|
|
11110
11691
|
});
|
|
11111
11692
|
var BackupEntrySchema = zod.z.object({
|
|
11112
11693
|
id: zod.z.string(),
|
|
@@ -11140,7 +11721,12 @@ var ArchiveManifestSchema = zod.z.object({
|
|
|
11140
11721
|
* Live SQLite databases this archive carries as their OWNER's verified
|
|
11141
11722
|
* snapshot instead of as files (D693). Absent on archives made before.
|
|
11142
11723
|
*/
|
|
11143
|
-
sqliteSnapshots: zod.z.array(ArchiveSqliteSnapshotSchema).optional()
|
|
11724
|
+
sqliteSnapshots: zod.z.array(ArchiveSqliteSnapshotSchema).optional(),
|
|
11725
|
+
/**
|
|
11726
|
+
* Owned database files the run did NOT carry (not selected): left out of the
|
|
11727
|
+
* tar and the entry list alike. Absent when every owned file was carried.
|
|
11728
|
+
*/
|
|
11729
|
+
omittedDatabases: zod.z.array(DataStoreDatabaseSchema).optional()
|
|
11144
11730
|
});
|
|
11145
11731
|
var LocationStatSchema = zod.z.object({
|
|
11146
11732
|
name: zod.z.string(),
|
|
@@ -11262,6 +11848,12 @@ var BackupScheduleSchema = zod.z.object({
|
|
|
11262
11848
|
/** Optional subset of source locations to include; omitted = all. */
|
|
11263
11849
|
dataSources: zod.z.array(zod.z.string()).readonly().optional(),
|
|
11264
11850
|
/**
|
|
11851
|
+
* Which database files this schedule carries. Absent = `['settings']`
|
|
11852
|
+
* (an unstated ask is the minimum, D382). Events and history run weekly,
|
|
11853
|
+
* settings nightly (D852).
|
|
11854
|
+
*/
|
|
11855
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly().optional(),
|
|
11856
|
+
/**
|
|
11265
11857
|
* ms-epoch of the last tick that FIRED this schedule. Stamped before the
|
|
11266
11858
|
* archive runs (it is the dedupe anchor), so it says "attempted", never
|
|
11267
11859
|
* "succeeded" — a run refused by every destination stamps it too.
|
|
@@ -11313,7 +11905,9 @@ var backupCapability = {
|
|
|
11313
11905
|
* retention). Omitted = each destination's own policy
|
|
11314
11906
|
* retention (manual runs).
|
|
11315
11907
|
*/
|
|
11316
|
-
retentionCount: zod.z.number().int().min(1).max(1e3).optional()
|
|
11908
|
+
retentionCount: zod.z.number().int().min(1).max(1e3).optional(),
|
|
11909
|
+
/** Database files to carry; omitted = `['settings']`. */
|
|
11910
|
+
databases: zod.z.array(DataStoreDatabaseSchema).optional()
|
|
11317
11911
|
}).optional(), BackupTriggerResultSchema, {
|
|
11318
11912
|
kind: "mutation",
|
|
11319
11913
|
auth: "admin"
|
|
@@ -11483,7 +12077,8 @@ var backupCapability = {
|
|
|
11483
12077
|
enabled: zod.z.boolean(),
|
|
11484
12078
|
locationIds: zod.z.array(zod.z.string()).readonly(),
|
|
11485
12079
|
retentionCount: zod.z.number().int().min(1).max(1e3),
|
|
11486
|
-
dataSources: zod.z.array(zod.z.string()).readonly().optional()
|
|
12080
|
+
dataSources: zod.z.array(zod.z.string()).readonly().optional(),
|
|
12081
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly().optional()
|
|
11487
12082
|
}), BackupScheduleSchema, {
|
|
11488
12083
|
kind: "mutation",
|
|
11489
12084
|
auth: "admin"
|
|
@@ -14778,774 +15373,275 @@ var CoreBlockCompileResultSchema = zod.z.object({
|
|
|
14778
15373
|
*/
|
|
14779
15374
|
var CoreBlockCompileInputSchema = zod.z.object({
|
|
14780
15375
|
code: zod.z.string().optional(),
|
|
14781
|
-
files: CoreBlockFilesSchema.optional(),
|
|
14782
|
-
entry: zod.z.string().min(1).max(260).optional()
|
|
14783
|
-
}).superRefine((val, ctx) => {
|
|
14784
|
-
if (val.files !== void 0) {
|
|
14785
|
-
const entry = val.entry ?? "main.ts";
|
|
14786
|
-
if (val.files[entry] === void 0) ctx.addIssue({
|
|
14787
|
-
code: "custom",
|
|
14788
|
-
message: `files must include the entry "${entry}"`,
|
|
14789
|
-
path: ["files"]
|
|
14790
|
-
});
|
|
14791
|
-
return;
|
|
14792
|
-
}
|
|
14793
|
-
if (val.code === void 0) ctx.addIssue({
|
|
14794
|
-
code: "custom",
|
|
14795
|
-
message: "code or files is required",
|
|
14796
|
-
path: ["code"]
|
|
14797
|
-
});
|
|
14798
|
-
});
|
|
14799
|
-
var coreBlocksCapability = {
|
|
14800
|
-
name: "core-blocks",
|
|
14801
|
-
scope: "system",
|
|
14802
|
-
mode: "singleton",
|
|
14803
|
-
methods: {
|
|
14804
|
-
list: method(zod.z.object({}), zod.z.object({ blocks: zod.z.array(CoreBlockSchema) }), { auth: "admin" }),
|
|
14805
|
-
get: method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema.nullable() }), { auth: "admin" }),
|
|
14806
|
-
/**
|
|
14807
|
-
* Create a block. The code is COMPILED first: storing source that does not
|
|
14808
|
-
* compile turns an editor error into a fork failure the operator meets
|
|
14809
|
-
* minutes later in a log.
|
|
14810
|
-
*/
|
|
14811
|
-
create: method(zod.z.object({ block: CoreBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
14812
|
-
kind: "mutation",
|
|
14813
|
-
auth: "admin",
|
|
14814
|
-
caller: "required"
|
|
14815
|
-
}),
|
|
14816
|
-
update: method(zod.z.object({
|
|
14817
|
-
blockId: zod.z.string(),
|
|
14818
|
-
block: CoreBlockInputFieldsSchema.partial()
|
|
14819
|
-
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
14820
|
-
kind: "mutation",
|
|
14821
|
-
auth: "admin",
|
|
14822
|
-
caller: "required"
|
|
14823
|
-
}),
|
|
14824
|
-
delete: method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
14825
|
-
kind: "mutation",
|
|
14826
|
-
auth: "admin"
|
|
14827
|
-
}),
|
|
14828
|
-
setEnabled: method(zod.z.object({
|
|
14829
|
-
blockId: zod.z.string(),
|
|
14830
|
-
enabled: zod.z.boolean()
|
|
14831
|
-
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
14832
|
-
kind: "mutation",
|
|
14833
|
-
auth: "admin"
|
|
14834
|
-
}),
|
|
14835
|
-
/**
|
|
14836
|
-
* Stop this block's runner and let the supervisor bring it back.
|
|
14837
|
-
*
|
|
14838
|
-
* **It stores nothing.** There is no "restart requested" flag and no second
|
|
14839
|
-
* lifecycle field: the supervisor already stops and respawns a runner when
|
|
14840
|
-
* the code hash changes, and this exposes that same path deliberately
|
|
14841
|
-
* (D62 — a switch writes the authority that already owned the function).
|
|
14842
|
-
* The next reconcile pass remains the authority, so a restart that lost a
|
|
14843
|
-
* race is corrected within one pass rather than leaving a stale flag behind.
|
|
14844
|
-
*
|
|
14845
|
-
* Refused for a DISABLED block: nothing would come back, and a button that
|
|
14846
|
-
* silently does nothing is worse than one that says why.
|
|
14847
|
-
*/
|
|
14848
|
-
restart: method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema }), {
|
|
14849
|
-
kind: "mutation",
|
|
14850
|
-
auth: "admin"
|
|
14851
|
-
}),
|
|
14852
|
-
/**
|
|
14853
|
-
* Type-check without saving — what the editor calls as the author types, so
|
|
14854
|
-
* the compiler's verdict is the same one the server will reach.
|
|
14855
|
-
* Accepts `{ code }` or `{ files, entry }` (multi-file project).
|
|
14856
|
-
*/
|
|
14857
|
-
compile: method(CoreBlockCompileInputSchema, CoreBlockCompileResultSchema, {
|
|
14858
|
-
kind: "mutation",
|
|
14859
|
-
auth: "admin"
|
|
14860
|
-
}),
|
|
14861
|
-
/**
|
|
14862
|
-
* Hydrated settings form for one block, or null until a `settingsSchema`
|
|
14863
|
-
* is known (extracted from the compiled entry's named export, or set on
|
|
14864
|
-
* the block). Values live in the `core-blocks:settings` collection.
|
|
14865
|
-
*/
|
|
14866
|
-
getBlockSettings: method(zod.z.object({ blockId: zod.z.string() }), SettingsSchemaWithValuesSchema.nullable(), { auth: "admin" }),
|
|
14867
|
-
/**
|
|
14868
|
-
* Patch persisted preference values for one block. The schema is not
|
|
14869
|
-
* rewritten here — only values. Scripts read the same blob via
|
|
14870
|
-
* `ctx.settings.readAddonStore()` (mirrored into the block addon's
|
|
14871
|
-
* `addon-settings` namespace on every patch).
|
|
14872
|
-
*/
|
|
14873
|
-
updateBlockSettings: method(zod.z.object({
|
|
14874
|
-
blockId: zod.z.string(),
|
|
14875
|
-
patch: SettingsPatchSchema
|
|
14876
|
-
}), SettingsUpdateResultSchema, {
|
|
14877
|
-
kind: "mutation",
|
|
14878
|
-
auth: "admin"
|
|
14879
|
-
}),
|
|
14880
|
-
/**
|
|
14881
|
-
* The declaration files the editor type-checks against.
|
|
14882
|
-
*
|
|
14883
|
-
* Served rather than bundled: the graph is 3.4 MB across 344 files, and
|
|
14884
|
-
* bundling it would roughly double the admin remote. Served rather than
|
|
14885
|
-
* hand-stubbed: a block runs with the same `ctx` an addon gets, so a stub
|
|
14886
|
-
* would drift and the editor would confidently autocomplete methods that
|
|
14887
|
-
* do not exist.
|
|
14888
|
-
*/
|
|
14889
|
-
getTypeDefs: method(zod.z.object({}), zod.z.object({ libs: zod.z.array(zod.z.object({
|
|
14890
|
-
filePath: zod.z.string(),
|
|
14891
|
-
content: zod.z.string()
|
|
14892
|
-
})) }), { auth: "admin" }),
|
|
14893
|
-
/**
|
|
14894
|
-
* Create a composition block (D659). VALIDATED first against the live
|
|
14895
|
-
* sources and every stored composition; a refusal names every problem by
|
|
14896
|
-
* path and reason (D391) and stores nothing.
|
|
14897
|
-
*/
|
|
14898
|
-
createComposition: method(zod.z.object({ block: CompositionBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
14899
|
-
kind: "mutation",
|
|
14900
|
-
auth: "admin",
|
|
14901
|
-
caller: "required"
|
|
14902
|
-
}),
|
|
14903
|
-
/**
|
|
14904
|
-
* Patch a composition block. A changed `composition` is validated exactly
|
|
14905
|
-
* as on create. `expectedUpdatedAt` is the `updatedAt` the caller READ: a
|
|
14906
|
-
* block changed since is refused by name, never silently overwritten.
|
|
14907
|
-
*/
|
|
14908
|
-
updateComposition: method(zod.z.object({
|
|
14909
|
-
blockId: zod.z.string(),
|
|
14910
|
-
expectedUpdatedAt: zod.z.number(),
|
|
14911
|
-
block: CompositionBlockInputSchema.partial()
|
|
14912
|
-
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
14913
|
-
kind: "mutation",
|
|
14914
|
-
auth: "admin",
|
|
14915
|
-
caller: "required"
|
|
14916
|
-
}),
|
|
14917
|
-
/** One composition and the composer's state for it, or `not-loaded` (D315). */
|
|
14918
|
-
getComposition: method(zod.z.object({ blockId: zod.z.string() }), CompositionGetReadSchema, { auth: "admin" }),
|
|
14919
|
-
listCompositions: method(zod.z.object({}), CompositionListReadSchema, { auth: "admin" }),
|
|
14920
|
-
/**
|
|
14921
|
-
* The composition that customizes an existing device (D663), found by its
|
|
14922
|
-
* TARGET — never by the block's derived name. One per device at most.
|
|
14923
|
-
*/
|
|
14924
|
-
getCustomization: method(zod.z.object({
|
|
14925
|
-
addonId: zod.z.string().min(1),
|
|
14926
|
-
stableId: zod.z.string().min(1)
|
|
14927
|
-
}), CompositionCustomizationReadSchema, { auth: "admin" }),
|
|
14928
|
-
/**
|
|
14929
|
-
* The capabilities a composition may BUILD on a device of `deviceType`
|
|
14930
|
-
* (a new device, or added to an existing one), with their fields — the
|
|
14931
|
-
* editor's feature list and the presets' availability (G2, D676). Built
|
|
14932
|
-
* from the validator's own blockers; a replace of a BOUND cap is not
|
|
14933
|
-
* listed here (the device's bindings say what it has).
|
|
14934
|
-
*/
|
|
14935
|
-
listComposableCaps: method(zod.z.object({ deviceType: zod.z.enum(DeviceType) }), ComposableCapabilitiesSchema, { auth: "admin" }),
|
|
14936
|
-
/**
|
|
14937
|
-
* Validate without saving — the same verdict the save reaches. A mutation
|
|
14938
|
-
* for its body size; it writes nothing, so its access is `view`.
|
|
14939
|
-
*/
|
|
14940
|
-
validateComposition: method(zod.z.object({
|
|
14941
|
-
composition: CompositionSchema,
|
|
14942
|
-
blockId: zod.z.string().optional()
|
|
14943
|
-
}), CompositionValidationSchema, {
|
|
14944
|
-
kind: "mutation",
|
|
14945
|
-
auth: "admin",
|
|
14946
|
-
access: "view"
|
|
14947
|
-
})
|
|
14948
|
-
}
|
|
14949
|
-
};
|
|
14950
|
-
/**
|
|
14951
|
-
* `custom-model-registry` — collection cap exposing operator-registered
|
|
14952
|
-
* custom detection models. Each provider (today: `addon-model-studio`)
|
|
14953
|
-
* contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
|
|
14954
|
-
* them across providers (`concatCollection`).
|
|
14955
|
-
*
|
|
14956
|
-
* The detection-pipeline is *aware* of this cap: when at least one provider
|
|
14957
|
-
* exists it unions these descriptors into the per-step model picker and the
|
|
14958
|
-
* runtime model-resolution path, alongside the static catalog. When no
|
|
14959
|
-
* provider exists the consumer no-ops entirely (identical to the catalog-only
|
|
14960
|
-
* behaviour).
|
|
14961
|
-
*
|
|
14962
|
-
* A descriptor carries a full `ModelCatalogEntry` directly — the same shape
|
|
14963
|
-
* the static catalog uses — so the existing download/resolution code consumes
|
|
14964
|
-
* it unchanged. `stepId` is the detection step the model targets
|
|
14965
|
-
* (e.g. `'object-detection'`).
|
|
14966
|
-
*/
|
|
14967
|
-
var CustomModelDescriptorSchema = zod.z.object({
|
|
14968
|
-
stepId: zod.z.string(),
|
|
14969
|
-
entry: ModelCatalogEntrySchema
|
|
14970
|
-
});
|
|
14971
|
-
/** One regular file of an imported bundle, as the producer measured it. */
|
|
14972
|
-
var ModelBundleFileSchema = zod.z.object({
|
|
14973
|
-
/** Relative path inside the bundle tar; an mlpackage member is `<x>.mlpackage/<member>`. */
|
|
14974
|
-
path: zod.z.string().min(1),
|
|
14975
|
-
bytes: zod.z.number().int().nonnegative(),
|
|
14976
|
-
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
14977
|
-
});
|
|
14978
|
-
var ImportModelBundleInputSchema = zod.z.object({
|
|
14979
|
-
/** The registry provider that keeps the model (Model Studio). */
|
|
14980
|
-
addonId: zod.z.string(),
|
|
14981
|
-
stepId: zod.z.string().min(1),
|
|
14982
|
-
/**
|
|
14983
|
-
* The catalog rows to register, complete, every format URL already
|
|
14984
|
-
* `camstack-local://<modelId>/<file>` naming a file of the bundle. One
|
|
14985
|
-
* bundle may carry several rows (a base and its INT8 variant).
|
|
14986
|
-
*/
|
|
14987
|
-
entries: zod.z.array(ModelCatalogEntrySchema).min(1).max(4),
|
|
14988
|
-
/** The bundle tar, offered by the producer over `ctx.peerBytes` (same host). */
|
|
14989
|
-
bundle: zod.z.object({
|
|
14990
|
-
ticket: PeerBytesTicketSchema,
|
|
14991
|
-
bytes: zod.z.number().int().positive(),
|
|
14992
|
-
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
14993
|
-
}),
|
|
14994
|
-
/** Every file the tar must hold; anything missing, extra or different is refused. */
|
|
14995
|
-
files: zod.z.array(ModelBundleFileSchema).min(1).max(64),
|
|
14996
|
-
/** Convert missing engine formats and push the model to every agent afterwards. */
|
|
14997
|
-
distribute: zod.z.boolean()
|
|
14998
|
-
});
|
|
14999
|
-
var ImportModelBundleResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
15000
|
-
kind: zod.z.literal("imported"),
|
|
15001
|
-
modelIds: zod.z.array(zod.z.string()).readonly(),
|
|
15002
|
-
distributed: zod.z.array(zod.z.object({
|
|
15003
|
-
modelId: zod.z.string(),
|
|
15004
|
-
nodeId: zod.z.string(),
|
|
15005
|
-
format: zod.z.enum(MODEL_FORMATS),
|
|
15006
|
-
ok: zod.z.boolean(),
|
|
15007
|
-
error: zod.z.string().optional()
|
|
15008
|
-
})).readonly()
|
|
15009
|
-
}), zod.z.object({
|
|
15010
|
-
kind: zod.z.literal("refused"),
|
|
15011
|
-
reason: zod.z.enum([
|
|
15012
|
-
"transfer-failed",
|
|
15013
|
-
"checksum-mismatch",
|
|
15014
|
-
"bundle-mismatch",
|
|
15015
|
-
"invalid-entry",
|
|
15016
|
-
"id-taken"
|
|
15017
|
-
]),
|
|
15018
|
-
detail: zod.z.string()
|
|
15019
|
-
})]);
|
|
15020
|
-
var customModelRegistryCapability = {
|
|
15021
|
-
name: "custom-model-registry",
|
|
15022
|
-
scope: "system",
|
|
15023
|
-
mode: "collection",
|
|
15024
|
-
internal: true,
|
|
15025
|
-
methods: {
|
|
15026
|
-
/**
|
|
15027
|
-
* `internal: true` did not gate the mount (see the 2026-08-26 note on
|
|
15028
|
-
* `data-store-provider`) — this was reachable on the AppRouter by ANY
|
|
15029
|
-
* authenticated session at the default `auth: 'protected'`. The only
|
|
15030
|
-
* consumer, the detection-pipeline's model resolution
|
|
15031
|
-
* (`addon-pipeline/src/detection-pipeline/provider.ts`), calls
|
|
15032
|
-
* `ctx.api.customModelRegistry.listModels.query()` — UDS/Moleculer,
|
|
15033
|
-
* never tRPC — so `auth: 'admin'` costs it nothing.
|
|
15034
|
-
*/
|
|
15035
|
-
listModels: method(zod.z.void(), zod.z.array(CustomModelDescriptorSchema).readonly(), { auth: "admin" }),
|
|
15036
|
-
/**
|
|
15037
|
-
* Register a model whose files arrive as ONE bundle tar (D806): the tar
|
|
15038
|
-
* is taken over `ctx.peerBytes`, checked against `bundle.sha256` and
|
|
15039
|
-
* every row of `files`, unpacked into the hub's flat modelsDir (directory
|
|
15040
|
-
* formats included), each format's `.revision` record written, the rows
|
|
15041
|
-
* upserted under the operator's name, the hub marked available and —
|
|
15042
|
-
* when asked — engine formats converted and the model distributed. A
|
|
15043
|
-
* model id already registered by another source is refused, never
|
|
15044
|
-
* overwritten.
|
|
15045
|
-
*/
|
|
15046
|
-
importModelBundle: method(ImportModelBundleInputSchema, ImportModelBundleResultSchema, {
|
|
15047
|
-
kind: "mutation",
|
|
15048
|
-
auth: "admin",
|
|
15049
|
-
timeoutMs: 30 * 6e4
|
|
15050
|
-
})
|
|
15051
|
-
}
|
|
15052
|
-
};
|
|
15053
|
-
/**
|
|
15054
|
-
* Query filter for settings-store collections.
|
|
15055
|
-
*/
|
|
15056
|
-
var QueryFilterSchema = zod.z.object({
|
|
15057
|
-
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
15058
|
-
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
15059
|
-
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
15060
|
-
/** NULL-safe exclusion: matches rows whose field is NULL OR != the value. */
|
|
15061
|
-
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
15062
|
-
/** NULL-safe exclusion of a SET — `whereNot` for more than one value. An
|
|
15063
|
-
* empty list excludes nothing. See `QueryFilter.whereNotIn`. */
|
|
15064
|
-
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
15065
|
-
orderBy: zod.z.object({
|
|
15066
|
-
field: zod.z.string(),
|
|
15067
|
-
direction: zod.z.enum(["asc", "desc"])
|
|
15068
|
-
}).optional(),
|
|
15069
|
-
limit: zod.z.number().optional(),
|
|
15070
|
-
offset: zod.z.number().optional()
|
|
15071
|
-
});
|
|
15072
|
-
/**
|
|
15073
|
-
* The predicate half of a filter, for BULK MUTATIONS.
|
|
15074
|
-
*
|
|
15075
|
-
* Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
|
|
15076
|
-
* meaning for a statement that rewrites a set, and accepting them would invite
|
|
15077
|
-
* a caller to believe `limit` bounds the damage. Every field is optional here
|
|
15078
|
-
* only so the shape stays composable — the implementation REJECTS a filter
|
|
15079
|
-
* that compiles to no predicate, because that is the whole collection.
|
|
15080
|
-
*/
|
|
15081
|
-
var MutationFilterSchema = zod.z.object({
|
|
15082
|
-
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
15083
|
-
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
15084
|
-
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
15085
|
-
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
15086
|
-
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional()
|
|
15087
|
-
});
|
|
15088
|
-
/**
|
|
15089
|
-
* One scalar an {@link settingsStoreCapability.methods.aggregate} call asks for.
|
|
15090
|
-
*
|
|
15091
|
-
* `as` names the slot in the result, so the SAME column may be asked twice with
|
|
15092
|
-
* two operations (`MIN(startMs)` and `MAX(startMs)` in one round trip) — which
|
|
15093
|
-
* a `Record<column, op>` shape could not express.
|
|
15094
|
-
*/
|
|
15095
|
-
var AggregateFieldSchema = zod.z.object({
|
|
15096
|
-
/** Result key. */
|
|
15097
|
-
as: zod.z.string().min(1),
|
|
15098
|
-
/** Column to aggregate. Must be a real column of a declared collection. */
|
|
15099
|
-
field: zod.z.string().min(1),
|
|
15100
|
-
op: zod.z.enum([
|
|
15101
|
-
"sum",
|
|
15102
|
-
"min",
|
|
15103
|
-
"max"
|
|
15104
|
-
])
|
|
15105
|
-
});
|
|
15106
|
-
/**
|
|
15107
|
-
* `COUNT(*)` plus one number per requested field.
|
|
15108
|
-
*
|
|
15109
|
-
* `null` means NO ROW MATCHED, never zero: a `SUM` over an empty set and a sum
|
|
15110
|
-
* that really is 0 are different facts, and an accounting caller that renders
|
|
15111
|
-
* "0 bytes, oldest = 0" for "nothing here" reports a lie about a disk.
|
|
15112
|
-
*/
|
|
15113
|
-
var AggregateResultSchema = zod.z.object({
|
|
15114
|
-
count: zod.z.number().int(),
|
|
15115
|
-
values: zod.z.record(zod.z.string(), zod.z.number().nullable())
|
|
15116
|
-
});
|
|
15117
|
-
/** A single stored record: `{ id, data }`. */
|
|
15118
|
-
var SettingsRecordSchema = zod.z.object({
|
|
15119
|
-
id: zod.z.string(),
|
|
15120
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
15121
|
-
});
|
|
15122
|
-
/**
|
|
15123
|
-
* One record of a BULK insert — {@link SettingsRecordSchema} with the id made
|
|
15124
|
-
* optional.
|
|
15125
|
-
*
|
|
15126
|
-
* A separate schema rather than loosening the shared one: every other method
|
|
15127
|
-
* on this cap addresses a row BY its id, and making that field optional
|
|
15128
|
-
* everywhere would turn a forgotten key into a silently generated one on
|
|
15129
|
-
* `update` and `delete` as well.
|
|
15130
|
-
*/
|
|
15131
|
-
var BulkRecordSchema = zod.z.object({
|
|
15132
|
-
id: zod.z.string().optional(),
|
|
15133
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
15134
|
-
});
|
|
15135
|
-
/**
|
|
15136
|
-
* One write inside a {@link settingsStoreCapability.methods.transact} call.
|
|
15137
|
-
* Only the three that a "replace this set, bump that revision" write needs.
|
|
15138
|
-
*/
|
|
15139
|
-
var TransactOpSchema = zod.z.discriminatedUnion("op", [
|
|
15140
|
-
zod.z.object({
|
|
15141
|
-
op: zod.z.literal("deleteWhere"),
|
|
15142
|
-
collection: zod.z.string(),
|
|
15143
|
-
filter: MutationFilterSchema
|
|
15144
|
-
}),
|
|
15145
|
-
zod.z.object({
|
|
15146
|
-
op: zod.z.literal("insertMany"),
|
|
15147
|
-
collection: zod.z.string(),
|
|
15148
|
-
records: zod.z.array(BulkRecordSchema).readonly()
|
|
15149
|
-
}),
|
|
15150
|
-
zod.z.object({
|
|
15151
|
-
op: zod.z.literal("update"),
|
|
15152
|
-
collection: zod.z.string(),
|
|
15153
|
-
id: zod.z.string(),
|
|
15154
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
15155
|
-
})
|
|
15156
|
-
]);
|
|
15157
|
-
/**
|
|
15158
|
-
* The precondition of a transaction: the row `key` of `collection` must hold
|
|
15159
|
-
* `equals` in `column`, read INSIDE the transaction.
|
|
15160
|
-
*/
|
|
15161
|
-
var TransactGuardSchema = zod.z.object({
|
|
15162
|
-
collection: zod.z.string(),
|
|
15163
|
-
key: zod.z.string(),
|
|
15164
|
-
column: zod.z.string(),
|
|
15165
|
-
equals: zod.z.unknown()
|
|
15166
|
-
});
|
|
15167
|
-
/**
|
|
15168
|
-
* Column declaration for a structured (SQL-backed) collection.
|
|
15169
|
-
*
|
|
15170
|
-
* Logical types — the backend translates each to the matching SQLite
|
|
15171
|
-
* storage class and handles per-type marshaling:
|
|
15172
|
-
* - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
|
|
15173
|
-
* - `JSON` — TEXT under the hood; serialised on write, parsed on read
|
|
15174
|
-
* - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
|
|
15175
|
-
*/
|
|
15176
|
-
var CollectionColumnSchema = zod.z.object({
|
|
15177
|
-
name: zod.z.string(),
|
|
15178
|
-
type: zod.z.enum([
|
|
15179
|
-
"TEXT",
|
|
15180
|
-
"INTEGER",
|
|
15181
|
-
"REAL",
|
|
15182
|
-
"JSON",
|
|
15183
|
-
"BOOLEAN"
|
|
15184
|
-
]),
|
|
15185
|
-
primaryKey: zod.z.boolean().optional(),
|
|
15186
|
-
notNull: zod.z.boolean().optional(),
|
|
15187
|
-
unique: zod.z.boolean().optional(),
|
|
15188
|
-
/**
|
|
15189
|
-
* Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
|
|
15190
|
-
* columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
|
|
15191
|
-
* collection surface simply cannot express their existing tables — which is
|
|
15192
|
-
* why they were still on the uncapped `table*` API.
|
|
15193
|
-
*/
|
|
15194
|
-
defaultValue: zod.z.union([
|
|
15195
|
-
zod.z.string(),
|
|
15196
|
-
zod.z.number(),
|
|
15197
|
-
zod.z.boolean()
|
|
15198
|
-
]).optional()
|
|
15199
|
-
});
|
|
15200
|
-
var CollectionIndexSchema = zod.z.object({
|
|
15201
|
-
name: zod.z.string(),
|
|
15202
|
-
columns: zod.z.array(zod.z.string()).readonly(),
|
|
15203
|
-
unique: zod.z.boolean().optional()
|
|
15204
|
-
});
|
|
15205
|
-
/**
|
|
15206
|
-
* settings-store — singleton capability for addon-scoped persistence.
|
|
15207
|
-
*
|
|
15208
|
-
* Every method operates within a `collection`. An optional `namespace`
|
|
15209
|
-
* field provides access to additional data spaces beyond the default
|
|
15210
|
-
* addon settings — useful for business data (events, tracks, faces, etc.).
|
|
15211
|
-
*
|
|
15212
|
-
* **Scoping is the CALLER's, and it is opt-in.** The table is
|
|
15213
|
-
* `namespace ? `${namespace}:${collection}` : collection` — nothing
|
|
15214
|
-
* consults the identity of the caller. An earlier version of this comment
|
|
15215
|
-
* claimed the implementation prefixes every collection with the calling
|
|
15216
|
-
* addon's ID and that "addons never see each other's data"; that was never
|
|
15217
|
-
* true, and this same file contradicted it under `declareCollection`. What
|
|
15218
|
-
* exists is `addon-context-factory`, which passes `namespace: addonId` ON
|
|
15219
|
-
* THE ADDON'S BEHALF for the `addon-settings` / `addon-devices` paths only.
|
|
15220
|
-
* Business collections use bare names, and any caller may name any
|
|
15221
|
-
* namespace, or none. Making the door enforce it is tracked separately —
|
|
15222
|
-
* it renames tables, so it needs a migration.
|
|
15223
|
-
*
|
|
15224
|
-
* **So every method is `auth: 'admin'` (D634).** Because nothing scopes a
|
|
15225
|
-
* call to its caller, a `protected` method here was a raw, unredacted read
|
|
15226
|
-
* (and write) of every addon's collections for any role holding
|
|
15227
|
-
* `category:system` — which is every role: a `viewer` could read every
|
|
15228
|
-
* notifier token in plaintext from `notifiers:notification-targets`. No
|
|
15229
|
-
* browser or app client calls this cap. Addons are not affected: an
|
|
15230
|
-
* addon's `ctx.api` cap call is resolved to the provider directly and never
|
|
15231
|
-
* enters the tRPC router (so the tier gates sessions and tokens, never
|
|
15232
|
-
* addons), and the hub itself calls it through the capability registry.
|
|
15233
|
-
*
|
|
15234
|
-
* - `{ collection: 'addon-settings' }` → table `addon-settings`
|
|
15235
|
-
* - `{ namespace: 'my-addon', collection: 'addon-settings' }` →
|
|
15236
|
-
* table `my-addon:addon-settings`
|
|
15237
|
-
*
|
|
15238
|
-
* Served by the **storage-orchestrator** builtin, which dispatches to the
|
|
15239
|
-
* `data-store-provider` engine registered for the collection
|
|
15240
|
-
* (`sqlite-settings`, a SQLite WAL backend, today). One addon owns the
|
|
15241
|
-
* data door; engines sit behind it
|
|
15242
|
-
* ([D44](../../../../docs/decisions/adr-0044.md)).
|
|
15243
|
-
* Addons access it via `ctx.api.settingsStore.*`.
|
|
15244
|
-
*/
|
|
15245
|
-
var settingsStoreCapability = {
|
|
15246
|
-
name: "settings-store",
|
|
15376
|
+
files: CoreBlockFilesSchema.optional(),
|
|
15377
|
+
entry: zod.z.string().min(1).max(260).optional()
|
|
15378
|
+
}).superRefine((val, ctx) => {
|
|
15379
|
+
if (val.files !== void 0) {
|
|
15380
|
+
const entry = val.entry ?? "main.ts";
|
|
15381
|
+
if (val.files[entry] === void 0) ctx.addIssue({
|
|
15382
|
+
code: "custom",
|
|
15383
|
+
message: `files must include the entry "${entry}"`,
|
|
15384
|
+
path: ["files"]
|
|
15385
|
+
});
|
|
15386
|
+
return;
|
|
15387
|
+
}
|
|
15388
|
+
if (val.code === void 0) ctx.addIssue({
|
|
15389
|
+
code: "custom",
|
|
15390
|
+
message: "code or files is required",
|
|
15391
|
+
path: ["code"]
|
|
15392
|
+
});
|
|
15393
|
+
});
|
|
15394
|
+
var coreBlocksCapability = {
|
|
15395
|
+
name: "core-blocks",
|
|
15247
15396
|
scope: "system",
|
|
15248
15397
|
mode: "singleton",
|
|
15249
15398
|
methods: {
|
|
15250
|
-
|
|
15251
|
-
get: method(zod.z.object({
|
|
15252
|
-
namespace: zod.z.string().optional(),
|
|
15253
|
-
collection: zod.z.string(),
|
|
15254
|
-
key: zod.z.string()
|
|
15255
|
-
}), zod.z.unknown(), { auth: "admin" }),
|
|
15256
|
-
/** Set a value by key in a collection (upsert). */
|
|
15257
|
-
set: method(zod.z.object({
|
|
15258
|
-
namespace: zod.z.string().optional(),
|
|
15259
|
-
collection: zod.z.string(),
|
|
15260
|
-
key: zod.z.string(),
|
|
15261
|
-
value: zod.z.unknown()
|
|
15262
|
-
}), zod.z.void(), {
|
|
15263
|
-
kind: "mutation",
|
|
15264
|
-
auth: "admin"
|
|
15265
|
-
}),
|
|
15266
|
-
/**
|
|
15267
|
-
* Rows matching a filter.
|
|
15268
|
-
*
|
|
15269
|
-
* `columns` is a SQL-level projection: the engine SELECTs only those
|
|
15270
|
-
* columns (plus the primary key) instead of the whole row. It is the only
|
|
15271
|
-
* way to stop paying disk for a column that is discarded — a heavy JSON
|
|
15272
|
-
* column dominates the row, and dropping it in JS after the read pays every
|
|
15273
|
-
* byte first. Measured on the live `pipeline-analytics:tracks` table: a
|
|
15274
|
-
* 501-row page is 4.6 MB whole and 0.11 MB projected, same index, same
|
|
15275
|
-
* plan.
|
|
15276
|
-
*
|
|
15277
|
-
* The engine REFUSES a column it cannot serve rather than omitting it —
|
|
15278
|
-
* see `SettingsQueryInput.columns` for why a projection may not be
|
|
15279
|
-
* forgiving the way a predicate is.
|
|
15280
|
-
*/
|
|
15281
|
-
query: method(zod.z.object({
|
|
15282
|
-
namespace: zod.z.string().optional(),
|
|
15283
|
-
collection: zod.z.string(),
|
|
15284
|
-
filter: QueryFilterSchema.optional(),
|
|
15285
|
-
columns: zod.z.array(zod.z.string()).readonly().optional()
|
|
15286
|
-
}), zod.z.array(SettingsRecordSchema).readonly(), { auth: "admin" }),
|
|
15399
|
+
list: method(zod.z.object({}), zod.z.object({ blocks: zod.z.array(CoreBlockSchema) }), { auth: "admin" }),
|
|
15400
|
+
get: method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema.nullable() }), { auth: "admin" }),
|
|
15287
15401
|
/**
|
|
15288
|
-
*
|
|
15289
|
-
*
|
|
15290
|
-
*
|
|
15291
|
-
* ## Why the store needed this
|
|
15292
|
-
*
|
|
15293
|
-
* {@link set} is already an upsert, but its slot is the PRIMARY KEY: the
|
|
15294
|
-
* caller has to know the id to address the row. That is exactly what a
|
|
15295
|
-
* collection keyed by an `INTEGER` rowid alias cannot do — SQLite assigns
|
|
15296
|
-
* the id, so a writer whose uniqueness rule is "one row per
|
|
15297
|
-
* `(ownerKind, ownerId, kind, slot)`" has no id to name and no way to
|
|
15298
|
-
* express the rule. {@link insert} can express it (a UNIQUE index
|
|
15299
|
-
* arbitrates) but only by THROWING at the loser of a race, and the loser
|
|
15300
|
-
* here is a legitimate re-capture, not an error.
|
|
15301
|
-
*
|
|
15302
|
-
* Getting there without this method means read-then-write: query the slot,
|
|
15303
|
-
* then `insert` or `update`. Two statements instead of one, a race between
|
|
15304
|
-
* them, and a recovery path that has to recognise a UNIQUE violation by its
|
|
15305
|
-
* MESSAGE — across a process boundary, because the store lives behind an
|
|
15306
|
-
* RPC door. A string match would be the whole gate, and a store that
|
|
15307
|
-
* rephrased its error would lose the row silently. One statement has no
|
|
15308
|
-
* such gate (D482).
|
|
15309
|
-
*
|
|
15310
|
-
* ## The contract
|
|
15311
|
-
*
|
|
15312
|
-
* `conflict` names the DECLARED columns that identify the slot. They must
|
|
15313
|
-
* be covered by a UNIQUE index on the collection — SQLite resolves an
|
|
15314
|
-
* `ON CONFLICT` target against its indexes and REFUSES the statement when
|
|
15315
|
-
* none matches, so a wrong list is a loud error on the first write, never a
|
|
15316
|
-
* silently duplicated row. An empty list is refused rather than passed on:
|
|
15317
|
-
* `ON CONFLICT()` is not valid SQL, and the intent it would most likely
|
|
15318
|
-
* encode ("no slot, just insert") is {@link insert}.
|
|
15319
|
-
*
|
|
15320
|
-
* Row shape is {@link insert}'s: `record.id` is used when the collection
|
|
15321
|
-
* needs a supplied key and IGNORED when the primary key is an `INTEGER`
|
|
15322
|
-
* rowid alias — exactly as `insert` and `insertMany` already treat it.
|
|
15323
|
-
*
|
|
15324
|
-
* Returns the id either way: the one SQLite assigned on an insert, or the
|
|
15325
|
-
* one the row it updated already had. A caller cannot tell which happened,
|
|
15326
|
-
* and deliberately — every caller wants the slot's id, and one that needed
|
|
15327
|
-
* to distinguish creation from replacement would have to read first anyway.
|
|
15402
|
+
* Create a block. The code is COMPILED first: storing source that does not
|
|
15403
|
+
* compile turns an editor error into a fork failure the operator meets
|
|
15404
|
+
* minutes later in a log.
|
|
15328
15405
|
*/
|
|
15329
|
-
|
|
15330
|
-
namespace: zod.z.string().optional(),
|
|
15331
|
-
collection: zod.z.string(),
|
|
15332
|
-
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
15333
|
-
* index on the collection. Never empty. */
|
|
15334
|
-
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
15335
|
-
record: BulkRecordSchema
|
|
15336
|
-
}), zod.z.object({
|
|
15337
|
-
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
15338
|
-
* row's own id on an update. */
|
|
15339
|
-
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
15406
|
+
create: method(zod.z.object({ block: CoreBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
15340
15407
|
kind: "mutation",
|
|
15341
|
-
auth: "admin"
|
|
15408
|
+
auth: "admin",
|
|
15409
|
+
caller: "required"
|
|
15342
15410
|
}),
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
|
|
15348
|
-
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
}), zod.z.object({
|
|
15352
|
-
/**
|
|
15353
|
-
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
15354
|
-
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
15355
|
-
* primary key — which is the only place an auto key is knowable.
|
|
15356
|
-
*/
|
|
15357
|
-
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
15411
|
+
update: method(zod.z.object({
|
|
15412
|
+
blockId: zod.z.string(),
|
|
15413
|
+
block: CoreBlockInputFieldsSchema.partial()
|
|
15414
|
+
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
15415
|
+
kind: "mutation",
|
|
15416
|
+
auth: "admin",
|
|
15417
|
+
caller: "required"
|
|
15418
|
+
}),
|
|
15419
|
+
delete: method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
15358
15420
|
kind: "mutation",
|
|
15359
15421
|
auth: "admin"
|
|
15360
15422
|
}),
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
* reason: without it, appending a batch is N round trips and N COMMITs on
|
|
15366
|
-
* the single shared connection that also serves every cluster-wide
|
|
15367
|
-
* configuration read. The durable load series writes one process row per
|
|
15368
|
-
* process per sample — 76 rows every 10 s on the live fleet — and the
|
|
15369
|
-
* operator's rule for it is *one transaction per sample, never one per
|
|
15370
|
-
* row*. `insert` cannot express that; nothing else could.
|
|
15371
|
-
*
|
|
15372
|
-
* **All or nothing.** A batch that fails on its fifth row leaves none of
|
|
15373
|
-
* the five behind. A half-written sample is worse than a missing one: the
|
|
15374
|
-
* missing one reads as "nobody reported", which is true, while the half
|
|
15375
|
-
* one reads as "these were the only processes running", which is not.
|
|
15376
|
-
*
|
|
15377
|
-
* `id` is OPTIONAL per record, and that is the difference from
|
|
15378
|
-
* {@link insert}. A collection whose primary key is an `INTEGER` rowid
|
|
15379
|
-
* alias has no id to supply — SQLite assigns it, for free, and inventing a
|
|
15380
|
-
* `randomUUID()` for such a column would write a 36-character string into
|
|
15381
|
-
* an integer key. Omitted on a TEXT key, a uuid is generated exactly as
|
|
15382
|
-
* `insert` does.
|
|
15383
|
-
*/
|
|
15384
|
-
insertMany: method(zod.z.object({
|
|
15385
|
-
namespace: zod.z.string().optional(),
|
|
15386
|
-
collection: zod.z.string(),
|
|
15387
|
-
records: zod.z.array(BulkRecordSchema).readonly()
|
|
15388
|
-
}), zod.z.object({ inserted: zod.z.number().int() }), {
|
|
15423
|
+
setEnabled: method(zod.z.object({
|
|
15424
|
+
blockId: zod.z.string(),
|
|
15425
|
+
enabled: zod.z.boolean()
|
|
15426
|
+
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
15389
15427
|
kind: "mutation",
|
|
15390
15428
|
auth: "admin"
|
|
15391
15429
|
}),
|
|
15392
15430
|
/**
|
|
15393
|
-
*
|
|
15394
|
-
*
|
|
15395
|
-
* The multi-collection twin of {@link insertMany}: a write that has to move
|
|
15396
|
-
* a set of rows in one collection AND a revision in another cannot be
|
|
15397
|
-
* expressed as separate calls without a window in which a reader (or a
|
|
15398
|
-
* crash) sees half of it. The retrain annotation save replaces a frame's
|
|
15399
|
-
* rows, its dismissed set and its revision this way.
|
|
15431
|
+
* Stop this block's runner and let the supervisor bring it back.
|
|
15400
15432
|
*
|
|
15401
|
-
*
|
|
15402
|
-
*
|
|
15403
|
-
*
|
|
15404
|
-
*
|
|
15405
|
-
*
|
|
15433
|
+
* **It stores nothing.** There is no "restart requested" flag and no second
|
|
15434
|
+
* lifecycle field: the supervisor already stops and respawns a runner when
|
|
15435
|
+
* the code hash changes, and this exposes that same path deliberately
|
|
15436
|
+
* (D62 — a switch writes the authority that already owned the function).
|
|
15437
|
+
* The next reconcile pass remains the authority, so a restart that lost a
|
|
15438
|
+
* race is corrected within one pass rather than leaving a stale flag behind.
|
|
15406
15439
|
*
|
|
15407
|
-
*
|
|
15408
|
-
*
|
|
15409
|
-
* replace a set). `namespace` applies to every collection named.
|
|
15440
|
+
* Refused for a DISABLED block: nothing would come back, and a button that
|
|
15441
|
+
* silently does nothing is worse than one that says why.
|
|
15410
15442
|
*/
|
|
15411
|
-
|
|
15412
|
-
namespace: zod.z.string().optional(),
|
|
15413
|
-
guard: TransactGuardSchema.optional(),
|
|
15414
|
-
ops: zod.z.array(TransactOpSchema).readonly()
|
|
15415
|
-
}), zod.z.object({
|
|
15416
|
-
applied: zod.z.boolean(),
|
|
15417
|
-
current: zod.z.unknown().optional()
|
|
15418
|
-
}), {
|
|
15443
|
+
restart: method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema }), {
|
|
15419
15444
|
kind: "mutation",
|
|
15420
15445
|
auth: "admin"
|
|
15421
15446
|
}),
|
|
15422
|
-
/**
|
|
15423
|
-
|
|
15424
|
-
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
}), zod.z.void(), {
|
|
15447
|
+
/**
|
|
15448
|
+
* Type-check without saving — what the editor calls as the author types, so
|
|
15449
|
+
* the compiler's verdict is the same one the server will reach.
|
|
15450
|
+
* Accepts `{ code }` or `{ files, entry }` (multi-file project).
|
|
15451
|
+
*/
|
|
15452
|
+
compile: method(CoreBlockCompileInputSchema, CoreBlockCompileResultSchema, {
|
|
15429
15453
|
kind: "mutation",
|
|
15430
15454
|
auth: "admin"
|
|
15431
15455
|
}),
|
|
15432
|
-
/**
|
|
15433
|
-
|
|
15434
|
-
|
|
15435
|
-
|
|
15436
|
-
|
|
15437
|
-
|
|
15456
|
+
/**
|
|
15457
|
+
* Hydrated settings form for one block, or null until a `settingsSchema`
|
|
15458
|
+
* is known (extracted from the compiled entry's named export, or set on
|
|
15459
|
+
* the block). Values live in the `core-blocks:settings` collection.
|
|
15460
|
+
*/
|
|
15461
|
+
getBlockSettings: method(zod.z.object({ blockId: zod.z.string() }), SettingsSchemaWithValuesSchema.nullable(), { auth: "admin" }),
|
|
15462
|
+
/**
|
|
15463
|
+
* Patch persisted preference values for one block. The schema is not
|
|
15464
|
+
* rewritten here — only values. Scripts read the same blob via
|
|
15465
|
+
* `ctx.settings.readAddonStore()` (mirrored into the block addon's
|
|
15466
|
+
* `addon-settings` namespace on every patch).
|
|
15467
|
+
*/
|
|
15468
|
+
updateBlockSettings: method(zod.z.object({
|
|
15469
|
+
blockId: zod.z.string(),
|
|
15470
|
+
patch: SettingsPatchSchema
|
|
15471
|
+
}), SettingsUpdateResultSchema, {
|
|
15438
15472
|
kind: "mutation",
|
|
15439
15473
|
auth: "admin"
|
|
15440
15474
|
}),
|
|
15441
15475
|
/**
|
|
15442
|
-
*
|
|
15443
|
-
* many rows went. This exists because its absence made every retention
|
|
15444
|
-
* path in the system an N+1 drain loop: `delete` takes a key, so a sweep
|
|
15445
|
-
* had to SELECT a page of full rows — every column, including the fat
|
|
15446
|
-
* ones — purely to learn their ids, then issue one call per row.
|
|
15476
|
+
* The declaration files the editor type-checks against.
|
|
15447
15477
|
*
|
|
15448
|
-
*
|
|
15449
|
-
*
|
|
15450
|
-
*
|
|
15451
|
-
*
|
|
15452
|
-
*
|
|
15453
|
-
* an empty object.
|
|
15478
|
+
* Served rather than bundled: the graph is 3.4 MB across 344 files, and
|
|
15479
|
+
* bundling it would roughly double the admin remote. Served rather than
|
|
15480
|
+
* hand-stubbed: a block runs with the same `ctx` an addon gets, so a stub
|
|
15481
|
+
* would drift and the editor would confidently autocomplete methods that
|
|
15482
|
+
* do not exist.
|
|
15454
15483
|
*/
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15484
|
+
getTypeDefs: method(zod.z.object({}), zod.z.object({ libs: zod.z.array(zod.z.object({
|
|
15485
|
+
filePath: zod.z.string(),
|
|
15486
|
+
content: zod.z.string()
|
|
15487
|
+
})) }), { auth: "admin" }),
|
|
15488
|
+
/**
|
|
15489
|
+
* Create a composition block (D659). VALIDATED first against the live
|
|
15490
|
+
* sources and every stored composition; a refusal names every problem by
|
|
15491
|
+
* path and reason (D391) and stores nothing.
|
|
15492
|
+
*/
|
|
15493
|
+
createComposition: method(zod.z.object({ block: CompositionBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
15460
15494
|
kind: "mutation",
|
|
15461
|
-
auth: "admin"
|
|
15495
|
+
auth: "admin",
|
|
15496
|
+
caller: "required"
|
|
15462
15497
|
}),
|
|
15463
15498
|
/**
|
|
15464
|
-
*
|
|
15465
|
-
*
|
|
15466
|
-
*
|
|
15499
|
+
* Patch a composition block. A changed `composition` is validated exactly
|
|
15500
|
+
* as on create. `expectedUpdatedAt` is the `updatedAt` the caller READ: a
|
|
15501
|
+
* block changed since is refused by name, never silently overwritten.
|
|
15467
15502
|
*/
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
}), zod.z.object({ updated: zod.z.number().int() }), {
|
|
15503
|
+
updateComposition: method(zod.z.object({
|
|
15504
|
+
blockId: zod.z.string(),
|
|
15505
|
+
expectedUpdatedAt: zod.z.number(),
|
|
15506
|
+
block: CompositionBlockInputSchema.partial()
|
|
15507
|
+
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
15474
15508
|
kind: "mutation",
|
|
15475
|
-
auth: "admin"
|
|
15509
|
+
auth: "admin",
|
|
15510
|
+
caller: "required"
|
|
15476
15511
|
}),
|
|
15477
|
-
/**
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
collection: zod.z.string(),
|
|
15481
|
-
filter: QueryFilterSchema.optional()
|
|
15482
|
-
}), zod.z.number(), { auth: "admin" }),
|
|
15512
|
+
/** One composition and the composer's state for it, or `not-loaded` (D315). */
|
|
15513
|
+
getComposition: method(zod.z.object({ blockId: zod.z.string() }), CompositionGetReadSchema, { auth: "admin" }),
|
|
15514
|
+
listCompositions: method(zod.z.object({}), CompositionListReadSchema, { auth: "admin" }),
|
|
15483
15515
|
/**
|
|
15484
|
-
*
|
|
15485
|
-
*
|
|
15486
|
-
*
|
|
15487
|
-
* Exists because "how much is there" was being answered by materialising
|
|
15488
|
-
* "what is there". The recorder's storage-pressure sweep asked its in-RAM
|
|
15489
|
-
* footage index for bytes/count/oldest/newest across a set of storage
|
|
15490
|
-
* locations twice a minute, and the only way to answer that from a map is
|
|
15491
|
-
* to visit every row — 7.1 M of them on the live hub, ~15 M row visits a
|
|
15492
|
-
* minute on the main thread, which is also why the whole archive had to
|
|
15493
|
-
* stay resident to be visited. The question is a sum; nothing needs to be
|
|
15494
|
-
* materialised to answer it.
|
|
15495
|
-
*
|
|
15496
|
-
* **The engine REFUSES a field it cannot serve**, exactly as
|
|
15497
|
-
* `query.columns` does and unlike a PREDICATE, which is skipped when
|
|
15498
|
-
* unresolvable. A dropped predicate over-matches and the caller sees extra
|
|
15499
|
-
* rows; a dropped aggregate returns a NUMBER that is wrong and looks
|
|
15500
|
-
* exactly like a real one. That asymmetry is what this repo has already
|
|
15501
|
-
* paid for once in `count`.
|
|
15516
|
+
* The composition that customizes an existing device (D663), found by its
|
|
15517
|
+
* TARGET — never by the block's derived name. One per device at most.
|
|
15502
15518
|
*/
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
filter: QueryFilterSchema.optional()
|
|
15508
|
-
}), AggregateResultSchema, { auth: "admin" }),
|
|
15509
|
-
/** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
|
|
15510
|
-
histogram: method(zod.z.object({
|
|
15511
|
-
namespace: zod.z.string().optional(),
|
|
15512
|
-
collection: zod.z.string(),
|
|
15513
|
-
field: zod.z.string(),
|
|
15514
|
-
bucketSize: zod.z.number().int().positive(),
|
|
15515
|
-
origin: zod.z.number().int(),
|
|
15516
|
-
filter: QueryFilterSchema.optional()
|
|
15517
|
-
}), zod.z.array(zod.z.object({
|
|
15518
|
-
bucket: zod.z.number().int(),
|
|
15519
|
-
count: zod.z.number().int()
|
|
15520
|
-
})).readonly(), { auth: "admin" }),
|
|
15521
|
-
/** Check if a collection is empty. */
|
|
15522
|
-
isEmpty: method(zod.z.object({
|
|
15523
|
-
namespace: zod.z.string().optional(),
|
|
15524
|
-
collection: zod.z.string()
|
|
15525
|
-
}), zod.z.boolean(), { auth: "admin" }),
|
|
15519
|
+
getCustomization: method(zod.z.object({
|
|
15520
|
+
addonId: zod.z.string().min(1),
|
|
15521
|
+
stableId: zod.z.string().min(1)
|
|
15522
|
+
}), CompositionCustomizationReadSchema, { auth: "admin" }),
|
|
15526
15523
|
/**
|
|
15527
|
-
*
|
|
15528
|
-
*
|
|
15529
|
-
*
|
|
15530
|
-
*
|
|
15531
|
-
*
|
|
15532
|
-
* JSON-blob storage — `record.data` fields are spread across
|
|
15533
|
-
* columns, `query.filter.where` matches real columns (no
|
|
15534
|
-
* `json_extract` overhead), `orderBy` uses column indexes.
|
|
15535
|
-
*
|
|
15536
|
-
* Addons call this in `onInitialize` before their first read/write.
|
|
15537
|
-
* Collection names should be namespaced by addon (e.g.
|
|
15538
|
-
* `pipeline-analytics:object-events`) to avoid cross-addon
|
|
15539
|
-
* clashes — no automatic prefix is added.
|
|
15524
|
+
* The capabilities a composition may BUILD on a device of `deviceType`
|
|
15525
|
+
* (a new device, or added to an existing one), with their fields — the
|
|
15526
|
+
* editor's feature list and the presets' availability (G2, D676). Built
|
|
15527
|
+
* from the validator's own blockers; a replace of a BOUND cap is not
|
|
15528
|
+
* listed here (the device's bindings say what it has).
|
|
15540
15529
|
*/
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
|
|
15530
|
+
listComposableCaps: method(zod.z.object({ deviceType: zod.z.enum(DeviceType) }), ComposableCapabilitiesSchema, { auth: "admin" }),
|
|
15531
|
+
/**
|
|
15532
|
+
* Validate without saving — the same verdict the save reaches. A mutation
|
|
15533
|
+
* for its body size; it writes nothing, so its access is `view`.
|
|
15534
|
+
*/
|
|
15535
|
+
validateComposition: method(zod.z.object({
|
|
15536
|
+
composition: CompositionSchema,
|
|
15537
|
+
blockId: zod.z.string().optional()
|
|
15538
|
+
}), CompositionValidationSchema, {
|
|
15547
15539
|
kind: "mutation",
|
|
15548
|
-
auth: "admin"
|
|
15540
|
+
auth: "admin",
|
|
15541
|
+
access: "view"
|
|
15542
|
+
})
|
|
15543
|
+
}
|
|
15544
|
+
};
|
|
15545
|
+
/**
|
|
15546
|
+
* `custom-model-registry` — collection cap exposing operator-registered
|
|
15547
|
+
* custom detection models. Each provider (today: `addon-model-studio`)
|
|
15548
|
+
* contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
|
|
15549
|
+
* them across providers (`concatCollection`).
|
|
15550
|
+
*
|
|
15551
|
+
* The detection-pipeline is *aware* of this cap: when at least one provider
|
|
15552
|
+
* exists it unions these descriptors into the per-step model picker and the
|
|
15553
|
+
* runtime model-resolution path, alongside the static catalog. When no
|
|
15554
|
+
* provider exists the consumer no-ops entirely (identical to the catalog-only
|
|
15555
|
+
* behaviour).
|
|
15556
|
+
*
|
|
15557
|
+
* A descriptor carries a full `ModelCatalogEntry` directly — the same shape
|
|
15558
|
+
* the static catalog uses — so the existing download/resolution code consumes
|
|
15559
|
+
* it unchanged. `stepId` is the detection step the model targets
|
|
15560
|
+
* (e.g. `'object-detection'`).
|
|
15561
|
+
*/
|
|
15562
|
+
var CustomModelDescriptorSchema = zod.z.object({
|
|
15563
|
+
stepId: zod.z.string(),
|
|
15564
|
+
entry: ModelCatalogEntrySchema
|
|
15565
|
+
});
|
|
15566
|
+
/** One regular file of an imported bundle, as the producer measured it. */
|
|
15567
|
+
var ModelBundleFileSchema = zod.z.object({
|
|
15568
|
+
/** Relative path inside the bundle tar; an mlpackage member is `<x>.mlpackage/<member>`. */
|
|
15569
|
+
path: zod.z.string().min(1),
|
|
15570
|
+
bytes: zod.z.number().int().nonnegative(),
|
|
15571
|
+
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
15572
|
+
});
|
|
15573
|
+
var ImportModelBundleInputSchema = zod.z.object({
|
|
15574
|
+
/** The registry provider that keeps the model (Model Studio). */
|
|
15575
|
+
addonId: zod.z.string(),
|
|
15576
|
+
stepId: zod.z.string().min(1),
|
|
15577
|
+
/**
|
|
15578
|
+
* The catalog rows to register, complete, every format URL already
|
|
15579
|
+
* `camstack-local://<modelId>/<file>` naming a file of the bundle. One
|
|
15580
|
+
* bundle may carry several rows (a base and its INT8 variant).
|
|
15581
|
+
*/
|
|
15582
|
+
entries: zod.z.array(ModelCatalogEntrySchema).min(1).max(4),
|
|
15583
|
+
/** The bundle tar, offered by the producer over `ctx.peerBytes` (same host). */
|
|
15584
|
+
bundle: zod.z.object({
|
|
15585
|
+
ticket: PeerBytesTicketSchema,
|
|
15586
|
+
bytes: zod.z.number().int().positive(),
|
|
15587
|
+
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
15588
|
+
}),
|
|
15589
|
+
/** Every file the tar must hold; anything missing, extra or different is refused. */
|
|
15590
|
+
files: zod.z.array(ModelBundleFileSchema).min(1).max(64),
|
|
15591
|
+
/** Convert missing engine formats and push the model to every agent afterwards. */
|
|
15592
|
+
distribute: zod.z.boolean()
|
|
15593
|
+
});
|
|
15594
|
+
var ImportModelBundleResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
15595
|
+
kind: zod.z.literal("imported"),
|
|
15596
|
+
modelIds: zod.z.array(zod.z.string()).readonly(),
|
|
15597
|
+
distributed: zod.z.array(zod.z.object({
|
|
15598
|
+
modelId: zod.z.string(),
|
|
15599
|
+
nodeId: zod.z.string(),
|
|
15600
|
+
format: zod.z.enum(MODEL_FORMATS),
|
|
15601
|
+
ok: zod.z.boolean(),
|
|
15602
|
+
error: zod.z.string().optional()
|
|
15603
|
+
})).readonly()
|
|
15604
|
+
}), zod.z.object({
|
|
15605
|
+
kind: zod.z.literal("refused"),
|
|
15606
|
+
reason: zod.z.enum([
|
|
15607
|
+
"transfer-failed",
|
|
15608
|
+
"checksum-mismatch",
|
|
15609
|
+
"bundle-mismatch",
|
|
15610
|
+
"invalid-entry",
|
|
15611
|
+
"id-taken"
|
|
15612
|
+
]),
|
|
15613
|
+
detail: zod.z.string()
|
|
15614
|
+
})]);
|
|
15615
|
+
var customModelRegistryCapability = {
|
|
15616
|
+
name: "custom-model-registry",
|
|
15617
|
+
scope: "system",
|
|
15618
|
+
mode: "collection",
|
|
15619
|
+
internal: true,
|
|
15620
|
+
methods: {
|
|
15621
|
+
/**
|
|
15622
|
+
* `internal: true` did not gate the mount (see the 2026-08-26 note on
|
|
15623
|
+
* `data-store-provider`) — this was reachable on the AppRouter by ANY
|
|
15624
|
+
* authenticated session at the default `auth: 'protected'`. The only
|
|
15625
|
+
* consumer, the detection-pipeline's model resolution
|
|
15626
|
+
* (`addon-pipeline/src/detection-pipeline/provider.ts`), calls
|
|
15627
|
+
* `ctx.api.customModelRegistry.listModels.query()` — UDS/Moleculer,
|
|
15628
|
+
* never tRPC — so `auth: 'admin'` costs it nothing.
|
|
15629
|
+
*/
|
|
15630
|
+
listModels: method(zod.z.void(), zod.z.array(CustomModelDescriptorSchema).readonly(), { auth: "admin" }),
|
|
15631
|
+
/**
|
|
15632
|
+
* Register a model whose files arrive as ONE bundle tar (D806): the tar
|
|
15633
|
+
* is taken over `ctx.peerBytes`, checked against `bundle.sha256` and
|
|
15634
|
+
* every row of `files`, unpacked into the hub's flat modelsDir (directory
|
|
15635
|
+
* formats included), each format's `.revision` record written, the rows
|
|
15636
|
+
* upserted under the operator's name, the hub marked available and —
|
|
15637
|
+
* when asked — engine formats converted and the model distributed. A
|
|
15638
|
+
* model id already registered by another source is refused, never
|
|
15639
|
+
* overwritten.
|
|
15640
|
+
*/
|
|
15641
|
+
importModelBundle: method(ImportModelBundleInputSchema, ImportModelBundleResultSchema, {
|
|
15642
|
+
kind: "mutation",
|
|
15643
|
+
auth: "admin",
|
|
15644
|
+
timeoutMs: 30 * 6e4
|
|
15549
15645
|
})
|
|
15550
15646
|
}
|
|
15551
15647
|
};
|
|
@@ -15694,6 +15790,16 @@ id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
|
15694
15790
|
kind: "mutation",
|
|
15695
15791
|
auth: "admin"
|
|
15696
15792
|
}),
|
|
15793
|
+
/** Upsert many records in ONE transaction; see the door's `upsertMany`. */
|
|
15794
|
+
upsertMany: method(zod.z.object({
|
|
15795
|
+
namespace: zod.z.string().optional(),
|
|
15796
|
+
collection: zod.z.string(),
|
|
15797
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
15798
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
15799
|
+
}), zod.z.object({ upserted: zod.z.number().int() }), {
|
|
15800
|
+
kind: "mutation",
|
|
15801
|
+
auth: "admin"
|
|
15802
|
+
}),
|
|
15697
15803
|
/** Insert many records in ONE transaction. All or nothing. */
|
|
15698
15804
|
insertMany: method(zod.z.object({
|
|
15699
15805
|
namespace: zod.z.string().optional(),
|
|
@@ -15786,12 +15892,7 @@ id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
|
15786
15892
|
collection: zod.z.string()
|
|
15787
15893
|
}), zod.z.boolean(), { auth: "admin" }),
|
|
15788
15894
|
/** Declare a typed (SQL-backed) collection with columns + indexes. */
|
|
15789
|
-
declareCollection: method(zod.z.
|
|
15790
|
-
namespace: zod.z.string().optional(),
|
|
15791
|
-
collection: zod.z.string(),
|
|
15792
|
-
columns: zod.z.array(CollectionColumnSchema).readonly(),
|
|
15793
|
-
indexes: zod.z.array(CollectionIndexSchema).readonly().optional()
|
|
15794
|
-
}), zod.z.void(), {
|
|
15895
|
+
declareCollection: method(DeclareCollectionInputSchema, zod.z.void(), {
|
|
15795
15896
|
kind: "mutation",
|
|
15796
15897
|
auth: "admin"
|
|
15797
15898
|
})
|
|
@@ -53098,6 +53199,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
53098
53199
|
addonId: null,
|
|
53099
53200
|
access: "create"
|
|
53100
53201
|
},
|
|
53202
|
+
"dataStoreProvider.upsertMany": {
|
|
53203
|
+
capName: "data-store-provider",
|
|
53204
|
+
capScope: "system",
|
|
53205
|
+
addonId: null,
|
|
53206
|
+
access: "create"
|
|
53207
|
+
},
|
|
53101
53208
|
"dayNight.getOptions": {
|
|
53102
53209
|
capName: "day-night",
|
|
53103
53210
|
capScope: "device",
|
|
@@ -57946,6 +58053,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
57946
58053
|
addonId: null,
|
|
57947
58054
|
access: "create"
|
|
57948
58055
|
},
|
|
58056
|
+
"settingsStore.upsertMany": {
|
|
58057
|
+
capName: "settings-store",
|
|
58058
|
+
capScope: "system",
|
|
58059
|
+
addonId: null,
|
|
58060
|
+
access: "create"
|
|
58061
|
+
},
|
|
57949
58062
|
"smoke.getStatus": {
|
|
57950
58063
|
capName: "smoke",
|
|
57951
58064
|
capScope: "device",
|
|
@@ -65568,6 +65681,12 @@ Object.defineProperty(exports, "DATAPLANE_SECRET_HEADER", {
|
|
|
65568
65681
|
return DATAPLANE_SECRET_HEADER;
|
|
65569
65682
|
}
|
|
65570
65683
|
});
|
|
65684
|
+
Object.defineProperty(exports, "DATA_STORE_DATABASES", {
|
|
65685
|
+
enumerable: true,
|
|
65686
|
+
get: function() {
|
|
65687
|
+
return DATA_STORE_DATABASES;
|
|
65688
|
+
}
|
|
65689
|
+
});
|
|
65571
65690
|
Object.defineProperty(exports, "DAY_NAMES", {
|
|
65572
65691
|
enumerable: true,
|
|
65573
65692
|
get: function() {
|