@camstack/types 1.2.379 → 1.2.380
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/addon.d.ts +1 -0
- package/dist/addon.js +57 -2
- package/dist/addon.mjs +5 -3
- package/dist/capabilities/caller-stamp.d.ts +12 -0
- package/dist/capabilities/index.d.ts +7 -2
- package/dist/capabilities/record-entries.cap.d.ts +84 -0
- package/dist/capabilities/records.cap.d.ts +399 -0
- package/dist/capabilities/storage-admin.cap.d.ts +246 -0
- package/dist/client.js +6 -0
- package/dist/client.mjs +6 -0
- package/dist/generated/addon-api.d.ts +177 -0
- package/dist/generated/cap-input-defaults.d.ts +1 -1
- package/dist/generated/capability-router-map.d.ts +8 -2
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +2 -2
- package/dist/generated/system-proxy.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +685 -2
- package/dist/index.mjs +617 -3
- package/dist/interfaces/addon.d.ts +13 -0
- package/dist/interfaces/event-bus.d.ts +32 -3
- package/dist/interfaces/storage.d.ts +1 -1
- package/dist/records/constants.d.ts +23 -0
- package/dist/records/entry-kind.d.ts +31 -0
- package/dist/records/errors.d.ts +81 -0
- package/dist/records/index.d.ts +6 -0
- package/dist/records/record-kind.d.ts +144 -0
- package/dist/records/records-access.d.ts +153 -0
- package/dist/records/secret-paths.d.ts +52 -0
- package/dist/{sleep-DQYi915G.js → sleep-CIGOw58l.js} +1503 -298
- package/dist/{sleep-D-Q2_Mcd.mjs → sleep-WsrozGDL.mjs} +999 -112
- package/package.json +1 -1
|
@@ -162,7 +162,7 @@ function collectKeychainStoredKeys(schema) {
|
|
|
162
162
|
return keys;
|
|
163
163
|
}
|
|
164
164
|
function walkKeychainField(field, out) {
|
|
165
|
-
if (!isRecord$
|
|
165
|
+
if (!isRecord$5(field)) return;
|
|
166
166
|
const type = field["type"];
|
|
167
167
|
const key = field["key"];
|
|
168
168
|
const isSecret = type === "password" || field["secret"] === true;
|
|
@@ -187,21 +187,21 @@ function schemaDeclaresAnyField(schema) {
|
|
|
187
187
|
for (const section of sectionsOf(schema)) if (fieldsOf(section).length > 0) return true;
|
|
188
188
|
return false;
|
|
189
189
|
}
|
|
190
|
-
function isRecord$
|
|
190
|
+
function isRecord$5(value) {
|
|
191
191
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
192
192
|
}
|
|
193
193
|
function sectionsOf(schema) {
|
|
194
|
-
if (!isRecord$
|
|
194
|
+
if (!isRecord$5(schema)) return [];
|
|
195
195
|
const sections = schema["sections"];
|
|
196
196
|
return Array.isArray(sections) ? sections : [];
|
|
197
197
|
}
|
|
198
198
|
function fieldsOf(node) {
|
|
199
|
-
if (!isRecord$
|
|
199
|
+
if (!isRecord$5(node)) return [];
|
|
200
200
|
const fields = node["fields"];
|
|
201
201
|
return Array.isArray(fields) ? fields : [];
|
|
202
202
|
}
|
|
203
203
|
function walkField(field, out) {
|
|
204
|
-
if (!isRecord$
|
|
204
|
+
if (!isRecord$5(field)) return;
|
|
205
205
|
const type = field["type"];
|
|
206
206
|
const key = field["key"];
|
|
207
207
|
if ((type === "password" || field["secret"] === true) && typeof key === "string" && key.length > 0) out.add(key);
|
|
@@ -241,7 +241,7 @@ function walkField(field, out) {
|
|
|
241
241
|
var SECRET_CLEAR = { $secretClear: true };
|
|
242
242
|
/** The `'***'` token D634 redaction writes for non-admins. */
|
|
243
243
|
var LEGACY_DEVICE_REDACTION = "***";
|
|
244
|
-
function isRecord$
|
|
244
|
+
function isRecord$4(value) {
|
|
245
245
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
246
246
|
}
|
|
247
247
|
function makeSecretMarker(ref) {
|
|
@@ -252,19 +252,19 @@ function makeSecretMarker(ref) {
|
|
|
252
252
|
}
|
|
253
253
|
/** A stored marker: an object whose `$secret` is a non-empty string. */
|
|
254
254
|
function isSecretMarker(value) {
|
|
255
|
-
if (!isRecord$
|
|
255
|
+
if (!isRecord$4(value)) return false;
|
|
256
256
|
const ref = value["$secret"];
|
|
257
257
|
return typeof ref === "string" && ref.length > 0;
|
|
258
258
|
}
|
|
259
259
|
/** Anything carrying a `$secret` key — a stored marker or a UI view of one. */
|
|
260
260
|
function isSecretMarkerLike(value) {
|
|
261
|
-
return isRecord$
|
|
261
|
+
return isRecord$4(value) && Object.prototype.hasOwnProperty.call(value, "$secret");
|
|
262
262
|
}
|
|
263
263
|
function isSecretClear(value) {
|
|
264
|
-
return isRecord$
|
|
264
|
+
return isRecord$4(value) && value["$secretClear"] === true;
|
|
265
265
|
}
|
|
266
266
|
function isSecretFieldView(value) {
|
|
267
|
-
return isRecord$
|
|
267
|
+
return isRecord$4(value) && value["set"] === true && isSecretMarkerLike(value);
|
|
268
268
|
}
|
|
269
269
|
/**
|
|
270
270
|
* The UI view of a stored secret field value: a marker becomes "set", inline
|
|
@@ -1018,7 +1018,7 @@ var KeychainWriteRefusedError = class extends Error {
|
|
|
1018
1018
|
}
|
|
1019
1019
|
};
|
|
1020
1020
|
var KEEP = { kind: "keep" };
|
|
1021
|
-
function isRecord$
|
|
1021
|
+
function isRecord$3(value) {
|
|
1022
1022
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1023
1023
|
}
|
|
1024
1024
|
function defaultMintId() {
|
|
@@ -1031,7 +1031,7 @@ function collectSecretMarkerRefs(value, out = []) {
|
|
|
1031
1031
|
return out;
|
|
1032
1032
|
}
|
|
1033
1033
|
if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
|
|
1034
|
-
else if (isRecord$
|
|
1034
|
+
else if (isRecord$3(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
|
|
1035
1035
|
return out;
|
|
1036
1036
|
}
|
|
1037
1037
|
async function storedValueEquals(secrets, marker, candidate) {
|
|
@@ -1086,7 +1086,7 @@ function rowId(row, idKey) {
|
|
|
1086
1086
|
return null;
|
|
1087
1087
|
}
|
|
1088
1088
|
async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
1089
|
-
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$
|
|
1089
|
+
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$3) : [];
|
|
1090
1090
|
if (!Array.isArray(incoming)) {
|
|
1091
1091
|
ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
|
|
1092
1092
|
return {
|
|
@@ -1102,7 +1102,7 @@ async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
|
1102
1102
|
const kept = /* @__PURE__ */ new Set();
|
|
1103
1103
|
const rows = [];
|
|
1104
1104
|
for (const row of incoming) {
|
|
1105
|
-
if (!isRecord$
|
|
1105
|
+
if (!isRecord$3(row)) {
|
|
1106
1106
|
rows.push(row);
|
|
1107
1107
|
continue;
|
|
1108
1108
|
}
|
|
@@ -1127,7 +1127,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
1127
1127
|
case "leaf": return writeLeaf(ctx, incoming, stored, fieldPath);
|
|
1128
1128
|
case "array": return writeArray(ctx, node, incoming, stored, fieldPath);
|
|
1129
1129
|
case "object": {
|
|
1130
|
-
if (!isRecord$
|
|
1130
|
+
if (!isRecord$3(incoming)) {
|
|
1131
1131
|
if (incoming === void 0) return KEEP;
|
|
1132
1132
|
ctx.deletes.push(...collectSecretMarkerRefs(stored));
|
|
1133
1133
|
return {
|
|
@@ -1135,7 +1135,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
1135
1135
|
value: incoming
|
|
1136
1136
|
};
|
|
1137
1137
|
}
|
|
1138
|
-
const storedObj = isRecord$
|
|
1138
|
+
const storedObj = isRecord$3(stored) ? stored : {};
|
|
1139
1139
|
return {
|
|
1140
1140
|
kind: "value",
|
|
1141
1141
|
value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
|
|
@@ -1258,7 +1258,7 @@ async function resolveSecretMarkers(value, secrets, options = {}) {
|
|
|
1258
1258
|
value: items
|
|
1259
1259
|
};
|
|
1260
1260
|
}
|
|
1261
|
-
if (isRecord$
|
|
1261
|
+
if (isRecord$3(v)) {
|
|
1262
1262
|
const out = {};
|
|
1263
1263
|
for (const [k, child] of Object.entries(v)) {
|
|
1264
1264
|
const s = substitute(child);
|
|
@@ -1292,7 +1292,7 @@ var SecretOverwriteRefusedError = class extends Error {
|
|
|
1292
1292
|
this.name = "SecretOverwriteRefusedError";
|
|
1293
1293
|
}
|
|
1294
1294
|
};
|
|
1295
|
-
function isRecord(value) {
|
|
1295
|
+
function isRecord$2(value) {
|
|
1296
1296
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1297
1297
|
}
|
|
1298
1298
|
function resolvedValue(pass, marker) {
|
|
@@ -1321,7 +1321,7 @@ function inArray(pass, incoming, stored) {
|
|
|
1321
1321
|
return incoming.map((item, index) => {
|
|
1322
1322
|
const twin = stored[index];
|
|
1323
1323
|
if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
|
|
1324
|
-
if (isRecord(item) && isRecord(twin)) return inArrayRow(pass, item, twin);
|
|
1324
|
+
if (isRecord$2(item) && isRecord$2(twin)) return inArrayRow(pass, item, twin);
|
|
1325
1325
|
if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
|
|
1326
1326
|
return item;
|
|
1327
1327
|
});
|
|
@@ -1332,7 +1332,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
1332
1332
|
const twin = stored[key];
|
|
1333
1333
|
if (isSecretMarker(twin)) {
|
|
1334
1334
|
if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
|
|
1335
|
-
} else if (isRecord(value) && isRecord(twin)) out[key] = inArrayRow(pass, value, twin);
|
|
1335
|
+
} else if (isRecord$2(value) && isRecord$2(twin)) out[key] = inArrayRow(pass, value, twin);
|
|
1336
1336
|
else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
|
|
1337
1337
|
}
|
|
1338
1338
|
return out;
|
|
@@ -1340,7 +1340,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
1340
1340
|
async function walk(pass, incoming, stored) {
|
|
1341
1341
|
if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
|
|
1342
1342
|
if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
|
|
1343
|
-
if (!isRecord(incoming) || !isRecord(stored)) return incoming;
|
|
1343
|
+
if (!isRecord$2(incoming) || !isRecord$2(stored)) return incoming;
|
|
1344
1344
|
const out = { ...incoming };
|
|
1345
1345
|
for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
|
|
1346
1346
|
return out;
|
|
@@ -1371,7 +1371,7 @@ async function restoreUnchangedSecrets(input) {
|
|
|
1371
1371
|
function isJsonEqual(a, b) {
|
|
1372
1372
|
if (Object.is(a, b)) return true;
|
|
1373
1373
|
if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
|
|
1374
|
-
if (isRecord(a) && isRecord(b)) {
|
|
1374
|
+
if (isRecord$2(a) && isRecord$2(b)) {
|
|
1375
1375
|
const keys = Object.keys(a);
|
|
1376
1376
|
if (keys.length !== Object.keys(b).length) return false;
|
|
1377
1377
|
return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
|
|
@@ -1395,7 +1395,7 @@ function markerKeysOf(blob, owner) {
|
|
|
1395
1395
|
}
|
|
1396
1396
|
function nodeFromStored(value, owner) {
|
|
1397
1397
|
if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
|
|
1398
|
-
if (!isRecord(value)) return null;
|
|
1398
|
+
if (!isRecord$2(value)) return null;
|
|
1399
1399
|
const children = /* @__PURE__ */ new Map();
|
|
1400
1400
|
for (const [key, child] of Object.entries(value)) {
|
|
1401
1401
|
const node = nodeFromStored(child, owner);
|
|
@@ -3122,183 +3122,1158 @@ async function resolveSecretViewsIn(args, secrets) {
|
|
|
3122
3122
|
return swap(args).value;
|
|
3123
3123
|
}
|
|
3124
3124
|
//#endregion
|
|
3125
|
-
//#region src/
|
|
3126
|
-
/**
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
"
|
|
3135
|
-
"
|
|
3136
|
-
"low"
|
|
3125
|
+
//#region src/records/constants.ts
|
|
3126
|
+
/** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
|
|
3127
|
+
/** The files a kind may live in. `history` is device-history's (D850), never records. */
|
|
3128
|
+
var RECORD_DATABASES = ["settings", "events"];
|
|
3129
|
+
/** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
|
|
3130
|
+
var RECORD_CLASSES = [
|
|
3131
|
+
"config",
|
|
3132
|
+
"ledger",
|
|
3133
|
+
"audit",
|
|
3134
|
+
"mirror",
|
|
3135
|
+
"ephemeral"
|
|
3137
3136
|
];
|
|
3137
|
+
var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
|
|
3138
|
+
var RECORD_MAX_DATA_BYTES = 1024 * 1024;
|
|
3139
|
+
var RECORD_ID_MAX_LENGTH = 256;
|
|
3140
|
+
var RECORD_BATCH_MAX = 1e3;
|
|
3141
|
+
var RECORD_BATCH_MAX_BYTES = 4 * 1024 * 1024;
|
|
3142
|
+
var RECORD_QUERY_MAX = 1e3;
|
|
3143
|
+
/** Rows one DELETE statement removes before the serving thread yields. */
|
|
3144
|
+
var RECORD_DELETE_BATCH = 5e3;
|
|
3145
|
+
/** A kind in the `settings` file may not bound itself above this (D447: high volume is `events`). */
|
|
3146
|
+
var RECORD_SETTINGS_MAX_ROWS = 5e4;
|
|
3147
|
+
var RECORD_MAX_INDEXES = 8;
|
|
3148
|
+
var RECORD_MAX_INDEX_FIELDS = 4;
|
|
3149
|
+
/** The engine's TTL sweep cadence. */
|
|
3150
|
+
var RECORD_SWEEP_INTERVAL_MS = 10 * 6e4;
|
|
3151
|
+
/** The `Column`-free proof prefix: a ref collection for a kind's secret fields. */
|
|
3152
|
+
var RECORD_SECRET_COLLECTION_PREFIX = "records:";
|
|
3153
|
+
//#endregion
|
|
3154
|
+
//#region src/records/errors.ts
|
|
3138
3155
|
/**
|
|
3139
|
-
*
|
|
3156
|
+
* The named failures of `ctx.records` (D881).
|
|
3140
3157
|
*
|
|
3141
|
-
*
|
|
3142
|
-
*
|
|
3143
|
-
*
|
|
3144
|
-
*
|
|
3145
|
-
*
|
|
3146
|
-
* "the lowest AVAILABLE native rung" (D537).
|
|
3158
|
+
* A records call crosses a worker thread, a UDS channel and a tRPC router, and
|
|
3159
|
+
* an error class does not survive any of them - only its message does. So
|
|
3160
|
+
* every message STARTS with a stable code, `records/<code>: <detail>`, and
|
|
3161
|
+
* {@link recordsErrorFromMessage} rebuilds the typed class on the caller's side.
|
|
3162
|
+
* A failed read is never `[]` or `undefined`: it throws one of these.
|
|
3147
3163
|
*/
|
|
3148
|
-
|
|
3149
|
-
var
|
|
3150
|
-
"
|
|
3151
|
-
"
|
|
3152
|
-
"
|
|
3153
|
-
"
|
|
3154
|
-
"
|
|
3155
|
-
"
|
|
3156
|
-
"
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3164
|
+
/** Every code a records failure carries. */
|
|
3165
|
+
var RECORDS_ERROR_CODES = [
|
|
3166
|
+
"rev-conflict",
|
|
3167
|
+
"too-large",
|
|
3168
|
+
"unindexed-filter",
|
|
3169
|
+
"filter-required",
|
|
3170
|
+
"unknown-kind",
|
|
3171
|
+
"not-found",
|
|
3172
|
+
"unique-violation",
|
|
3173
|
+
"plaintext-secret",
|
|
3174
|
+
"foreign-marker",
|
|
3175
|
+
"secret-unavailable",
|
|
3176
|
+
"invalid-record",
|
|
3177
|
+
"declaration-refused",
|
|
3178
|
+
"adoption-pending",
|
|
3179
|
+
"no-caller",
|
|
3180
|
+
"batch-too-large"
|
|
3181
|
+
];
|
|
3182
|
+
var PREFIX = "records/";
|
|
3183
|
+
/** The base of every records failure. `detail` is the human part of the message. */
|
|
3184
|
+
var RecordsError = class extends Error {
|
|
3185
|
+
code;
|
|
3186
|
+
detail;
|
|
3187
|
+
constructor(code, detail) {
|
|
3188
|
+
super(`${PREFIX}${code}: ${detail}`);
|
|
3189
|
+
this.name = "RecordsError";
|
|
3190
|
+
this.code = code;
|
|
3191
|
+
this.detail = detail;
|
|
3192
|
+
}
|
|
3193
|
+
};
|
|
3194
|
+
/** A write guarded by `ifRev` found another revision (or an existing row for `ifRev: 0`). */
|
|
3195
|
+
var RevConflictError = class extends RecordsError {
|
|
3196
|
+
constructor(detail) {
|
|
3197
|
+
super("rev-conflict", detail);
|
|
3198
|
+
this.name = "RevConflictError";
|
|
3199
|
+
}
|
|
3200
|
+
};
|
|
3201
|
+
/** `data` exceeds the kind's `maxDataBytes`. Bytes are never record fields (D613). */
|
|
3202
|
+
var RecordTooLargeError = class extends RecordsError {
|
|
3203
|
+
constructor(detail) {
|
|
3204
|
+
super("too-large", detail);
|
|
3205
|
+
this.name = "RecordTooLargeError";
|
|
3206
|
+
}
|
|
3207
|
+
};
|
|
3208
|
+
/** A filter, order or aggregate names a field no declared index serves. */
|
|
3209
|
+
var UnindexedFilterError = class extends RecordsError {
|
|
3210
|
+
constructor(detail) {
|
|
3211
|
+
super("unindexed-filter", detail);
|
|
3212
|
+
this.name = "UnindexedFilterError";
|
|
3213
|
+
}
|
|
3214
|
+
};
|
|
3215
|
+
/** A bulk delete with no predicate at all. */
|
|
3216
|
+
var FilterRequiredError = class extends RecordsError {
|
|
3217
|
+
constructor(detail) {
|
|
3218
|
+
super("filter-required", detail);
|
|
3219
|
+
this.name = "FilterRequiredError";
|
|
3220
|
+
}
|
|
3221
|
+
};
|
|
3222
|
+
/** The caller declared no such kind (another addon's kind is indistinguishable from none). */
|
|
3223
|
+
var UnknownRecordKindError = class extends RecordsError {
|
|
3224
|
+
constructor(detail) {
|
|
3225
|
+
super("unknown-kind", detail);
|
|
3226
|
+
this.name = "UnknownRecordKindError";
|
|
3227
|
+
}
|
|
3228
|
+
};
|
|
3229
|
+
var RecordNotFoundError = class extends RecordsError {
|
|
3230
|
+
constructor(detail) {
|
|
3231
|
+
super("not-found", detail);
|
|
3232
|
+
this.name = "RecordNotFoundError";
|
|
3233
|
+
}
|
|
3234
|
+
};
|
|
3235
|
+
/** A unique index refused the write. */
|
|
3236
|
+
var RecordUniqueViolationError = class extends RecordsError {
|
|
3237
|
+
constructor(detail) {
|
|
3238
|
+
super("unique-violation", detail);
|
|
3239
|
+
this.name = "RecordUniqueViolationError";
|
|
3240
|
+
}
|
|
3241
|
+
};
|
|
3242
|
+
/** A secret field held a plain string where only a keychain marker may be stored. */
|
|
3243
|
+
var PlaintextSecretError = class extends RecordsError {
|
|
3244
|
+
constructor(detail) {
|
|
3245
|
+
super("plaintext-secret", detail);
|
|
3246
|
+
this.name = "PlaintextSecretError";
|
|
3247
|
+
}
|
|
3248
|
+
};
|
|
3249
|
+
/** A marker whose ref is not the row's own (the D878 rule). */
|
|
3250
|
+
var ForeignSecretMarkerError = class extends RecordsError {
|
|
3251
|
+
constructor(detail) {
|
|
3252
|
+
super("foreign-marker", detail);
|
|
3253
|
+
this.name = "ForeignSecretMarkerError";
|
|
3254
|
+
}
|
|
3255
|
+
};
|
|
3256
|
+
/** The keychain could not store or serve a value: explicit, never an empty string. */
|
|
3257
|
+
var RecordSecretUnavailableError = class extends RecordsError {
|
|
3258
|
+
constructor(detail) {
|
|
3259
|
+
super("secret-unavailable", detail);
|
|
3260
|
+
this.name = "RecordSecretUnavailableError";
|
|
3261
|
+
}
|
|
3262
|
+
};
|
|
3263
|
+
var InvalidRecordError = class extends RecordsError {
|
|
3264
|
+
constructor(detail) {
|
|
3265
|
+
super("invalid-record", detail);
|
|
3266
|
+
this.name = "InvalidRecordError";
|
|
3267
|
+
}
|
|
3268
|
+
};
|
|
3269
|
+
/** A kind declaration the engine refuses (non-additive change, bad shape, wrong file). */
|
|
3270
|
+
var DeclarationRefusedError = class extends RecordsError {
|
|
3271
|
+
constructor(detail) {
|
|
3272
|
+
super("declaration-refused", detail);
|
|
3273
|
+
this.name = "DeclarationRefusedError";
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
/** A kind is empty while the legacy table it adopts from still holds rows. */
|
|
3277
|
+
var AdoptionPendingError = class extends RecordsError {
|
|
3278
|
+
constructor(detail) {
|
|
3279
|
+
super("adoption-pending", detail);
|
|
3280
|
+
this.name = "AdoptionPendingError";
|
|
3281
|
+
}
|
|
3282
|
+
};
|
|
3283
|
+
var NoCallerError = class extends RecordsError {
|
|
3284
|
+
constructor(detail) {
|
|
3285
|
+
super("no-caller", detail);
|
|
3286
|
+
this.name = "NoCallerError";
|
|
3287
|
+
}
|
|
3288
|
+
};
|
|
3289
|
+
var BatchTooLargeError = class extends RecordsError {
|
|
3290
|
+
constructor(detail) {
|
|
3291
|
+
super("batch-too-large", detail);
|
|
3292
|
+
this.name = "BatchTooLargeError";
|
|
3293
|
+
}
|
|
3294
|
+
};
|
|
3295
|
+
var FACTORIES = {
|
|
3296
|
+
"rev-conflict": (d) => new RevConflictError(d),
|
|
3297
|
+
"too-large": (d) => new RecordTooLargeError(d),
|
|
3298
|
+
"unindexed-filter": (d) => new UnindexedFilterError(d),
|
|
3299
|
+
"filter-required": (d) => new FilterRequiredError(d),
|
|
3300
|
+
"unknown-kind": (d) => new UnknownRecordKindError(d),
|
|
3301
|
+
"not-found": (d) => new RecordNotFoundError(d),
|
|
3302
|
+
"unique-violation": (d) => new RecordUniqueViolationError(d),
|
|
3303
|
+
"plaintext-secret": (d) => new PlaintextSecretError(d),
|
|
3304
|
+
"foreign-marker": (d) => new ForeignSecretMarkerError(d),
|
|
3305
|
+
"secret-unavailable": (d) => new RecordSecretUnavailableError(d),
|
|
3306
|
+
"invalid-record": (d) => new InvalidRecordError(d),
|
|
3307
|
+
"declaration-refused": (d) => new DeclarationRefusedError(d),
|
|
3308
|
+
"adoption-pending": (d) => new AdoptionPendingError(d),
|
|
3309
|
+
"no-caller": (d) => new NoCallerError(d),
|
|
3310
|
+
"batch-too-large": (d) => new BatchTooLargeError(d)
|
|
3311
|
+
};
|
|
3312
|
+
function isCode(value) {
|
|
3313
|
+
return RECORDS_ERROR_CODES.some((code) => code === value);
|
|
3244
3314
|
}
|
|
3245
3315
|
/**
|
|
3246
|
-
*
|
|
3247
|
-
*
|
|
3248
|
-
* `camStreamId` like `native:main` — as opposed to the public profile alias
|
|
3249
|
-
* {@link makeProfileBrokerId}. Used to resolve a source's restream endpoint
|
|
3250
|
-
* (e.g. routing a transcode's ffmpeg input through the broker so it rides the
|
|
3251
|
-
* single source dial instead of opening a second camera connection).
|
|
3316
|
+
* Rebuild the typed error from a message that crossed a wire; `null` when the
|
|
3317
|
+
* message is not a records failure.
|
|
3252
3318
|
*/
|
|
3253
|
-
function
|
|
3254
|
-
return
|
|
3319
|
+
function recordsErrorFromMessage(message) {
|
|
3320
|
+
if (!message.startsWith(PREFIX)) return null;
|
|
3321
|
+
const colon = message.indexOf(": ");
|
|
3322
|
+
if (colon < 0) return null;
|
|
3323
|
+
const code = message.slice(8, colon);
|
|
3324
|
+
if (!isCode(code)) return null;
|
|
3325
|
+
return FACTORIES[code](message.slice(colon + 2));
|
|
3326
|
+
}
|
|
3327
|
+
/** The records failure inside any thrown value (a wrapped tRPC error included), or the value. */
|
|
3328
|
+
function asRecordsError(err) {
|
|
3329
|
+
if (err instanceof RecordsError) return err;
|
|
3330
|
+
if (err instanceof Error) {
|
|
3331
|
+
const typed = recordsErrorFromMessage(err.message);
|
|
3332
|
+
if (typed !== null) return typed;
|
|
3333
|
+
}
|
|
3334
|
+
return err;
|
|
3255
3335
|
}
|
|
3336
|
+
//#endregion
|
|
3337
|
+
//#region src/device/zod-secret.ts
|
|
3256
3338
|
/**
|
|
3257
|
-
*
|
|
3258
|
-
*
|
|
3259
|
-
*
|
|
3260
|
-
*
|
|
3261
|
-
*
|
|
3339
|
+
* Secret declaration on a Zod config schema (D783).
|
|
3340
|
+
*
|
|
3341
|
+
* A field is a secret because its schema SAYS so — `.meta({ secret: true })`,
|
|
3342
|
+
* spelled {@link SECRET_META} — never because its key looks like a credential.
|
|
3343
|
+
* It is the Zod twin of `secret: true` / `type: 'password'` on a config-UI
|
|
3344
|
+
* field (`isSecretConfigField`), and every consumer that treats secrets
|
|
3345
|
+
* specially reads it: the settings form (`zodEntriesToConfigUI`), the paths a
|
|
3346
|
+
* device advertises at `registerDevice` (`secretConfigPaths`, which the
|
|
3347
|
+
* non-admin redaction withholds at any depth), and the keychain later.
|
|
3348
|
+
*
|
|
3349
|
+
* Zod keeps `.meta()` in `z.globalRegistry`, which lives on `globalThis`, so a
|
|
3350
|
+
* declaration made by an addon's own copy of zod is visible here.
|
|
3262
3351
|
*/
|
|
3263
|
-
function parseProfileBrokerId(brokerId) {
|
|
3264
|
-
const slash = brokerId.indexOf("/");
|
|
3265
|
-
if (slash <= 0) return null;
|
|
3266
|
-
const idPart = brokerId.slice(0, slash);
|
|
3267
|
-
const profilePart = brokerId.slice(slash + 1);
|
|
3268
|
-
if (!/^\d+$/.test(idPart)) return null;
|
|
3269
|
-
const parsed = CamProfileSchema.safeParse(profilePart);
|
|
3270
|
-
if (!parsed.success) return null;
|
|
3271
|
-
return {
|
|
3272
|
-
deviceId: Number(idPart),
|
|
3273
|
-
profile: parsed.data
|
|
3274
|
-
};
|
|
3275
|
-
}
|
|
3276
3352
|
/**
|
|
3277
|
-
*
|
|
3278
|
-
* (`sourceCamStreamId != null`), DEDUPED by physical source so the same
|
|
3279
|
-
* camera encoder is never subscribed/recorded twice, ordered high→mid→low.
|
|
3280
|
-
* Optionally scoped to one `deviceId`. Pure; never mutates the input.
|
|
3353
|
+
* `{ secret: true }` — the one spelling of "this field holds a credential".
|
|
3281
3354
|
*
|
|
3282
|
-
*
|
|
3283
|
-
*
|
|
3284
|
-
*
|
|
3355
|
+
* Addons write the LITERAL `.meta({ secret: true })` rather than importing
|
|
3356
|
+
* this constant: an addon running against an older `@camstack/types` would
|
|
3357
|
+
* otherwise call `.meta(undefined)`, which in zod v4 is the metadata GETTER
|
|
3358
|
+
* and returns no schema at all.
|
|
3285
3359
|
*/
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3360
|
+
var SECRET_META = { secret: true };
|
|
3361
|
+
function defOf(schema) {
|
|
3362
|
+
return schema._zod?.def ?? {};
|
|
3363
|
+
}
|
|
3364
|
+
function declaredHere(schema) {
|
|
3365
|
+
return zod.z.globalRegistry.get(schema)?.secret === true;
|
|
3366
|
+
}
|
|
3367
|
+
/** Wrapper kinds whose `innerType` is the field itself. */
|
|
3368
|
+
var WRAPPERS = new Set([
|
|
3369
|
+
"optional",
|
|
3370
|
+
"nullable",
|
|
3371
|
+
"default",
|
|
3372
|
+
"prefault",
|
|
3373
|
+
"catch",
|
|
3374
|
+
"readonly",
|
|
3375
|
+
"nonoptional"
|
|
3376
|
+
]);
|
|
3377
|
+
/**
|
|
3378
|
+
* The schema layers that make up ONE field: the schema itself and every
|
|
3379
|
+
* wrapper below it (optional / default / nullable / readonly / catch), plus
|
|
3380
|
+
* both sides of a pipe (`z.preprocess` puts the real schema on `out`,
|
|
3381
|
+
* `.transform` on `in`).
|
|
3382
|
+
*/
|
|
3383
|
+
function layersOf(schema) {
|
|
3289
3384
|
const out = [];
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
if (
|
|
3294
|
-
seenSources.add(src);
|
|
3385
|
+
const queue = [schema];
|
|
3386
|
+
while (queue.length > 0) {
|
|
3387
|
+
const s = queue.shift();
|
|
3388
|
+
if (!s || out.includes(s)) continue;
|
|
3295
3389
|
out.push(s);
|
|
3390
|
+
const def = defOf(s);
|
|
3391
|
+
if (def.type !== void 0 && WRAPPERS.has(def.type) && def.innerType) queue.push(def.innerType);
|
|
3392
|
+
if (def.type === "pipe") {
|
|
3393
|
+
if (def.in) queue.push(def.in);
|
|
3394
|
+
if (def.out) queue.push(def.out);
|
|
3395
|
+
}
|
|
3296
3396
|
}
|
|
3297
3397
|
return out;
|
|
3298
3398
|
}
|
|
3399
|
+
/** True when any layer of this field declares `.meta({ secret: true })`. */
|
|
3400
|
+
function isZodSecret(schema) {
|
|
3401
|
+
return layersOf(schema).some(declaredHere);
|
|
3402
|
+
}
|
|
3299
3403
|
/**
|
|
3300
|
-
*
|
|
3301
|
-
*
|
|
3404
|
+
* Every declared secret path in a config schema: dotted keys, `[]` for "each
|
|
3405
|
+
* element of this array" (`connection.password`, `rows[].token`). A declared
|
|
3406
|
+
* object or array is reported as one path and not descended into — everything
|
|
3407
|
+
* under it is secret.
|
|
3408
|
+
*/
|
|
3409
|
+
function collectZodSecretPaths(schema, prefix = "") {
|
|
3410
|
+
if (isZodSecret(schema)) return prefix.length > 0 ? [prefix] : [];
|
|
3411
|
+
const paths = [];
|
|
3412
|
+
for (const layer of layersOf(schema)) {
|
|
3413
|
+
const def = defOf(layer);
|
|
3414
|
+
if (def.type === "object" && def.shape) for (const [key, child] of Object.entries(def.shape)) paths.push(...collectZodSecretPaths(child, prefix ? `${prefix}.${key}` : key));
|
|
3415
|
+
else if (def.type === "array" && def.element) paths.push(...collectZodSecretPaths(def.element, `${prefix}[]`));
|
|
3416
|
+
else if (def.type === "union" && def.options) for (const option of def.options) paths.push(...collectZodSecretPaths(option, prefix));
|
|
3417
|
+
else if (def.type === "intersection") {
|
|
3418
|
+
if (def.left) paths.push(...collectZodSecretPaths(def.left, prefix));
|
|
3419
|
+
if (def.right) paths.push(...collectZodSecretPaths(def.right, prefix));
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
return [...new Set(paths)];
|
|
3423
|
+
}
|
|
3424
|
+
//#endregion
|
|
3425
|
+
//#region src/records/secret-paths.ts
|
|
3426
|
+
/**
|
|
3427
|
+
* Secret fields of a record, addressed the way a Zod schema declares them
|
|
3428
|
+
* (`collectZodSecretPaths`): dotted keys, `[]` for "each element of this array"
|
|
3429
|
+
* (`auth.accessToken`, `headers[].value`).
|
|
3430
|
+
*
|
|
3431
|
+
* Array elements are matched by a DECLARED id key (`secretArrayKeys`:
|
|
3432
|
+
* `{ headers: 'name' }`), never by index, so reordering a list keeps every
|
|
3433
|
+
* keychain ref (the same rule as `arrayItemFieldPath`). The concrete path of a
|
|
3434
|
+
* leaf names its element: `headers[X-Api].value`.
|
|
3435
|
+
*
|
|
3436
|
+
* Pure and browser-safe. Nothing here mutates: every transform returns a new value.
|
|
3437
|
+
*/
|
|
3438
|
+
/** The array prefixes (declared form, e.g. `headers` or `a.headers`) of a path. */
|
|
3439
|
+
function parseSecretPath(path) {
|
|
3440
|
+
if (path.length === 0) throw new InvalidRecordError("an empty secret path");
|
|
3441
|
+
return path.split(".").map((raw) => {
|
|
3442
|
+
const each = raw.endsWith("[]");
|
|
3443
|
+
const key = each ? raw.slice(0, -2) : raw;
|
|
3444
|
+
if (key.length === 0) throw new InvalidRecordError(`secret path "${path}" has an empty segment`);
|
|
3445
|
+
return {
|
|
3446
|
+
key,
|
|
3447
|
+
each
|
|
3448
|
+
};
|
|
3449
|
+
});
|
|
3450
|
+
}
|
|
3451
|
+
/** The declared array prefixes of `path` that need an id key (`headers`, `a.rows`). */
|
|
3452
|
+
function secretArrayPrefixes(path) {
|
|
3453
|
+
const segments = parseSecretPath(path);
|
|
3454
|
+
const prefixes = [];
|
|
3455
|
+
const walked = [];
|
|
3456
|
+
for (const segment of segments) {
|
|
3457
|
+
walked.push(segment.key);
|
|
3458
|
+
if (segment.each) prefixes.push(walked.join("."));
|
|
3459
|
+
}
|
|
3460
|
+
return prefixes;
|
|
3461
|
+
}
|
|
3462
|
+
function isRecord$1(value) {
|
|
3463
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3464
|
+
}
|
|
3465
|
+
function elementId(element, idKey, declared, prefix) {
|
|
3466
|
+
const id = isRecord$1(element) ? element[idKey] : void 0;
|
|
3467
|
+
if (typeof id !== "string" || id.length === 0) throw new InvalidRecordError(`"${declared}": every element of "${prefix}" needs a non-empty string "${idKey}" to carry a secret`);
|
|
3468
|
+
return id;
|
|
3469
|
+
}
|
|
3470
|
+
/**
|
|
3471
|
+
* Visit every secret leaf PRESENT in `data` (an absent branch has nothing to
|
|
3472
|
+
* visit). `replace` returns the new leaf value, or {@link REMOVE_LEAF}; the
|
|
3473
|
+
* result is a new body, `data` is untouched.
|
|
3474
|
+
*/
|
|
3475
|
+
var REMOVE_LEAF = Symbol("remove-leaf");
|
|
3476
|
+
function mapAt(node, segments, index, walkedKeys, concretePrefix, declared, arrayKeys, visit) {
|
|
3477
|
+
if (!isRecord$1(node)) return node;
|
|
3478
|
+
const segment = segments[index];
|
|
3479
|
+
if (segment === void 0) return node;
|
|
3480
|
+
if (!Object.prototype.hasOwnProperty.call(node, segment.key)) return node;
|
|
3481
|
+
const child = node[segment.key];
|
|
3482
|
+
const keys = [...walkedKeys, segment.key];
|
|
3483
|
+
const last = index === segments.length - 1;
|
|
3484
|
+
if (segment.each) {
|
|
3485
|
+
if (!Array.isArray(child)) return node;
|
|
3486
|
+
const prefix = keys.join(".");
|
|
3487
|
+
const idKey = arrayKeys[prefix];
|
|
3488
|
+
if (idKey === void 0) throw new InvalidRecordError(`"${declared}": no id key declared for the array "${prefix}"`);
|
|
3489
|
+
const mapped = child.map((element) => {
|
|
3490
|
+
const id = elementId(element, idKey, declared, prefix);
|
|
3491
|
+
const concrete = `${concretePrefix}${concretePrefix.length > 0 ? "." : ""}${segment.key}[${encodeURIComponent(id)}]`;
|
|
3492
|
+
return last ? element : mapAt(element, segments, index + 1, keys, concrete, declared, arrayKeys, visit);
|
|
3493
|
+
});
|
|
3494
|
+
return {
|
|
3495
|
+
...node,
|
|
3496
|
+
[segment.key]: mapped
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
const concrete = `${concretePrefix}${concretePrefix.length > 0 ? "." : ""}${segment.key}`;
|
|
3500
|
+
if (last) {
|
|
3501
|
+
const replacement = visit({
|
|
3502
|
+
declared,
|
|
3503
|
+
concrete,
|
|
3504
|
+
value: child
|
|
3505
|
+
});
|
|
3506
|
+
if (replacement === REMOVE_LEAF) return Object.fromEntries(Object.entries(node).filter(([key]) => key !== segment.key));
|
|
3507
|
+
return {
|
|
3508
|
+
...node,
|
|
3509
|
+
[segment.key]: replacement
|
|
3510
|
+
};
|
|
3511
|
+
}
|
|
3512
|
+
return {
|
|
3513
|
+
...node,
|
|
3514
|
+
[segment.key]: mapAt(child, segments, index + 1, keys, concrete, declared, arrayKeys, visit)
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
/** Replace/remove every present secret leaf; returns a NEW body. */
|
|
3518
|
+
function mapSecretLeaves(data, paths, arrayKeys, visit) {
|
|
3519
|
+
let current = data;
|
|
3520
|
+
for (const declared of paths) current = mapAt(current, parseSecretPath(declared), 0, [], "", declared, arrayKeys, visit);
|
|
3521
|
+
return current;
|
|
3522
|
+
}
|
|
3523
|
+
/** Every present secret leaf, read-only. */
|
|
3524
|
+
function collectSecretLeaves(data, paths, arrayKeys) {
|
|
3525
|
+
const found = [];
|
|
3526
|
+
mapSecretLeaves(data, paths, arrayKeys, (leaf) => {
|
|
3527
|
+
found.push(leaf);
|
|
3528
|
+
return leaf.value;
|
|
3529
|
+
});
|
|
3530
|
+
return found;
|
|
3531
|
+
}
|
|
3532
|
+
/**
|
|
3533
|
+
* The keychain collection name a kind's secrets live under. Prefixed so a
|
|
3534
|
+
* record's refs never collide with the refs a legacy collection of the same name
|
|
3535
|
+
* already holds during an adoption.
|
|
3536
|
+
*/
|
|
3537
|
+
function recordSecretCollection(kind) {
|
|
3538
|
+
return `${RECORD_SECRET_COLLECTION_PREFIX}${kind}`;
|
|
3539
|
+
}
|
|
3540
|
+
/** The ONE ref a row's secret field may carry: the engine and the facade both build it here. */
|
|
3541
|
+
function recordSecretRef(owner, kind, rowId, concretePath) {
|
|
3542
|
+
return buildSecretRef({
|
|
3543
|
+
owner,
|
|
3544
|
+
scope: {
|
|
3545
|
+
kind: "row",
|
|
3546
|
+
collection: recordSecretCollection(kind),
|
|
3547
|
+
rowId
|
|
3548
|
+
},
|
|
3549
|
+
fieldPath: concretePath
|
|
3550
|
+
});
|
|
3551
|
+
}
|
|
3552
|
+
/** A concrete path built from a flat array item, re-exported for adoption tooling. */
|
|
3553
|
+
var recordArrayItemPath = arrayItemFieldPath;
|
|
3554
|
+
//#endregion
|
|
3555
|
+
//#region src/records/record-kind.ts
|
|
3556
|
+
/**
|
|
3557
|
+
* Record kinds (D881): the declaration an addon makes of one kind of fact, the
|
|
3558
|
+
* Zod row schema that describes it, and the helper that turns the two into the
|
|
3559
|
+
* JSON the engine stores.
|
|
3560
|
+
*
|
|
3561
|
+
* A kind is declared ONCE, next to the code that owns it, and the engine's
|
|
3562
|
+
* reconciler creates its indexes - nothing creates DDL at runtime from a write.
|
|
3563
|
+
* Everything the generic machinery needs (secret fields, the entry descriptor)
|
|
3564
|
+
* is DERIVED from the Zod schema: `.meta({ secret: true })` marks a credential,
|
|
3565
|
+
* never a field name (D879).
|
|
3566
|
+
*/
|
|
3567
|
+
/** A JSON field path: `trackId`, `auth.accessToken`. Charset-restricted: it is rendered into DDL. */
|
|
3568
|
+
var RecordFieldPathSchema = zod.z.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,63}(\.[A-Za-z_][A-Za-z0-9_]{0,63}){0,3}$/);
|
|
3569
|
+
var RecordIndexSchema = zod.z.object({
|
|
3570
|
+
name: zod.z.string().regex(/^[a-z][a-z0-9_]{0,31}$/),
|
|
3571
|
+
fields: zod.z.array(RecordFieldPathSchema).min(1).max(4),
|
|
3572
|
+
unique: zod.z.boolean().optional()
|
|
3573
|
+
}).strict();
|
|
3574
|
+
var RecordRetentionSchema = zod.z.union([
|
|
3575
|
+
zod.z.object({
|
|
3576
|
+
ttlMs: zod.z.number().int().positive(),
|
|
3577
|
+
from: zod.z.enum(["at", "write"])
|
|
3578
|
+
}).strict(),
|
|
3579
|
+
zod.z.object({
|
|
3580
|
+
maxRows: zod.z.number().int().positive().optional(),
|
|
3581
|
+
maxRowsPerDevice: zod.z.number().int().positive().optional()
|
|
3582
|
+
}).strict().refine((r) => r.maxRows !== void 0 || r.maxRowsPerDevice !== void 0, { message: "name maxRows, maxRowsPerDevice or both" }),
|
|
3583
|
+
zod.z.object({
|
|
3584
|
+
owner: zod.z.string().min(1),
|
|
3585
|
+
reason: zod.z.string().min(1)
|
|
3586
|
+
}).strict(),
|
|
3587
|
+
zod.z.object({ none: zod.z.string().min(1) }).strict()
|
|
3588
|
+
]);
|
|
3589
|
+
/** The descriptor a generic entries UI reads (D881 "generic entries"). */
|
|
3590
|
+
var EntryDescriptorSchema = zod.z.object({
|
|
3591
|
+
title: zod.z.string().min(1),
|
|
3592
|
+
/** The record body field shown as the entry's name. */
|
|
3593
|
+
nameField: zod.z.string().min(1),
|
|
3594
|
+
/** JSON Schema of the entry body; `secret: true` marks a password field. */
|
|
3595
|
+
fields: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
3596
|
+
}).strict();
|
|
3597
|
+
/** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
|
|
3598
|
+
var RecordKindDeclarationSchema = zod.z.object({
|
|
3599
|
+
database: zod.z.enum(RECORD_DATABASES).default("settings"),
|
|
3600
|
+
class: zod.z.enum(RECORD_CLASSES),
|
|
3601
|
+
writeTrigger: zod.z.string().min(1),
|
|
3602
|
+
device: zod.z.enum([
|
|
3603
|
+
"required",
|
|
3604
|
+
"optional",
|
|
3605
|
+
"none"
|
|
3606
|
+
]).default("none"),
|
|
3607
|
+
at: zod.z.enum(["required", "none"]).default("none"),
|
|
3608
|
+
indexes: zod.z.array(RecordIndexSchema).max(8).default([]),
|
|
3609
|
+
retention: RecordRetentionSchema,
|
|
3610
|
+
deviceRemoval: zod.z.enum(["delete", "none"]).default("none"),
|
|
3611
|
+
maxDataBytes: zod.z.number().int().positive().max(RECORD_MAX_DATA_BYTES).default(RECORD_DEFAULT_MAX_DATA_BYTES),
|
|
3612
|
+
/** Derived from the Zod schema; never written by hand. */
|
|
3613
|
+
secretPaths: zod.z.array(zod.z.string().min(1)).default([]),
|
|
3614
|
+
/** The id key of each array that carries a secret (`{ headers: 'name' }`). */
|
|
3615
|
+
secretArrayKeys: zod.z.record(zod.z.string(), zod.z.string()).default({}),
|
|
3616
|
+
/** The legacy table this kind adopts from; the boot guard reads it (D853: no migration code). */
|
|
3617
|
+
adoptsFrom: zod.z.string().min(1).optional(),
|
|
3618
|
+
/** Kinds that must agree through `transact` sit in one file under one family name. */
|
|
3619
|
+
transactFamily: zod.z.string().min(1).optional(),
|
|
3620
|
+
entry: EntryDescriptorSchema.optional()
|
|
3621
|
+
}).strict();
|
|
3622
|
+
/** The kind names: lower-case, dash separated, short enough for an index name. */
|
|
3623
|
+
var RecordKindNameSchema = zod.z.string().regex(/^[a-z][a-z0-9-]{0,47}$/);
|
|
3624
|
+
/** Cross-field rules a declaration must satisfy. Throws {@link DeclarationRefusedError}. */
|
|
3625
|
+
function assertValidDeclaration(name, decl) {
|
|
3626
|
+
const refuse = (why) => {
|
|
3627
|
+
throw new DeclarationRefusedError(`kind "${name}": ${why}`);
|
|
3628
|
+
};
|
|
3629
|
+
if (!RecordKindNameSchema.safeParse(name).success) refuse("the name must be lower-case-dashed");
|
|
3630
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3631
|
+
for (const index of decl.indexes) {
|
|
3632
|
+
if (seen.has(index.name)) refuse(`index name "${index.name}" is declared twice`);
|
|
3633
|
+
seen.add(index.name);
|
|
3634
|
+
}
|
|
3635
|
+
const { retention } = decl;
|
|
3636
|
+
const hasSecrets = decl.secretPaths.length > 0;
|
|
3637
|
+
if ("ttlMs" in retention) {
|
|
3638
|
+
if (retention.from === "at" && decl.at !== "required") refuse("a ttl from \"at\" needs at: \"required\"");
|
|
3639
|
+
if (hasSecrets) refuse("a kind with secret fields cannot use engine TTL (its keychain values would be orphaned)");
|
|
3640
|
+
}
|
|
3641
|
+
if ("maxRows" in retention || "maxRowsPerDevice" in retention) {
|
|
3642
|
+
if (retention.maxRowsPerDevice !== void 0 && decl.device !== "required") refuse("maxRowsPerDevice needs device: \"required\"");
|
|
3643
|
+
if (decl.at !== "required") refuse("a row bound trims the oldest \"at\": it needs at: \"required\"");
|
|
3644
|
+
if (hasSecrets) refuse("a kind with secret fields cannot use an engine row bound");
|
|
3645
|
+
const bound = Math.max(retention.maxRows ?? 0, retention.maxRowsPerDevice ?? 0);
|
|
3646
|
+
if (decl.database === "settings" && bound > 5e4) refuse(`a row bound above ${RECORD_SETTINGS_MAX_ROWS} belongs in database: "events" (a big delete on the settings thread stalls every configuration read)`);
|
|
3647
|
+
}
|
|
3648
|
+
if (decl.deviceRemoval === "delete" && decl.device === "none") refuse("deviceRemoval: \"delete\" needs a device: \"required\" or \"optional\"");
|
|
3649
|
+
for (const path of decl.secretPaths) for (const prefix of secretArrayPrefixes(path)) if (decl.secretArrayKeys[prefix] === void 0) refuse(`secret path "${path}" crosses the array "${prefix}": declare its id key in secretArrayKeys`);
|
|
3650
|
+
}
|
|
3651
|
+
function bodyFieldsOf(schema) {
|
|
3652
|
+
return { ...zod.z.toJSONSchema(schema, {
|
|
3653
|
+
unrepresentable: "any",
|
|
3654
|
+
io: "input"
|
|
3655
|
+
}) };
|
|
3656
|
+
}
|
|
3657
|
+
function isRecordLike(value) {
|
|
3658
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3659
|
+
}
|
|
3660
|
+
/** Does every branch of the body schema carry `field`? (A discriminated union has several.) */
|
|
3661
|
+
function hasNameField(json, field) {
|
|
3662
|
+
const branches = json["oneOf"] ?? json["anyOf"];
|
|
3663
|
+
if (Array.isArray(branches)) return branches.length > 0 && branches.every((b) => isRecordLike(b) && hasNameField(b, field));
|
|
3664
|
+
const properties = json["properties"];
|
|
3665
|
+
return isRecordLike(properties) && Object.prototype.hasOwnProperty.call(properties, field);
|
|
3666
|
+
}
|
|
3667
|
+
/**
|
|
3668
|
+
* Declare the kinds of a package. The keys are the kind names. The result is
|
|
3669
|
+
* what `ctx.records.declare` sends to the engine and what `ctx.records.kind`
|
|
3670
|
+
* types its handle from.
|
|
3671
|
+
*/
|
|
3672
|
+
function defineRecordKinds(specs) {
|
|
3673
|
+
const out = {};
|
|
3674
|
+
for (const [name, spec] of Object.entries(specs)) {
|
|
3675
|
+
const secretPaths = collectZodSecretPaths(spec.schema);
|
|
3676
|
+
const nameField = spec.entry?.nameField ?? "name";
|
|
3677
|
+
const fields = bodyFieldsOf(spec.schema);
|
|
3678
|
+
if (spec.entry !== void 0 && !hasNameField(fields, nameField)) throw new DeclarationRefusedError(`kind "${name}": an entry kind's schema needs a "${nameField}" field`);
|
|
3679
|
+
const parsed = RecordKindDeclarationSchema.parse({
|
|
3680
|
+
database: spec.database,
|
|
3681
|
+
class: spec.class,
|
|
3682
|
+
writeTrigger: spec.writeTrigger,
|
|
3683
|
+
device: spec.device,
|
|
3684
|
+
at: spec.at,
|
|
3685
|
+
indexes: spec.indexes === void 0 ? void 0 : [...spec.indexes],
|
|
3686
|
+
retention: spec.retention,
|
|
3687
|
+
deviceRemoval: spec.deviceRemoval,
|
|
3688
|
+
maxDataBytes: spec.maxDataBytes,
|
|
3689
|
+
secretPaths: [...secretPaths],
|
|
3690
|
+
secretArrayKeys: spec.secretArrayKeys === void 0 ? void 0 : { ...spec.secretArrayKeys },
|
|
3691
|
+
adoptsFrom: spec.adoptsFrom,
|
|
3692
|
+
transactFamily: spec.transactFamily,
|
|
3693
|
+
entry: spec.entry === void 0 ? void 0 : {
|
|
3694
|
+
title: spec.entry.title,
|
|
3695
|
+
nameField,
|
|
3696
|
+
fields
|
|
3697
|
+
}
|
|
3698
|
+
});
|
|
3699
|
+
assertValidDeclaration(name, parsed);
|
|
3700
|
+
out[name] = {
|
|
3701
|
+
name,
|
|
3702
|
+
schema: spec.schema,
|
|
3703
|
+
declaration: parsed
|
|
3704
|
+
};
|
|
3705
|
+
}
|
|
3706
|
+
return out;
|
|
3707
|
+
}
|
|
3708
|
+
/** The wire form of a package's kinds: name -> declaration. */
|
|
3709
|
+
function declarationsOf(kinds) {
|
|
3710
|
+
return Object.fromEntries(Object.entries(kinds).map(([name, kind]) => [name, kind.declaration]));
|
|
3711
|
+
}
|
|
3712
|
+
//#endregion
|
|
3713
|
+
//#region src/records/records-access.ts
|
|
3714
|
+
function isRecord(value) {
|
|
3715
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3716
|
+
}
|
|
3717
|
+
/** Run a transport call and give a wire failure its typed class back. */
|
|
3718
|
+
async function call(fn) {
|
|
3719
|
+
try {
|
|
3720
|
+
return await fn();
|
|
3721
|
+
} catch (err) {
|
|
3722
|
+
throw asRecordsError(err);
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
function zodSummary(error) {
|
|
3726
|
+
return error.issues.slice(0, 5).map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`).join("; ");
|
|
3727
|
+
}
|
|
3728
|
+
function toRow(view, data) {
|
|
3729
|
+
return {
|
|
3730
|
+
id: view.id,
|
|
3731
|
+
deviceId: view.deviceId,
|
|
3732
|
+
at: view.at,
|
|
3733
|
+
expiresAt: view.expiresAt,
|
|
3734
|
+
rev: view.rev,
|
|
3735
|
+
updatedAt: view.updatedAt,
|
|
3736
|
+
data
|
|
3737
|
+
};
|
|
3738
|
+
}
|
|
3739
|
+
var KindHandle = class {
|
|
3740
|
+
def;
|
|
3741
|
+
o;
|
|
3742
|
+
name;
|
|
3743
|
+
decl;
|
|
3744
|
+
constructor(def, o) {
|
|
3745
|
+
this.def = def;
|
|
3746
|
+
this.o = o;
|
|
3747
|
+
this.name = def.name;
|
|
3748
|
+
this.decl = def.declaration;
|
|
3749
|
+
}
|
|
3750
|
+
get hasSecrets() {
|
|
3751
|
+
return this.decl.secretPaths.length > 0;
|
|
3752
|
+
}
|
|
3753
|
+
requireSecrets() {
|
|
3754
|
+
if (this.o.secrets === null) throw new RecordSecretUnavailableError(`kind "${this.name}" has secret fields and this process has no keychain door`);
|
|
3755
|
+
return this.o.secrets;
|
|
3756
|
+
}
|
|
3757
|
+
/** Read the body as the schema's type. The engine already redacted the secrets. */
|
|
3758
|
+
typed(view) {
|
|
3759
|
+
return toRow(view, view.data);
|
|
3760
|
+
}
|
|
3761
|
+
/**
|
|
3762
|
+
* Classify and store the secret leaves of a body about to be written. The
|
|
3763
|
+
* keychain is written FIRST (a failure throws before any row is touched), and
|
|
3764
|
+
* what each ref held before is remembered: when the row write is then refused
|
|
3765
|
+
* (a stale `ifRev`, too large, a unique index) `rollback` puts the previous
|
|
3766
|
+
* values back, so a refused write never destroys the secret that was stored.
|
|
3767
|
+
*/
|
|
3768
|
+
async storeSecrets(id, body, mode) {
|
|
3769
|
+
if (!this.hasSecrets) return {
|
|
3770
|
+
body,
|
|
3771
|
+
rollback: async () => {}
|
|
3772
|
+
};
|
|
3773
|
+
const secrets = this.requireSecrets();
|
|
3774
|
+
const writes = [];
|
|
3775
|
+
const prepared = mapSecretLeaves(body, this.decl.secretPaths, this.decl.secretArrayKeys, (leaf) => {
|
|
3776
|
+
const intent = classifySecretWrite(leaf.value);
|
|
3777
|
+
if (intent.kind === "clear") return REMOVE_LEAF;
|
|
3778
|
+
if (intent.kind === "keep") {
|
|
3779
|
+
if (mode === "put") return REDACTED_SECRET;
|
|
3780
|
+
if (leaf.value === null) return null;
|
|
3781
|
+
return leaf.concrete.includes("[") ? REDACTED_SECRET : REMOVE_LEAF;
|
|
3782
|
+
}
|
|
3783
|
+
const ref = recordSecretRef(this.o.owner, this.name, id, leaf.concrete);
|
|
3784
|
+
writes.push({
|
|
3785
|
+
ref,
|
|
3786
|
+
value: intent.value
|
|
3787
|
+
});
|
|
3788
|
+
return makeSecretMarker(ref);
|
|
3789
|
+
});
|
|
3790
|
+
const done = [];
|
|
3791
|
+
const rollback = async () => {
|
|
3792
|
+
for (const { ref, previous } of done) try {
|
|
3793
|
+
if (previous === void 0) await secrets.delete([ref]);
|
|
3794
|
+
else await secrets.put(ref, previous);
|
|
3795
|
+
} catch (err) {
|
|
3796
|
+
this.o.logger?.warn("records: could not restore a keychain value after a refused write", { meta: {
|
|
3797
|
+
kind: this.name,
|
|
3798
|
+
error: err instanceof Error ? err.message : "unknown"
|
|
3799
|
+
} });
|
|
3800
|
+
}
|
|
3801
|
+
};
|
|
3802
|
+
for (const write of writes) try {
|
|
3803
|
+
const before = (await secrets.resolve([write.ref]))[write.ref];
|
|
3804
|
+
const previous = before?.kind === "value" ? before.value : void 0;
|
|
3805
|
+
await secrets.put(write.ref, write.value);
|
|
3806
|
+
done.push({
|
|
3807
|
+
ref: write.ref,
|
|
3808
|
+
previous
|
|
3809
|
+
});
|
|
3810
|
+
} catch (err) {
|
|
3811
|
+
await rollback();
|
|
3812
|
+
throw new RecordSecretUnavailableError(`cannot store a secret of ${this.name}/${id}: ${err instanceof Error ? err.message : "the keychain refused"}. Unlock the keychain (System -> Secrets) and save again`);
|
|
3813
|
+
}
|
|
3814
|
+
return {
|
|
3815
|
+
body: prepared,
|
|
3816
|
+
rollback
|
|
3817
|
+
};
|
|
3818
|
+
}
|
|
3819
|
+
async releaseRefs(refs) {
|
|
3820
|
+
if (refs.length === 0 || this.o.secrets === null) return;
|
|
3821
|
+
try {
|
|
3822
|
+
await this.o.secrets.delete(refs);
|
|
3823
|
+
} catch (err) {
|
|
3824
|
+
this.o.logger?.warn("records: could not remove released keychain values", { meta: {
|
|
3825
|
+
kind: this.name,
|
|
3826
|
+
count: refs.length,
|
|
3827
|
+
error: err instanceof Error ? err.message : "unknown"
|
|
3828
|
+
} });
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
validate(data, id) {
|
|
3832
|
+
const shaped = this.hasSecrets ? mapSecretLeaves(data, this.decl.secretPaths, this.decl.secretArrayKeys, (leaf) => {
|
|
3833
|
+
const intent = classifySecretWrite(leaf.value);
|
|
3834
|
+
if (intent.kind === "clear") return REMOVE_LEAF;
|
|
3835
|
+
return intent.kind === "keep" ? REDACTED_SECRET : leaf.value;
|
|
3836
|
+
}) : data;
|
|
3837
|
+
const parsed = this.def.schema.safeParse(shaped);
|
|
3838
|
+
if (!parsed.success) throw new InvalidRecordError(`${this.name}/${id}: ${zodSummary(parsed.error)}`);
|
|
3839
|
+
if (!isRecord(parsed.data)) throw new InvalidRecordError(`${this.name}/${id}: the body must be an object`);
|
|
3840
|
+
return parsed.data;
|
|
3841
|
+
}
|
|
3842
|
+
async get(id) {
|
|
3843
|
+
const view = await call(() => this.o.transport.get({
|
|
3844
|
+
kind: this.name,
|
|
3845
|
+
id
|
|
3846
|
+
}));
|
|
3847
|
+
return view === null ? null : this.typed(view);
|
|
3848
|
+
}
|
|
3849
|
+
async getMany(ids) {
|
|
3850
|
+
if (ids.length === 0) return [];
|
|
3851
|
+
return (await call(() => this.o.transport.getMany({
|
|
3852
|
+
kind: this.name,
|
|
3853
|
+
ids: [...ids]
|
|
3854
|
+
}))).map((v) => this.typed(v));
|
|
3855
|
+
}
|
|
3856
|
+
async getResolved(id) {
|
|
3857
|
+
const row = await this.get(id);
|
|
3858
|
+
if (row === null) return null;
|
|
3859
|
+
return (await this.resolveRows([row]))[0] ?? row;
|
|
3860
|
+
}
|
|
3861
|
+
async resolveRows(rows) {
|
|
3862
|
+
if (!this.hasSecrets || rows.length === 0) return rows;
|
|
3863
|
+
const secrets = this.requireSecrets();
|
|
3864
|
+
const refsById = await call(() => this.o.transport.secretRefs({
|
|
3865
|
+
kind: this.name,
|
|
3866
|
+
ids: rows.map((r) => r.id)
|
|
3867
|
+
}));
|
|
3868
|
+
const refs = Object.values(refsById).flatMap((byPath) => Object.values(byPath));
|
|
3869
|
+
if (refs.length === 0) return rows;
|
|
3870
|
+
const answers = await secrets.resolve(refs);
|
|
3871
|
+
return rows.map((row) => {
|
|
3872
|
+
const byPath = refsById[row.id] ?? {};
|
|
3873
|
+
const resolved = mapSecretLeaves(row.data, this.decl.secretPaths, this.decl.secretArrayKeys, (leaf) => {
|
|
3874
|
+
const ref = byPath[leaf.concrete];
|
|
3875
|
+
if (ref === void 0) return leaf.value;
|
|
3876
|
+
const answer = answers[ref];
|
|
3877
|
+
if (answer?.kind === "value") return answer.value;
|
|
3878
|
+
const why = answer?.kind === "unavailable" ? answer.reason : answer?.kind ?? "no answer";
|
|
3879
|
+
throw new RecordSecretUnavailableError(`the secret "${leaf.concrete}" of ${this.name}/${row.id} cannot be served (${why})`);
|
|
3880
|
+
});
|
|
3881
|
+
return {
|
|
3882
|
+
...row,
|
|
3883
|
+
data: resolved
|
|
3884
|
+
};
|
|
3885
|
+
});
|
|
3886
|
+
}
|
|
3887
|
+
async put(input, opts = {}) {
|
|
3888
|
+
const checked = this.validate(input.data, input.id);
|
|
3889
|
+
const { body, rollback } = await this.storeSecrets(input.id, checked, "put");
|
|
3890
|
+
const result = await call(() => this.o.transport.put({
|
|
3891
|
+
kind: this.name,
|
|
3892
|
+
record: {
|
|
3893
|
+
...input,
|
|
3894
|
+
data: toBody(body)
|
|
3895
|
+
},
|
|
3896
|
+
...opts.ifRev === void 0 ? {} : { ifRev: opts.ifRev }
|
|
3897
|
+
})).catch(async (err) => {
|
|
3898
|
+
await rollback();
|
|
3899
|
+
throw err;
|
|
3900
|
+
});
|
|
3901
|
+
await this.releaseRefs(result.releasedRefs);
|
|
3902
|
+
return { rev: result.rev };
|
|
3903
|
+
}
|
|
3904
|
+
async putMany(inputs) {
|
|
3905
|
+
if (inputs.length === 0) return { count: 0 };
|
|
3906
|
+
const prepared = [];
|
|
3907
|
+
const rollbacks = [];
|
|
3908
|
+
try {
|
|
3909
|
+
for (const input of inputs) {
|
|
3910
|
+
const checked = this.validate(input.data, input.id);
|
|
3911
|
+
const { body, rollback } = await this.storeSecrets(input.id, checked, "put");
|
|
3912
|
+
rollbacks.push(rollback);
|
|
3913
|
+
prepared.push({
|
|
3914
|
+
...input,
|
|
3915
|
+
data: toBody(body)
|
|
3916
|
+
});
|
|
3917
|
+
}
|
|
3918
|
+
} catch (err) {
|
|
3919
|
+
for (const rollback of rollbacks) await rollback();
|
|
3920
|
+
throw err;
|
|
3921
|
+
}
|
|
3922
|
+
const result = await call(() => this.o.transport.putMany({
|
|
3923
|
+
kind: this.name,
|
|
3924
|
+
records: prepared
|
|
3925
|
+
})).catch(async (err) => {
|
|
3926
|
+
for (const rollback of rollbacks) await rollback();
|
|
3927
|
+
throw err;
|
|
3928
|
+
});
|
|
3929
|
+
await this.releaseRefs(result.releasedRefs);
|
|
3930
|
+
return { count: result.count };
|
|
3931
|
+
}
|
|
3932
|
+
async patch(id, partial, opts = {}) {
|
|
3933
|
+
const { body, rollback } = await this.storeSecrets(id, partial, "patch");
|
|
3934
|
+
const result = await call(() => this.o.transport.patch({
|
|
3935
|
+
kind: this.name,
|
|
3936
|
+
id,
|
|
3937
|
+
data: toBody(body),
|
|
3938
|
+
...opts.at === void 0 ? {} : { at: opts.at },
|
|
3939
|
+
...opts.expiresAt === void 0 ? {} : { expiresAt: opts.expiresAt },
|
|
3940
|
+
...opts.ifRev === void 0 ? {} : { ifRev: opts.ifRev }
|
|
3941
|
+
})).catch(async (err) => {
|
|
3942
|
+
await rollback();
|
|
3943
|
+
throw err;
|
|
3944
|
+
});
|
|
3945
|
+
await this.releaseRefs(result.releasedRefs);
|
|
3946
|
+
return { rev: result.rev };
|
|
3947
|
+
}
|
|
3948
|
+
async delete(id) {
|
|
3949
|
+
const result = await call(() => this.o.transport.delete({
|
|
3950
|
+
kind: this.name,
|
|
3951
|
+
id
|
|
3952
|
+
}));
|
|
3953
|
+
await this.releaseRefs(result.secretRefs);
|
|
3954
|
+
return result.deleted;
|
|
3955
|
+
}
|
|
3956
|
+
async deleteMany(ids) {
|
|
3957
|
+
if (ids.length === 0) return 0;
|
|
3958
|
+
const result = await call(() => this.o.transport.deleteMany({
|
|
3959
|
+
kind: this.name,
|
|
3960
|
+
ids: [...ids]
|
|
3961
|
+
}));
|
|
3962
|
+
await this.releaseRefs(result.secretRefs);
|
|
3963
|
+
return result.deleted;
|
|
3964
|
+
}
|
|
3965
|
+
async query(q, opts = {}) {
|
|
3966
|
+
const result = await call(() => this.o.transport.query({
|
|
3967
|
+
...q,
|
|
3968
|
+
kind: this.name,
|
|
3969
|
+
limit: q.limit ?? 100
|
|
3970
|
+
}));
|
|
3971
|
+
const rows = result.records.map((v) => this.typed(v));
|
|
3972
|
+
return {
|
|
3973
|
+
records: opts.resolveSecrets === true ? await this.resolveRows(rows) : rows,
|
|
3974
|
+
nextCursor: result.nextCursor
|
|
3975
|
+
};
|
|
3976
|
+
}
|
|
3977
|
+
async count(q) {
|
|
3978
|
+
return (await call(() => this.o.transport.count({
|
|
3979
|
+
...q,
|
|
3980
|
+
kind: this.name
|
|
3981
|
+
}))).count;
|
|
3982
|
+
}
|
|
3983
|
+
async histogram(q) {
|
|
3984
|
+
return (await call(() => this.o.transport.histogram({
|
|
3985
|
+
...q,
|
|
3986
|
+
kind: this.name
|
|
3987
|
+
}))).buckets;
|
|
3988
|
+
}
|
|
3989
|
+
async aggregate(q) {
|
|
3990
|
+
return (await call(() => this.o.transport.aggregate({
|
|
3991
|
+
...q,
|
|
3992
|
+
kind: this.name
|
|
3993
|
+
}))).rows;
|
|
3994
|
+
}
|
|
3995
|
+
async deleteWhere(q) {
|
|
3996
|
+
const result = await call(() => this.o.transport.deleteWhere({
|
|
3997
|
+
...q,
|
|
3998
|
+
kind: this.name
|
|
3999
|
+
}));
|
|
4000
|
+
await this.releaseRefs(result.secretRefs);
|
|
4001
|
+
return result.deleted;
|
|
4002
|
+
}
|
|
4003
|
+
async allocateId() {
|
|
4004
|
+
return (await call(() => this.o.transport.allocateId({ kind: this.name }))).id;
|
|
4005
|
+
}
|
|
4006
|
+
};
|
|
4007
|
+
function toBody(value) {
|
|
4008
|
+
if (!isRecord(value)) throw new InvalidRecordError("the record body must be an object");
|
|
4009
|
+
return value;
|
|
4010
|
+
}
|
|
4011
|
+
/** Build the owner's records handle. */
|
|
4012
|
+
function createRecordsAccess(options) {
|
|
4013
|
+
const handles = /* @__PURE__ */ new WeakMap();
|
|
4014
|
+
const delegates = /* @__PURE__ */ new Map();
|
|
4015
|
+
return {
|
|
4016
|
+
owner: options.owner,
|
|
4017
|
+
forOwner: options.transportForOwner === void 0 ? null : (other) => {
|
|
4018
|
+
const existing = delegates.get(other);
|
|
4019
|
+
if (existing !== void 0) return existing;
|
|
4020
|
+
const build = options.transportForOwner;
|
|
4021
|
+
if (build === void 0) throw new Error("forOwner: no delegate transport");
|
|
4022
|
+
const delegate = createRecordsAccess({
|
|
4023
|
+
owner: other,
|
|
4024
|
+
transport: build(other),
|
|
4025
|
+
secrets: options.secrets?.forOwner?.(other) ?? null,
|
|
4026
|
+
...options.logger === void 0 ? {} : { logger: options.logger }
|
|
4027
|
+
});
|
|
4028
|
+
delegates.set(other, delegate);
|
|
4029
|
+
return delegate;
|
|
4030
|
+
},
|
|
4031
|
+
async declare(kinds) {
|
|
4032
|
+
const result = await call(() => options.transport.declareKinds({ kinds: { ...declarationsOf(kinds) } }));
|
|
4033
|
+
const pending = Object.entries(result.kinds).filter((entry) => entry[1].adoptionPending !== null);
|
|
4034
|
+
if (pending.length > 0) throw new AdoptionPendingError(`${pending.map(([name, r]) => r.adoptionPending === null ? name : `${name} (legacy table "${r.adoptionPending.legacyTable}" holds ${r.adoptionPending.legacyRows} rows)`).join(", ")}. Stop the addon and run scripts/hub/records-adopt.ts --copy --apply before starting this build`);
|
|
4035
|
+
return result.kinds;
|
|
4036
|
+
},
|
|
4037
|
+
kind(definition) {
|
|
4038
|
+
const existing = handles.get(definition);
|
|
4039
|
+
if (existing !== void 0) return existing;
|
|
4040
|
+
const handle = new KindHandle(definition, options);
|
|
4041
|
+
handles.set(definition, handle);
|
|
4042
|
+
return handle;
|
|
4043
|
+
},
|
|
4044
|
+
async deleteDevice(deviceId, opts = {}) {
|
|
4045
|
+
const result = await call(() => options.transport.deleteDevice({
|
|
4046
|
+
deviceId,
|
|
4047
|
+
...opts.kinds === void 0 ? {} : { kinds: [...opts.kinds] }
|
|
4048
|
+
}));
|
|
4049
|
+
if (result.secretRefs.length > 0 && options.secrets !== null) try {
|
|
4050
|
+
await options.secrets.delete(result.secretRefs);
|
|
4051
|
+
} catch (err) {
|
|
4052
|
+
options.logger?.warn("records: could not remove released keychain values", { meta: {
|
|
4053
|
+
count: result.secretRefs.length,
|
|
4054
|
+
error: err instanceof Error ? err.message : "unknown"
|
|
4055
|
+
} });
|
|
4056
|
+
}
|
|
4057
|
+
return result.deleted;
|
|
4058
|
+
}
|
|
4059
|
+
};
|
|
4060
|
+
}
|
|
4061
|
+
//#endregion
|
|
4062
|
+
//#region src/records/entry-kind.ts
|
|
4063
|
+
/**
|
|
4064
|
+
* Entry kinds (D881): every list of user-created entries (notification
|
|
4065
|
+
* targets, brokers, LLM profiles) is ONE record kind with an id, a name and a
|
|
4066
|
+
* kind-specific body, and the admin UI lists/adds/edits/deletes all of them
|
|
4067
|
+
* through the `record-entries` capability with password fields derived from
|
|
4068
|
+
* the schema (`.meta({ secret: true })`).
|
|
4069
|
+
*/
|
|
4070
|
+
/** The body of a plain entry: a name and the fields the kind adds. */
|
|
4071
|
+
function entryBody(shape) {
|
|
4072
|
+
return zod.z.object({
|
|
4073
|
+
name: zod.z.string().min(1),
|
|
4074
|
+
...shape
|
|
4075
|
+
});
|
|
4076
|
+
}
|
|
4077
|
+
/**
|
|
4078
|
+
* Declare one entry kind. An entry is configuration: never trimmed by the
|
|
4079
|
+
* engine, never aged, belonging to no device.
|
|
4080
|
+
*/
|
|
4081
|
+
function defineEntryKind(name, spec) {
|
|
4082
|
+
const defined = defineRecordKinds({ [name]: {
|
|
4083
|
+
schema: spec.schema,
|
|
4084
|
+
class: "config",
|
|
4085
|
+
writeTrigger: spec.writeTrigger ?? "an operator adds or edits an entry in the entries UI",
|
|
4086
|
+
retention: { none: "an entry goes only when the operator deletes it" },
|
|
4087
|
+
...spec.database === void 0 ? {} : { database: spec.database },
|
|
4088
|
+
...spec.indexes === void 0 ? {} : { indexes: spec.indexes },
|
|
4089
|
+
...spec.secretArrayKeys === void 0 ? {} : { secretArrayKeys: spec.secretArrayKeys },
|
|
4090
|
+
...spec.adoptsFrom === void 0 ? {} : { adoptsFrom: spec.adoptsFrom },
|
|
4091
|
+
entry: {
|
|
4092
|
+
title: spec.title,
|
|
4093
|
+
...spec.nameField === void 0 ? {} : { nameField: spec.nameField }
|
|
4094
|
+
}
|
|
4095
|
+
} })[name];
|
|
4096
|
+
if (defined === void 0) throw new DeclarationRefusedError(`entry kind "${name}" was not built`);
|
|
4097
|
+
return defined;
|
|
4098
|
+
}
|
|
4099
|
+
//#endregion
|
|
4100
|
+
//#region src/capabilities/schemas/streaming-shared.ts
|
|
4101
|
+
/** Shared Zod schemas used across streaming capabilities. */
|
|
4102
|
+
var CamProfileSchema = zod.z.enum([
|
|
4103
|
+
"high",
|
|
4104
|
+
"mid",
|
|
4105
|
+
"low"
|
|
4106
|
+
]);
|
|
4107
|
+
/** Canonical ordering. Hard-coded; never sorted. */
|
|
4108
|
+
var CAM_PROFILE_ORDER = [
|
|
4109
|
+
"high",
|
|
4110
|
+
"mid",
|
|
4111
|
+
"low"
|
|
4112
|
+
];
|
|
4113
|
+
/**
|
|
4114
|
+
* Which rung a per-camera consumer listens on: an explicit profile, or `auto`.
|
|
4115
|
+
*
|
|
4116
|
+
* `auto` is a REAL value, not an absent one — it means "resolve it by the rule
|
|
4117
|
+
* that consumer owns". It lives beside `CamProfile` because a rung is the only
|
|
4118
|
+
* operator-facing way to name a stream: a cam-stream id is broker-internal and
|
|
4119
|
+
* moves when a slot is reassigned, so a stored id silently stops meaning what
|
|
4120
|
+
* the operator picked. Today's one user is the audio analyser, whose rule is
|
|
4121
|
+
* "the lowest AVAILABLE native rung" (D537).
|
|
4122
|
+
*/
|
|
4123
|
+
var AudioStreamPickSchema = zod.z.union([CamProfileSchema, zod.z.literal("auto")]);
|
|
4124
|
+
var CamStreamKindSchema = zod.z.enum([
|
|
4125
|
+
"pull-rtsp",
|
|
4126
|
+
"pull-rtmp",
|
|
4127
|
+
"pull-http",
|
|
4128
|
+
"pull-flv",
|
|
4129
|
+
"pull-rfc4571",
|
|
4130
|
+
"push-annexb",
|
|
4131
|
+
"derived"
|
|
4132
|
+
]);
|
|
4133
|
+
var CamStreamResolutionSchema = zod.z.object({
|
|
4134
|
+
width: zod.z.number().int().positive(),
|
|
4135
|
+
height: zod.z.number().int().positive()
|
|
4136
|
+
});
|
|
4137
|
+
var CameraStreamSchema = zod.z.object({
|
|
4138
|
+
/** Stable, provider-assigned id unique within the (deviceId) scope. */
|
|
4139
|
+
camStreamId: zod.z.string().min(1),
|
|
4140
|
+
deviceId: zod.z.number().int().nonnegative(),
|
|
4141
|
+
kind: CamStreamKindSchema,
|
|
4142
|
+
/** Required for pull-* kinds. Ignored for push-annexb. */
|
|
4143
|
+
url: zod.z.string().optional(),
|
|
4144
|
+
codec: zod.z.string().optional(),
|
|
4145
|
+
resolution: CamStreamResolutionSchema.optional(),
|
|
4146
|
+
fps: zod.z.number().positive().optional(),
|
|
4147
|
+
/** Human label surfaced in the Admin UI "Camera Stream" dropdown. */
|
|
4148
|
+
label: zod.z.string().optional(),
|
|
4149
|
+
/**
|
|
4150
|
+
* Device-level features the publisher advertised (e.g. `battery-operated`).
|
|
4151
|
+
* The broker, snapshot orchestrator, and prebuffer manager all consult
|
|
4152
|
+
* this list to derive policy — relaxed stall watchdog for battery
|
|
4153
|
+
* cams, prebuffer off by default, longer snapshot rate-limit, etc.
|
|
4154
|
+
*
|
|
4155
|
+
* Single source of truth replacing per-stream flags like the
|
|
4156
|
+
* historical `allowStall`: if the publisher knows the camera is
|
|
4157
|
+
* battery-powered, every downstream service derives the right policy
|
|
4158
|
+
* from this list.
|
|
4159
|
+
*/
|
|
4160
|
+
deviceFeatures: zod.z.array(zod.z.string()).optional(),
|
|
4161
|
+
/**
|
|
4162
|
+
* Whether this stream participates in the broker's automatic profile
|
|
4163
|
+
* assignment (`computeInitialAssignment`). Defaults to `true`. Publishers
|
|
4164
|
+
* use `false` when they want a stream to be SELECTABLE in the UI but not
|
|
4165
|
+
* picked by default — e.g. Reolink publishes its native Baichuan streams
|
|
4166
|
+
* as `autoEligible: true` (the recommended path) and its RTSP / RTMP
|
|
4167
|
+
* mirrors as `autoEligible: false` (still pickable per slot, just not
|
|
4168
|
+
* the auto choice). Manual `assignProfile` calls remain valid for
|
|
4169
|
+
* non-eligible streams.
|
|
4170
|
+
*/
|
|
4171
|
+
autoEligible: zod.z.boolean().optional(),
|
|
4172
|
+
/**
|
|
4173
|
+
* The profile slot the PUBLISHER says this stream is: `low` for a stream
|
|
4174
|
+
* whose only sensible role is the low-bandwidth one, `high` for a main
|
|
4175
|
+
* stream. Consulted by the broker's automatic ranking
|
|
4176
|
+
* (`rankInitialAssignment`) BEFORE the pixel-count heuristic, and only there:
|
|
4177
|
+
* an operator's manual assignment still wins, and an absent hint is the
|
|
4178
|
+
* pixel-ranked default every camera had before this field existed.
|
|
4179
|
+
*
|
|
4180
|
+
* Why it exists: a camera with ONE stream ranked to `mid` — the slot no
|
|
4181
|
+
* storage class is written for on its own (`recordings` is high|mid,
|
|
4182
|
+
* `recordingsLow` is low) and the one profile scrub does not read. The robot
|
|
4183
|
+
* camera's single 720p relay is a `low` in every respect except the slot the
|
|
4184
|
+
* heuristic put it in.
|
|
4185
|
+
*/
|
|
4186
|
+
profileHint: CamProfileSchema.optional(),
|
|
4187
|
+
/**
|
|
4188
|
+
* Transport-specific opaque metadata. The broker passes it through to
|
|
4189
|
+
* the source reader without inspecting it. Currently used by
|
|
4190
|
+
* `pull-rfc4571` streams to carry the upstream SDP (so the reader can
|
|
4191
|
+
* route RTP packets to the right depacketizer without an in-band
|
|
4192
|
+
* DESCRIBE phase). Other kinds typically leave it undefined.
|
|
4193
|
+
*/
|
|
4194
|
+
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
4195
|
+
});
|
|
4196
|
+
var ProfileSlotStatusSchema = zod.z.enum([
|
|
4197
|
+
"unassigned",
|
|
4198
|
+
"idle",
|
|
4199
|
+
"connecting",
|
|
4200
|
+
"streaming",
|
|
4201
|
+
"error"
|
|
4202
|
+
]);
|
|
4203
|
+
var ProfileSlotSchema = zod.z.object({
|
|
4204
|
+
deviceId: zod.z.number().int().nonnegative(),
|
|
4205
|
+
profile: CamProfileSchema,
|
|
4206
|
+
/** Broker id the rest of the system addresses: `${deviceId}/${profile}`. */
|
|
4207
|
+
brokerId: zod.z.string(),
|
|
4208
|
+
/** `null` when the profile is unassigned. */
|
|
4209
|
+
sourceCamStreamId: zod.z.string().nullable(),
|
|
4210
|
+
status: ProfileSlotStatusSchema,
|
|
4211
|
+
resolution: CamStreamResolutionSchema.optional(),
|
|
4212
|
+
codec: zod.z.string().optional(),
|
|
4213
|
+
preBufferSec: zod.z.number().nonnegative().optional(),
|
|
4214
|
+
errorMessage: zod.z.string().optional()
|
|
4215
|
+
});
|
|
4216
|
+
/** The canonical consumer-facing broker id for a device profile. */
|
|
4217
|
+
function makeProfileBrokerId(deviceId, profile) {
|
|
4218
|
+
return `${deviceId}/${profile}`;
|
|
4219
|
+
}
|
|
4220
|
+
/**
|
|
4221
|
+
* The broker id keying a physical SOURCE stream: `${deviceId}/${camStreamId}`.
|
|
4222
|
+
* This is the broker's internal source key (`brokerIdFor` in the manager) — a
|
|
4223
|
+
* `camStreamId` like `native:main` — as opposed to the public profile alias
|
|
4224
|
+
* {@link makeProfileBrokerId}. Used to resolve a source's restream endpoint
|
|
4225
|
+
* (e.g. routing a transcode's ffmpeg input through the broker so it rides the
|
|
4226
|
+
* single source dial instead of opening a second camera connection).
|
|
4227
|
+
*/
|
|
4228
|
+
function makeSourceBrokerId(deviceId, camStreamId) {
|
|
4229
|
+
return `${deviceId}/${camStreamId}`;
|
|
4230
|
+
}
|
|
4231
|
+
/**
|
|
4232
|
+
* Inverse of {@link makeProfileBrokerId}. Returns `null` when the string is
|
|
4233
|
+
* not a canonical `${deviceId}/${profile}` id — e.g. a broker-internal
|
|
4234
|
+
* cam-stream id (`5/native:main`), a derived/adaptive ref, or a malformed
|
|
4235
|
+
* value. So a caller can safely distinguish "addresses a public profile"
|
|
4236
|
+
* from "addresses something broker-internal".
|
|
4237
|
+
*/
|
|
4238
|
+
function parseProfileBrokerId(brokerId) {
|
|
4239
|
+
const slash = brokerId.indexOf("/");
|
|
4240
|
+
if (slash <= 0) return null;
|
|
4241
|
+
const idPart = brokerId.slice(0, slash);
|
|
4242
|
+
const profilePart = brokerId.slice(slash + 1);
|
|
4243
|
+
if (!/^\d+$/.test(idPart)) return null;
|
|
4244
|
+
const parsed = CamProfileSchema.safeParse(profilePart);
|
|
4245
|
+
if (!parsed.success) return null;
|
|
4246
|
+
return {
|
|
4247
|
+
deviceId: Number(idPart),
|
|
4248
|
+
profile: parsed.data
|
|
4249
|
+
};
|
|
4250
|
+
}
|
|
4251
|
+
/**
|
|
4252
|
+
* The profile slots worth consuming/recording: ASSIGNED only
|
|
4253
|
+
* (`sourceCamStreamId != null`), DEDUPED by physical source so the same
|
|
4254
|
+
* camera encoder is never subscribed/recorded twice, ordered high→mid→low.
|
|
4255
|
+
* Optionally scoped to one `deviceId`. Pure; never mutates the input.
|
|
4256
|
+
*
|
|
4257
|
+
* Recording `main` and `mid` when both point at the same `sourceCamStreamId`
|
|
4258
|
+
* would dial the camera's internal stream twice for no benefit — this is the
|
|
4259
|
+
* dedup that prevents that.
|
|
4260
|
+
*/
|
|
4261
|
+
function selectAssignedProfileSlots(slots, deviceId) {
|
|
4262
|
+
const ordered = [...slots].filter((s) => deviceId === void 0 || s.deviceId === deviceId).toSorted((a, b) => CAM_PROFILE_ORDER.indexOf(a.profile) - CAM_PROFILE_ORDER.indexOf(b.profile));
|
|
4263
|
+
const seenSources = /* @__PURE__ */ new Set();
|
|
4264
|
+
const out = [];
|
|
4265
|
+
for (const s of ordered) {
|
|
4266
|
+
const src = s.sourceCamStreamId;
|
|
4267
|
+
if (src === null) continue;
|
|
4268
|
+
if (seenSources.has(src)) continue;
|
|
4269
|
+
seenSources.add(src);
|
|
4270
|
+
out.push(s);
|
|
4271
|
+
}
|
|
4272
|
+
return out;
|
|
4273
|
+
}
|
|
4274
|
+
/**
|
|
4275
|
+
* Zod schema for StreamSourceEntry — the canonical stream descriptor
|
|
4276
|
+
* exposed by ICameraDevice.getStreamSources() and consumed by the broker.
|
|
3302
4277
|
*/
|
|
3303
4278
|
var StreamSourceEntrySchema$1 = zod.z.object({
|
|
3304
4279
|
id: zod.z.string(),
|
|
@@ -4507,123 +5482,35 @@ var DEFAULT_TOKEN_EXPIRY = "30d";
|
|
|
4507
5482
|
* Moved from @camstack/system/config-schema to @camstack/types so that
|
|
4508
5483
|
* @camstack/system can reference it without a cross-package kernel import.
|
|
4509
5484
|
*/
|
|
4510
|
-
var RUNTIME_DEFAULTS = {
|
|
4511
|
-
"features.streaming": true,
|
|
4512
|
-
"features.notifications": true,
|
|
4513
|
-
"features.objectDetection": false,
|
|
4514
|
-
"features.remoteAccess": true,
|
|
4515
|
-
"features.agentCluster": false,
|
|
4516
|
-
"features.smartHome": true,
|
|
4517
|
-
"features.recordings": true,
|
|
4518
|
-
"features.backup": true,
|
|
4519
|
-
"features.repl": true,
|
|
4520
|
-
"retention.detectionEventsDays": 30,
|
|
4521
|
-
"retention.audioLevelsDays": 7,
|
|
4522
|
-
"logging.level": "info",
|
|
4523
|
-
"logging.retentionDays": 30,
|
|
4524
|
-
"eventBus.ringBufferSize": 1e4,
|
|
4525
|
-
"storage.provider": "sqlite-storage",
|
|
4526
|
-
"storage.locations": {
|
|
4527
|
-
data: "camstack-data/data",
|
|
4528
|
-
media: "camstack-data/media",
|
|
4529
|
-
recordings: "camstack-data/recordings",
|
|
4530
|
-
cache: "/tmp/camstack-cache",
|
|
4531
|
-
logs: "camstack-data/logs",
|
|
4532
|
-
models: "camstack-data/models"
|
|
4533
|
-
},
|
|
4534
|
-
providers: [],
|
|
4535
|
-
"ffmpeg.hwAccel": "auto",
|
|
4536
|
-
"ffmpeg.threadCount": 0,
|
|
4537
|
-
"auth.tokenExpiry": "30d"
|
|
4538
|
-
};
|
|
4539
|
-
//#endregion
|
|
4540
|
-
//#region src/device/zod-secret.ts
|
|
4541
|
-
/**
|
|
4542
|
-
* Secret declaration on a Zod config schema (D783).
|
|
4543
|
-
*
|
|
4544
|
-
* A field is a secret because its schema SAYS so — `.meta({ secret: true })`,
|
|
4545
|
-
* spelled {@link SECRET_META} — never because its key looks like a credential.
|
|
4546
|
-
* It is the Zod twin of `secret: true` / `type: 'password'` on a config-UI
|
|
4547
|
-
* field (`isSecretConfigField`), and every consumer that treats secrets
|
|
4548
|
-
* specially reads it: the settings form (`zodEntriesToConfigUI`), the paths a
|
|
4549
|
-
* device advertises at `registerDevice` (`secretConfigPaths`, which the
|
|
4550
|
-
* non-admin redaction withholds at any depth), and the keychain later.
|
|
4551
|
-
*
|
|
4552
|
-
* Zod keeps `.meta()` in `z.globalRegistry`, which lives on `globalThis`, so a
|
|
4553
|
-
* declaration made by an addon's own copy of zod is visible here.
|
|
4554
|
-
*/
|
|
4555
|
-
/**
|
|
4556
|
-
* `{ secret: true }` — the one spelling of "this field holds a credential".
|
|
4557
|
-
*
|
|
4558
|
-
* Addons write the LITERAL `.meta({ secret: true })` rather than importing
|
|
4559
|
-
* this constant: an addon running against an older `@camstack/types` would
|
|
4560
|
-
* otherwise call `.meta(undefined)`, which in zod v4 is the metadata GETTER
|
|
4561
|
-
* and returns no schema at all.
|
|
4562
|
-
*/
|
|
4563
|
-
var SECRET_META = { secret: true };
|
|
4564
|
-
function defOf(schema) {
|
|
4565
|
-
return schema._zod?.def ?? {};
|
|
4566
|
-
}
|
|
4567
|
-
function declaredHere(schema) {
|
|
4568
|
-
return zod.z.globalRegistry.get(schema)?.secret === true;
|
|
4569
|
-
}
|
|
4570
|
-
/** Wrapper kinds whose `innerType` is the field itself. */
|
|
4571
|
-
var WRAPPERS = new Set([
|
|
4572
|
-
"optional",
|
|
4573
|
-
"nullable",
|
|
4574
|
-
"default",
|
|
4575
|
-
"prefault",
|
|
4576
|
-
"catch",
|
|
4577
|
-
"readonly",
|
|
4578
|
-
"nonoptional"
|
|
4579
|
-
]);
|
|
4580
|
-
/**
|
|
4581
|
-
* The schema layers that make up ONE field: the schema itself and every
|
|
4582
|
-
* wrapper below it (optional / default / nullable / readonly / catch), plus
|
|
4583
|
-
* both sides of a pipe (`z.preprocess` puts the real schema on `out`,
|
|
4584
|
-
* `.transform` on `in`).
|
|
4585
|
-
*/
|
|
4586
|
-
function layersOf(schema) {
|
|
4587
|
-
const out = [];
|
|
4588
|
-
const queue = [schema];
|
|
4589
|
-
while (queue.length > 0) {
|
|
4590
|
-
const s = queue.shift();
|
|
4591
|
-
if (!s || out.includes(s)) continue;
|
|
4592
|
-
out.push(s);
|
|
4593
|
-
const def = defOf(s);
|
|
4594
|
-
if (def.type !== void 0 && WRAPPERS.has(def.type) && def.innerType) queue.push(def.innerType);
|
|
4595
|
-
if (def.type === "pipe") {
|
|
4596
|
-
if (def.in) queue.push(def.in);
|
|
4597
|
-
if (def.out) queue.push(def.out);
|
|
4598
|
-
}
|
|
4599
|
-
}
|
|
4600
|
-
return out;
|
|
4601
|
-
}
|
|
4602
|
-
/** True when any layer of this field declares `.meta({ secret: true })`. */
|
|
4603
|
-
function isZodSecret(schema) {
|
|
4604
|
-
return layersOf(schema).some(declaredHere);
|
|
4605
|
-
}
|
|
4606
|
-
/**
|
|
4607
|
-
* Every declared secret path in a config schema: dotted keys, `[]` for "each
|
|
4608
|
-
* element of this array" (`connection.password`, `rows[].token`). A declared
|
|
4609
|
-
* object or array is reported as one path and not descended into — everything
|
|
4610
|
-
* under it is secret.
|
|
4611
|
-
*/
|
|
4612
|
-
function collectZodSecretPaths(schema, prefix = "") {
|
|
4613
|
-
if (isZodSecret(schema)) return prefix.length > 0 ? [prefix] : [];
|
|
4614
|
-
const paths = [];
|
|
4615
|
-
for (const layer of layersOf(schema)) {
|
|
4616
|
-
const def = defOf(layer);
|
|
4617
|
-
if (def.type === "object" && def.shape) for (const [key, child] of Object.entries(def.shape)) paths.push(...collectZodSecretPaths(child, prefix ? `${prefix}.${key}` : key));
|
|
4618
|
-
else if (def.type === "array" && def.element) paths.push(...collectZodSecretPaths(def.element, `${prefix}[]`));
|
|
4619
|
-
else if (def.type === "union" && def.options) for (const option of def.options) paths.push(...collectZodSecretPaths(option, prefix));
|
|
4620
|
-
else if (def.type === "intersection") {
|
|
4621
|
-
if (def.left) paths.push(...collectZodSecretPaths(def.left, prefix));
|
|
4622
|
-
if (def.right) paths.push(...collectZodSecretPaths(def.right, prefix));
|
|
4623
|
-
}
|
|
4624
|
-
}
|
|
4625
|
-
return [...new Set(paths)];
|
|
4626
|
-
}
|
|
5485
|
+
var RUNTIME_DEFAULTS = {
|
|
5486
|
+
"features.streaming": true,
|
|
5487
|
+
"features.notifications": true,
|
|
5488
|
+
"features.objectDetection": false,
|
|
5489
|
+
"features.remoteAccess": true,
|
|
5490
|
+
"features.agentCluster": false,
|
|
5491
|
+
"features.smartHome": true,
|
|
5492
|
+
"features.recordings": true,
|
|
5493
|
+
"features.backup": true,
|
|
5494
|
+
"features.repl": true,
|
|
5495
|
+
"retention.detectionEventsDays": 30,
|
|
5496
|
+
"retention.audioLevelsDays": 7,
|
|
5497
|
+
"logging.level": "info",
|
|
5498
|
+
"logging.retentionDays": 30,
|
|
5499
|
+
"eventBus.ringBufferSize": 1e4,
|
|
5500
|
+
"storage.provider": "sqlite-storage",
|
|
5501
|
+
"storage.locations": {
|
|
5502
|
+
data: "camstack-data/data",
|
|
5503
|
+
media: "camstack-data/media",
|
|
5504
|
+
recordings: "camstack-data/recordings",
|
|
5505
|
+
cache: "/tmp/camstack-cache",
|
|
5506
|
+
logs: "camstack-data/logs",
|
|
5507
|
+
models: "camstack-data/models"
|
|
5508
|
+
},
|
|
5509
|
+
providers: [],
|
|
5510
|
+
"ffmpeg.hwAccel": "auto",
|
|
5511
|
+
"ffmpeg.threadCount": 0,
|
|
5512
|
+
"auth.tokenExpiry": "30d"
|
|
5513
|
+
};
|
|
4627
5514
|
//#endregion
|
|
4628
5515
|
//#region src/device/device-state-handle.ts
|
|
4629
5516
|
var DEVICE_STATE_EVENT_CATEGORY = "device.state-changed";
|
|
@@ -6193,6 +7080,12 @@ Object.defineProperty(exports, "AUDIO_CHUNK_FORMATS", {
|
|
|
6193
7080
|
return AUDIO_CHUNK_FORMATS;
|
|
6194
7081
|
}
|
|
6195
7082
|
});
|
|
7083
|
+
Object.defineProperty(exports, "AdoptionPendingError", {
|
|
7084
|
+
enumerable: true,
|
|
7085
|
+
get: function() {
|
|
7086
|
+
return AdoptionPendingError;
|
|
7087
|
+
}
|
|
7088
|
+
});
|
|
6196
7089
|
Object.defineProperty(exports, "AudioChunkFormatSchema", {
|
|
6197
7090
|
enumerable: true,
|
|
6198
7091
|
get: function() {
|
|
@@ -6217,6 +7110,12 @@ Object.defineProperty(exports, "BaseAddon", {
|
|
|
6217
7110
|
return BaseAddon;
|
|
6218
7111
|
}
|
|
6219
7112
|
});
|
|
7113
|
+
Object.defineProperty(exports, "BatchTooLargeError", {
|
|
7114
|
+
enumerable: true,
|
|
7115
|
+
get: function() {
|
|
7116
|
+
return BatchTooLargeError;
|
|
7117
|
+
}
|
|
7118
|
+
});
|
|
6220
7119
|
Object.defineProperty(exports, "BrokerStatsSchema", {
|
|
6221
7120
|
enumerable: true,
|
|
6222
7121
|
get: function() {
|
|
@@ -6313,6 +7212,12 @@ Object.defineProperty(exports, "DEVICE_STATUS_METHOD", {
|
|
|
6313
7212
|
return DEVICE_STATUS_METHOD;
|
|
6314
7213
|
}
|
|
6315
7214
|
});
|
|
7215
|
+
Object.defineProperty(exports, "DeclarationRefusedError", {
|
|
7216
|
+
enumerable: true,
|
|
7217
|
+
get: function() {
|
|
7218
|
+
return DeclarationRefusedError;
|
|
7219
|
+
}
|
|
7220
|
+
});
|
|
6316
7221
|
Object.defineProperty(exports, "DecodedAudioChunkSchema", {
|
|
6317
7222
|
enumerable: true,
|
|
6318
7223
|
get: function() {
|
|
@@ -6325,6 +7230,12 @@ Object.defineProperty(exports, "DisposerChain", {
|
|
|
6325
7230
|
return DisposerChain;
|
|
6326
7231
|
}
|
|
6327
7232
|
});
|
|
7233
|
+
Object.defineProperty(exports, "EntryDescriptorSchema", {
|
|
7234
|
+
enumerable: true,
|
|
7235
|
+
get: function() {
|
|
7236
|
+
return EntryDescriptorSchema;
|
|
7237
|
+
}
|
|
7238
|
+
});
|
|
6328
7239
|
Object.defineProperty(exports, "ErrorCodeSchema", {
|
|
6329
7240
|
enumerable: true,
|
|
6330
7241
|
get: function() {
|
|
@@ -6337,6 +7248,18 @@ Object.defineProperty(exports, "ErrorI18nPayloadSchema", {
|
|
|
6337
7248
|
return ErrorI18nPayloadSchema;
|
|
6338
7249
|
}
|
|
6339
7250
|
});
|
|
7251
|
+
Object.defineProperty(exports, "FilterRequiredError", {
|
|
7252
|
+
enumerable: true,
|
|
7253
|
+
get: function() {
|
|
7254
|
+
return FilterRequiredError;
|
|
7255
|
+
}
|
|
7256
|
+
});
|
|
7257
|
+
Object.defineProperty(exports, "ForeignSecretMarkerError", {
|
|
7258
|
+
enumerable: true,
|
|
7259
|
+
get: function() {
|
|
7260
|
+
return ForeignSecretMarkerError;
|
|
7261
|
+
}
|
|
7262
|
+
});
|
|
6340
7263
|
Object.defineProperty(exports, "FrameHandleSchema", {
|
|
6341
7264
|
enumerable: true,
|
|
6342
7265
|
get: function() {
|
|
@@ -6367,6 +7290,12 @@ Object.defineProperty(exports, "HISTORY_UNIT_LABELS", {
|
|
|
6367
7290
|
return HISTORY_UNIT_LABELS;
|
|
6368
7291
|
}
|
|
6369
7292
|
});
|
|
7293
|
+
Object.defineProperty(exports, "InvalidRecordError", {
|
|
7294
|
+
enumerable: true,
|
|
7295
|
+
get: function() {
|
|
7296
|
+
return InvalidRecordError;
|
|
7297
|
+
}
|
|
7298
|
+
});
|
|
6370
7299
|
Object.defineProperty(exports, "KeychainWriteRefusedError", {
|
|
6371
7300
|
enumerable: true,
|
|
6372
7301
|
get: function() {
|
|
@@ -6385,6 +7314,12 @@ Object.defineProperty(exports, "MODEL_FORMATS", {
|
|
|
6385
7314
|
return MODEL_FORMATS;
|
|
6386
7315
|
}
|
|
6387
7316
|
});
|
|
7317
|
+
Object.defineProperty(exports, "NoCallerError", {
|
|
7318
|
+
enumerable: true,
|
|
7319
|
+
get: function() {
|
|
7320
|
+
return NoCallerError;
|
|
7321
|
+
}
|
|
7322
|
+
});
|
|
6388
7323
|
Object.defineProperty(exports, "PEER_BYTES_CHUNK_BYTES", {
|
|
6389
7324
|
enumerable: true,
|
|
6390
7325
|
get: function() {
|
|
@@ -6421,6 +7356,12 @@ Object.defineProperty(exports, "PeerBytesTicketSchema", {
|
|
|
6421
7356
|
return PeerBytesTicketSchema;
|
|
6422
7357
|
}
|
|
6423
7358
|
});
|
|
7359
|
+
Object.defineProperty(exports, "PlaintextSecretError", {
|
|
7360
|
+
enumerable: true,
|
|
7361
|
+
get: function() {
|
|
7362
|
+
return PlaintextSecretError;
|
|
7363
|
+
}
|
|
7364
|
+
});
|
|
6424
7365
|
Object.defineProperty(exports, "ProfileRtspEntrySchema", {
|
|
6425
7366
|
enumerable: true,
|
|
6426
7367
|
get: function() {
|
|
@@ -6439,12 +7380,108 @@ Object.defineProperty(exports, "ProfileSlotStatusSchema", {
|
|
|
6439
7380
|
return ProfileSlotStatusSchema;
|
|
6440
7381
|
}
|
|
6441
7382
|
});
|
|
7383
|
+
Object.defineProperty(exports, "RECORDS_ERROR_CODES", {
|
|
7384
|
+
enumerable: true,
|
|
7385
|
+
get: function() {
|
|
7386
|
+
return RECORDS_ERROR_CODES;
|
|
7387
|
+
}
|
|
7388
|
+
});
|
|
7389
|
+
Object.defineProperty(exports, "RECORD_BATCH_MAX", {
|
|
7390
|
+
enumerable: true,
|
|
7391
|
+
get: function() {
|
|
7392
|
+
return RECORD_BATCH_MAX;
|
|
7393
|
+
}
|
|
7394
|
+
});
|
|
7395
|
+
Object.defineProperty(exports, "RECORD_BATCH_MAX_BYTES", {
|
|
7396
|
+
enumerable: true,
|
|
7397
|
+
get: function() {
|
|
7398
|
+
return RECORD_BATCH_MAX_BYTES;
|
|
7399
|
+
}
|
|
7400
|
+
});
|
|
7401
|
+
Object.defineProperty(exports, "RECORD_CLASSES", {
|
|
7402
|
+
enumerable: true,
|
|
7403
|
+
get: function() {
|
|
7404
|
+
return RECORD_CLASSES;
|
|
7405
|
+
}
|
|
7406
|
+
});
|
|
7407
|
+
Object.defineProperty(exports, "RECORD_DATABASES", {
|
|
7408
|
+
enumerable: true,
|
|
7409
|
+
get: function() {
|
|
7410
|
+
return RECORD_DATABASES;
|
|
7411
|
+
}
|
|
7412
|
+
});
|
|
7413
|
+
Object.defineProperty(exports, "RECORD_DEFAULT_MAX_DATA_BYTES", {
|
|
7414
|
+
enumerable: true,
|
|
7415
|
+
get: function() {
|
|
7416
|
+
return RECORD_DEFAULT_MAX_DATA_BYTES;
|
|
7417
|
+
}
|
|
7418
|
+
});
|
|
7419
|
+
Object.defineProperty(exports, "RECORD_DELETE_BATCH", {
|
|
7420
|
+
enumerable: true,
|
|
7421
|
+
get: function() {
|
|
7422
|
+
return RECORD_DELETE_BATCH;
|
|
7423
|
+
}
|
|
7424
|
+
});
|
|
7425
|
+
Object.defineProperty(exports, "RECORD_ID_MAX_LENGTH", {
|
|
7426
|
+
enumerable: true,
|
|
7427
|
+
get: function() {
|
|
7428
|
+
return RECORD_ID_MAX_LENGTH;
|
|
7429
|
+
}
|
|
7430
|
+
});
|
|
7431
|
+
Object.defineProperty(exports, "RECORD_MAX_DATA_BYTES", {
|
|
7432
|
+
enumerable: true,
|
|
7433
|
+
get: function() {
|
|
7434
|
+
return RECORD_MAX_DATA_BYTES;
|
|
7435
|
+
}
|
|
7436
|
+
});
|
|
7437
|
+
Object.defineProperty(exports, "RECORD_MAX_INDEXES", {
|
|
7438
|
+
enumerable: true,
|
|
7439
|
+
get: function() {
|
|
7440
|
+
return RECORD_MAX_INDEXES;
|
|
7441
|
+
}
|
|
7442
|
+
});
|
|
7443
|
+
Object.defineProperty(exports, "RECORD_MAX_INDEX_FIELDS", {
|
|
7444
|
+
enumerable: true,
|
|
7445
|
+
get: function() {
|
|
7446
|
+
return RECORD_MAX_INDEX_FIELDS;
|
|
7447
|
+
}
|
|
7448
|
+
});
|
|
7449
|
+
Object.defineProperty(exports, "RECORD_QUERY_MAX", {
|
|
7450
|
+
enumerable: true,
|
|
7451
|
+
get: function() {
|
|
7452
|
+
return RECORD_QUERY_MAX;
|
|
7453
|
+
}
|
|
7454
|
+
});
|
|
7455
|
+
Object.defineProperty(exports, "RECORD_SECRET_COLLECTION_PREFIX", {
|
|
7456
|
+
enumerable: true,
|
|
7457
|
+
get: function() {
|
|
7458
|
+
return RECORD_SECRET_COLLECTION_PREFIX;
|
|
7459
|
+
}
|
|
7460
|
+
});
|
|
7461
|
+
Object.defineProperty(exports, "RECORD_SETTINGS_MAX_ROWS", {
|
|
7462
|
+
enumerable: true,
|
|
7463
|
+
get: function() {
|
|
7464
|
+
return RECORD_SETTINGS_MAX_ROWS;
|
|
7465
|
+
}
|
|
7466
|
+
});
|
|
7467
|
+
Object.defineProperty(exports, "RECORD_SWEEP_INTERVAL_MS", {
|
|
7468
|
+
enumerable: true,
|
|
7469
|
+
get: function() {
|
|
7470
|
+
return RECORD_SWEEP_INTERVAL_MS;
|
|
7471
|
+
}
|
|
7472
|
+
});
|
|
6442
7473
|
Object.defineProperty(exports, "REDACTED_SECRET", {
|
|
6443
7474
|
enumerable: true,
|
|
6444
7475
|
get: function() {
|
|
6445
7476
|
return REDACTED_SECRET;
|
|
6446
7477
|
}
|
|
6447
7478
|
});
|
|
7479
|
+
Object.defineProperty(exports, "REMOVE_LEAF", {
|
|
7480
|
+
enumerable: true,
|
|
7481
|
+
get: function() {
|
|
7482
|
+
return REMOVE_LEAF;
|
|
7483
|
+
}
|
|
7484
|
+
});
|
|
6448
7485
|
Object.defineProperty(exports, "REVALIDATE_AFTER_MS", {
|
|
6449
7486
|
enumerable: true,
|
|
6450
7487
|
get: function() {
|
|
@@ -6475,6 +7512,72 @@ Object.defineProperty(exports, "ReadinessTimeoutError", {
|
|
|
6475
7512
|
return ReadinessTimeoutError;
|
|
6476
7513
|
}
|
|
6477
7514
|
});
|
|
7515
|
+
Object.defineProperty(exports, "RecordFieldPathSchema", {
|
|
7516
|
+
enumerable: true,
|
|
7517
|
+
get: function() {
|
|
7518
|
+
return RecordFieldPathSchema;
|
|
7519
|
+
}
|
|
7520
|
+
});
|
|
7521
|
+
Object.defineProperty(exports, "RecordIndexSchema", {
|
|
7522
|
+
enumerable: true,
|
|
7523
|
+
get: function() {
|
|
7524
|
+
return RecordIndexSchema;
|
|
7525
|
+
}
|
|
7526
|
+
});
|
|
7527
|
+
Object.defineProperty(exports, "RecordKindDeclarationSchema", {
|
|
7528
|
+
enumerable: true,
|
|
7529
|
+
get: function() {
|
|
7530
|
+
return RecordKindDeclarationSchema;
|
|
7531
|
+
}
|
|
7532
|
+
});
|
|
7533
|
+
Object.defineProperty(exports, "RecordKindNameSchema", {
|
|
7534
|
+
enumerable: true,
|
|
7535
|
+
get: function() {
|
|
7536
|
+
return RecordKindNameSchema;
|
|
7537
|
+
}
|
|
7538
|
+
});
|
|
7539
|
+
Object.defineProperty(exports, "RecordNotFoundError", {
|
|
7540
|
+
enumerable: true,
|
|
7541
|
+
get: function() {
|
|
7542
|
+
return RecordNotFoundError;
|
|
7543
|
+
}
|
|
7544
|
+
});
|
|
7545
|
+
Object.defineProperty(exports, "RecordRetentionSchema", {
|
|
7546
|
+
enumerable: true,
|
|
7547
|
+
get: function() {
|
|
7548
|
+
return RecordRetentionSchema;
|
|
7549
|
+
}
|
|
7550
|
+
});
|
|
7551
|
+
Object.defineProperty(exports, "RecordSecretUnavailableError", {
|
|
7552
|
+
enumerable: true,
|
|
7553
|
+
get: function() {
|
|
7554
|
+
return RecordSecretUnavailableError;
|
|
7555
|
+
}
|
|
7556
|
+
});
|
|
7557
|
+
Object.defineProperty(exports, "RecordTooLargeError", {
|
|
7558
|
+
enumerable: true,
|
|
7559
|
+
get: function() {
|
|
7560
|
+
return RecordTooLargeError;
|
|
7561
|
+
}
|
|
7562
|
+
});
|
|
7563
|
+
Object.defineProperty(exports, "RecordUniqueViolationError", {
|
|
7564
|
+
enumerable: true,
|
|
7565
|
+
get: function() {
|
|
7566
|
+
return RecordUniqueViolationError;
|
|
7567
|
+
}
|
|
7568
|
+
});
|
|
7569
|
+
Object.defineProperty(exports, "RecordsError", {
|
|
7570
|
+
enumerable: true,
|
|
7571
|
+
get: function() {
|
|
7572
|
+
return RecordsError;
|
|
7573
|
+
}
|
|
7574
|
+
});
|
|
7575
|
+
Object.defineProperty(exports, "RevConflictError", {
|
|
7576
|
+
enumerable: true,
|
|
7577
|
+
get: function() {
|
|
7578
|
+
return RevConflictError;
|
|
7579
|
+
}
|
|
7580
|
+
});
|
|
6478
7581
|
Object.defineProperty(exports, "SECRET_CLEAR", {
|
|
6479
7582
|
enumerable: true,
|
|
6480
7583
|
get: function() {
|
|
@@ -6523,6 +7626,18 @@ Object.defineProperty(exports, "SubscribeAudioChunksResultSchema", {
|
|
|
6523
7626
|
return SubscribeAudioChunksResultSchema;
|
|
6524
7627
|
}
|
|
6525
7628
|
});
|
|
7629
|
+
Object.defineProperty(exports, "UnindexedFilterError", {
|
|
7630
|
+
enumerable: true,
|
|
7631
|
+
get: function() {
|
|
7632
|
+
return UnindexedFilterError;
|
|
7633
|
+
}
|
|
7634
|
+
});
|
|
7635
|
+
Object.defineProperty(exports, "UnknownRecordKindError", {
|
|
7636
|
+
enumerable: true,
|
|
7637
|
+
get: function() {
|
|
7638
|
+
return UnknownRecordKindError;
|
|
7639
|
+
}
|
|
7640
|
+
});
|
|
6526
7641
|
Object.defineProperty(exports, "WELL_KNOWN_TABS", {
|
|
6527
7642
|
enumerable: true,
|
|
6528
7643
|
get: function() {
|
|
@@ -6571,12 +7686,24 @@ Object.defineProperty(exports, "asNumber", {
|
|
|
6571
7686
|
return asNumber;
|
|
6572
7687
|
}
|
|
6573
7688
|
});
|
|
7689
|
+
Object.defineProperty(exports, "asRecordsError", {
|
|
7690
|
+
enumerable: true,
|
|
7691
|
+
get: function() {
|
|
7692
|
+
return asRecordsError;
|
|
7693
|
+
}
|
|
7694
|
+
});
|
|
6574
7695
|
Object.defineProperty(exports, "asString", {
|
|
6575
7696
|
enumerable: true,
|
|
6576
7697
|
get: function() {
|
|
6577
7698
|
return asString;
|
|
6578
7699
|
}
|
|
6579
7700
|
});
|
|
7701
|
+
Object.defineProperty(exports, "assertValidDeclaration", {
|
|
7702
|
+
enumerable: true,
|
|
7703
|
+
get: function() {
|
|
7704
|
+
return assertValidDeclaration;
|
|
7705
|
+
}
|
|
7706
|
+
});
|
|
6580
7707
|
Object.defineProperty(exports, "audioChunkBytesPerSample", {
|
|
6581
7708
|
enumerable: true,
|
|
6582
7709
|
get: function() {
|
|
@@ -6631,6 +7758,12 @@ Object.defineProperty(exports, "collectSecretConfigKeys", {
|
|
|
6631
7758
|
return collectSecretConfigKeys;
|
|
6632
7759
|
}
|
|
6633
7760
|
});
|
|
7761
|
+
Object.defineProperty(exports, "collectSecretLeaves", {
|
|
7762
|
+
enumerable: true,
|
|
7763
|
+
get: function() {
|
|
7764
|
+
return collectSecretLeaves;
|
|
7765
|
+
}
|
|
7766
|
+
});
|
|
6634
7767
|
Object.defineProperty(exports, "collectSecretMarkerRefs", {
|
|
6635
7768
|
enumerable: true,
|
|
6636
7769
|
get: function() {
|
|
@@ -6679,6 +7812,12 @@ Object.defineProperty(exports, "createMirrorSource", {
|
|
|
6679
7812
|
return createMirrorSource;
|
|
6680
7813
|
}
|
|
6681
7814
|
});
|
|
7815
|
+
Object.defineProperty(exports, "createRecordsAccess", {
|
|
7816
|
+
enumerable: true,
|
|
7817
|
+
get: function() {
|
|
7818
|
+
return createRecordsAccess;
|
|
7819
|
+
}
|
|
7820
|
+
});
|
|
6682
7821
|
Object.defineProperty(exports, "createSecretsAccess", {
|
|
6683
7822
|
enumerable: true,
|
|
6684
7823
|
get: function() {
|
|
@@ -6697,12 +7836,30 @@ Object.defineProperty(exports, "customAction", {
|
|
|
6697
7836
|
return customAction;
|
|
6698
7837
|
}
|
|
6699
7838
|
});
|
|
7839
|
+
Object.defineProperty(exports, "declarationsOf", {
|
|
7840
|
+
enumerable: true,
|
|
7841
|
+
get: function() {
|
|
7842
|
+
return declarationsOf;
|
|
7843
|
+
}
|
|
7844
|
+
});
|
|
6700
7845
|
Object.defineProperty(exports, "defineCustomActions", {
|
|
6701
7846
|
enumerable: true,
|
|
6702
7847
|
get: function() {
|
|
6703
7848
|
return defineCustomActions;
|
|
6704
7849
|
}
|
|
6705
7850
|
});
|
|
7851
|
+
Object.defineProperty(exports, "defineEntryKind", {
|
|
7852
|
+
enumerable: true,
|
|
7853
|
+
get: function() {
|
|
7854
|
+
return defineEntryKind;
|
|
7855
|
+
}
|
|
7856
|
+
});
|
|
7857
|
+
Object.defineProperty(exports, "defineRecordKinds", {
|
|
7858
|
+
enumerable: true,
|
|
7859
|
+
get: function() {
|
|
7860
|
+
return defineRecordKinds;
|
|
7861
|
+
}
|
|
7862
|
+
});
|
|
6706
7863
|
Object.defineProperty(exports, "describeCustomActions", {
|
|
6707
7864
|
enumerable: true,
|
|
6708
7865
|
get: function() {
|
|
@@ -6733,6 +7890,12 @@ Object.defineProperty(exports, "emitReadiness", {
|
|
|
6733
7890
|
return emitReadiness;
|
|
6734
7891
|
}
|
|
6735
7892
|
});
|
|
7893
|
+
Object.defineProperty(exports, "entryBody", {
|
|
7894
|
+
enumerable: true,
|
|
7895
|
+
get: function() {
|
|
7896
|
+
return entryBody;
|
|
7897
|
+
}
|
|
7898
|
+
});
|
|
6736
7899
|
Object.defineProperty(exports, "event", {
|
|
6737
7900
|
enumerable: true,
|
|
6738
7901
|
get: function() {
|
|
@@ -6883,6 +8046,12 @@ Object.defineProperty(exports, "makeSourceBrokerId", {
|
|
|
6883
8046
|
return makeSourceBrokerId;
|
|
6884
8047
|
}
|
|
6885
8048
|
});
|
|
8049
|
+
Object.defineProperty(exports, "mapSecretLeaves", {
|
|
8050
|
+
enumerable: true,
|
|
8051
|
+
get: function() {
|
|
8052
|
+
return mapSecretLeaves;
|
|
8053
|
+
}
|
|
8054
|
+
});
|
|
6886
8055
|
Object.defineProperty(exports, "maskUrlCredentials", {
|
|
6887
8056
|
enumerable: true,
|
|
6888
8057
|
get: function() {
|
|
@@ -6955,6 +8124,12 @@ Object.defineProperty(exports, "parseProfileBrokerId", {
|
|
|
6955
8124
|
return parseProfileBrokerId;
|
|
6956
8125
|
}
|
|
6957
8126
|
});
|
|
8127
|
+
Object.defineProperty(exports, "parseSecretPath", {
|
|
8128
|
+
enumerable: true,
|
|
8129
|
+
get: function() {
|
|
8130
|
+
return parseSecretPath;
|
|
8131
|
+
}
|
|
8132
|
+
});
|
|
6958
8133
|
Object.defineProperty(exports, "parseSecretRef", {
|
|
6959
8134
|
enumerable: true,
|
|
6960
8135
|
get: function() {
|
|
@@ -6985,6 +8160,30 @@ Object.defineProperty(exports, "readinessKey", {
|
|
|
6985
8160
|
return readinessKey;
|
|
6986
8161
|
}
|
|
6987
8162
|
});
|
|
8163
|
+
Object.defineProperty(exports, "recordArrayItemPath", {
|
|
8164
|
+
enumerable: true,
|
|
8165
|
+
get: function() {
|
|
8166
|
+
return recordArrayItemPath;
|
|
8167
|
+
}
|
|
8168
|
+
});
|
|
8169
|
+
Object.defineProperty(exports, "recordSecretCollection", {
|
|
8170
|
+
enumerable: true,
|
|
8171
|
+
get: function() {
|
|
8172
|
+
return recordSecretCollection;
|
|
8173
|
+
}
|
|
8174
|
+
});
|
|
8175
|
+
Object.defineProperty(exports, "recordSecretRef", {
|
|
8176
|
+
enumerable: true,
|
|
8177
|
+
get: function() {
|
|
8178
|
+
return recordSecretRef;
|
|
8179
|
+
}
|
|
8180
|
+
});
|
|
8181
|
+
Object.defineProperty(exports, "recordsErrorFromMessage", {
|
|
8182
|
+
enumerable: true,
|
|
8183
|
+
get: function() {
|
|
8184
|
+
return recordsErrorFromMessage;
|
|
8185
|
+
}
|
|
8186
|
+
});
|
|
6988
8187
|
Object.defineProperty(exports, "registerKnownSecret", {
|
|
6989
8188
|
enumerable: true,
|
|
6990
8189
|
get: function() {
|
|
@@ -7033,6 +8232,12 @@ Object.defineProperty(exports, "scrubKnownSecrets", {
|
|
|
7033
8232
|
return scrubKnownSecrets;
|
|
7034
8233
|
}
|
|
7035
8234
|
});
|
|
8235
|
+
Object.defineProperty(exports, "secretArrayPrefixes", {
|
|
8236
|
+
enumerable: true,
|
|
8237
|
+
get: function() {
|
|
8238
|
+
return secretArrayPrefixes;
|
|
8239
|
+
}
|
|
8240
|
+
});
|
|
7036
8241
|
Object.defineProperty(exports, "secretTreeFromPaths", {
|
|
7037
8242
|
enumerable: true,
|
|
7038
8243
|
get: function() {
|