@camstack/system 1.2.424 → 1.2.426
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-databases.d.ts +51 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +19 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +268 -17
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +268 -17
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +23 -3
- package/dist/builtins/backup-orchestrator/run-queue.d.ts +3 -0
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +7 -1
- package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +34 -0
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- package/dist/builtins/local-network/address-book.d.ts +21 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +6 -0
- package/dist/builtins/local-network/local-network.addon.js +48 -7
- package/dist/builtins/local-network/local-network.addon.mjs +48 -7
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/database-snapshot-provider.d.ts +18 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +49 -7
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +49 -7
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-backup/system-backup.service.d.ts +48 -15
- package/dist/builtins/system-config/system-config.addon.js +2 -2
- package/dist/builtins/system-config/system-config.addon.mjs +2 -2
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-BWNs-ZeH.js → composition-sources-60tuHQ9N.js} +1 -1
- package/dist/{composition-sources-tRG7nKWK.mjs → composition-sources-gxVpghXh.mjs} +1 -1
- package/dist/{constants-DHhhVjkt.mjs → constants-B6YTf0v2.mjs} +1 -1
- package/dist/{constants-BBWZlnpQ.js → constants-CO5zpJQY.js} +1 -1
- package/dist/{dist-B-NmfvVC.mjs → dist-CGz9u2HD.mjs} +869 -800
- package/dist/{dist-CiUKtVkX.js → dist-K3WFop9Q.js} +869 -800
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/index.js +272 -198
- package/dist/index.mjs +272 -198
- package/dist/{jwt-signing-key-nwRpRgf_.js → jwt-signing-key-BdDy9ZJN.js} +1 -1
- package/dist/{jwt-signing-key-CUpweD22.mjs → jwt-signing-key-C_w5ielw.mjs} +1 -1
- package/dist/kernel/moleculer/process-service.d.ts +1 -110
- package/dist/kernel/moleculer/runner-heap-flags.d.ts +228 -0
- package/dist/{restore-archive-DA-aJtg7.js → restore-archive-BJp4Llea.js} +156 -65
- package/dist/{restore-archive-CFmPVlWQ.mjs → restore-archive-CZyUM8Qf.mjs} +151 -66
- package/dist/{retired-settings-keys-D62kN_hT.js → retired-settings-keys-Dr2AyhsD.js} +1 -1
- package/dist/{retired-settings-keys-DCGEI4Vi.mjs → retired-settings-keys-Dut6QWh6.mjs} +1 -1
- package/dist/{wal-maintenance-BlqNqaQ3.mjs → wal-maintenance-BZhzoxqA.mjs} +0 -0
- package/dist/{wal-maintenance-BzdCQGjH.js → wal-maintenance-Bzm3O2Nj.js} +0 -0
- package/package.json +1 -1
|
@@ -1,9 +1,141 @@
|
|
|
1
|
-
import { Br as nodePin, Fn as storageOccupancyCapability, Qr as toNodeId, X as backupCapability, lr as BaseAddon, ti as EventCategory, tn as mayWriteToLocation } from "../../dist-
|
|
2
|
-
import { a as BackupSnapshotRefusedError,
|
|
1
|
+
import { Br as nodePin, Fn as storageOccupancyCapability, Qr as toNodeId, X as backupCapability, lr as BaseAddon, ti as EventCategory, tn as mayWriteToLocation } from "../../dist-CGz9u2HD.mjs";
|
|
2
|
+
import { a as BackupSnapshotRefusedError, d as ENCRYPTED_BACKUP_SUFFIX, f as generateBackupKeyPair, i as BackupCancelledError, l as BackupKeyFormatError, m as parseBackupSecretKey, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as parseBackupPublicKey, r as prepareRestoreArchive, s as SystemBackupService } from "../../restore-archive-CZyUM8Qf.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import * as fsp from "node:fs/promises";
|
|
5
5
|
import * as path$1 from "node:path";
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
|
+
//#region src/builtins/backup-orchestrator/backup-databases.ts
|
|
8
|
+
/** Stable id of the seeded weekly schedule. */
|
|
9
|
+
var WEEKLY_SCHEDULE_ID = "weekly-events-history";
|
|
10
|
+
var WEEKLY_SCHEDULE_LABEL = "Weekly — events & history";
|
|
11
|
+
/** Sundays 04:00 — an hour after the nightly settings run. */
|
|
12
|
+
var WEEKLY_SCHEDULE_CRON = "0 4 * * 0";
|
|
13
|
+
/**
|
|
14
|
+
* Events and history ONLY: a run that does not select settings carries no
|
|
15
|
+
* data-root walk either, so the weekly archive is just the two snapshots.
|
|
16
|
+
*/
|
|
17
|
+
var WEEKLY_SCHEDULE_DATABASES = ["events", "history"];
|
|
18
|
+
/** What a schedule carries: its own list, else the minimum (D382). */
|
|
19
|
+
function databasesOfSchedule(schedule) {
|
|
20
|
+
return schedule.databases !== void 0 && schedule.databases.length > 0 ? schedule.databases : DEFAULT_BACKUP_DATABASES;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* True when a run asks for a database beyond settings and the owner has none
|
|
24
|
+
* of them open: the run would only repeat the nightly archive. A settings-only
|
|
25
|
+
* run is never nothing-to-carry.
|
|
26
|
+
*/
|
|
27
|
+
function hasNothingBeyondSettings(requested, owned) {
|
|
28
|
+
const extra = requested.filter((id) => id !== "settings");
|
|
29
|
+
if (extra.length === 0) return false;
|
|
30
|
+
return !extra.some((id) => owned.includes(id));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The weekly schedule to seed, or null. Created only when NO schedule carries
|
|
34
|
+
* `events` (a seed never overwrites, D728 — an operator's own weekly schedule,
|
|
35
|
+
* or an edited seed, is left alone), and only when there is a nightly schedule
|
|
36
|
+
* to take the destinations from: a hub that backs up nowhere gets no weekly
|
|
37
|
+
* archive either.
|
|
38
|
+
*/
|
|
39
|
+
function planWeeklySeed(existing) {
|
|
40
|
+
if (existing.some((s) => s.id === "weekly-events-history")) return null;
|
|
41
|
+
if (existing.some((s) => databasesOfSchedule(s).includes("events"))) return null;
|
|
42
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
43
|
+
for (const s of existing) {
|
|
44
|
+
if (!s.enabled) continue;
|
|
45
|
+
for (const id of s.locationIds) destinations.add(id);
|
|
46
|
+
}
|
|
47
|
+
if (destinations.size === 0) return null;
|
|
48
|
+
return {
|
|
49
|
+
id: WEEKLY_SCHEDULE_ID,
|
|
50
|
+
label: WEEKLY_SCHEDULE_LABEL,
|
|
51
|
+
cron: WEEKLY_SCHEDULE_CRON,
|
|
52
|
+
enabled: true,
|
|
53
|
+
locationIds: [...destinations].toSorted(),
|
|
54
|
+
retentionCount: 4,
|
|
55
|
+
databases: WEEKLY_SCHEDULE_DATABASES
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Seed the weekly schedule if {@link planWeeklySeed} says so; returns what it
|
|
60
|
+
* wrote. Exactly once ever: the marker is written after the row, and a marker
|
|
61
|
+
* that exists ends the seed for good — an operator who disabled or deleted the
|
|
62
|
+
* weekly is never second-guessed. A weekly row found with no marker (seeded
|
|
63
|
+
* before the marker existed) is marked, not re-created.
|
|
64
|
+
*/
|
|
65
|
+
async function seedWeeklySchedule(store, markers) {
|
|
66
|
+
if (await markers.has("weekly-events-history")) return null;
|
|
67
|
+
const existing = await store.list();
|
|
68
|
+
if (existing.some((s) => s.id === "weekly-events-history")) {
|
|
69
|
+
await markers.mark(WEEKLY_SCHEDULE_ID);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const seed = planWeeklySeed(existing);
|
|
73
|
+
if (seed === null) return null;
|
|
74
|
+
await store.upsert(seed);
|
|
75
|
+
await markers.mark(WEEKLY_SCHEDULE_ID);
|
|
76
|
+
return seed;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/builtins/backup-orchestrator/seed-marker-store.ts
|
|
80
|
+
/**
|
|
81
|
+
* @durable class=config owner=backup-orchestrator
|
|
82
|
+
* write="the orchestrator inserts one row per seed id the first time that
|
|
83
|
+
* seed is created (or found already created); never updated"
|
|
84
|
+
* retention="none — one tiny row per seed ever made; deleting it lets the
|
|
85
|
+
* seed be re-created once more on the next boot"
|
|
86
|
+
*/
|
|
87
|
+
var BACKUP_SEED_MARKERS_COLLECTION = "backup_seed_markers";
|
|
88
|
+
var COLUMNS$1 = [{
|
|
89
|
+
name: "seed_id",
|
|
90
|
+
type: "TEXT",
|
|
91
|
+
primaryKey: true
|
|
92
|
+
}, {
|
|
93
|
+
name: "seeded_at",
|
|
94
|
+
type: "INTEGER",
|
|
95
|
+
notNull: true
|
|
96
|
+
}];
|
|
97
|
+
var BackupSeedMarkerStore = class {
|
|
98
|
+
store;
|
|
99
|
+
now;
|
|
100
|
+
declared = false;
|
|
101
|
+
constructor(store, now = Date.now) {
|
|
102
|
+
this.store = store;
|
|
103
|
+
this.now = now;
|
|
104
|
+
}
|
|
105
|
+
async ensureDeclared() {
|
|
106
|
+
if (this.declared) return;
|
|
107
|
+
await this.store.declareCollection({
|
|
108
|
+
collection: BACKUP_SEED_MARKERS_COLLECTION,
|
|
109
|
+
columns: COLUMNS$1
|
|
110
|
+
});
|
|
111
|
+
this.declared = true;
|
|
112
|
+
}
|
|
113
|
+
async has(seedId) {
|
|
114
|
+
await this.ensureDeclared();
|
|
115
|
+
return (await this.store.query({
|
|
116
|
+
collection: BACKUP_SEED_MARKERS_COLLECTION,
|
|
117
|
+
filter: {
|
|
118
|
+
where: { seed_id: seedId },
|
|
119
|
+
limit: 1
|
|
120
|
+
}
|
|
121
|
+
})).length > 0;
|
|
122
|
+
}
|
|
123
|
+
async mark(seedId) {
|
|
124
|
+
await this.ensureDeclared();
|
|
125
|
+
if (await this.has(seedId)) return;
|
|
126
|
+
await this.store.insert({
|
|
127
|
+
collection: BACKUP_SEED_MARKERS_COLLECTION,
|
|
128
|
+
record: {
|
|
129
|
+
id: seedId,
|
|
130
|
+
data: {
|
|
131
|
+
seed_id: seedId,
|
|
132
|
+
seeded_at: this.now()
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
//#endregion
|
|
7
139
|
//#region ../../node_modules/croner/dist/croner.js
|
|
8
140
|
function T(s) {
|
|
9
141
|
return Date.UTC(s.y, s.m - 1, s.d, s.h, s.i, s.s);
|
|
@@ -1269,7 +1401,8 @@ function normalizeManifest(raw) {
|
|
|
1269
1401
|
sizeBytes: Number(cand["sizeBytes"]),
|
|
1270
1402
|
...typeof cand["label"] === "string" ? { label: cand["label"] } : {},
|
|
1271
1403
|
manifest,
|
|
1272
|
-
...encryptionOf(cand["encryption"])
|
|
1404
|
+
...encryptionOf(cand["encryption"]),
|
|
1405
|
+
...databasesOf(cand["databases"])
|
|
1273
1406
|
};
|
|
1274
1407
|
archives.push(entry);
|
|
1275
1408
|
}
|
|
@@ -1282,6 +1415,15 @@ var EMPTY_MANIFEST = {
|
|
|
1282
1415
|
version: 1,
|
|
1283
1416
|
archives: []
|
|
1284
1417
|
};
|
|
1418
|
+
function databasesOf(raw) {
|
|
1419
|
+
if (!Array.isArray(raw)) return {};
|
|
1420
|
+
const known = [];
|
|
1421
|
+
const unknown = [];
|
|
1422
|
+
for (const item of raw) if (item === "settings" || item === "events" || item === "history") known.push(item);
|
|
1423
|
+
else if (typeof item === "string") unknown.push(item);
|
|
1424
|
+
if (known.length > 0) return { databases: known };
|
|
1425
|
+
return unknown.length > 0 ? { unrecognisedDatabases: unknown } : {};
|
|
1426
|
+
}
|
|
1285
1427
|
function encryptionOf(raw) {
|
|
1286
1428
|
if (typeof raw !== "object" || raw === null) return {};
|
|
1287
1429
|
const scheme = Reflect.get(raw, "scheme");
|
|
@@ -1305,7 +1447,8 @@ function outlineOfManifest(manifest) {
|
|
|
1305
1447
|
locations: [...manifest.locations],
|
|
1306
1448
|
entries: [],
|
|
1307
1449
|
totalBytes: manifest.totalBytes,
|
|
1308
|
-
totalFiles: manifest.totalFiles
|
|
1450
|
+
totalFiles: manifest.totalFiles,
|
|
1451
|
+
...manifest.omittedDatabases !== void 0 ? { omittedDatabases: [...manifest.omittedDatabases] } : {}
|
|
1309
1452
|
};
|
|
1310
1453
|
}
|
|
1311
1454
|
/**
|
|
@@ -1321,9 +1464,15 @@ function buildArchiveEntry(input) {
|
|
|
1321
1464
|
sizeBytes: input.sizeBytes,
|
|
1322
1465
|
...input.label !== void 0 ? { label: input.label } : {},
|
|
1323
1466
|
manifest: input.encryption !== void 0 ? outlineOfManifest(input.manifest) : input.manifest,
|
|
1324
|
-
...input.encryption !== void 0 ? { encryption: input.encryption } : {}
|
|
1467
|
+
...input.encryption !== void 0 ? { encryption: input.encryption } : {},
|
|
1468
|
+
...input.databases !== void 0 ? { databases: [...input.databases] } : {}
|
|
1325
1469
|
};
|
|
1326
1470
|
}
|
|
1471
|
+
/** The key under which archives of one cadence prune each other. */
|
|
1472
|
+
function retentionClassOf(entry) {
|
|
1473
|
+
if (entry.databases === void 0 && entry.unrecognisedDatabases !== void 0) return `?${[...entry.unrecognisedDatabases].toSorted().join("+")}`;
|
|
1474
|
+
return [...entry.databases ?? DEFAULT_BACKUP_DATABASES].toSorted().join("+");
|
|
1475
|
+
}
|
|
1327
1476
|
/**
|
|
1328
1477
|
* Pure retention split: given an archive list and the operator's
|
|
1329
1478
|
* `retentionCount`, return `{ keep, drop }` where `keep` is the most-
|
|
@@ -1332,20 +1481,27 @@ function buildArchiveEntry(input) {
|
|
|
1332
1481
|
* `retentionCount <= 0` is treated as "no pruning" — defensive against
|
|
1333
1482
|
* a config value that would otherwise wipe every archive on the next
|
|
1334
1483
|
* write.
|
|
1484
|
+
*
|
|
1485
|
+
* `cadence` (see {@link retentionClassOf}) restricts the count to archives of
|
|
1486
|
+
* the run that was just written: nightly archives (settings) and weekly ones
|
|
1487
|
+
* (settings + events + history) are retained separately.
|
|
1335
1488
|
*/
|
|
1336
|
-
function applyRetention(archives, retentionCount) {
|
|
1489
|
+
function applyRetention(archives, retentionCount, cadence) {
|
|
1337
1490
|
if (retentionCount <= 0) return {
|
|
1338
1491
|
keep: archives,
|
|
1339
1492
|
drop: []
|
|
1340
1493
|
};
|
|
1341
1494
|
const sorted = [...archives].toSorted((a, b) => b.createdAt - a.createdAt);
|
|
1342
|
-
|
|
1495
|
+
const inCadence = cadence === void 0 ? sorted : sorted.filter((a) => retentionClassOf(a) === cadence);
|
|
1496
|
+
if (inCadence.length <= retentionCount) return {
|
|
1343
1497
|
keep: sorted,
|
|
1344
1498
|
drop: []
|
|
1345
1499
|
};
|
|
1500
|
+
const drop = inCadence.slice(retentionCount);
|
|
1501
|
+
const dropped = new Set(drop);
|
|
1346
1502
|
return {
|
|
1347
|
-
keep: sorted.
|
|
1348
|
-
drop
|
|
1503
|
+
keep: sorted.filter((a) => !dropped.has(a)),
|
|
1504
|
+
drop
|
|
1349
1505
|
};
|
|
1350
1506
|
}
|
|
1351
1507
|
/**
|
|
@@ -1629,7 +1785,8 @@ function requestSignature(request) {
|
|
|
1629
1785
|
destinations: [...request.destinations ?? []].toSorted(),
|
|
1630
1786
|
locations: [...request.locations ?? []].toSorted(),
|
|
1631
1787
|
label: request.label ?? null,
|
|
1632
|
-
retentionCount: request.retentionCount ?? null
|
|
1788
|
+
retentionCount: request.retentionCount ?? null,
|
|
1789
|
+
databases: [...request.databases ?? []].toSorted()
|
|
1633
1790
|
});
|
|
1634
1791
|
}
|
|
1635
1792
|
//#endregion
|
|
@@ -1688,6 +1845,10 @@ var BACKUP_SCHEDULES_COLUMNS = [
|
|
|
1688
1845
|
name: "data_sources",
|
|
1689
1846
|
type: "JSON"
|
|
1690
1847
|
},
|
|
1848
|
+
{
|
|
1849
|
+
name: "databases",
|
|
1850
|
+
type: "JSON"
|
|
1851
|
+
},
|
|
1691
1852
|
{
|
|
1692
1853
|
name: "last_run_at",
|
|
1693
1854
|
type: "INTEGER"
|
|
@@ -1777,6 +1938,7 @@ function mapScheduleToRow(s) {
|
|
|
1777
1938
|
location_ids: [...s.locationIds],
|
|
1778
1939
|
retention_count: s.retentionCount,
|
|
1779
1940
|
data_sources: s.dataSources ? [...s.dataSources] : null,
|
|
1941
|
+
databases: s.databases ? [...s.databases] : null,
|
|
1780
1942
|
last_run_at: s.lastAttemptAt ?? null,
|
|
1781
1943
|
last_success_at: s.lastSuccessAt ?? null,
|
|
1782
1944
|
last_error: s.lastError ?? null
|
|
@@ -1793,6 +1955,12 @@ function parseStringArray(raw) {
|
|
|
1793
1955
|
if (!Array.isArray(value)) return [];
|
|
1794
1956
|
return value.filter((v) => typeof v === "string");
|
|
1795
1957
|
}
|
|
1958
|
+
/** Known database ids only: an unknown name in a stored row is dropped, not carried. */
|
|
1959
|
+
function parseDatabaseIds(raw) {
|
|
1960
|
+
const out = [];
|
|
1961
|
+
for (const id of parseStringArray(raw)) if (id === "settings" || id === "events" || id === "history") out.push(id);
|
|
1962
|
+
return out;
|
|
1963
|
+
}
|
|
1796
1964
|
function tryParseJson(raw) {
|
|
1797
1965
|
if (raw.length === 0) return null;
|
|
1798
1966
|
try {
|
|
@@ -1806,6 +1974,8 @@ function mapRowToSchedule(row) {
|
|
|
1806
1974
|
if (!id) return null;
|
|
1807
1975
|
const dataSourcesRaw = row["data_sources"];
|
|
1808
1976
|
const dataSources = dataSourcesRaw === null || dataSourcesRaw === void 0 ? void 0 : parseStringArray(dataSourcesRaw);
|
|
1977
|
+
const databasesRaw = row["databases"];
|
|
1978
|
+
const databases = databasesRaw === null || databasesRaw === void 0 ? void 0 : parseDatabaseIds(databasesRaw);
|
|
1809
1979
|
const lastRunRaw = row["last_run_at"];
|
|
1810
1980
|
const lastAttemptAt = typeof lastRunRaw === "number" && lastRunRaw > 0 ? lastRunRaw : void 0;
|
|
1811
1981
|
const lastSuccessRaw = row["last_success_at"];
|
|
@@ -1820,6 +1990,7 @@ function mapRowToSchedule(row) {
|
|
|
1820
1990
|
locationIds: parseStringArray(row["location_ids"]),
|
|
1821
1991
|
retentionCount: Number(row["retention_count"] ?? 7),
|
|
1822
1992
|
...dataSources !== void 0 ? { dataSources } : {},
|
|
1993
|
+
...databases !== void 0 && databases.length > 0 ? { databases } : {},
|
|
1823
1994
|
...lastAttemptAt !== void 0 ? { lastAttemptAt } : {},
|
|
1824
1995
|
...lastSuccessAt !== void 0 ? { lastSuccessAt } : {},
|
|
1825
1996
|
...lastError !== void 0 ? { lastError } : {}
|
|
@@ -2072,6 +2243,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2072
2243
|
this.ctx.logger.error("backup-orchestrator: schedule table init failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
2073
2244
|
this.schedules = null;
|
|
2074
2245
|
}
|
|
2246
|
+
await this.seedWeekly();
|
|
2075
2247
|
const settingsStore = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
|
|
2076
2248
|
this.encryptionKeys = settingsStore ? new BackupEncryptionKeyStore(settingsStore) : null;
|
|
2077
2249
|
const provider = {
|
|
@@ -2092,6 +2264,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2092
2264
|
upsertDestinationPolicy: (input) => this.upsertDestinationPolicy(input),
|
|
2093
2265
|
previewSchedule: (input) => this.previewSchedule(input),
|
|
2094
2266
|
listSchedules: () => this.listSchedules(),
|
|
2267
|
+
listAvailableDatabases: () => this.listAvailableDatabases(),
|
|
2095
2268
|
upsertSchedule: (input) => this.upsertSchedule(input),
|
|
2096
2269
|
deleteSchedule: (input) => this.deleteSchedule(input)
|
|
2097
2270
|
};
|
|
@@ -2377,7 +2550,8 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2377
2550
|
...input?.destinations ? { destinations: input.destinations } : {},
|
|
2378
2551
|
...input?.locations ? { locations: input.locations } : {},
|
|
2379
2552
|
...input?.label !== void 0 ? { label: input.label } : {},
|
|
2380
|
-
...input?.retentionCount !== void 0 ? { retentionCount: input.retentionCount } : {}
|
|
2553
|
+
...input?.retentionCount !== void 0 ? { retentionCount: input.retentionCount } : {},
|
|
2554
|
+
...input?.databases ? { databases: input.databases } : {}
|
|
2381
2555
|
};
|
|
2382
2556
|
const submitted = this.runQueue.submit(request);
|
|
2383
2557
|
if (submitted.queued) this.ctx.logger.info(submitted.joined ? "backup trigger: identical run already queued — joined it" : "backup trigger: a run is in flight — enqueued behind it", { meta: { runId: submitted.runId } });
|
|
@@ -2451,6 +2625,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2451
2625
|
signal,
|
|
2452
2626
|
onArchiveBytes: (bytes) => progress.setStagedBytes(bytes),
|
|
2453
2627
|
owner: this.databaseOwner(),
|
|
2628
|
+
...input.databases ? { databases: input.databases } : {},
|
|
2454
2629
|
...encryptTo !== null ? { encryptTo: encryptTo.publicKey } : {}
|
|
2455
2630
|
});
|
|
2456
2631
|
} catch (err) {
|
|
@@ -2483,6 +2658,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2483
2658
|
sizeBytes: result.sizeBytes,
|
|
2484
2659
|
archiveManifest: result.manifest,
|
|
2485
2660
|
retentionCount: input.retentionCount ?? policy.retentionCount,
|
|
2661
|
+
databases: input.databases ?? DEFAULT_BACKUP_DATABASES,
|
|
2486
2662
|
createdAt,
|
|
2487
2663
|
label: formatArchiveLabel(dest.id, createdAt, input.label),
|
|
2488
2664
|
...result.encryption !== void 0 ? { encryption: result.encryption } : {},
|
|
@@ -2554,9 +2730,9 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2554
2730
|
};
|
|
2555
2731
|
return {
|
|
2556
2732
|
listDatabases: async () => {
|
|
2557
|
-
return (await this.ctx.api.databaseSnapshot.listDatabases.query({}, pin())).databases
|
|
2733
|
+
return (await this.ctx.api.databaseSnapshot.listDatabases.query({}, pin())).databases;
|
|
2558
2734
|
},
|
|
2559
|
-
writeSnapshot: async () => this.ctx.api.databaseSnapshot.writeSnapshot.mutate({}, pin())
|
|
2735
|
+
writeSnapshot: async (databaseId) => this.ctx.api.databaseSnapshot.writeSnapshot.mutate({ databaseId }, pin())
|
|
2560
2736
|
};
|
|
2561
2737
|
}
|
|
2562
2738
|
/**
|
|
@@ -2608,10 +2784,11 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2608
2784
|
sizeBytes: input.sizeBytes,
|
|
2609
2785
|
label: input.label,
|
|
2610
2786
|
manifest: input.archiveManifest,
|
|
2611
|
-
...input.encryption !== void 0 ? { encryption: input.encryption } : {}
|
|
2787
|
+
...input.encryption !== void 0 ? { encryption: input.encryption } : {},
|
|
2788
|
+
databases: input.databases
|
|
2612
2789
|
});
|
|
2613
2790
|
await this.manifestLock.run(input.locationId, async () => {
|
|
2614
|
-
const { keep, drop } = applyRetention([...(await readLocationManifest(this.storageApi(), input.locationId)).archives, entry], input.retentionCount);
|
|
2791
|
+
const { keep, drop } = applyRetention([...(await readLocationManifest(this.storageApi(), input.locationId)).archives, entry], input.retentionCount, retentionClassOf(entry));
|
|
2615
2792
|
for (const stale of drop) try {
|
|
2616
2793
|
await this.ctx.api.storage.delete.mutate({
|
|
2617
2794
|
location: input.locationId,
|
|
@@ -2665,7 +2842,8 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
2665
2842
|
sizeBytes: a.sizeBytes,
|
|
2666
2843
|
...a.label !== void 0 ? { label: a.label } : {},
|
|
2667
2844
|
locations: [...a.manifest.locations],
|
|
2668
|
-
...a.encryption !== void 0 ? { encryption: a.encryption } : {}
|
|
2845
|
+
...a.encryption !== void 0 ? { encryption: a.encryption } : {},
|
|
2846
|
+
...a.databases !== void 0 ? { databases: [...a.databases] } : {}
|
|
2669
2847
|
}));
|
|
2670
2848
|
}
|
|
2671
2849
|
/**
|
|
@@ -3032,6 +3210,55 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
3032
3210
|
}
|
|
3033
3211
|
}
|
|
3034
3212
|
/**
|
|
3213
|
+
* A schedule that asks for events/history while the owner has neither open
|
|
3214
|
+
* would only repeat the nightly archive (D852: the weekly schedule has
|
|
3215
|
+
* nothing to carry until those files exist). Said on the record, no archive
|
|
3216
|
+
* built, no outcome stamped. An owner that cannot answer never skips: the
|
|
3217
|
+
* run goes ahead and fails — or succeeds — in the open.
|
|
3218
|
+
*/
|
|
3219
|
+
async nothingToCarry(schedule) {
|
|
3220
|
+
const requested = databasesOfSchedule(schedule);
|
|
3221
|
+
if (!requested.some((id) => id !== "settings")) return false;
|
|
3222
|
+
let owned;
|
|
3223
|
+
try {
|
|
3224
|
+
owned = (await this.databaseOwner().listDatabases()).map((d) => d.databaseId);
|
|
3225
|
+
} catch (err) {
|
|
3226
|
+
this.ctx.logger.warn("Scheduled backup: the database owner did not answer — running anyway", { meta: {
|
|
3227
|
+
scheduleId: schedule.id,
|
|
3228
|
+
label: schedule.label,
|
|
3229
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3230
|
+
} });
|
|
3231
|
+
return false;
|
|
3232
|
+
}
|
|
3233
|
+
if (!hasNothingBeyondSettings(requested, owned)) return false;
|
|
3234
|
+
this.ctx.logger.info("Scheduled backup skipped — no database it carries exists yet", { meta: {
|
|
3235
|
+
scheduleId: schedule.id,
|
|
3236
|
+
label: schedule.label,
|
|
3237
|
+
requested: [...requested],
|
|
3238
|
+
owned
|
|
3239
|
+
} });
|
|
3240
|
+
return true;
|
|
3241
|
+
}
|
|
3242
|
+
/**
|
|
3243
|
+
* Seed the weekly "events & history" schedule (D852) — once, and never over
|
|
3244
|
+
* anything the operator has: see `planWeeklySeed`.
|
|
3245
|
+
*/
|
|
3246
|
+
async seedWeekly() {
|
|
3247
|
+
if (!this.schedules) return;
|
|
3248
|
+
try {
|
|
3249
|
+
const store = this.ctx.kernel.capabilityRegistry?.getSingleton("settings-store");
|
|
3250
|
+
if (!store) return;
|
|
3251
|
+
const seed = await seedWeeklySchedule(this.schedules, new BackupSeedMarkerStore(store));
|
|
3252
|
+
if (seed === null) return;
|
|
3253
|
+
this.ctx.logger.info("backup: seeded the weekly events & history schedule", { meta: {
|
|
3254
|
+
scheduleId: seed.id,
|
|
3255
|
+
destinationIds: [...seed.locationIds]
|
|
3256
|
+
} });
|
|
3257
|
+
} catch (err) {
|
|
3258
|
+
this.ctx.logger.warn("backup: the weekly schedule could not be seeded", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
/**
|
|
3035
3262
|
* Fire one schedule and RECORD what happened to it, naming every
|
|
3036
3263
|
* destination. Three outcomes, three different persisted states —
|
|
3037
3264
|
* because "fired" and "backed up" were the same field until D384:
|
|
@@ -3042,13 +3269,15 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
3042
3269
|
*/
|
|
3043
3270
|
async runScheduledBackup(schedule, firedAt) {
|
|
3044
3271
|
const destinationIds = [...schedule.locationIds];
|
|
3272
|
+
if (await this.nothingToCarry(schedule)) return;
|
|
3045
3273
|
let failure;
|
|
3046
3274
|
try {
|
|
3047
3275
|
const result = await this.triggerBackup({
|
|
3048
3276
|
destinations: destinationIds,
|
|
3049
3277
|
...schedule.dataSources && schedule.dataSources.length > 0 ? { locations: [...schedule.dataSources] } : {},
|
|
3050
3278
|
label: schedule.label,
|
|
3051
|
-
retentionCount: schedule.retentionCount
|
|
3279
|
+
retentionCount: schedule.retentionCount,
|
|
3280
|
+
...schedule.databases ? { databases: [...schedule.databases] } : {}
|
|
3052
3281
|
});
|
|
3053
3282
|
if (result.entries.length === 0 && !result.cancelled) failure = `no destination accepted the archive (${destinationIds.join(", ")})`;
|
|
3054
3283
|
} catch (err) {
|
|
@@ -3081,6 +3310,25 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
3081
3310
|
} });
|
|
3082
3311
|
}
|
|
3083
3312
|
}
|
|
3313
|
+
/**
|
|
3314
|
+
* The database files the owner has open right now, for the selection UI. An
|
|
3315
|
+
* owner that cannot answer is `answered: false` — never an empty list, which
|
|
3316
|
+
* the UI would read as "none exists yet".
|
|
3317
|
+
*/
|
|
3318
|
+
async listAvailableDatabases() {
|
|
3319
|
+
try {
|
|
3320
|
+
return {
|
|
3321
|
+
answered: true,
|
|
3322
|
+
databases: (await this.databaseOwner().listDatabases()).map((d) => d.databaseId)
|
|
3323
|
+
};
|
|
3324
|
+
} catch (err) {
|
|
3325
|
+
this.ctx.logger.warn("Backup database list: the database owner did not answer", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
3326
|
+
return {
|
|
3327
|
+
answered: false,
|
|
3328
|
+
databases: []
|
|
3329
|
+
};
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3084
3332
|
async listSchedules() {
|
|
3085
3333
|
if (!this.schedules) return [];
|
|
3086
3334
|
return (await this.schedules.list()).map((s) => {
|
|
@@ -3097,6 +3345,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
3097
3345
|
locationIds: [...s.locationIds],
|
|
3098
3346
|
retentionCount: s.retentionCount,
|
|
3099
3347
|
...s.dataSources !== void 0 ? { dataSources: [...s.dataSources] } : {},
|
|
3348
|
+
...s.databases !== void 0 ? { databases: [...s.databases] } : {},
|
|
3100
3349
|
...s.lastAttemptAt !== void 0 ? { lastAttemptAt: s.lastAttemptAt } : {},
|
|
3101
3350
|
...s.lastSuccessAt !== void 0 ? { lastSuccessAt: s.lastSuccessAt } : {},
|
|
3102
3351
|
...s.lastError !== void 0 ? { lastError: s.lastError } : {},
|
|
@@ -3118,6 +3367,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
3118
3367
|
locationIds: [...input.locationIds],
|
|
3119
3368
|
retentionCount: input.retentionCount,
|
|
3120
3369
|
...input.dataSources && input.dataSources.length > 0 ? { dataSources: [...input.dataSources] } : {},
|
|
3370
|
+
...input.databases && input.databases.length > 0 ? { databases: [...input.databases] } : {},
|
|
3121
3371
|
...existing?.lastAttemptAt !== void 0 ? { lastAttemptAt: existing.lastAttemptAt } : {},
|
|
3122
3372
|
...existing?.lastSuccessAt !== void 0 ? { lastSuccessAt: existing.lastSuccessAt } : {},
|
|
3123
3373
|
...existing?.lastError !== void 0 ? { lastError: existing.lastError } : {}
|
|
@@ -3136,6 +3386,7 @@ var BackupOrchestratorAddon = class extends BaseAddon {
|
|
|
3136
3386
|
locationIds: [...next.locationIds],
|
|
3137
3387
|
retentionCount: next.retentionCount,
|
|
3138
3388
|
...next.dataSources !== void 0 ? { dataSources: [...next.dataSources] } : {},
|
|
3389
|
+
...next.databases !== void 0 ? { databases: [...next.databases] } : {},
|
|
3139
3390
|
...next.lastAttemptAt !== void 0 ? { lastAttemptAt: next.lastAttemptAt } : {},
|
|
3140
3391
|
...next.lastSuccessAt !== void 0 ? { lastSuccessAt: next.lastSuccessAt } : {},
|
|
3141
3392
|
...next.lastError !== void 0 ? { lastError: next.lastError } : {},
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* snapshot of the embedded `ArchiveManifest` so `getEntries` can
|
|
18
18
|
* serve the contents preview without re-reading the tarball.
|
|
19
19
|
*/
|
|
20
|
-
import type { AddonApi } from "@camstack/types";
|
|
21
|
-
import type
|
|
20
|
+
import type { AddonApi, DataStoreDatabase } from "@camstack/types";
|
|
21
|
+
import { type ArchiveManifest } from "../system-backup/system-backup.service.js";
|
|
22
22
|
/** File path (relative to the location root) where the index lives. */
|
|
23
23
|
export declare const MANIFESTS_FILENAME = "manifests.json";
|
|
24
24
|
export interface ManifestArchiveEntry {
|
|
@@ -37,6 +37,19 @@ export interface ManifestArchiveEntry {
|
|
|
37
37
|
readonly manifest: ArchiveManifest;
|
|
38
38
|
/** Present when the archive is encrypted to a backup key. */
|
|
39
39
|
readonly encryption?: ManifestArchiveEncryption;
|
|
40
|
+
/**
|
|
41
|
+
* The databases the run ASKED to carry — its retention class: archives of one
|
|
42
|
+
* cadence prune each other, never another cadence's (a weekly archive that
|
|
43
|
+
* holds the events ledgers must not be evicted by seven nightly ones).
|
|
44
|
+
* Absent on an entry written before several files were owned: `['settings']`.
|
|
45
|
+
*/
|
|
46
|
+
readonly databases?: readonly DataStoreDatabase[];
|
|
47
|
+
/**
|
|
48
|
+
* Ids this build does not know, kept ONLY when no known id remains: such an
|
|
49
|
+
* entry is its own retention class and is never counted or pruned by another
|
|
50
|
+
* cadence (a newer build's database must not collapse to `settings`).
|
|
51
|
+
*/
|
|
52
|
+
readonly unrecognisedDatabases?: readonly string[];
|
|
40
53
|
}
|
|
41
54
|
export interface ManifestArchiveEncryption {
|
|
42
55
|
readonly scheme: string;
|
|
@@ -87,7 +100,10 @@ export declare function buildArchiveEntry(input: {
|
|
|
87
100
|
label?: string;
|
|
88
101
|
manifest: ArchiveManifest;
|
|
89
102
|
encryption?: ManifestArchiveEncryption;
|
|
103
|
+
databases?: readonly DataStoreDatabase[];
|
|
90
104
|
}): ManifestArchiveEntry;
|
|
105
|
+
/** The key under which archives of one cadence prune each other. */
|
|
106
|
+
export declare function retentionClassOf(entry: Pick<ManifestArchiveEntry, "databases" | "unrecognisedDatabases">): string;
|
|
91
107
|
/**
|
|
92
108
|
* Pure retention split: given an archive list and the operator's
|
|
93
109
|
* `retentionCount`, return `{ keep, drop }` where `keep` is the most-
|
|
@@ -96,8 +112,12 @@ export declare function buildArchiveEntry(input: {
|
|
|
96
112
|
* `retentionCount <= 0` is treated as "no pruning" — defensive against
|
|
97
113
|
* a config value that would otherwise wipe every archive on the next
|
|
98
114
|
* write.
|
|
115
|
+
*
|
|
116
|
+
* `cadence` (see {@link retentionClassOf}) restricts the count to archives of
|
|
117
|
+
* the run that was just written: nightly archives (settings) and weekly ones
|
|
118
|
+
* (settings + events + history) are retained separately.
|
|
99
119
|
*/
|
|
100
|
-
export declare function applyRetention(archives: readonly ManifestArchiveEntry[], retentionCount: number): {
|
|
120
|
+
export declare function applyRetention(archives: readonly ManifestArchiveEntry[], retentionCount: number, cadence?: string): {
|
|
101
121
|
readonly keep: readonly ManifestArchiveEntry[];
|
|
102
122
|
readonly drop: readonly ManifestArchiveEntry[];
|
|
103
123
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DataStoreDatabase } from "@camstack/types";
|
|
1
2
|
export type BackupRunState = "queued" | "running" | "succeeded" | "failed" | "cancelled";
|
|
2
3
|
export type BackupRunPhase = "queued" | "building" | "uploading" | "done";
|
|
3
4
|
/** What a trigger asks for — the queue keys joining on this. */
|
|
@@ -6,6 +7,8 @@ export interface BackupRunRequest {
|
|
|
6
7
|
readonly locations?: readonly string[];
|
|
7
8
|
readonly label?: string;
|
|
8
9
|
readonly retentionCount?: number;
|
|
10
|
+
/** Database files to carry; absent = settings only. */
|
|
11
|
+
readonly databases?: readonly DataStoreDatabase[];
|
|
9
12
|
}
|
|
10
13
|
/** Immutable snapshot of one run — the wire shape of `backup.listRuns`. */
|
|
11
14
|
export interface BackupRunSnapshot {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* the surface serialises and parses them, so this file passes and
|
|
15
15
|
* receives real arrays.
|
|
16
16
|
*/
|
|
17
|
-
import type { CollectionColumn, ISettingsStoreProvider } from "@camstack/types";
|
|
17
|
+
import type { CollectionColumn, DataStoreDatabase, ISettingsStoreProvider } from "@camstack/types";
|
|
18
18
|
/**
|
|
19
19
|
* A backup schedule row.
|
|
20
20
|
*
|
|
@@ -32,6 +32,12 @@ export interface BackupSchedule {
|
|
|
32
32
|
readonly retentionCount: number;
|
|
33
33
|
readonly dataSources?: readonly string[];
|
|
34
34
|
/**
|
|
35
|
+
* Which database files this schedule carries. Absent (a `NULL` column) =
|
|
36
|
+
* `['settings']`: an unstated ask is the minimum (D382). Settings runs
|
|
37
|
+
* nightly, events and history weekly (D852).
|
|
38
|
+
*/
|
|
39
|
+
readonly databases?: readonly DataStoreDatabase[];
|
|
40
|
+
/**
|
|
35
41
|
* ms-epoch of the last tick that FIRED this schedule. Stamped BEFORE the
|
|
36
42
|
* archive runs — it is the dedupe anchor and the cron's "after" cursor —
|
|
37
43
|
* so it means "attempted", never "succeeded". It was documented as the
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "This seed has run, once, ever" (D728, D852).
|
|
3
|
+
*
|
|
4
|
+
* A seed that decides from the data alone re-creates what the operator deleted
|
|
5
|
+
* on the next boot. The marker is the orchestrator's own row in the settings
|
|
6
|
+
* store it already owns (D62: no new authority), one per seed id, written
|
|
7
|
+
* AFTER the seeded row landed. A read that fails THROWS: "could not read the
|
|
8
|
+
* marker" must never look like "never seeded".
|
|
9
|
+
*/
|
|
10
|
+
import type { ISettingsStoreProvider } from "@camstack/types";
|
|
11
|
+
/**
|
|
12
|
+
* @durable class=config owner=backup-orchestrator
|
|
13
|
+
* write="the orchestrator inserts one row per seed id the first time that
|
|
14
|
+
* seed is created (or found already created); never updated"
|
|
15
|
+
* retention="none — one tiny row per seed ever made; deleting it lets the
|
|
16
|
+
* seed be re-created once more on the next boot"
|
|
17
|
+
*/
|
|
18
|
+
export declare const BACKUP_SEED_MARKERS_COLLECTION = "backup_seed_markers";
|
|
19
|
+
type Store = Pick<ISettingsStoreProvider, "declareCollection" | "query" | "insert">;
|
|
20
|
+
/** The slice of the marker store a seed needs. */
|
|
21
|
+
export interface SeedMarkers {
|
|
22
|
+
has(seedId: string): Promise<boolean>;
|
|
23
|
+
mark(seedId: string): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare class BackupSeedMarkerStore implements SeedMarkers {
|
|
26
|
+
private readonly store;
|
|
27
|
+
private readonly now;
|
|
28
|
+
private declared;
|
|
29
|
+
constructor(store: Store, now?: () => number);
|
|
30
|
+
private ensureDeclared;
|
|
31
|
+
has(seedId: string): Promise<boolean>;
|
|
32
|
+
mark(seedId: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/builtins/calendars/calendar-color.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { lr as BaseAddon, p as CalendarPreferencesSchema, tt as calendarsCapability } from "../../dist-
|
|
1
|
+
import { lr as BaseAddon, p as CalendarPreferencesSchema, tt as calendarsCapability } from "../../dist-CGz9u2HD.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/builtins/calendars/calendar-color.ts
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
7
|
let zod = require("zod");
|
|
8
8
|
let _camstack_types_node = require("@camstack/types/node");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Jn as buildFfmpegArgs, Ln as streamCatalogCapability, Mn as snapshotCapability, Mr as hydrateSchema, P as MOTION_CLOSE_AFTER_MS, Tr as createEvent, an as motionCapability, ar as DeviceFeature, b as DERIVED_CAMERA_SILENCED_CAP_NAMES, cr as errMsg, ht as declarationOwnerNodeId, i as BaseDevice, lr as BaseAddon, nn as memoizePinnedFfmpeg, nt as cameraGridLayoutCapability, sr as DeviceType, ti as EventCategory, x as DeclaredDevices } from "../../dist-
|
|
1
|
+
import { Jn as buildFfmpegArgs, Ln as streamCatalogCapability, Mn as snapshotCapability, Mr as hydrateSchema, P as MOTION_CLOSE_AFTER_MS, Tr as createEvent, an as motionCapability, ar as DeviceFeature, b as DERIVED_CAMERA_SILENCED_CAP_NAMES, cr as errMsg, ht as declarationOwnerNodeId, i as BaseDevice, lr as BaseAddon, nn as memoizePinnedFfmpeg, nt as cameraGridLayoutCapability, sr as DeviceType, ti as EventCategory, x as DeclaredDevices } from "../../dist-CGz9u2HD.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { FfmpegProcess } from "@camstack/types/node";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
7
|
-
const require_composition_sources = require("../../composition-sources-
|
|
6
|
+
const require_dist = require("../../dist-K3WFop9Q.js");
|
|
7
|
+
const require_composition_sources = require("../../composition-sources-60tuHQ9N.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/builtins/shared/device-state-changed.ts
|
|
10
10
|
/** Structural narrowing helper for untrusted bus payloads. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as buildCapabilityLookup, $n as compositionItemFieldPath, At as expressionContainsBuiltinCall, Dt as evaluateCompositionField, Qn as compositionFeatureEnabled, Tr as createEvent, Xn as composedDeviceRef, Yn as cloneStatefulExpressionMemory, Zn as composedDeviceStableId, at as compositionFieldKey, cr as errMsg, er as compositionSliceKey, fn as planComposition, i as BaseDevice, ir as toExpressionValue, it as composerCapability, l as COMPOSED_ITEM_FIXED_FIELDS, lr as BaseAddon, nr as createStatefulExpressionMemory, qn as COMPOSER_ADDON_ID, rr as disarmRoseMemory, sr as DeviceType, t as ALL_CAPABILITY_DEFINITIONS, ti as EventCategory, tr as compositionSourceKey, x as DeclaredDevices } from "../../dist-
|
|
2
|
-
import { n as normalizedNativeOwner } from "../../composition-sources-
|
|
1
|
+
import { $ as buildCapabilityLookup, $n as compositionItemFieldPath, At as expressionContainsBuiltinCall, Dt as evaluateCompositionField, Qn as compositionFeatureEnabled, Tr as createEvent, Xn as composedDeviceRef, Yn as cloneStatefulExpressionMemory, Zn as composedDeviceStableId, at as compositionFieldKey, cr as errMsg, er as compositionSliceKey, fn as planComposition, i as BaseDevice, ir as toExpressionValue, it as composerCapability, l as COMPOSED_ITEM_FIXED_FIELDS, lr as BaseAddon, nr as createStatefulExpressionMemory, qn as COMPOSER_ADDON_ID, rr as disarmRoseMemory, sr as DeviceType, t as ALL_CAPABILITY_DEFINITIONS, ti as EventCategory, tr as compositionSourceKey, x as DeclaredDevices } from "../../dist-CGz9u2HD.mjs";
|
|
2
|
+
import { n as normalizedNativeOwner } from "../../composition-sources-gxVpghXh.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/builtins/shared/device-state-changed.ts
|
|
5
5
|
/** Structural narrowing helper for untrusted bus payloads. */
|