@camstack/types 1.2.361 → 1.2.363
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/capabilities/backup.cap.d.ts +69 -0
- package/dist/capabilities/calendar-source.cap.d.ts +26 -0
- package/dist/capabilities/database-snapshot.cap.d.ts +67 -7
- package/dist/capabilities/index.d.ts +3 -3
- package/dist/capabilities/local-network.cap.d.ts +5 -0
- package/dist/client.js +1 -0
- package/dist/client.mjs +1 -0
- package/dist/generated/addon-api.d.ts +7 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.js +901 -793
- package/dist/index.mjs +898 -794
- package/dist/interfaces/addon.d.ts +37 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8326,6 +8326,570 @@ var authProviderCapability = {
|
|
|
8326
8326
|
mount: { kind: "skip" }
|
|
8327
8327
|
};
|
|
8328
8328
|
//#endregion
|
|
8329
|
+
//#region src/capabilities/settings-store.cap.ts
|
|
8330
|
+
/**
|
|
8331
|
+
* Query filter for settings-store collections.
|
|
8332
|
+
*/
|
|
8333
|
+
var QueryFilterSchema = zod.z.object({
|
|
8334
|
+
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
8335
|
+
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
8336
|
+
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
8337
|
+
/** NULL-safe exclusion: matches rows whose field is NULL OR != the value. */
|
|
8338
|
+
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
8339
|
+
/** NULL-safe exclusion of a SET — `whereNot` for more than one value. An
|
|
8340
|
+
* empty list excludes nothing. See `QueryFilter.whereNotIn`. */
|
|
8341
|
+
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
8342
|
+
orderBy: zod.z.object({
|
|
8343
|
+
field: zod.z.string(),
|
|
8344
|
+
direction: zod.z.enum(["asc", "desc"])
|
|
8345
|
+
}).optional(),
|
|
8346
|
+
limit: zod.z.number().optional(),
|
|
8347
|
+
offset: zod.z.number().optional()
|
|
8348
|
+
});
|
|
8349
|
+
/**
|
|
8350
|
+
* The predicate half of a filter, for BULK MUTATIONS.
|
|
8351
|
+
*
|
|
8352
|
+
* Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
|
|
8353
|
+
* meaning for a statement that rewrites a set, and accepting them would invite
|
|
8354
|
+
* a caller to believe `limit` bounds the damage. Every field is optional here
|
|
8355
|
+
* only so the shape stays composable — the implementation REJECTS a filter
|
|
8356
|
+
* that compiles to no predicate, because that is the whole collection.
|
|
8357
|
+
*/
|
|
8358
|
+
var MutationFilterSchema = zod.z.object({
|
|
8359
|
+
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
8360
|
+
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
8361
|
+
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
8362
|
+
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
8363
|
+
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional()
|
|
8364
|
+
});
|
|
8365
|
+
/**
|
|
8366
|
+
* One scalar an {@link settingsStoreCapability.methods.aggregate} call asks for.
|
|
8367
|
+
*
|
|
8368
|
+
* `as` names the slot in the result, so the SAME column may be asked twice with
|
|
8369
|
+
* two operations (`MIN(startMs)` and `MAX(startMs)` in one round trip) — which
|
|
8370
|
+
* a `Record<column, op>` shape could not express.
|
|
8371
|
+
*/
|
|
8372
|
+
var AggregateFieldSchema = zod.z.object({
|
|
8373
|
+
/** Result key. */
|
|
8374
|
+
as: zod.z.string().min(1),
|
|
8375
|
+
/** Column to aggregate. Must be a real column of a declared collection. */
|
|
8376
|
+
field: zod.z.string().min(1),
|
|
8377
|
+
op: zod.z.enum([
|
|
8378
|
+
"sum",
|
|
8379
|
+
"min",
|
|
8380
|
+
"max"
|
|
8381
|
+
])
|
|
8382
|
+
});
|
|
8383
|
+
/**
|
|
8384
|
+
* `COUNT(*)` plus one number per requested field.
|
|
8385
|
+
*
|
|
8386
|
+
* `null` means NO ROW MATCHED, never zero: a `SUM` over an empty set and a sum
|
|
8387
|
+
* that really is 0 are different facts, and an accounting caller that renders
|
|
8388
|
+
* "0 bytes, oldest = 0" for "nothing here" reports a lie about a disk.
|
|
8389
|
+
*/
|
|
8390
|
+
var AggregateResultSchema = zod.z.object({
|
|
8391
|
+
count: zod.z.number().int(),
|
|
8392
|
+
values: zod.z.record(zod.z.string(), zod.z.number().nullable())
|
|
8393
|
+
});
|
|
8394
|
+
/** A single stored record: `{ id, data }`. */
|
|
8395
|
+
var SettingsRecordSchema = zod.z.object({
|
|
8396
|
+
id: zod.z.string(),
|
|
8397
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
8398
|
+
});
|
|
8399
|
+
/**
|
|
8400
|
+
* One record of a BULK insert — {@link SettingsRecordSchema} with the id made
|
|
8401
|
+
* optional.
|
|
8402
|
+
*
|
|
8403
|
+
* A separate schema rather than loosening the shared one: every other method
|
|
8404
|
+
* on this cap addresses a row BY its id, and making that field optional
|
|
8405
|
+
* everywhere would turn a forgotten key into a silently generated one on
|
|
8406
|
+
* `update` and `delete` as well.
|
|
8407
|
+
*/
|
|
8408
|
+
var BulkRecordSchema = zod.z.object({
|
|
8409
|
+
id: zod.z.string().optional(),
|
|
8410
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
8411
|
+
});
|
|
8412
|
+
/**
|
|
8413
|
+
* The database FILES one `sqlite-settings` engine process owns (D851).
|
|
8414
|
+
* Closed on purpose: a file is a thing the engine opens, backs up and gives a
|
|
8415
|
+
* serving thread, so a new one is a code change, never a string a caller
|
|
8416
|
+
* invents. `settings` is `camstack.db` and the default for every collection
|
|
8417
|
+
* that names no file.
|
|
8418
|
+
*/
|
|
8419
|
+
var DataStoreDatabaseSchema = zod.z.enum([
|
|
8420
|
+
"settings",
|
|
8421
|
+
"events",
|
|
8422
|
+
"history"
|
|
8423
|
+
]);
|
|
8424
|
+
/** Every database file, in a stable order (settings first). */
|
|
8425
|
+
var DATA_STORE_DATABASES = DataStoreDatabaseSchema.options;
|
|
8426
|
+
/**
|
|
8427
|
+
* One write inside a {@link settingsStoreCapability.methods.transact} call.
|
|
8428
|
+
* The three that a "replace this set, bump that revision" write needs, plus
|
|
8429
|
+
* the batched upsert a rollup writer needs.
|
|
8430
|
+
*/
|
|
8431
|
+
var TransactOpSchema = zod.z.discriminatedUnion("op", [
|
|
8432
|
+
zod.z.object({
|
|
8433
|
+
op: zod.z.literal("deleteWhere"),
|
|
8434
|
+
collection: zod.z.string(),
|
|
8435
|
+
filter: MutationFilterSchema
|
|
8436
|
+
}),
|
|
8437
|
+
zod.z.object({
|
|
8438
|
+
op: zod.z.literal("insertMany"),
|
|
8439
|
+
collection: zod.z.string(),
|
|
8440
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
8441
|
+
}),
|
|
8442
|
+
zod.z.object({
|
|
8443
|
+
op: zod.z.literal("update"),
|
|
8444
|
+
collection: zod.z.string(),
|
|
8445
|
+
id: zod.z.string(),
|
|
8446
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
8447
|
+
}),
|
|
8448
|
+
zod.z.object({
|
|
8449
|
+
op: zod.z.literal("upsertMany"),
|
|
8450
|
+
collection: zod.z.string(),
|
|
8451
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
8452
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
8453
|
+
})
|
|
8454
|
+
]);
|
|
8455
|
+
/**
|
|
8456
|
+
* The precondition of a transaction: the row `key` of `collection` must hold
|
|
8457
|
+
* `equals` in `column`, read INSIDE the transaction.
|
|
8458
|
+
*/
|
|
8459
|
+
var TransactGuardSchema = zod.z.object({
|
|
8460
|
+
collection: zod.z.string(),
|
|
8461
|
+
key: zod.z.string(),
|
|
8462
|
+
column: zod.z.string(),
|
|
8463
|
+
equals: zod.z.unknown()
|
|
8464
|
+
});
|
|
8465
|
+
/**
|
|
8466
|
+
* Column declaration for a structured (SQL-backed) collection.
|
|
8467
|
+
*
|
|
8468
|
+
* Logical types — the backend translates each to the matching SQLite
|
|
8469
|
+
* storage class and handles per-type marshaling:
|
|
8470
|
+
* - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
|
|
8471
|
+
* - `JSON` — TEXT under the hood; serialised on write, parsed on read
|
|
8472
|
+
* - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
|
|
8473
|
+
*/
|
|
8474
|
+
var CollectionColumnSchema = zod.z.object({
|
|
8475
|
+
name: zod.z.string(),
|
|
8476
|
+
type: zod.z.enum([
|
|
8477
|
+
"TEXT",
|
|
8478
|
+
"INTEGER",
|
|
8479
|
+
"REAL",
|
|
8480
|
+
"JSON",
|
|
8481
|
+
"BOOLEAN"
|
|
8482
|
+
]),
|
|
8483
|
+
primaryKey: zod.z.boolean().optional(),
|
|
8484
|
+
notNull: zod.z.boolean().optional(),
|
|
8485
|
+
unique: zod.z.boolean().optional(),
|
|
8486
|
+
/**
|
|
8487
|
+
* Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
|
|
8488
|
+
* columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
|
|
8489
|
+
* collection surface simply cannot express their existing tables — which is
|
|
8490
|
+
* why they were still on the uncapped `table*` API.
|
|
8491
|
+
*/
|
|
8492
|
+
defaultValue: zod.z.union([
|
|
8493
|
+
zod.z.string(),
|
|
8494
|
+
zod.z.number(),
|
|
8495
|
+
zod.z.boolean()
|
|
8496
|
+
]).optional()
|
|
8497
|
+
});
|
|
8498
|
+
var CollectionIndexSchema = zod.z.object({
|
|
8499
|
+
name: zod.z.string(),
|
|
8500
|
+
columns: zod.z.array(zod.z.string()).readonly(),
|
|
8501
|
+
unique: zod.z.boolean().optional()
|
|
8502
|
+
});
|
|
8503
|
+
/**
|
|
8504
|
+
* The input of `declareCollection` — ONE schema for the door and for the
|
|
8505
|
+
* engine behind it, so the two surfaces cannot drift (the dispatcher forwards
|
|
8506
|
+
* the payload untouched).
|
|
8507
|
+
*
|
|
8508
|
+
* - `database` — the file the collection lives in (D851). Absent means
|
|
8509
|
+
* `settings`. A declaration naming a file other than the one the table is
|
|
8510
|
+
* already in is REFUSED by the engine, never moved.
|
|
8511
|
+
* - `primaryKey` — a COMPOSITE key, as column names. A single name is the same
|
|
8512
|
+
* as `primaryKey: true` on that column. A composite-keyed collection has no
|
|
8513
|
+
* `id`: it is written with `insertMany` / `upsertMany` / `transact` and read
|
|
8514
|
+
* with `query` / `count` / `aggregate` / `deleteWhere`; the calls that
|
|
8515
|
+
* address one row by id are refused.
|
|
8516
|
+
* - `withoutRowid` — emit `WITHOUT ROWID`. Requires a primary key.
|
|
8517
|
+
*/
|
|
8518
|
+
var DeclareCollectionInputSchema = zod.z.object({
|
|
8519
|
+
namespace: zod.z.string().optional(),
|
|
8520
|
+
collection: zod.z.string(),
|
|
8521
|
+
columns: zod.z.array(CollectionColumnSchema).readonly(),
|
|
8522
|
+
indexes: zod.z.array(CollectionIndexSchema).readonly().optional(),
|
|
8523
|
+
database: DataStoreDatabaseSchema.optional(),
|
|
8524
|
+
primaryKey: zod.z.array(zod.z.string()).readonly().optional(),
|
|
8525
|
+
withoutRowid: zod.z.boolean().optional()
|
|
8526
|
+
});
|
|
8527
|
+
/**
|
|
8528
|
+
* settings-store — singleton capability for addon-scoped persistence.
|
|
8529
|
+
*
|
|
8530
|
+
* Every method operates within a `collection`. An optional `namespace`
|
|
8531
|
+
* field provides access to additional data spaces beyond the default
|
|
8532
|
+
* addon settings — useful for business data (events, tracks, faces, etc.).
|
|
8533
|
+
*
|
|
8534
|
+
* **Scoping is the CALLER's, and it is opt-in.** The table is
|
|
8535
|
+
* `namespace ? `${namespace}:${collection}` : collection` — nothing
|
|
8536
|
+
* consults the identity of the caller. An earlier version of this comment
|
|
8537
|
+
* claimed the implementation prefixes every collection with the calling
|
|
8538
|
+
* addon's ID and that "addons never see each other's data"; that was never
|
|
8539
|
+
* true, and this same file contradicted it under `declareCollection`. What
|
|
8540
|
+
* exists is `addon-context-factory`, which passes `namespace: addonId` ON
|
|
8541
|
+
* THE ADDON'S BEHALF for the `addon-settings` / `addon-devices` paths only.
|
|
8542
|
+
* Business collections use bare names, and any caller may name any
|
|
8543
|
+
* namespace, or none. Making the door enforce it is tracked separately —
|
|
8544
|
+
* it renames tables, so it needs a migration.
|
|
8545
|
+
*
|
|
8546
|
+
* **So every method is `auth: 'admin'` (D634).** Because nothing scopes a
|
|
8547
|
+
* call to its caller, a `protected` method here was a raw, unredacted read
|
|
8548
|
+
* (and write) of every addon's collections for any role holding
|
|
8549
|
+
* `category:system` — which is every role: a `viewer` could read every
|
|
8550
|
+
* notifier token in plaintext from `notifiers:notification-targets`. No
|
|
8551
|
+
* browser or app client calls this cap. Addons are not affected: an
|
|
8552
|
+
* addon's `ctx.api` cap call is resolved to the provider directly and never
|
|
8553
|
+
* enters the tRPC router (so the tier gates sessions and tokens, never
|
|
8554
|
+
* addons), and the hub itself calls it through the capability registry.
|
|
8555
|
+
*
|
|
8556
|
+
* - `{ collection: 'addon-settings' }` → table `addon-settings`
|
|
8557
|
+
* - `{ namespace: 'my-addon', collection: 'addon-settings' }` →
|
|
8558
|
+
* table `my-addon:addon-settings`
|
|
8559
|
+
*
|
|
8560
|
+
* Served by the **storage-orchestrator** builtin, which dispatches to the
|
|
8561
|
+
* `data-store-provider` engine registered for the collection
|
|
8562
|
+
* (`sqlite-settings`, a SQLite WAL backend, today). One addon owns the
|
|
8563
|
+
* data door; engines sit behind it
|
|
8564
|
+
* ([D44](../../../../docs/decisions/adr-0044.md)).
|
|
8565
|
+
* Addons access it via `ctx.api.settingsStore.*`.
|
|
8566
|
+
*/
|
|
8567
|
+
var settingsStoreCapability = {
|
|
8568
|
+
name: "settings-store",
|
|
8569
|
+
scope: "system",
|
|
8570
|
+
mode: "singleton",
|
|
8571
|
+
methods: {
|
|
8572
|
+
/** Get a single value by key from a collection. */
|
|
8573
|
+
get: require_sleep.method(zod.z.object({
|
|
8574
|
+
namespace: zod.z.string().optional(),
|
|
8575
|
+
collection: zod.z.string(),
|
|
8576
|
+
key: zod.z.string()
|
|
8577
|
+
}), zod.z.unknown(), { auth: "admin" }),
|
|
8578
|
+
/** Set a value by key in a collection (upsert). */
|
|
8579
|
+
set: require_sleep.method(zod.z.object({
|
|
8580
|
+
namespace: zod.z.string().optional(),
|
|
8581
|
+
collection: zod.z.string(),
|
|
8582
|
+
key: zod.z.string(),
|
|
8583
|
+
value: zod.z.unknown()
|
|
8584
|
+
}), zod.z.void(), {
|
|
8585
|
+
kind: "mutation",
|
|
8586
|
+
auth: "admin"
|
|
8587
|
+
}),
|
|
8588
|
+
/**
|
|
8589
|
+
* Rows matching a filter.
|
|
8590
|
+
*
|
|
8591
|
+
* `columns` is a SQL-level projection: the engine SELECTs only those
|
|
8592
|
+
* columns (plus the primary key) instead of the whole row. It is the only
|
|
8593
|
+
* way to stop paying disk for a column that is discarded — a heavy JSON
|
|
8594
|
+
* column dominates the row, and dropping it in JS after the read pays every
|
|
8595
|
+
* byte first. Measured on the live `pipeline-analytics:tracks` table: a
|
|
8596
|
+
* 501-row page is 4.6 MB whole and 0.11 MB projected, same index, same
|
|
8597
|
+
* plan.
|
|
8598
|
+
*
|
|
8599
|
+
* The engine REFUSES a column it cannot serve rather than omitting it —
|
|
8600
|
+
* see `SettingsQueryInput.columns` for why a projection may not be
|
|
8601
|
+
* forgiving the way a predicate is.
|
|
8602
|
+
*/
|
|
8603
|
+
query: require_sleep.method(zod.z.object({
|
|
8604
|
+
namespace: zod.z.string().optional(),
|
|
8605
|
+
collection: zod.z.string(),
|
|
8606
|
+
filter: QueryFilterSchema.optional(),
|
|
8607
|
+
columns: zod.z.array(zod.z.string()).readonly().optional()
|
|
8608
|
+
}), zod.z.array(SettingsRecordSchema).readonly(), { auth: "admin" }),
|
|
8609
|
+
/**
|
|
8610
|
+
* Make a SLOT hold this row — insert it, or update whatever already
|
|
8611
|
+
* occupies the slot — and answer with the id the row HAS.
|
|
8612
|
+
*
|
|
8613
|
+
* ## Why the store needed this
|
|
8614
|
+
*
|
|
8615
|
+
* {@link set} is already an upsert, but its slot is the PRIMARY KEY: the
|
|
8616
|
+
* caller has to know the id to address the row. That is exactly what a
|
|
8617
|
+
* collection keyed by an `INTEGER` rowid alias cannot do — SQLite assigns
|
|
8618
|
+
* the id, so a writer whose uniqueness rule is "one row per
|
|
8619
|
+
* `(ownerKind, ownerId, kind, slot)`" has no id to name and no way to
|
|
8620
|
+
* express the rule. {@link insert} can express it (a UNIQUE index
|
|
8621
|
+
* arbitrates) but only by THROWING at the loser of a race, and the loser
|
|
8622
|
+
* here is a legitimate re-capture, not an error.
|
|
8623
|
+
*
|
|
8624
|
+
* Getting there without this method means read-then-write: query the slot,
|
|
8625
|
+
* then `insert` or `update`. Two statements instead of one, a race between
|
|
8626
|
+
* them, and a recovery path that has to recognise a UNIQUE violation by its
|
|
8627
|
+
* MESSAGE — across a process boundary, because the store lives behind an
|
|
8628
|
+
* RPC door. A string match would be the whole gate, and a store that
|
|
8629
|
+
* rephrased its error would lose the row silently. One statement has no
|
|
8630
|
+
* such gate (D482).
|
|
8631
|
+
*
|
|
8632
|
+
* ## The contract
|
|
8633
|
+
*
|
|
8634
|
+
* `conflict` names the DECLARED columns that identify the slot. They must
|
|
8635
|
+
* be covered by a UNIQUE index on the collection — SQLite resolves an
|
|
8636
|
+
* `ON CONFLICT` target against its indexes and REFUSES the statement when
|
|
8637
|
+
* none matches, so a wrong list is a loud error on the first write, never a
|
|
8638
|
+
* silently duplicated row. An empty list is refused rather than passed on:
|
|
8639
|
+
* `ON CONFLICT()` is not valid SQL, and the intent it would most likely
|
|
8640
|
+
* encode ("no slot, just insert") is {@link insert}.
|
|
8641
|
+
*
|
|
8642
|
+
* Row shape is {@link insert}'s: `record.id` is used when the collection
|
|
8643
|
+
* needs a supplied key and IGNORED when the primary key is an `INTEGER`
|
|
8644
|
+
* rowid alias — exactly as `insert` and `insertMany` already treat it.
|
|
8645
|
+
*
|
|
8646
|
+
* Returns the id either way: the one SQLite assigned on an insert, or the
|
|
8647
|
+
* one the row it updated already had. A caller cannot tell which happened,
|
|
8648
|
+
* and deliberately — every caller wants the slot's id, and one that needed
|
|
8649
|
+
* to distinguish creation from replacement would have to read first anyway.
|
|
8650
|
+
*/
|
|
8651
|
+
upsert: require_sleep.method(zod.z.object({
|
|
8652
|
+
namespace: zod.z.string().optional(),
|
|
8653
|
+
collection: zod.z.string(),
|
|
8654
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
8655
|
+
* index on the collection. Never empty. */
|
|
8656
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
8657
|
+
record: BulkRecordSchema
|
|
8658
|
+
}), zod.z.object({
|
|
8659
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
8660
|
+
* row's own id on an update. */
|
|
8661
|
+
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
8662
|
+
kind: "mutation",
|
|
8663
|
+
auth: "admin"
|
|
8664
|
+
}),
|
|
8665
|
+
/**
|
|
8666
|
+
* {@link upsert} for a BATCH, in ONE transaction on ONE prepared statement.
|
|
8667
|
+
*
|
|
8668
|
+
* The write-side twin of {@link insertMany} for rows that may already
|
|
8669
|
+
* exist: a rollup writer recomputes a bucket and must overwrite it, and
|
|
8670
|
+
* N round trips with N COMMITs is the cost {@link insertMany} was added to
|
|
8671
|
+
* avoid. `conflict` has the meaning it has on {@link upsert} (declared
|
|
8672
|
+
* columns covered by a UNIQUE index or the primary key, never empty).
|
|
8673
|
+
*
|
|
8674
|
+
* Every record of a batch must carry the SAME set of declared columns and
|
|
8675
|
+
* every `conflict` column: one batch is one statement shape, and a record
|
|
8676
|
+
* that silently bound NULL over a column it did not mention would erase
|
|
8677
|
+
* it. A heterogeneous batch is refused whole. **All or nothing.**
|
|
8678
|
+
*/
|
|
8679
|
+
upsertMany: require_sleep.method(zod.z.object({
|
|
8680
|
+
namespace: zod.z.string().optional(),
|
|
8681
|
+
collection: zod.z.string(),
|
|
8682
|
+
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
8683
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
8684
|
+
}), zod.z.object({ upserted: zod.z.number().int() }), {
|
|
8685
|
+
kind: "mutation",
|
|
8686
|
+
auth: "admin"
|
|
8687
|
+
}),
|
|
8688
|
+
/** Insert a new record. */
|
|
8689
|
+
insert: require_sleep.method(zod.z.object({
|
|
8690
|
+
namespace: zod.z.string().optional(),
|
|
8691
|
+
collection: zod.z.string(),
|
|
8692
|
+
record: zod.z.object({
|
|
8693
|
+
id: zod.z.string().optional(),
|
|
8694
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
8695
|
+
})
|
|
8696
|
+
}), zod.z.object({
|
|
8697
|
+
/**
|
|
8698
|
+
* The id the row ACTUALLY got (D473): the one supplied, the UUID minted
|
|
8699
|
+
* for an absent one, or the ROWID SQLite assigned on an `INTEGER`
|
|
8700
|
+
* primary key — which is the only place an auto key is knowable.
|
|
8701
|
+
*/
|
|
8702
|
+
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
8703
|
+
kind: "mutation",
|
|
8704
|
+
auth: "admin"
|
|
8705
|
+
}),
|
|
8706
|
+
/**
|
|
8707
|
+
* Insert MANY records in ONE transaction, returning how many landed.
|
|
8708
|
+
*
|
|
8709
|
+
* The write-side twin of {@link deleteWhere}, and it exists for the same
|
|
8710
|
+
* reason: without it, appending a batch is N round trips and N COMMITs on
|
|
8711
|
+
* the single shared connection that also serves every cluster-wide
|
|
8712
|
+
* configuration read. The durable load series writes one process row per
|
|
8713
|
+
* process per sample — 76 rows every 10 s on the live fleet — and the
|
|
8714
|
+
* operator's rule for it is *one transaction per sample, never one per
|
|
8715
|
+
* row*. `insert` cannot express that; nothing else could.
|
|
8716
|
+
*
|
|
8717
|
+
* **All or nothing.** A batch that fails on its fifth row leaves none of
|
|
8718
|
+
* the five behind. A half-written sample is worse than a missing one: the
|
|
8719
|
+
* missing one reads as "nobody reported", which is true, while the half
|
|
8720
|
+
* one reads as "these were the only processes running", which is not.
|
|
8721
|
+
*
|
|
8722
|
+
* `id` is OPTIONAL per record, and that is the difference from
|
|
8723
|
+
* {@link insert}. A collection whose primary key is an `INTEGER` rowid
|
|
8724
|
+
* alias has no id to supply — SQLite assigns it, for free, and inventing a
|
|
8725
|
+
* `randomUUID()` for such a column would write a 36-character string into
|
|
8726
|
+
* an integer key. Omitted on a TEXT key, a uuid is generated exactly as
|
|
8727
|
+
* `insert` does.
|
|
8728
|
+
*/
|
|
8729
|
+
insertMany: require_sleep.method(zod.z.object({
|
|
8730
|
+
namespace: zod.z.string().optional(),
|
|
8731
|
+
collection: zod.z.string(),
|
|
8732
|
+
records: zod.z.array(BulkRecordSchema).readonly()
|
|
8733
|
+
}), zod.z.object({ inserted: zod.z.number().int() }), {
|
|
8734
|
+
kind: "mutation",
|
|
8735
|
+
auth: "admin"
|
|
8736
|
+
}),
|
|
8737
|
+
/**
|
|
8738
|
+
* Several writes, ONE transaction, behind an optional precondition.
|
|
8739
|
+
*
|
|
8740
|
+
* The multi-collection twin of {@link insertMany}: a write that has to move
|
|
8741
|
+
* a set of rows in one collection AND a revision in another cannot be
|
|
8742
|
+
* expressed as separate calls without a window in which a reader (or a
|
|
8743
|
+
* crash) sees half of it. The retrain annotation save replaces a frame's
|
|
8744
|
+
* rows, its dismissed set and its revision this way.
|
|
8745
|
+
*
|
|
8746
|
+
* `guard`, when given, is read inside the transaction: if the row is
|
|
8747
|
+
* missing or its column differs from `equals`, NOTHING is written and the
|
|
8748
|
+
* answer is `{ applied: false, current }` with what was found — the
|
|
8749
|
+
* compare-and-set a revisioned write needs, with no second reader able to
|
|
8750
|
+
* slip between the check and the writes.
|
|
8751
|
+
*
|
|
8752
|
+
* **All or nothing**, like {@link insertMany}: a throw in any op rolls the
|
|
8753
|
+
* whole call back. Ops run in the order given (delete before insert to
|
|
8754
|
+
* replace a set). `namespace` applies to every collection named.
|
|
8755
|
+
*/
|
|
8756
|
+
transact: require_sleep.method(zod.z.object({
|
|
8757
|
+
namespace: zod.z.string().optional(),
|
|
8758
|
+
guard: TransactGuardSchema.optional(),
|
|
8759
|
+
ops: zod.z.array(TransactOpSchema).readonly()
|
|
8760
|
+
}), zod.z.object({
|
|
8761
|
+
applied: zod.z.boolean(),
|
|
8762
|
+
current: zod.z.unknown().optional()
|
|
8763
|
+
}), {
|
|
8764
|
+
kind: "mutation",
|
|
8765
|
+
auth: "admin"
|
|
8766
|
+
}),
|
|
8767
|
+
/** Update an existing record by ID. */
|
|
8768
|
+
update: require_sleep.method(zod.z.object({
|
|
8769
|
+
namespace: zod.z.string().optional(),
|
|
8770
|
+
collection: zod.z.string(),
|
|
8771
|
+
id: zod.z.string(),
|
|
8772
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
8773
|
+
}), zod.z.void(), {
|
|
8774
|
+
kind: "mutation",
|
|
8775
|
+
auth: "admin"
|
|
8776
|
+
}),
|
|
8777
|
+
/** Delete a record by key/ID. */
|
|
8778
|
+
delete: require_sleep.method(zod.z.object({
|
|
8779
|
+
namespace: zod.z.string().optional(),
|
|
8780
|
+
collection: zod.z.string(),
|
|
8781
|
+
key: zod.z.string()
|
|
8782
|
+
}), zod.z.void(), {
|
|
8783
|
+
kind: "mutation",
|
|
8784
|
+
auth: "admin"
|
|
8785
|
+
}),
|
|
8786
|
+
/**
|
|
8787
|
+
* Delete every record matching `filter`, in ONE statement, returning how
|
|
8788
|
+
* many rows went. This exists because its absence made every retention
|
|
8789
|
+
* path in the system an N+1 drain loop: `delete` takes a key, so a sweep
|
|
8790
|
+
* had to SELECT a page of full rows — every column, including the fat
|
|
8791
|
+
* ones — purely to learn their ids, then issue one call per row.
|
|
8792
|
+
*
|
|
8793
|
+
* **The filter is required and must resolve.** A predicate naming
|
|
8794
|
+
* something the collection cannot express is an ERROR here, not a
|
|
8795
|
+
* widening as it is on `query`, and a filter with no predicates is an
|
|
8796
|
+
* error rather than "every row". Deleting a whole collection is a
|
|
8797
|
+
* legitimate intent, but it must be asked for by name — not reached by
|
|
8798
|
+
* an empty object.
|
|
8799
|
+
*/
|
|
8800
|
+
deleteWhere: require_sleep.method(zod.z.object({
|
|
8801
|
+
namespace: zod.z.string().optional(),
|
|
8802
|
+
collection: zod.z.string(),
|
|
8803
|
+
filter: MutationFilterSchema
|
|
8804
|
+
}), zod.z.object({ deleted: zod.z.number().int() }), {
|
|
8805
|
+
kind: "mutation",
|
|
8806
|
+
auth: "admin"
|
|
8807
|
+
}),
|
|
8808
|
+
/**
|
|
8809
|
+
* Apply `data` to every record matching `filter`, in one statement,
|
|
8810
|
+
* returning how many rows changed. Same filter contract as
|
|
8811
|
+
* {@link deleteWhere} — an unresolvable predicate is an error.
|
|
8812
|
+
*/
|
|
8813
|
+
updateWhere: require_sleep.method(zod.z.object({
|
|
8814
|
+
namespace: zod.z.string().optional(),
|
|
8815
|
+
collection: zod.z.string(),
|
|
8816
|
+
filter: MutationFilterSchema,
|
|
8817
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
8818
|
+
}), zod.z.object({ updated: zod.z.number().int() }), {
|
|
8819
|
+
kind: "mutation",
|
|
8820
|
+
auth: "admin"
|
|
8821
|
+
}),
|
|
8822
|
+
/** Count entries in a collection, optionally filtered. */
|
|
8823
|
+
count: require_sleep.method(zod.z.object({
|
|
8824
|
+
namespace: zod.z.string().optional(),
|
|
8825
|
+
collection: zod.z.string(),
|
|
8826
|
+
filter: QueryFilterSchema.optional()
|
|
8827
|
+
}), zod.z.number(), { auth: "admin" }),
|
|
8828
|
+
/**
|
|
8829
|
+
* `COUNT(*)` and one `SUM` / `MIN` / `MAX` per requested field, in ONE
|
|
8830
|
+
* statement, over the rows `filter` selects.
|
|
8831
|
+
*
|
|
8832
|
+
* Exists because "how much is there" was being answered by materialising
|
|
8833
|
+
* "what is there". The recorder's storage-pressure sweep asked its in-RAM
|
|
8834
|
+
* footage index for bytes/count/oldest/newest across a set of storage
|
|
8835
|
+
* locations twice a minute, and the only way to answer that from a map is
|
|
8836
|
+
* to visit every row — 7.1 M of them on the live hub, ~15 M row visits a
|
|
8837
|
+
* minute on the main thread, which is also why the whole archive had to
|
|
8838
|
+
* stay resident to be visited. The question is a sum; nothing needs to be
|
|
8839
|
+
* materialised to answer it.
|
|
8840
|
+
*
|
|
8841
|
+
* **The engine REFUSES a field it cannot serve**, exactly as
|
|
8842
|
+
* `query.columns` does and unlike a PREDICATE, which is skipped when
|
|
8843
|
+
* unresolvable. A dropped predicate over-matches and the caller sees extra
|
|
8844
|
+
* rows; a dropped aggregate returns a NUMBER that is wrong and looks
|
|
8845
|
+
* exactly like a real one. That asymmetry is what this repo has already
|
|
8846
|
+
* paid for once in `count`.
|
|
8847
|
+
*/
|
|
8848
|
+
aggregate: require_sleep.method(zod.z.object({
|
|
8849
|
+
namespace: zod.z.string().optional(),
|
|
8850
|
+
collection: zod.z.string(),
|
|
8851
|
+
fields: zod.z.array(AggregateFieldSchema).readonly(),
|
|
8852
|
+
filter: QueryFilterSchema.optional()
|
|
8853
|
+
}), AggregateResultSchema, { auth: "admin" }),
|
|
8854
|
+
/** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
|
|
8855
|
+
histogram: require_sleep.method(zod.z.object({
|
|
8856
|
+
namespace: zod.z.string().optional(),
|
|
8857
|
+
collection: zod.z.string(),
|
|
8858
|
+
field: zod.z.string(),
|
|
8859
|
+
bucketSize: zod.z.number().int().positive(),
|
|
8860
|
+
origin: zod.z.number().int(),
|
|
8861
|
+
filter: QueryFilterSchema.optional()
|
|
8862
|
+
}), zod.z.array(zod.z.object({
|
|
8863
|
+
bucket: zod.z.number().int(),
|
|
8864
|
+
count: zod.z.number().int()
|
|
8865
|
+
})).readonly(), { auth: "admin" }),
|
|
8866
|
+
/** Check if a collection is empty. */
|
|
8867
|
+
isEmpty: require_sleep.method(zod.z.object({
|
|
8868
|
+
namespace: zod.z.string().optional(),
|
|
8869
|
+
collection: zod.z.string()
|
|
8870
|
+
}), zod.z.boolean(), { auth: "admin" }),
|
|
8871
|
+
/**
|
|
8872
|
+
* Declare a typed (SQL-backed) collection with explicit columns +
|
|
8873
|
+
* indexes. Idempotent: re-declaring an existing collection with the
|
|
8874
|
+
* same shape is a no-op; shape changes (new columns, new indexes)
|
|
8875
|
+
* are applied additively. Subsequent `insert` / `update` / `delete`
|
|
8876
|
+
* / `query` calls on this collection use typed columns instead of
|
|
8877
|
+
* JSON-blob storage — `record.data` fields are spread across
|
|
8878
|
+
* columns, `query.filter.where` matches real columns (no
|
|
8879
|
+
* `json_extract` overhead), `orderBy` uses column indexes.
|
|
8880
|
+
*
|
|
8881
|
+
* Addons call this in `onInitialize` before their first read/write.
|
|
8882
|
+
* Collection names should be namespaced by addon (e.g.
|
|
8883
|
+
* `pipeline-analytics:object-events`) to avoid cross-addon
|
|
8884
|
+
* clashes — no automatic prefix is added.
|
|
8885
|
+
*/
|
|
8886
|
+
declareCollection: require_sleep.method(DeclareCollectionInputSchema, zod.z.void(), {
|
|
8887
|
+
kind: "mutation",
|
|
8888
|
+
auth: "admin"
|
|
8889
|
+
})
|
|
8890
|
+
}
|
|
8891
|
+
};
|
|
8892
|
+
//#endregion
|
|
8329
8893
|
//#region src/capabilities/database-snapshot.cap.ts
|
|
8330
8894
|
/**
|
|
8331
8895
|
* The suffix of a verified snapshot, written next to the live database it
|
|
@@ -8354,7 +8918,11 @@ var DATABASE_SNAPSHOT_TIMEOUT_MS = 30 * 6e4;
|
|
|
8354
8918
|
* database has no sidecars and is just as owned). Paths are absolute on the
|
|
8355
8919
|
* owner's host.
|
|
8356
8920
|
*/
|
|
8357
|
-
var DatabaseSnapshotTargetsSchema = zod.z.object({ databases: zod.z.array(zod.z.object({
|
|
8921
|
+
var DatabaseSnapshotTargetsSchema = zod.z.object({ databases: zod.z.array(zod.z.object({
|
|
8922
|
+
/** Which owned file this is — the handle `writeSnapshot` takes. */
|
|
8923
|
+
databaseId: DataStoreDatabaseSchema,
|
|
8924
|
+
livePath: zod.z.string()
|
|
8925
|
+
})) });
|
|
8358
8926
|
/** One b-tree table of the snapshot and the rows it holds. */
|
|
8359
8927
|
var DatabaseSnapshotTableSchema = zod.z.object({
|
|
8360
8928
|
name: zod.z.string(),
|
|
@@ -8387,6 +8955,10 @@ var DatabaseSnapshotResultSchema = zod.z.object({
|
|
|
8387
8955
|
/** When the pinned read transaction began (ms epoch) — the snapshot's instant. */
|
|
8388
8956
|
takenAt: zod.z.number()
|
|
8389
8957
|
});
|
|
8958
|
+
/** A snapshot the owner wrote, with the file it belongs to. */
|
|
8959
|
+
var DatabaseSnapshotWrittenSchema = DatabaseSnapshotResultSchema.extend({ databaseId: DataStoreDatabaseSchema });
|
|
8960
|
+
/** Which database `writeSnapshot` copies. Required: an unstated ask is not guessed. */
|
|
8961
|
+
var DatabaseSnapshotRequestSchema = zod.z.object({ databaseId: DataStoreDatabaseSchema });
|
|
8390
8962
|
/**
|
|
8391
8963
|
* A snapshot as an ARCHIVE records it (`ArchiveManifest.sqliteSnapshots`):
|
|
8392
8964
|
* the same facts, with both paths relative to the archive root (the node's
|
|
@@ -8396,7 +8968,9 @@ var ArchiveSqliteSnapshotSchema = DatabaseSnapshotResultSchema.extend({
|
|
|
8396
8968
|
/** Archive-relative path of the live database the archive does NOT carry. */
|
|
8397
8969
|
livePath: zod.z.string(),
|
|
8398
8970
|
/** Archive-relative path of the verified copy it carries in its place. */
|
|
8399
|
-
snapshotPath: zod.z.string()
|
|
8971
|
+
snapshotPath: zod.z.string(),
|
|
8972
|
+
/** Absent on an archive made before several files were owned: that was `settings`. */
|
|
8973
|
+
databaseId: DataStoreDatabaseSchema.optional()
|
|
8400
8974
|
});
|
|
8401
8975
|
/**
|
|
8402
8976
|
* database-snapshot — the OWNER of a live SQLite database writes a consistent,
|
|
@@ -8421,17 +8995,21 @@ var databaseSnapshotCapability = {
|
|
|
8421
8995
|
internal: true,
|
|
8422
8996
|
methods: {
|
|
8423
8997
|
/**
|
|
8424
|
-
*
|
|
8425
|
-
* touched — so a backup can ask it before deciding
|
|
8998
|
+
* EVERY database file this owner has open, with its id. Answered from
|
|
8999
|
+
* memory — no file is touched — so a backup can ask it before deciding
|
|
9000
|
+
* anything. A file created at runtime is listed from the moment it opens,
|
|
9001
|
+
* so no backup can leave it out (D693).
|
|
8426
9002
|
*/
|
|
8427
9003
|
listDatabases: require_sleep.method(zod.z.object({}), DatabaseSnapshotTargetsSchema, { auth: "admin" }),
|
|
8428
9004
|
/**
|
|
8429
|
-
* Write `<db>.backup-snapshot` and return what it holds.
|
|
8430
|
-
* leaves no file under the final name — when the copy fails
|
|
8431
|
-
* `integrity_check` or its row counts differ from the pinned source's
|
|
8432
|
-
* A second call
|
|
9005
|
+
* Write `<db>.backup-snapshot` for ONE database and return what it holds.
|
|
9006
|
+
* Throws — and leaves no file under the final name — when the copy fails
|
|
9007
|
+
* `integrity_check` or its row counts differ from the pinned source's, or
|
|
9008
|
+
* when the database is not open. A second call for the SAME database while
|
|
9009
|
+
* one is running joins it; different databases run one after the other
|
|
9010
|
+
* (the disk reserve check is per copy).
|
|
8433
9011
|
*/
|
|
8434
|
-
writeSnapshot: require_sleep.method(
|
|
9012
|
+
writeSnapshot: require_sleep.method(DatabaseSnapshotRequestSchema, DatabaseSnapshotWrittenSchema, {
|
|
8435
9013
|
kind: "mutation",
|
|
8436
9014
|
auth: "admin",
|
|
8437
9015
|
timeoutMs: DATABASE_SNAPSHOT_TIMEOUT_MS
|
|
@@ -8554,7 +9132,12 @@ var BackupArchiveEntrySchema = zod.z.object({
|
|
|
8554
9132
|
/** Top-level locations included in the archive (db, addons, tls, …). */
|
|
8555
9133
|
locations: zod.z.array(zod.z.string()).readonly(),
|
|
8556
9134
|
/** Present when the archive is encrypted; restore then needs that key. */
|
|
8557
|
-
encryption: BackupArchiveEncryptionSchema.optional()
|
|
9135
|
+
encryption: BackupArchiveEncryptionSchema.optional(),
|
|
9136
|
+
/**
|
|
9137
|
+
* The databases the run asked to carry (its retention class). Absent on an
|
|
9138
|
+
* archive made before several files were owned: that was `['settings']`.
|
|
9139
|
+
*/
|
|
9140
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly().optional()
|
|
8558
9141
|
});
|
|
8559
9142
|
var BackupEntrySchema = zod.z.object({
|
|
8560
9143
|
id: zod.z.string(),
|
|
@@ -8588,7 +9171,12 @@ var ArchiveManifestSchema = zod.z.object({
|
|
|
8588
9171
|
* Live SQLite databases this archive carries as their OWNER's verified
|
|
8589
9172
|
* snapshot instead of as files (D693). Absent on archives made before.
|
|
8590
9173
|
*/
|
|
8591
|
-
sqliteSnapshots: zod.z.array(ArchiveSqliteSnapshotSchema).optional()
|
|
9174
|
+
sqliteSnapshots: zod.z.array(ArchiveSqliteSnapshotSchema).optional(),
|
|
9175
|
+
/**
|
|
9176
|
+
* Owned database files the run did NOT carry (not selected): left out of the
|
|
9177
|
+
* tar and the entry list alike. Absent when every owned file was carried.
|
|
9178
|
+
*/
|
|
9179
|
+
omittedDatabases: zod.z.array(DataStoreDatabaseSchema).optional()
|
|
8592
9180
|
});
|
|
8593
9181
|
var LocationStatSchema = zod.z.object({
|
|
8594
9182
|
name: zod.z.string(),
|
|
@@ -8710,6 +9298,12 @@ var BackupScheduleSchema = zod.z.object({
|
|
|
8710
9298
|
/** Optional subset of source locations to include; omitted = all. */
|
|
8711
9299
|
dataSources: zod.z.array(zod.z.string()).readonly().optional(),
|
|
8712
9300
|
/**
|
|
9301
|
+
* Which database files this schedule carries. Absent = `['settings']`
|
|
9302
|
+
* (an unstated ask is the minimum, D382). Events and history run weekly,
|
|
9303
|
+
* settings nightly (D852).
|
|
9304
|
+
*/
|
|
9305
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly().optional(),
|
|
9306
|
+
/**
|
|
8713
9307
|
* ms-epoch of the last tick that FIRED this schedule. Stamped before the
|
|
8714
9308
|
* archive runs (it is the dedupe anchor), so it says "attempted", never
|
|
8715
9309
|
* "succeeded" — a run refused by every destination stamps it too.
|
|
@@ -8761,7 +9355,9 @@ var backupCapability = {
|
|
|
8761
9355
|
* retention). Omitted = each destination's own policy
|
|
8762
9356
|
* retention (manual runs).
|
|
8763
9357
|
*/
|
|
8764
|
-
retentionCount: zod.z.number().int().min(1).max(1e3).optional()
|
|
9358
|
+
retentionCount: zod.z.number().int().min(1).max(1e3).optional(),
|
|
9359
|
+
/** Database files to carry; omitted = `['settings']`. */
|
|
9360
|
+
databases: zod.z.array(DataStoreDatabaseSchema).optional()
|
|
8765
9361
|
}).optional(), BackupTriggerResultSchema, {
|
|
8766
9362
|
kind: "mutation",
|
|
8767
9363
|
auth: "admin"
|
|
@@ -8919,6 +9515,16 @@ var backupCapability = {
|
|
|
8919
9515
|
*/
|
|
8920
9516
|
listSchedules: require_sleep.method(zod.z.void(), zod.z.array(BackupScheduleSchema).readonly(), { auth: "admin" }),
|
|
8921
9517
|
/**
|
|
9518
|
+
* The database files that exist on this hub right now (the owner's open
|
|
9519
|
+
* files), so the selection UI can offer all of them and mark a file that
|
|
9520
|
+
* is not created yet. `answered: false` = the owner did not answer, which
|
|
9521
|
+
* is not the same as "none exist".
|
|
9522
|
+
*/
|
|
9523
|
+
listAvailableDatabases: require_sleep.method(zod.z.void(), zod.z.object({
|
|
9524
|
+
answered: zod.z.boolean(),
|
|
9525
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly()
|
|
9526
|
+
}), { auth: "admin" }),
|
|
9527
|
+
/**
|
|
8922
9528
|
* Create or replace a schedule. An empty / absent `id` mints a new
|
|
8923
9529
|
* one; a present `id` replaces in place. `cron` is validated
|
|
8924
9530
|
* server-side; `locationIds` must reference existing `backups`
|
|
@@ -8931,7 +9537,8 @@ var backupCapability = {
|
|
|
8931
9537
|
enabled: zod.z.boolean(),
|
|
8932
9538
|
locationIds: zod.z.array(zod.z.string()).readonly(),
|
|
8933
9539
|
retentionCount: zod.z.number().int().min(1).max(1e3),
|
|
8934
|
-
dataSources: zod.z.array(zod.z.string()).readonly().optional()
|
|
9540
|
+
dataSources: zod.z.array(zod.z.string()).readonly().optional(),
|
|
9541
|
+
databases: zod.z.array(DataStoreDatabaseSchema).readonly().optional()
|
|
8935
9542
|
}), BackupScheduleSchema, {
|
|
8936
9543
|
kind: "mutation",
|
|
8937
9544
|
auth: "admin"
|
|
@@ -12320,828 +12927,264 @@ var CoreBlockCompileInputSchema = zod.z.object({
|
|
|
12320
12927
|
return;
|
|
12321
12928
|
}
|
|
12322
12929
|
if (val.code === void 0) ctx.addIssue({
|
|
12323
|
-
code: "custom",
|
|
12324
|
-
message: "code or files is required",
|
|
12325
|
-
path: ["code"]
|
|
12326
|
-
});
|
|
12327
|
-
});
|
|
12328
|
-
var coreBlocksCapability = {
|
|
12329
|
-
name: "core-blocks",
|
|
12330
|
-
scope: "system",
|
|
12331
|
-
mode: "singleton",
|
|
12332
|
-
methods: {
|
|
12333
|
-
list: require_sleep.method(zod.z.object({}), zod.z.object({ blocks: zod.z.array(CoreBlockSchema) }), { auth: "admin" }),
|
|
12334
|
-
get: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema.nullable() }), { auth: "admin" }),
|
|
12335
|
-
/**
|
|
12336
|
-
* Create a block. The code is COMPILED first: storing source that does not
|
|
12337
|
-
* compile turns an editor error into a fork failure the operator meets
|
|
12338
|
-
* minutes later in a log.
|
|
12339
|
-
*/
|
|
12340
|
-
create: require_sleep.method(zod.z.object({ block: CoreBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
12341
|
-
kind: "mutation",
|
|
12342
|
-
auth: "admin",
|
|
12343
|
-
caller: "required"
|
|
12344
|
-
}),
|
|
12345
|
-
update: require_sleep.method(zod.z.object({
|
|
12346
|
-
blockId: zod.z.string(),
|
|
12347
|
-
block: CoreBlockInputFieldsSchema.partial()
|
|
12348
|
-
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
12349
|
-
kind: "mutation",
|
|
12350
|
-
auth: "admin",
|
|
12351
|
-
caller: "required"
|
|
12352
|
-
}),
|
|
12353
|
-
delete: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
12354
|
-
kind: "mutation",
|
|
12355
|
-
auth: "admin"
|
|
12356
|
-
}),
|
|
12357
|
-
setEnabled: require_sleep.method(zod.z.object({
|
|
12358
|
-
blockId: zod.z.string(),
|
|
12359
|
-
enabled: zod.z.boolean()
|
|
12360
|
-
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
12361
|
-
kind: "mutation",
|
|
12362
|
-
auth: "admin"
|
|
12363
|
-
}),
|
|
12364
|
-
/**
|
|
12365
|
-
* Stop this block's runner and let the supervisor bring it back.
|
|
12366
|
-
*
|
|
12367
|
-
* **It stores nothing.** There is no "restart requested" flag and no second
|
|
12368
|
-
* lifecycle field: the supervisor already stops and respawns a runner when
|
|
12369
|
-
* the code hash changes, and this exposes that same path deliberately
|
|
12370
|
-
* (D62 — a switch writes the authority that already owned the function).
|
|
12371
|
-
* The next reconcile pass remains the authority, so a restart that lost a
|
|
12372
|
-
* race is corrected within one pass rather than leaving a stale flag behind.
|
|
12373
|
-
*
|
|
12374
|
-
* Refused for a DISABLED block: nothing would come back, and a button that
|
|
12375
|
-
* silently does nothing is worse than one that says why.
|
|
12376
|
-
*/
|
|
12377
|
-
restart: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema }), {
|
|
12378
|
-
kind: "mutation",
|
|
12379
|
-
auth: "admin"
|
|
12380
|
-
}),
|
|
12381
|
-
/**
|
|
12382
|
-
* Type-check without saving — what the editor calls as the author types, so
|
|
12383
|
-
* the compiler's verdict is the same one the server will reach.
|
|
12384
|
-
* Accepts `{ code }` or `{ files, entry }` (multi-file project).
|
|
12385
|
-
*/
|
|
12386
|
-
compile: require_sleep.method(CoreBlockCompileInputSchema, CoreBlockCompileResultSchema, {
|
|
12387
|
-
kind: "mutation",
|
|
12388
|
-
auth: "admin"
|
|
12389
|
-
}),
|
|
12390
|
-
/**
|
|
12391
|
-
* Hydrated settings form for one block, or null until a `settingsSchema`
|
|
12392
|
-
* is known (extracted from the compiled entry's named export, or set on
|
|
12393
|
-
* the block). Values live in the `core-blocks:settings` collection.
|
|
12394
|
-
*/
|
|
12395
|
-
getBlockSettings: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), SettingsSchemaWithValuesSchema.nullable(), { auth: "admin" }),
|
|
12396
|
-
/**
|
|
12397
|
-
* Patch persisted preference values for one block. The schema is not
|
|
12398
|
-
* rewritten here — only values. Scripts read the same blob via
|
|
12399
|
-
* `ctx.settings.readAddonStore()` (mirrored into the block addon's
|
|
12400
|
-
* `addon-settings` namespace on every patch).
|
|
12401
|
-
*/
|
|
12402
|
-
updateBlockSettings: require_sleep.method(zod.z.object({
|
|
12403
|
-
blockId: zod.z.string(),
|
|
12404
|
-
patch: SettingsPatchSchema
|
|
12405
|
-
}), SettingsUpdateResultSchema, {
|
|
12406
|
-
kind: "mutation",
|
|
12407
|
-
auth: "admin"
|
|
12408
|
-
}),
|
|
12409
|
-
/**
|
|
12410
|
-
* The declaration files the editor type-checks against.
|
|
12411
|
-
*
|
|
12412
|
-
* Served rather than bundled: the graph is 3.4 MB across 344 files, and
|
|
12413
|
-
* bundling it would roughly double the admin remote. Served rather than
|
|
12414
|
-
* hand-stubbed: a block runs with the same `ctx` an addon gets, so a stub
|
|
12415
|
-
* would drift and the editor would confidently autocomplete methods that
|
|
12416
|
-
* do not exist.
|
|
12417
|
-
*/
|
|
12418
|
-
getTypeDefs: require_sleep.method(zod.z.object({}), zod.z.object({ libs: zod.z.array(zod.z.object({
|
|
12419
|
-
filePath: zod.z.string(),
|
|
12420
|
-
content: zod.z.string()
|
|
12421
|
-
})) }), { auth: "admin" }),
|
|
12422
|
-
/**
|
|
12423
|
-
* Create a composition block (D659). VALIDATED first against the live
|
|
12424
|
-
* sources and every stored composition; a refusal names every problem by
|
|
12425
|
-
* path and reason (D391) and stores nothing.
|
|
12426
|
-
*/
|
|
12427
|
-
createComposition: require_sleep.method(zod.z.object({ block: CompositionBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
12428
|
-
kind: "mutation",
|
|
12429
|
-
auth: "admin",
|
|
12430
|
-
caller: "required"
|
|
12431
|
-
}),
|
|
12432
|
-
/**
|
|
12433
|
-
* Patch a composition block. A changed `composition` is validated exactly
|
|
12434
|
-
* as on create. `expectedUpdatedAt` is the `updatedAt` the caller READ: a
|
|
12435
|
-
* block changed since is refused by name, never silently overwritten.
|
|
12436
|
-
*/
|
|
12437
|
-
updateComposition: require_sleep.method(zod.z.object({
|
|
12438
|
-
blockId: zod.z.string(),
|
|
12439
|
-
expectedUpdatedAt: zod.z.number(),
|
|
12440
|
-
block: CompositionBlockInputSchema.partial()
|
|
12441
|
-
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
12442
|
-
kind: "mutation",
|
|
12443
|
-
auth: "admin",
|
|
12444
|
-
caller: "required"
|
|
12445
|
-
}),
|
|
12446
|
-
/** One composition and the composer's state for it, or `not-loaded` (D315). */
|
|
12447
|
-
getComposition: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), CompositionGetReadSchema, { auth: "admin" }),
|
|
12448
|
-
listCompositions: require_sleep.method(zod.z.object({}), CompositionListReadSchema, { auth: "admin" }),
|
|
12449
|
-
/**
|
|
12450
|
-
* The composition that customizes an existing device (D663), found by its
|
|
12451
|
-
* TARGET — never by the block's derived name. One per device at most.
|
|
12452
|
-
*/
|
|
12453
|
-
getCustomization: require_sleep.method(zod.z.object({
|
|
12454
|
-
addonId: zod.z.string().min(1),
|
|
12455
|
-
stableId: zod.z.string().min(1)
|
|
12456
|
-
}), CompositionCustomizationReadSchema, { auth: "admin" }),
|
|
12457
|
-
/**
|
|
12458
|
-
* The capabilities a composition may BUILD on a device of `deviceType`
|
|
12459
|
-
* (a new device, or added to an existing one), with their fields — the
|
|
12460
|
-
* editor's feature list and the presets' availability (G2, D676). Built
|
|
12461
|
-
* from the validator's own blockers; a replace of a BOUND cap is not
|
|
12462
|
-
* listed here (the device's bindings say what it has).
|
|
12463
|
-
*/
|
|
12464
|
-
listComposableCaps: require_sleep.method(zod.z.object({ deviceType: zod.z.enum(require_err_msg.DeviceType) }), ComposableCapabilitiesSchema, { auth: "admin" }),
|
|
12465
|
-
/**
|
|
12466
|
-
* Validate without saving — the same verdict the save reaches. A mutation
|
|
12467
|
-
* for its body size; it writes nothing, so its access is `view`.
|
|
12468
|
-
*/
|
|
12469
|
-
validateComposition: require_sleep.method(zod.z.object({
|
|
12470
|
-
composition: require_composition.CompositionSchema,
|
|
12471
|
-
blockId: zod.z.string().optional()
|
|
12472
|
-
}), CompositionValidationSchema, {
|
|
12473
|
-
kind: "mutation",
|
|
12474
|
-
auth: "admin",
|
|
12475
|
-
access: "view"
|
|
12476
|
-
})
|
|
12477
|
-
}
|
|
12478
|
-
};
|
|
12479
|
-
//#endregion
|
|
12480
|
-
//#region src/capabilities/custom-model-registry.cap.ts
|
|
12481
|
-
/**
|
|
12482
|
-
* `custom-model-registry` — collection cap exposing operator-registered
|
|
12483
|
-
* custom detection models. Each provider (today: `addon-model-studio`)
|
|
12484
|
-
* contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
|
|
12485
|
-
* them across providers (`concatCollection`).
|
|
12486
|
-
*
|
|
12487
|
-
* The detection-pipeline is *aware* of this cap: when at least one provider
|
|
12488
|
-
* exists it unions these descriptors into the per-step model picker and the
|
|
12489
|
-
* runtime model-resolution path, alongside the static catalog. When no
|
|
12490
|
-
* provider exists the consumer no-ops entirely (identical to the catalog-only
|
|
12491
|
-
* behaviour).
|
|
12492
|
-
*
|
|
12493
|
-
* A descriptor carries a full `ModelCatalogEntry` directly — the same shape
|
|
12494
|
-
* the static catalog uses — so the existing download/resolution code consumes
|
|
12495
|
-
* it unchanged. `stepId` is the detection step the model targets
|
|
12496
|
-
* (e.g. `'object-detection'`).
|
|
12497
|
-
*/
|
|
12498
|
-
var CustomModelDescriptorSchema = zod.z.object({
|
|
12499
|
-
stepId: zod.z.string(),
|
|
12500
|
-
entry: ModelCatalogEntrySchema
|
|
12501
|
-
});
|
|
12502
|
-
/** One regular file of an imported bundle, as the producer measured it. */
|
|
12503
|
-
var ModelBundleFileSchema = zod.z.object({
|
|
12504
|
-
/** Relative path inside the bundle tar; an mlpackage member is `<x>.mlpackage/<member>`. */
|
|
12505
|
-
path: zod.z.string().min(1),
|
|
12506
|
-
bytes: zod.z.number().int().nonnegative(),
|
|
12507
|
-
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
12508
|
-
});
|
|
12509
|
-
var ImportModelBundleInputSchema = zod.z.object({
|
|
12510
|
-
/** The registry provider that keeps the model (Model Studio). */
|
|
12511
|
-
addonId: zod.z.string(),
|
|
12512
|
-
stepId: zod.z.string().min(1),
|
|
12513
|
-
/**
|
|
12514
|
-
* The catalog rows to register, complete, every format URL already
|
|
12515
|
-
* `camstack-local://<modelId>/<file>` naming a file of the bundle. One
|
|
12516
|
-
* bundle may carry several rows (a base and its INT8 variant).
|
|
12517
|
-
*/
|
|
12518
|
-
entries: zod.z.array(ModelCatalogEntrySchema).min(1).max(4),
|
|
12519
|
-
/** The bundle tar, offered by the producer over `ctx.peerBytes` (same host). */
|
|
12520
|
-
bundle: zod.z.object({
|
|
12521
|
-
ticket: require_sleep.PeerBytesTicketSchema,
|
|
12522
|
-
bytes: zod.z.number().int().positive(),
|
|
12523
|
-
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
12524
|
-
}),
|
|
12525
|
-
/** Every file the tar must hold; anything missing, extra or different is refused. */
|
|
12526
|
-
files: zod.z.array(ModelBundleFileSchema).min(1).max(64),
|
|
12527
|
-
/** Convert missing engine formats and push the model to every agent afterwards. */
|
|
12528
|
-
distribute: zod.z.boolean()
|
|
12529
|
-
});
|
|
12530
|
-
var ImportModelBundleResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
12531
|
-
kind: zod.z.literal("imported"),
|
|
12532
|
-
modelIds: zod.z.array(zod.z.string()).readonly(),
|
|
12533
|
-
distributed: zod.z.array(zod.z.object({
|
|
12534
|
-
modelId: zod.z.string(),
|
|
12535
|
-
nodeId: zod.z.string(),
|
|
12536
|
-
format: zod.z.enum(require_sleep.MODEL_FORMATS),
|
|
12537
|
-
ok: zod.z.boolean(),
|
|
12538
|
-
error: zod.z.string().optional()
|
|
12539
|
-
})).readonly()
|
|
12540
|
-
}), zod.z.object({
|
|
12541
|
-
kind: zod.z.literal("refused"),
|
|
12542
|
-
reason: zod.z.enum([
|
|
12543
|
-
"transfer-failed",
|
|
12544
|
-
"checksum-mismatch",
|
|
12545
|
-
"bundle-mismatch",
|
|
12546
|
-
"invalid-entry",
|
|
12547
|
-
"id-taken"
|
|
12548
|
-
]),
|
|
12549
|
-
detail: zod.z.string()
|
|
12550
|
-
})]);
|
|
12551
|
-
var customModelRegistryCapability = {
|
|
12552
|
-
name: "custom-model-registry",
|
|
12553
|
-
scope: "system",
|
|
12554
|
-
mode: "collection",
|
|
12555
|
-
internal: true,
|
|
12556
|
-
methods: {
|
|
12557
|
-
/**
|
|
12558
|
-
* `internal: true` did not gate the mount (see the 2026-08-26 note on
|
|
12559
|
-
* `data-store-provider`) — this was reachable on the AppRouter by ANY
|
|
12560
|
-
* authenticated session at the default `auth: 'protected'`. The only
|
|
12561
|
-
* consumer, the detection-pipeline's model resolution
|
|
12562
|
-
* (`addon-pipeline/src/detection-pipeline/provider.ts`), calls
|
|
12563
|
-
* `ctx.api.customModelRegistry.listModels.query()` — UDS/Moleculer,
|
|
12564
|
-
* never tRPC — so `auth: 'admin'` costs it nothing.
|
|
12565
|
-
*/
|
|
12566
|
-
listModels: require_sleep.method(zod.z.void(), zod.z.array(CustomModelDescriptorSchema).readonly(), { auth: "admin" }),
|
|
12567
|
-
/**
|
|
12568
|
-
* Register a model whose files arrive as ONE bundle tar (D806): the tar
|
|
12569
|
-
* is taken over `ctx.peerBytes`, checked against `bundle.sha256` and
|
|
12570
|
-
* every row of `files`, unpacked into the hub's flat modelsDir (directory
|
|
12571
|
-
* formats included), each format's `.revision` record written, the rows
|
|
12572
|
-
* upserted under the operator's name, the hub marked available and —
|
|
12573
|
-
* when asked — engine formats converted and the model distributed. A
|
|
12574
|
-
* model id already registered by another source is refused, never
|
|
12575
|
-
* overwritten.
|
|
12576
|
-
*/
|
|
12577
|
-
importModelBundle: require_sleep.method(ImportModelBundleInputSchema, ImportModelBundleResultSchema, {
|
|
12578
|
-
kind: "mutation",
|
|
12579
|
-
auth: "admin",
|
|
12580
|
-
timeoutMs: 30 * 6e4
|
|
12581
|
-
})
|
|
12582
|
-
}
|
|
12583
|
-
};
|
|
12584
|
-
//#endregion
|
|
12585
|
-
//#region src/capabilities/settings-store.cap.ts
|
|
12586
|
-
/**
|
|
12587
|
-
* Query filter for settings-store collections.
|
|
12588
|
-
*/
|
|
12589
|
-
var QueryFilterSchema = zod.z.object({
|
|
12590
|
-
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
12591
|
-
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
12592
|
-
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
12593
|
-
/** NULL-safe exclusion: matches rows whose field is NULL OR != the value. */
|
|
12594
|
-
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
12595
|
-
/** NULL-safe exclusion of a SET — `whereNot` for more than one value. An
|
|
12596
|
-
* empty list excludes nothing. See `QueryFilter.whereNotIn`. */
|
|
12597
|
-
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
12598
|
-
orderBy: zod.z.object({
|
|
12599
|
-
field: zod.z.string(),
|
|
12600
|
-
direction: zod.z.enum(["asc", "desc"])
|
|
12601
|
-
}).optional(),
|
|
12602
|
-
limit: zod.z.number().optional(),
|
|
12603
|
-
offset: zod.z.number().optional()
|
|
12604
|
-
});
|
|
12605
|
-
/**
|
|
12606
|
-
* The predicate half of a filter, for BULK MUTATIONS.
|
|
12607
|
-
*
|
|
12608
|
-
* Deliberately not `QueryFilterSchema`: `orderBy` / `limit` / `offset` have no
|
|
12609
|
-
* meaning for a statement that rewrites a set, and accepting them would invite
|
|
12610
|
-
* a caller to believe `limit` bounds the damage. Every field is optional here
|
|
12611
|
-
* only so the shape stays composable — the implementation REJECTS a filter
|
|
12612
|
-
* that compiles to no predicate, because that is the whole collection.
|
|
12613
|
-
*/
|
|
12614
|
-
var MutationFilterSchema = zod.z.object({
|
|
12615
|
-
where: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
12616
|
-
whereIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional(),
|
|
12617
|
-
whereBetween: zod.z.record(zod.z.string(), zod.z.tuple([zod.z.unknown(), zod.z.unknown()])).optional(),
|
|
12618
|
-
whereNot: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
12619
|
-
whereNotIn: zod.z.record(zod.z.string(), zod.z.array(zod.z.unknown())).optional()
|
|
12620
|
-
});
|
|
12621
|
-
/**
|
|
12622
|
-
* One scalar an {@link settingsStoreCapability.methods.aggregate} call asks for.
|
|
12623
|
-
*
|
|
12624
|
-
* `as` names the slot in the result, so the SAME column may be asked twice with
|
|
12625
|
-
* two operations (`MIN(startMs)` and `MAX(startMs)` in one round trip) — which
|
|
12626
|
-
* a `Record<column, op>` shape could not express.
|
|
12627
|
-
*/
|
|
12628
|
-
var AggregateFieldSchema = zod.z.object({
|
|
12629
|
-
/** Result key. */
|
|
12630
|
-
as: zod.z.string().min(1),
|
|
12631
|
-
/** Column to aggregate. Must be a real column of a declared collection. */
|
|
12632
|
-
field: zod.z.string().min(1),
|
|
12633
|
-
op: zod.z.enum([
|
|
12634
|
-
"sum",
|
|
12635
|
-
"min",
|
|
12636
|
-
"max"
|
|
12637
|
-
])
|
|
12638
|
-
});
|
|
12639
|
-
/**
|
|
12640
|
-
* `COUNT(*)` plus one number per requested field.
|
|
12641
|
-
*
|
|
12642
|
-
* `null` means NO ROW MATCHED, never zero: a `SUM` over an empty set and a sum
|
|
12643
|
-
* that really is 0 are different facts, and an accounting caller that renders
|
|
12644
|
-
* "0 bytes, oldest = 0" for "nothing here" reports a lie about a disk.
|
|
12645
|
-
*/
|
|
12646
|
-
var AggregateResultSchema = zod.z.object({
|
|
12647
|
-
count: zod.z.number().int(),
|
|
12648
|
-
values: zod.z.record(zod.z.string(), zod.z.number().nullable())
|
|
12649
|
-
});
|
|
12650
|
-
/** A single stored record: `{ id, data }`. */
|
|
12651
|
-
var SettingsRecordSchema = zod.z.object({
|
|
12652
|
-
id: zod.z.string(),
|
|
12653
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
12654
|
-
});
|
|
12655
|
-
/**
|
|
12656
|
-
* One record of a BULK insert — {@link SettingsRecordSchema} with the id made
|
|
12657
|
-
* optional.
|
|
12658
|
-
*
|
|
12659
|
-
* A separate schema rather than loosening the shared one: every other method
|
|
12660
|
-
* on this cap addresses a row BY its id, and making that field optional
|
|
12661
|
-
* everywhere would turn a forgotten key into a silently generated one on
|
|
12662
|
-
* `update` and `delete` as well.
|
|
12663
|
-
*/
|
|
12664
|
-
var BulkRecordSchema = zod.z.object({
|
|
12665
|
-
id: zod.z.string().optional(),
|
|
12666
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
12667
|
-
});
|
|
12668
|
-
/**
|
|
12669
|
-
* The database FILES one `sqlite-settings` engine process owns (D851).
|
|
12670
|
-
* Closed on purpose: a file is a thing the engine opens, backs up and gives a
|
|
12671
|
-
* serving thread, so a new one is a code change, never a string a caller
|
|
12672
|
-
* invents. `settings` is `camstack.db` and the default for every collection
|
|
12673
|
-
* that names no file.
|
|
12674
|
-
*/
|
|
12675
|
-
var DataStoreDatabaseSchema = zod.z.enum([
|
|
12676
|
-
"settings",
|
|
12677
|
-
"events",
|
|
12678
|
-
"history"
|
|
12679
|
-
]);
|
|
12680
|
-
/** Every database file, in a stable order (settings first). */
|
|
12681
|
-
var DATA_STORE_DATABASES = DataStoreDatabaseSchema.options;
|
|
12682
|
-
/**
|
|
12683
|
-
* One write inside a {@link settingsStoreCapability.methods.transact} call.
|
|
12684
|
-
* The three that a "replace this set, bump that revision" write needs, plus
|
|
12685
|
-
* the batched upsert a rollup writer needs.
|
|
12686
|
-
*/
|
|
12687
|
-
var TransactOpSchema = zod.z.discriminatedUnion("op", [
|
|
12688
|
-
zod.z.object({
|
|
12689
|
-
op: zod.z.literal("deleteWhere"),
|
|
12690
|
-
collection: zod.z.string(),
|
|
12691
|
-
filter: MutationFilterSchema
|
|
12692
|
-
}),
|
|
12693
|
-
zod.z.object({
|
|
12694
|
-
op: zod.z.literal("insertMany"),
|
|
12695
|
-
collection: zod.z.string(),
|
|
12696
|
-
records: zod.z.array(BulkRecordSchema).readonly()
|
|
12697
|
-
}),
|
|
12698
|
-
zod.z.object({
|
|
12699
|
-
op: zod.z.literal("update"),
|
|
12700
|
-
collection: zod.z.string(),
|
|
12701
|
-
id: zod.z.string(),
|
|
12702
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
12703
|
-
}),
|
|
12704
|
-
zod.z.object({
|
|
12705
|
-
op: zod.z.literal("upsertMany"),
|
|
12706
|
-
collection: zod.z.string(),
|
|
12707
|
-
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
12708
|
-
records: zod.z.array(BulkRecordSchema).readonly()
|
|
12709
|
-
})
|
|
12710
|
-
]);
|
|
12711
|
-
/**
|
|
12712
|
-
* The precondition of a transaction: the row `key` of `collection` must hold
|
|
12713
|
-
* `equals` in `column`, read INSIDE the transaction.
|
|
12714
|
-
*/
|
|
12715
|
-
var TransactGuardSchema = zod.z.object({
|
|
12716
|
-
collection: zod.z.string(),
|
|
12717
|
-
key: zod.z.string(),
|
|
12718
|
-
column: zod.z.string(),
|
|
12719
|
-
equals: zod.z.unknown()
|
|
12720
|
-
});
|
|
12721
|
-
/**
|
|
12722
|
-
* Column declaration for a structured (SQL-backed) collection.
|
|
12723
|
-
*
|
|
12724
|
-
* Logical types — the backend translates each to the matching SQLite
|
|
12725
|
-
* storage class and handles per-type marshaling:
|
|
12726
|
-
* - `TEXT` / `INTEGER` / `REAL` — native SQLite types, pass-through
|
|
12727
|
-
* - `JSON` — TEXT under the hood; serialised on write, parsed on read
|
|
12728
|
-
* - `BOOLEAN` — INTEGER 0/1 under the hood; coerced both directions
|
|
12729
|
-
*/
|
|
12730
|
-
var CollectionColumnSchema = zod.z.object({
|
|
12731
|
-
name: zod.z.string(),
|
|
12732
|
-
type: zod.z.enum([
|
|
12733
|
-
"TEXT",
|
|
12734
|
-
"INTEGER",
|
|
12735
|
-
"REAL",
|
|
12736
|
-
"JSON",
|
|
12737
|
-
"BOOLEAN"
|
|
12738
|
-
]),
|
|
12739
|
-
primaryKey: zod.z.boolean().optional(),
|
|
12740
|
-
notNull: zod.z.boolean().optional(),
|
|
12741
|
-
unique: zod.z.boolean().optional(),
|
|
12742
|
-
/**
|
|
12743
|
-
* Column DEFAULT. Required for B2: the four `ensureTable` consumers declare
|
|
12744
|
-
* columns like `enabled INTEGER NOT NULL DEFAULT 1`, and without this the
|
|
12745
|
-
* collection surface simply cannot express their existing tables — which is
|
|
12746
|
-
* why they were still on the uncapped `table*` API.
|
|
12747
|
-
*/
|
|
12748
|
-
defaultValue: zod.z.union([
|
|
12749
|
-
zod.z.string(),
|
|
12750
|
-
zod.z.number(),
|
|
12751
|
-
zod.z.boolean()
|
|
12752
|
-
]).optional()
|
|
12753
|
-
});
|
|
12754
|
-
var CollectionIndexSchema = zod.z.object({
|
|
12755
|
-
name: zod.z.string(),
|
|
12756
|
-
columns: zod.z.array(zod.z.string()).readonly(),
|
|
12757
|
-
unique: zod.z.boolean().optional()
|
|
12758
|
-
});
|
|
12759
|
-
/**
|
|
12760
|
-
* The input of `declareCollection` — ONE schema for the door and for the
|
|
12761
|
-
* engine behind it, so the two surfaces cannot drift (the dispatcher forwards
|
|
12762
|
-
* the payload untouched).
|
|
12763
|
-
*
|
|
12764
|
-
* - `database` — the file the collection lives in (D851). Absent means
|
|
12765
|
-
* `settings`. A declaration naming a file other than the one the table is
|
|
12766
|
-
* already in is REFUSED by the engine, never moved.
|
|
12767
|
-
* - `primaryKey` — a COMPOSITE key, as column names. A single name is the same
|
|
12768
|
-
* as `primaryKey: true` on that column. A composite-keyed collection has no
|
|
12769
|
-
* `id`: it is written with `insertMany` / `upsertMany` / `transact` and read
|
|
12770
|
-
* with `query` / `count` / `aggregate` / `deleteWhere`; the calls that
|
|
12771
|
-
* address one row by id are refused.
|
|
12772
|
-
* - `withoutRowid` — emit `WITHOUT ROWID`. Requires a primary key.
|
|
12773
|
-
*/
|
|
12774
|
-
var DeclareCollectionInputSchema = zod.z.object({
|
|
12775
|
-
namespace: zod.z.string().optional(),
|
|
12776
|
-
collection: zod.z.string(),
|
|
12777
|
-
columns: zod.z.array(CollectionColumnSchema).readonly(),
|
|
12778
|
-
indexes: zod.z.array(CollectionIndexSchema).readonly().optional(),
|
|
12779
|
-
database: DataStoreDatabaseSchema.optional(),
|
|
12780
|
-
primaryKey: zod.z.array(zod.z.string()).readonly().optional(),
|
|
12781
|
-
withoutRowid: zod.z.boolean().optional()
|
|
12782
|
-
});
|
|
12783
|
-
/**
|
|
12784
|
-
* settings-store — singleton capability for addon-scoped persistence.
|
|
12785
|
-
*
|
|
12786
|
-
* Every method operates within a `collection`. An optional `namespace`
|
|
12787
|
-
* field provides access to additional data spaces beyond the default
|
|
12788
|
-
* addon settings — useful for business data (events, tracks, faces, etc.).
|
|
12789
|
-
*
|
|
12790
|
-
* **Scoping is the CALLER's, and it is opt-in.** The table is
|
|
12791
|
-
* `namespace ? `${namespace}:${collection}` : collection` — nothing
|
|
12792
|
-
* consults the identity of the caller. An earlier version of this comment
|
|
12793
|
-
* claimed the implementation prefixes every collection with the calling
|
|
12794
|
-
* addon's ID and that "addons never see each other's data"; that was never
|
|
12795
|
-
* true, and this same file contradicted it under `declareCollection`. What
|
|
12796
|
-
* exists is `addon-context-factory`, which passes `namespace: addonId` ON
|
|
12797
|
-
* THE ADDON'S BEHALF for the `addon-settings` / `addon-devices` paths only.
|
|
12798
|
-
* Business collections use bare names, and any caller may name any
|
|
12799
|
-
* namespace, or none. Making the door enforce it is tracked separately —
|
|
12800
|
-
* it renames tables, so it needs a migration.
|
|
12801
|
-
*
|
|
12802
|
-
* **So every method is `auth: 'admin'` (D634).** Because nothing scopes a
|
|
12803
|
-
* call to its caller, a `protected` method here was a raw, unredacted read
|
|
12804
|
-
* (and write) of every addon's collections for any role holding
|
|
12805
|
-
* `category:system` — which is every role: a `viewer` could read every
|
|
12806
|
-
* notifier token in plaintext from `notifiers:notification-targets`. No
|
|
12807
|
-
* browser or app client calls this cap. Addons are not affected: an
|
|
12808
|
-
* addon's `ctx.api` cap call is resolved to the provider directly and never
|
|
12809
|
-
* enters the tRPC router (so the tier gates sessions and tokens, never
|
|
12810
|
-
* addons), and the hub itself calls it through the capability registry.
|
|
12811
|
-
*
|
|
12812
|
-
* - `{ collection: 'addon-settings' }` → table `addon-settings`
|
|
12813
|
-
* - `{ namespace: 'my-addon', collection: 'addon-settings' }` →
|
|
12814
|
-
* table `my-addon:addon-settings`
|
|
12815
|
-
*
|
|
12816
|
-
* Served by the **storage-orchestrator** builtin, which dispatches to the
|
|
12817
|
-
* `data-store-provider` engine registered for the collection
|
|
12818
|
-
* (`sqlite-settings`, a SQLite WAL backend, today). One addon owns the
|
|
12819
|
-
* data door; engines sit behind it
|
|
12820
|
-
* ([D44](../../../../docs/decisions/adr-0044.md)).
|
|
12821
|
-
* Addons access it via `ctx.api.settingsStore.*`.
|
|
12822
|
-
*/
|
|
12823
|
-
var settingsStoreCapability = {
|
|
12824
|
-
name: "settings-store",
|
|
12930
|
+
code: "custom",
|
|
12931
|
+
message: "code or files is required",
|
|
12932
|
+
path: ["code"]
|
|
12933
|
+
});
|
|
12934
|
+
});
|
|
12935
|
+
var coreBlocksCapability = {
|
|
12936
|
+
name: "core-blocks",
|
|
12825
12937
|
scope: "system",
|
|
12826
12938
|
mode: "singleton",
|
|
12827
12939
|
methods: {
|
|
12828
|
-
|
|
12829
|
-
get: require_sleep.method(zod.z.object({
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
12840
|
-
|
|
12940
|
+
list: require_sleep.method(zod.z.object({}), zod.z.object({ blocks: zod.z.array(CoreBlockSchema) }), { auth: "admin" }),
|
|
12941
|
+
get: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema.nullable() }), { auth: "admin" }),
|
|
12942
|
+
/**
|
|
12943
|
+
* Create a block. The code is COMPILED first: storing source that does not
|
|
12944
|
+
* compile turns an editor error into a fork failure the operator meets
|
|
12945
|
+
* minutes later in a log.
|
|
12946
|
+
*/
|
|
12947
|
+
create: require_sleep.method(zod.z.object({ block: CoreBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
12948
|
+
kind: "mutation",
|
|
12949
|
+
auth: "admin",
|
|
12950
|
+
caller: "required"
|
|
12951
|
+
}),
|
|
12952
|
+
update: require_sleep.method(zod.z.object({
|
|
12953
|
+
blockId: zod.z.string(),
|
|
12954
|
+
block: CoreBlockInputFieldsSchema.partial()
|
|
12955
|
+
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
12956
|
+
kind: "mutation",
|
|
12957
|
+
auth: "admin",
|
|
12958
|
+
caller: "required"
|
|
12959
|
+
}),
|
|
12960
|
+
delete: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ success: zod.z.literal(true) }), {
|
|
12841
12961
|
kind: "mutation",
|
|
12842
12962
|
auth: "admin"
|
|
12843
12963
|
}),
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
* columns (plus the primary key) instead of the whole row. It is the only
|
|
12849
|
-
* way to stop paying disk for a column that is discarded — a heavy JSON
|
|
12850
|
-
* column dominates the row, and dropping it in JS after the read pays every
|
|
12851
|
-
* byte first. Measured on the live `pipeline-analytics:tracks` table: a
|
|
12852
|
-
* 501-row page is 4.6 MB whole and 0.11 MB projected, same index, same
|
|
12853
|
-
* plan.
|
|
12854
|
-
*
|
|
12855
|
-
* The engine REFUSES a column it cannot serve rather than omitting it —
|
|
12856
|
-
* see `SettingsQueryInput.columns` for why a projection may not be
|
|
12857
|
-
* forgiving the way a predicate is.
|
|
12858
|
-
*/
|
|
12859
|
-
query: require_sleep.method(zod.z.object({
|
|
12860
|
-
namespace: zod.z.string().optional(),
|
|
12861
|
-
collection: zod.z.string(),
|
|
12862
|
-
filter: QueryFilterSchema.optional(),
|
|
12863
|
-
columns: zod.z.array(zod.z.string()).readonly().optional()
|
|
12864
|
-
}), zod.z.array(SettingsRecordSchema).readonly(), { auth: "admin" }),
|
|
12865
|
-
/**
|
|
12866
|
-
* Make a SLOT hold this row — insert it, or update whatever already
|
|
12867
|
-
* occupies the slot — and answer with the id the row HAS.
|
|
12868
|
-
*
|
|
12869
|
-
* ## Why the store needed this
|
|
12870
|
-
*
|
|
12871
|
-
* {@link set} is already an upsert, but its slot is the PRIMARY KEY: the
|
|
12872
|
-
* caller has to know the id to address the row. That is exactly what a
|
|
12873
|
-
* collection keyed by an `INTEGER` rowid alias cannot do — SQLite assigns
|
|
12874
|
-
* the id, so a writer whose uniqueness rule is "one row per
|
|
12875
|
-
* `(ownerKind, ownerId, kind, slot)`" has no id to name and no way to
|
|
12876
|
-
* express the rule. {@link insert} can express it (a UNIQUE index
|
|
12877
|
-
* arbitrates) but only by THROWING at the loser of a race, and the loser
|
|
12878
|
-
* here is a legitimate re-capture, not an error.
|
|
12879
|
-
*
|
|
12880
|
-
* Getting there without this method means read-then-write: query the slot,
|
|
12881
|
-
* then `insert` or `update`. Two statements instead of one, a race between
|
|
12882
|
-
* them, and a recovery path that has to recognise a UNIQUE violation by its
|
|
12883
|
-
* MESSAGE — across a process boundary, because the store lives behind an
|
|
12884
|
-
* RPC door. A string match would be the whole gate, and a store that
|
|
12885
|
-
* rephrased its error would lose the row silently. One statement has no
|
|
12886
|
-
* such gate (D482).
|
|
12887
|
-
*
|
|
12888
|
-
* ## The contract
|
|
12889
|
-
*
|
|
12890
|
-
* `conflict` names the DECLARED columns that identify the slot. They must
|
|
12891
|
-
* be covered by a UNIQUE index on the collection — SQLite resolves an
|
|
12892
|
-
* `ON CONFLICT` target against its indexes and REFUSES the statement when
|
|
12893
|
-
* none matches, so a wrong list is a loud error on the first write, never a
|
|
12894
|
-
* silently duplicated row. An empty list is refused rather than passed on:
|
|
12895
|
-
* `ON CONFLICT()` is not valid SQL, and the intent it would most likely
|
|
12896
|
-
* encode ("no slot, just insert") is {@link insert}.
|
|
12897
|
-
*
|
|
12898
|
-
* Row shape is {@link insert}'s: `record.id` is used when the collection
|
|
12899
|
-
* needs a supplied key and IGNORED when the primary key is an `INTEGER`
|
|
12900
|
-
* rowid alias — exactly as `insert` and `insertMany` already treat it.
|
|
12901
|
-
*
|
|
12902
|
-
* Returns the id either way: the one SQLite assigned on an insert, or the
|
|
12903
|
-
* one the row it updated already had. A caller cannot tell which happened,
|
|
12904
|
-
* and deliberately — every caller wants the slot's id, and one that needed
|
|
12905
|
-
* to distinguish creation from replacement would have to read first anyway.
|
|
12906
|
-
*/
|
|
12907
|
-
upsert: require_sleep.method(zod.z.object({
|
|
12908
|
-
namespace: zod.z.string().optional(),
|
|
12909
|
-
collection: zod.z.string(),
|
|
12910
|
-
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12911
|
-
* index on the collection. Never empty. */
|
|
12912
|
-
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
12913
|
-
record: BulkRecordSchema
|
|
12914
|
-
}), zod.z.object({
|
|
12915
|
-
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12916
|
-
* row's own id on an update. */
|
|
12917
|
-
id: zod.z.union([zod.z.string(), zod.z.number()]) }), {
|
|
12964
|
+
setEnabled: require_sleep.method(zod.z.object({
|
|
12965
|
+
blockId: zod.z.string(),
|
|
12966
|
+
enabled: zod.z.boolean()
|
|
12967
|
+
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
12918
12968
|
kind: "mutation",
|
|
12919
12969
|
auth: "admin"
|
|
12920
12970
|
}),
|
|
12921
12971
|
/**
|
|
12922
|
-
*
|
|
12972
|
+
* Stop this block's runner and let the supervisor bring it back.
|
|
12923
12973
|
*
|
|
12924
|
-
*
|
|
12925
|
-
*
|
|
12926
|
-
*
|
|
12927
|
-
*
|
|
12928
|
-
*
|
|
12974
|
+
* **It stores nothing.** There is no "restart requested" flag and no second
|
|
12975
|
+
* lifecycle field: the supervisor already stops and respawns a runner when
|
|
12976
|
+
* the code hash changes, and this exposes that same path deliberately
|
|
12977
|
+
* (D62 — a switch writes the authority that already owned the function).
|
|
12978
|
+
* The next reconcile pass remains the authority, so a restart that lost a
|
|
12979
|
+
* race is corrected within one pass rather than leaving a stale flag behind.
|
|
12929
12980
|
*
|
|
12930
|
-
*
|
|
12931
|
-
*
|
|
12932
|
-
* that silently bound NULL over a column it did not mention would erase
|
|
12933
|
-
* it. A heterogeneous batch is refused whole. **All or nothing.**
|
|
12981
|
+
* Refused for a DISABLED block: nothing would come back, and a button that
|
|
12982
|
+
* silently does nothing is worse than one that says why.
|
|
12934
12983
|
*/
|
|
12935
|
-
|
|
12936
|
-
namespace: zod.z.string().optional(),
|
|
12937
|
-
collection: zod.z.string(),
|
|
12938
|
-
conflict: zod.z.array(zod.z.string()).readonly(),
|
|
12939
|
-
records: zod.z.array(BulkRecordSchema).readonly()
|
|
12940
|
-
}), zod.z.object({ upserted: zod.z.number().int() }), {
|
|
12984
|
+
restart: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), zod.z.object({ block: CoreBlockSchema }), {
|
|
12941
12985
|
kind: "mutation",
|
|
12942
12986
|
auth: "admin"
|
|
12943
12987
|
}),
|
|
12944
|
-
/** Insert a new record. */
|
|
12945
|
-
insert: require_sleep.method(zod.z.object({
|
|
12946
|
-
namespace: zod.z.string().optional(),
|
|
12947
|
-
collection: zod.z.string(),
|
|
12948
|
-
record: zod.z.object({
|
|
12949
|
-
id: zod.z.string().optional(),
|
|
12950
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
12951
|
-
})
|
|
12952
|
-
}), zod.z.object({
|
|
12953
12988
|
/**
|
|
12954
|
-
*
|
|
12955
|
-
*
|
|
12956
|
-
*
|
|
12989
|
+
* Type-check without saving — what the editor calls as the author types, so
|
|
12990
|
+
* the compiler's verdict is the same one the server will reach.
|
|
12991
|
+
* Accepts `{ code }` or `{ files, entry }` (multi-file project).
|
|
12957
12992
|
*/
|
|
12958
|
-
|
|
12993
|
+
compile: require_sleep.method(CoreBlockCompileInputSchema, CoreBlockCompileResultSchema, {
|
|
12959
12994
|
kind: "mutation",
|
|
12960
12995
|
auth: "admin"
|
|
12961
12996
|
}),
|
|
12962
12997
|
/**
|
|
12963
|
-
*
|
|
12964
|
-
*
|
|
12965
|
-
*
|
|
12966
|
-
* reason: without it, appending a batch is N round trips and N COMMITs on
|
|
12967
|
-
* the single shared connection that also serves every cluster-wide
|
|
12968
|
-
* configuration read. The durable load series writes one process row per
|
|
12969
|
-
* process per sample — 76 rows every 10 s on the live fleet — and the
|
|
12970
|
-
* operator's rule for it is *one transaction per sample, never one per
|
|
12971
|
-
* row*. `insert` cannot express that; nothing else could.
|
|
12972
|
-
*
|
|
12973
|
-
* **All or nothing.** A batch that fails on its fifth row leaves none of
|
|
12974
|
-
* the five behind. A half-written sample is worse than a missing one: the
|
|
12975
|
-
* missing one reads as "nobody reported", which is true, while the half
|
|
12976
|
-
* one reads as "these were the only processes running", which is not.
|
|
12977
|
-
*
|
|
12978
|
-
* `id` is OPTIONAL per record, and that is the difference from
|
|
12979
|
-
* {@link insert}. A collection whose primary key is an `INTEGER` rowid
|
|
12980
|
-
* alias has no id to supply — SQLite assigns it, for free, and inventing a
|
|
12981
|
-
* `randomUUID()` for such a column would write a 36-character string into
|
|
12982
|
-
* an integer key. Omitted on a TEXT key, a uuid is generated exactly as
|
|
12983
|
-
* `insert` does.
|
|
12998
|
+
* Hydrated settings form for one block, or null until a `settingsSchema`
|
|
12999
|
+
* is known (extracted from the compiled entry's named export, or set on
|
|
13000
|
+
* the block). Values live in the `core-blocks:settings` collection.
|
|
12984
13001
|
*/
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
13002
|
+
getBlockSettings: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), SettingsSchemaWithValuesSchema.nullable(), { auth: "admin" }),
|
|
13003
|
+
/**
|
|
13004
|
+
* Patch persisted preference values for one block. The schema is not
|
|
13005
|
+
* rewritten here — only values. Scripts read the same blob via
|
|
13006
|
+
* `ctx.settings.readAddonStore()` (mirrored into the block addon's
|
|
13007
|
+
* `addon-settings` namespace on every patch).
|
|
13008
|
+
*/
|
|
13009
|
+
updateBlockSettings: require_sleep.method(zod.z.object({
|
|
13010
|
+
blockId: zod.z.string(),
|
|
13011
|
+
patch: SettingsPatchSchema
|
|
13012
|
+
}), SettingsUpdateResultSchema, {
|
|
12990
13013
|
kind: "mutation",
|
|
12991
13014
|
auth: "admin"
|
|
12992
13015
|
}),
|
|
12993
13016
|
/**
|
|
12994
|
-
*
|
|
12995
|
-
*
|
|
12996
|
-
* The multi-collection twin of {@link insertMany}: a write that has to move
|
|
12997
|
-
* a set of rows in one collection AND a revision in another cannot be
|
|
12998
|
-
* expressed as separate calls without a window in which a reader (or a
|
|
12999
|
-
* crash) sees half of it. The retrain annotation save replaces a frame's
|
|
13000
|
-
* rows, its dismissed set and its revision this way.
|
|
13001
|
-
*
|
|
13002
|
-
* `guard`, when given, is read inside the transaction: if the row is
|
|
13003
|
-
* missing or its column differs from `equals`, NOTHING is written and the
|
|
13004
|
-
* answer is `{ applied: false, current }` with what was found — the
|
|
13005
|
-
* compare-and-set a revisioned write needs, with no second reader able to
|
|
13006
|
-
* slip between the check and the writes.
|
|
13017
|
+
* The declaration files the editor type-checks against.
|
|
13007
13018
|
*
|
|
13008
|
-
*
|
|
13009
|
-
*
|
|
13010
|
-
*
|
|
13019
|
+
* Served rather than bundled: the graph is 3.4 MB across 344 files, and
|
|
13020
|
+
* bundling it would roughly double the admin remote. Served rather than
|
|
13021
|
+
* hand-stubbed: a block runs with the same `ctx` an addon gets, so a stub
|
|
13022
|
+
* would drift and the editor would confidently autocomplete methods that
|
|
13023
|
+
* do not exist.
|
|
13011
13024
|
*/
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
}),
|
|
13023
|
-
/** Update an existing record by ID. */
|
|
13024
|
-
update: require_sleep.method(zod.z.object({
|
|
13025
|
-
namespace: zod.z.string().optional(),
|
|
13026
|
-
collection: zod.z.string(),
|
|
13027
|
-
id: zod.z.string(),
|
|
13028
|
-
data: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
13029
|
-
}), zod.z.void(), {
|
|
13030
|
-
kind: "mutation",
|
|
13031
|
-
auth: "admin"
|
|
13032
|
-
}),
|
|
13033
|
-
/** Delete a record by key/ID. */
|
|
13034
|
-
delete: require_sleep.method(zod.z.object({
|
|
13035
|
-
namespace: zod.z.string().optional(),
|
|
13036
|
-
collection: zod.z.string(),
|
|
13037
|
-
key: zod.z.string()
|
|
13038
|
-
}), zod.z.void(), {
|
|
13025
|
+
getTypeDefs: require_sleep.method(zod.z.object({}), zod.z.object({ libs: zod.z.array(zod.z.object({
|
|
13026
|
+
filePath: zod.z.string(),
|
|
13027
|
+
content: zod.z.string()
|
|
13028
|
+
})) }), { auth: "admin" }),
|
|
13029
|
+
/**
|
|
13030
|
+
* Create a composition block (D659). VALIDATED first against the live
|
|
13031
|
+
* sources and every stored composition; a refusal names every problem by
|
|
13032
|
+
* path and reason (D391) and stores nothing.
|
|
13033
|
+
*/
|
|
13034
|
+
createComposition: require_sleep.method(zod.z.object({ block: CompositionBlockInputSchema }), zod.z.object({ block: CoreBlockSchema }), {
|
|
13039
13035
|
kind: "mutation",
|
|
13040
|
-
auth: "admin"
|
|
13036
|
+
auth: "admin",
|
|
13037
|
+
caller: "required"
|
|
13041
13038
|
}),
|
|
13042
13039
|
/**
|
|
13043
|
-
*
|
|
13044
|
-
*
|
|
13045
|
-
*
|
|
13046
|
-
* had to SELECT a page of full rows — every column, including the fat
|
|
13047
|
-
* ones — purely to learn their ids, then issue one call per row.
|
|
13048
|
-
*
|
|
13049
|
-
* **The filter is required and must resolve.** A predicate naming
|
|
13050
|
-
* something the collection cannot express is an ERROR here, not a
|
|
13051
|
-
* widening as it is on `query`, and a filter with no predicates is an
|
|
13052
|
-
* error rather than "every row". Deleting a whole collection is a
|
|
13053
|
-
* legitimate intent, but it must be asked for by name — not reached by
|
|
13054
|
-
* an empty object.
|
|
13040
|
+
* Patch a composition block. A changed `composition` is validated exactly
|
|
13041
|
+
* as on create. `expectedUpdatedAt` is the `updatedAt` the caller READ: a
|
|
13042
|
+
* block changed since is refused by name, never silently overwritten.
|
|
13055
13043
|
*/
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
}), zod.z.object({
|
|
13044
|
+
updateComposition: require_sleep.method(zod.z.object({
|
|
13045
|
+
blockId: zod.z.string(),
|
|
13046
|
+
expectedUpdatedAt: zod.z.number(),
|
|
13047
|
+
block: CompositionBlockInputSchema.partial()
|
|
13048
|
+
}), zod.z.object({ block: CoreBlockSchema }), {
|
|
13061
13049
|
kind: "mutation",
|
|
13062
|
-
auth: "admin"
|
|
13050
|
+
auth: "admin",
|
|
13051
|
+
caller: "required"
|
|
13063
13052
|
}),
|
|
13053
|
+
/** One composition and the composer's state for it, or `not-loaded` (D315). */
|
|
13054
|
+
getComposition: require_sleep.method(zod.z.object({ blockId: zod.z.string() }), CompositionGetReadSchema, { auth: "admin" }),
|
|
13055
|
+
listCompositions: require_sleep.method(zod.z.object({}), CompositionListReadSchema, { auth: "admin" }),
|
|
13064
13056
|
/**
|
|
13065
|
-
*
|
|
13066
|
-
*
|
|
13067
|
-
* {@link deleteWhere} — an unresolvable predicate is an error.
|
|
13057
|
+
* The composition that customizes an existing device (D663), found by its
|
|
13058
|
+
* TARGET — never by the block's derived name. One per device at most.
|
|
13068
13059
|
*/
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13060
|
+
getCustomization: require_sleep.method(zod.z.object({
|
|
13061
|
+
addonId: zod.z.string().min(1),
|
|
13062
|
+
stableId: zod.z.string().min(1)
|
|
13063
|
+
}), CompositionCustomizationReadSchema, { auth: "admin" }),
|
|
13064
|
+
/**
|
|
13065
|
+
* The capabilities a composition may BUILD on a device of `deviceType`
|
|
13066
|
+
* (a new device, or added to an existing one), with their fields — the
|
|
13067
|
+
* editor's feature list and the presets' availability (G2, D676). Built
|
|
13068
|
+
* from the validator's own blockers; a replace of a BOUND cap is not
|
|
13069
|
+
* listed here (the device's bindings say what it has).
|
|
13070
|
+
*/
|
|
13071
|
+
listComposableCaps: require_sleep.method(zod.z.object({ deviceType: zod.z.enum(require_err_msg.DeviceType) }), ComposableCapabilitiesSchema, { auth: "admin" }),
|
|
13072
|
+
/**
|
|
13073
|
+
* Validate without saving — the same verdict the save reaches. A mutation
|
|
13074
|
+
* for its body size; it writes nothing, so its access is `view`.
|
|
13075
|
+
*/
|
|
13076
|
+
validateComposition: require_sleep.method(zod.z.object({
|
|
13077
|
+
composition: require_composition.CompositionSchema,
|
|
13078
|
+
blockId: zod.z.string().optional()
|
|
13079
|
+
}), CompositionValidationSchema, {
|
|
13075
13080
|
kind: "mutation",
|
|
13076
|
-
auth: "admin"
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13081
|
+
auth: "admin",
|
|
13082
|
+
access: "view"
|
|
13083
|
+
})
|
|
13084
|
+
}
|
|
13085
|
+
};
|
|
13086
|
+
//#endregion
|
|
13087
|
+
//#region src/capabilities/custom-model-registry.cap.ts
|
|
13088
|
+
/**
|
|
13089
|
+
* `custom-model-registry` — collection cap exposing operator-registered
|
|
13090
|
+
* custom detection models. Each provider (today: `addon-model-studio`)
|
|
13091
|
+
* contributes a list of `CustomModelDescriptor`s; the hub auto-concatenates
|
|
13092
|
+
* them across providers (`concatCollection`).
|
|
13093
|
+
*
|
|
13094
|
+
* The detection-pipeline is *aware* of this cap: when at least one provider
|
|
13095
|
+
* exists it unions these descriptors into the per-step model picker and the
|
|
13096
|
+
* runtime model-resolution path, alongside the static catalog. When no
|
|
13097
|
+
* provider exists the consumer no-ops entirely (identical to the catalog-only
|
|
13098
|
+
* behaviour).
|
|
13099
|
+
*
|
|
13100
|
+
* A descriptor carries a full `ModelCatalogEntry` directly — the same shape
|
|
13101
|
+
* the static catalog uses — so the existing download/resolution code consumes
|
|
13102
|
+
* it unchanged. `stepId` is the detection step the model targets
|
|
13103
|
+
* (e.g. `'object-detection'`).
|
|
13104
|
+
*/
|
|
13105
|
+
var CustomModelDescriptorSchema = zod.z.object({
|
|
13106
|
+
stepId: zod.z.string(),
|
|
13107
|
+
entry: ModelCatalogEntrySchema
|
|
13108
|
+
});
|
|
13109
|
+
/** One regular file of an imported bundle, as the producer measured it. */
|
|
13110
|
+
var ModelBundleFileSchema = zod.z.object({
|
|
13111
|
+
/** Relative path inside the bundle tar; an mlpackage member is `<x>.mlpackage/<member>`. */
|
|
13112
|
+
path: zod.z.string().min(1),
|
|
13113
|
+
bytes: zod.z.number().int().nonnegative(),
|
|
13114
|
+
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
13115
|
+
});
|
|
13116
|
+
var ImportModelBundleInputSchema = zod.z.object({
|
|
13117
|
+
/** The registry provider that keeps the model (Model Studio). */
|
|
13118
|
+
addonId: zod.z.string(),
|
|
13119
|
+
stepId: zod.z.string().min(1),
|
|
13120
|
+
/**
|
|
13121
|
+
* The catalog rows to register, complete, every format URL already
|
|
13122
|
+
* `camstack-local://<modelId>/<file>` naming a file of the bundle. One
|
|
13123
|
+
* bundle may carry several rows (a base and its INT8 variant).
|
|
13124
|
+
*/
|
|
13125
|
+
entries: zod.z.array(ModelCatalogEntrySchema).min(1).max(4),
|
|
13126
|
+
/** The bundle tar, offered by the producer over `ctx.peerBytes` (same host). */
|
|
13127
|
+
bundle: zod.z.object({
|
|
13128
|
+
ticket: require_sleep.PeerBytesTicketSchema,
|
|
13129
|
+
bytes: zod.z.number().int().positive(),
|
|
13130
|
+
sha256: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
13131
|
+
}),
|
|
13132
|
+
/** Every file the tar must hold; anything missing, extra or different is refused. */
|
|
13133
|
+
files: zod.z.array(ModelBundleFileSchema).min(1).max(64),
|
|
13134
|
+
/** Convert missing engine formats and push the model to every agent afterwards. */
|
|
13135
|
+
distribute: zod.z.boolean()
|
|
13136
|
+
});
|
|
13137
|
+
var ImportModelBundleResultSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
13138
|
+
kind: zod.z.literal("imported"),
|
|
13139
|
+
modelIds: zod.z.array(zod.z.string()).readonly(),
|
|
13140
|
+
distributed: zod.z.array(zod.z.object({
|
|
13141
|
+
modelId: zod.z.string(),
|
|
13142
|
+
nodeId: zod.z.string(),
|
|
13143
|
+
format: zod.z.enum(require_sleep.MODEL_FORMATS),
|
|
13144
|
+
ok: zod.z.boolean(),
|
|
13145
|
+
error: zod.z.string().optional()
|
|
13146
|
+
})).readonly()
|
|
13147
|
+
}), zod.z.object({
|
|
13148
|
+
kind: zod.z.literal("refused"),
|
|
13149
|
+
reason: zod.z.enum([
|
|
13150
|
+
"transfer-failed",
|
|
13151
|
+
"checksum-mismatch",
|
|
13152
|
+
"bundle-mismatch",
|
|
13153
|
+
"invalid-entry",
|
|
13154
|
+
"id-taken"
|
|
13155
|
+
]),
|
|
13156
|
+
detail: zod.z.string()
|
|
13157
|
+
})]);
|
|
13158
|
+
var customModelRegistryCapability = {
|
|
13159
|
+
name: "custom-model-registry",
|
|
13160
|
+
scope: "system",
|
|
13161
|
+
mode: "collection",
|
|
13162
|
+
internal: true,
|
|
13163
|
+
methods: {
|
|
13084
13164
|
/**
|
|
13085
|
-
* `
|
|
13086
|
-
*
|
|
13087
|
-
*
|
|
13088
|
-
*
|
|
13089
|
-
*
|
|
13090
|
-
*
|
|
13091
|
-
*
|
|
13092
|
-
* to visit every row — 7.1 M of them on the live hub, ~15 M row visits a
|
|
13093
|
-
* minute on the main thread, which is also why the whole archive had to
|
|
13094
|
-
* stay resident to be visited. The question is a sum; nothing needs to be
|
|
13095
|
-
* materialised to answer it.
|
|
13096
|
-
*
|
|
13097
|
-
* **The engine REFUSES a field it cannot serve**, exactly as
|
|
13098
|
-
* `query.columns` does and unlike a PREDICATE, which is skipped when
|
|
13099
|
-
* unresolvable. A dropped predicate over-matches and the caller sees extra
|
|
13100
|
-
* rows; a dropped aggregate returns a NUMBER that is wrong and looks
|
|
13101
|
-
* exactly like a real one. That asymmetry is what this repo has already
|
|
13102
|
-
* paid for once in `count`.
|
|
13165
|
+
* `internal: true` did not gate the mount (see the 2026-08-26 note on
|
|
13166
|
+
* `data-store-provider`) — this was reachable on the AppRouter by ANY
|
|
13167
|
+
* authenticated session at the default `auth: 'protected'`. The only
|
|
13168
|
+
* consumer, the detection-pipeline's model resolution
|
|
13169
|
+
* (`addon-pipeline/src/detection-pipeline/provider.ts`), calls
|
|
13170
|
+
* `ctx.api.customModelRegistry.listModels.query()` — UDS/Moleculer,
|
|
13171
|
+
* never tRPC — so `auth: 'admin'` costs it nothing.
|
|
13103
13172
|
*/
|
|
13104
|
-
|
|
13105
|
-
namespace: zod.z.string().optional(),
|
|
13106
|
-
collection: zod.z.string(),
|
|
13107
|
-
fields: zod.z.array(AggregateFieldSchema).readonly(),
|
|
13108
|
-
filter: QueryFilterSchema.optional()
|
|
13109
|
-
}), AggregateResultSchema, { auth: "admin" }),
|
|
13110
|
-
/** Grouped counts per ((field-origin)/bucketSize) bucket, filtered. */
|
|
13111
|
-
histogram: require_sleep.method(zod.z.object({
|
|
13112
|
-
namespace: zod.z.string().optional(),
|
|
13113
|
-
collection: zod.z.string(),
|
|
13114
|
-
field: zod.z.string(),
|
|
13115
|
-
bucketSize: zod.z.number().int().positive(),
|
|
13116
|
-
origin: zod.z.number().int(),
|
|
13117
|
-
filter: QueryFilterSchema.optional()
|
|
13118
|
-
}), zod.z.array(zod.z.object({
|
|
13119
|
-
bucket: zod.z.number().int(),
|
|
13120
|
-
count: zod.z.number().int()
|
|
13121
|
-
})).readonly(), { auth: "admin" }),
|
|
13122
|
-
/** Check if a collection is empty. */
|
|
13123
|
-
isEmpty: require_sleep.method(zod.z.object({
|
|
13124
|
-
namespace: zod.z.string().optional(),
|
|
13125
|
-
collection: zod.z.string()
|
|
13126
|
-
}), zod.z.boolean(), { auth: "admin" }),
|
|
13173
|
+
listModels: require_sleep.method(zod.z.void(), zod.z.array(CustomModelDescriptorSchema).readonly(), { auth: "admin" }),
|
|
13127
13174
|
/**
|
|
13128
|
-
*
|
|
13129
|
-
*
|
|
13130
|
-
*
|
|
13131
|
-
*
|
|
13132
|
-
*
|
|
13133
|
-
*
|
|
13134
|
-
*
|
|
13135
|
-
*
|
|
13136
|
-
*
|
|
13137
|
-
* Addons call this in `onInitialize` before their first read/write.
|
|
13138
|
-
* Collection names should be namespaced by addon (e.g.
|
|
13139
|
-
* `pipeline-analytics:object-events`) to avoid cross-addon
|
|
13140
|
-
* clashes — no automatic prefix is added.
|
|
13175
|
+
* Register a model whose files arrive as ONE bundle tar (D806): the tar
|
|
13176
|
+
* is taken over `ctx.peerBytes`, checked against `bundle.sha256` and
|
|
13177
|
+
* every row of `files`, unpacked into the hub's flat modelsDir (directory
|
|
13178
|
+
* formats included), each format's `.revision` record written, the rows
|
|
13179
|
+
* upserted under the operator's name, the hub marked available and —
|
|
13180
|
+
* when asked — engine formats converted and the model distributed. A
|
|
13181
|
+
* model id already registered by another source is refused, never
|
|
13182
|
+
* overwritten.
|
|
13141
13183
|
*/
|
|
13142
|
-
|
|
13184
|
+
importModelBundle: require_sleep.method(ImportModelBundleInputSchema, ImportModelBundleResultSchema, {
|
|
13143
13185
|
kind: "mutation",
|
|
13144
|
-
auth: "admin"
|
|
13186
|
+
auth: "admin",
|
|
13187
|
+
timeoutMs: 30 * 6e4
|
|
13145
13188
|
})
|
|
13146
13189
|
}
|
|
13147
13190
|
};
|
|
@@ -37862,6 +37905,18 @@ var CalendarInfoSchema = zod.z.object({
|
|
|
37862
37905
|
source: CalendarSourceKindSchema,
|
|
37863
37906
|
enabled: zod.z.boolean()
|
|
37864
37907
|
});
|
|
37908
|
+
/**
|
|
37909
|
+
* Time contract of {@link CalendarEvent}.
|
|
37910
|
+
*
|
|
37911
|
+
* - Timed event: `startMs` / `endMs` are real instants; `endMs` is exclusive.
|
|
37912
|
+
* - All-day event (`allDay: true`): the event is a run of calendar DATES, not
|
|
37913
|
+
* instants. `startMs` is UTC midnight of the first date and `endMs` is UTC
|
|
37914
|
+
* midnight of the day AFTER the last date (RFC 5545 exclusive DTEND), so a
|
|
37915
|
+
* one-day event spans exactly 24 h. Every provider produces that and no
|
|
37916
|
+
* consumer may read the instants in a local timezone: use
|
|
37917
|
+
* {@link calendarEventLocalSpan}. Reading UTC midnight as local time put an
|
|
37918
|
+
* all-day event on the following day for any viewer ahead of UTC.
|
|
37919
|
+
*/
|
|
37865
37920
|
var CalendarEventSchema = zod.z.object({
|
|
37866
37921
|
id: zod.z.string().min(1),
|
|
37867
37922
|
calendarId: zod.z.string().min(1),
|
|
@@ -37888,6 +37943,40 @@ var calendarSourceCapability = {
|
|
|
37888
37943
|
listEvents: require_sleep.method(CalendarListEventsInputSchema, zod.z.array(CalendarEventSchema).readonly(), { auth: "admin" })
|
|
37889
37944
|
}
|
|
37890
37945
|
};
|
|
37946
|
+
function localMidnightOfUtcDate(utcMidnightMs) {
|
|
37947
|
+
const d = new Date(utcMidnightMs);
|
|
37948
|
+
return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()).getTime();
|
|
37949
|
+
}
|
|
37950
|
+
/**
|
|
37951
|
+
* The interval an event occupies on the viewer's local clock, end exclusive.
|
|
37952
|
+
* A timed event is returned as is; an all-day event's UTC dates are re-read as
|
|
37953
|
+
* local calendar dates (local midnight to local midnight, DST-safe). A
|
|
37954
|
+
* degenerate all-day end (`<=` start) is widened to one day.
|
|
37955
|
+
*/
|
|
37956
|
+
function calendarEventLocalSpan(ev) {
|
|
37957
|
+
if (ev.allDay !== true) return {
|
|
37958
|
+
startMs: ev.startMs,
|
|
37959
|
+
endMs: ev.endMs
|
|
37960
|
+
};
|
|
37961
|
+
const startMs = localMidnightOfUtcDate(ev.startMs);
|
|
37962
|
+
const endMs = localMidnightOfUtcDate(ev.endMs);
|
|
37963
|
+
if (endMs > startMs) return {
|
|
37964
|
+
startMs,
|
|
37965
|
+
endMs
|
|
37966
|
+
};
|
|
37967
|
+
const start = new Date(startMs);
|
|
37968
|
+
return {
|
|
37969
|
+
startMs,
|
|
37970
|
+
endMs: new Date(start.getFullYear(), start.getMonth(), start.getDate() + 1).getTime()
|
|
37971
|
+
};
|
|
37972
|
+
}
|
|
37973
|
+
/** Does the event touch the local calendar day starting at `dayStartMs`? */
|
|
37974
|
+
function calendarEventOnLocalDay(ev, dayStartMs) {
|
|
37975
|
+
const day = new Date(dayStartMs);
|
|
37976
|
+
const dayEndMs = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1).getTime();
|
|
37977
|
+
const span = calendarEventLocalSpan(ev);
|
|
37978
|
+
return span.startMs < dayEndMs && span.endMs > dayStartMs;
|
|
37979
|
+
}
|
|
37891
37980
|
//#endregion
|
|
37892
37981
|
//#region src/capabilities/calendars.cap.ts
|
|
37893
37982
|
/**
|
|
@@ -41161,7 +41250,15 @@ var HubAddressBookSchema = zod.z.object({
|
|
|
41161
41250
|
publicEndpoint: HubAddressRoleResolutionSchema
|
|
41162
41251
|
}),
|
|
41163
41252
|
/** The `hub=` an app link carries (D709), or null. */
|
|
41164
|
-
appLinkHub: zod.z.string().nullable()
|
|
41253
|
+
appLinkHub: zod.z.string().nullable(),
|
|
41254
|
+
/**
|
|
41255
|
+
* Every origin a browser can really reach this hub at, in the scheme each
|
|
41256
|
+
* listener serves: `https://<lan>:<httpsPort>`, and `http://<lan>:<httpPort>`
|
|
41257
|
+
* while LAN HTTP is on, plus the public and custom addresses. Distinct from
|
|
41258
|
+
* `rows`, which show `http://` only while LAN HTTP is on. Never loopback,
|
|
41259
|
+
* never the app link. Absent on a hub older than D794's amendment.
|
|
41260
|
+
*/
|
|
41261
|
+
listenerOrigins: zod.z.array(zod.z.string()).readonly().optional()
|
|
41165
41262
|
});
|
|
41166
41263
|
var AllowedAddressesSchema = zod.z.object({
|
|
41167
41264
|
/**
|
|
@@ -55400,6 +55497,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
55400
55497
|
addonId: null,
|
|
55401
55498
|
access: "view"
|
|
55402
55499
|
},
|
|
55500
|
+
"backup.listAvailableDatabases": {
|
|
55501
|
+
capName: "backup",
|
|
55502
|
+
capScope: "system",
|
|
55503
|
+
addonId: null,
|
|
55504
|
+
access: "view"
|
|
55505
|
+
},
|
|
55403
55506
|
"backup.listDestinations": {
|
|
55404
55507
|
capName: "backup",
|
|
55405
55508
|
capScope: "system",
|
|
@@ -70716,6 +70819,7 @@ function createSystemProxy(api) {
|
|
|
70716
70819
|
upsertDestinationPolicy: (input) => dispatch("backup", "upsertDestinationPolicy", "mutation", input),
|
|
70717
70820
|
previewSchedule: (input) => dispatch("backup", "previewSchedule", "query", input),
|
|
70718
70821
|
listSchedules: (input) => dispatch("backup", "listSchedules", "query", input),
|
|
70822
|
+
listAvailableDatabases: (input) => dispatch("backup", "listAvailableDatabases", "query", input),
|
|
70719
70823
|
upsertSchedule: (input) => dispatch("backup", "upsertSchedule", "mutation", input),
|
|
70720
70824
|
deleteSchedule: (input) => dispatch("backup", "deleteSchedule", "mutation", input)
|
|
70721
70825
|
},
|
|
@@ -80262,9 +80366,11 @@ exports.DISPLAY_ICON_VOCABULARY = DISPLAY_ICON_VOCABULARY;
|
|
|
80262
80366
|
exports.DOORBELL_RISE_DEBOUNCE_MS = DOORBELL_RISE_DEBOUNCE_MS;
|
|
80263
80367
|
exports.DataStoreDatabaseSchema = DataStoreDatabaseSchema;
|
|
80264
80368
|
exports.DataStoreEngineInfoSchema = EngineInfoSchema;
|
|
80369
|
+
exports.DatabaseSnapshotRequestSchema = DatabaseSnapshotRequestSchema;
|
|
80265
80370
|
exports.DatabaseSnapshotResultSchema = DatabaseSnapshotResultSchema;
|
|
80266
80371
|
exports.DatabaseSnapshotTableSchema = DatabaseSnapshotTableSchema;
|
|
80267
80372
|
exports.DatabaseSnapshotTargetsSchema = DatabaseSnapshotTargetsSchema;
|
|
80373
|
+
exports.DatabaseSnapshotWrittenSchema = DatabaseSnapshotWrittenSchema;
|
|
80268
80374
|
exports.DayNightModeSchema = DayNightModeSchema;
|
|
80269
80375
|
exports.DayNightOptionsSchema = DayNightOptionsSchema;
|
|
80270
80376
|
exports.DayNightSettingsPatchSchema = DayNightSettingsPatchSchema;
|
|
@@ -81620,6 +81726,8 @@ exports.buildVideoArgs = require_composition.buildVideoArgs;
|
|
|
81620
81726
|
exports.buildViewerLink = buildViewerLink;
|
|
81621
81727
|
exports.builtCapabilityBlockers = builtCapabilityBlockers;
|
|
81622
81728
|
exports.buttonCapability = buttonCapability;
|
|
81729
|
+
exports.calendarEventLocalSpan = calendarEventLocalSpan;
|
|
81730
|
+
exports.calendarEventOnLocalDay = calendarEventOnLocalDay;
|
|
81623
81731
|
exports.calendarSourceCapability = calendarSourceCapability;
|
|
81624
81732
|
exports.calendarsCapability = calendarsCapability;
|
|
81625
81733
|
exports.cameraCredentialsCapability = cameraCredentialsCapability;
|