@camstack/types 1.2.386 → 1.2.388
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.js +26 -16
- package/dist/addon.mjs +26 -16
- package/dist/auth/credential-scope.d.ts +37 -5
- package/dist/auth/principal-scope.d.ts +1 -1
- package/dist/capabilities/alarm-panel.cap.d.ts +10 -2
- package/dist/capabilities/capability-definition.d.ts +21 -3
- package/dist/capabilities/connectivity.cap.d.ts +10 -2
- package/dist/capabilities/device-history.cap.d.ts +195 -3
- package/dist/capabilities/dishwasher.cap.d.ts +17 -0
- package/dist/capabilities/enum-sensor.cap.d.ts +12 -2
- package/dist/capabilities/index.d.ts +6 -5
- package/dist/capabilities/llm.cap.d.ts +252 -309
- package/dist/capabilities/lock-control.cap.d.ts +9 -2
- package/dist/capabilities/log-destination.cap.d.ts +148 -19
- package/dist/capabilities/media-player.cap.d.ts +15 -2
- package/dist/capabilities/notification-rules.cap.d.ts +213 -13
- package/dist/capabilities/stream-params.cap.d.ts +24 -2
- package/dist/capabilities/user-management.cap.d.ts +4 -409
- package/dist/client.js +76 -11
- package/dist/client.mjs +76 -11
- package/dist/device/base-device.d.ts +34 -1
- package/dist/device/index.d.ts +2 -2
- package/dist/generated/addon-api.d.ts +548 -187
- package/dist/generated/cap-input-defaults.d.ts +1 -1
- package/dist/generated/collection-array-methods.d.ts +2 -2
- package/dist/generated/history-catalog.d.ts +1 -1
- 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 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +861 -164
- package/dist/index.mjs +815 -162
- package/dist/interfaces/addon-data-plane.d.ts +4 -4
- package/dist/interfaces/addon-peer-bytes.d.ts +1 -1
- package/dist/interfaces/logging.d.ts +16 -1
- package/dist/notification/media-image.d.ts +67 -0
- package/dist/schemas/auth-records.d.ts +1 -1
- package/dist/schemas/user-preferences.d.ts +103 -0
- package/dist/{sleep-BxjU_fJM.mjs → sleep-BSuCCFjf.mjs} +34 -5
- package/dist/{sleep-BE7_6UnC.js → sleep-DKtoyk6X.js} +34 -5
- package/package.json +1 -1
|
@@ -40,9 +40,9 @@ export interface AddonDataPlane {
|
|
|
40
40
|
* transport in front of it (auth + reverse-proxy). */
|
|
41
41
|
export type DataPlaneHandler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
|
|
42
42
|
/**
|
|
43
|
-
* The share-view scope kinds a
|
|
44
|
-
* and validates them (`
|
|
45
|
-
* list); a data plane names the kinds it ACCEPTS in `share`.
|
|
43
|
+
* The share-view scope kinds a share-link token can carry. The hub mints
|
|
44
|
+
* and validates them (`ShareViewGrantSchema` builds its
|
|
45
|
+
* enum from this list); a data plane names the kinds it ACCEPTS in `share`.
|
|
46
46
|
*/
|
|
47
47
|
export declare const SHARE_VIEW_KINDS: readonly ['grid-view', 'events-view'];
|
|
48
48
|
export type ShareViewKind = (typeof SHARE_VIEW_KINDS)[number];
|
|
@@ -57,7 +57,7 @@ export interface AddonDataPlaneServeOptions {
|
|
|
57
57
|
/** The addon's request handler — real `IncomingMessage`/`ServerResponse`. */
|
|
58
58
|
readonly handler: DataPlaneHandler;
|
|
59
59
|
/**
|
|
60
|
-
* Share-token scope kinds this plane serves. ABSENT means a
|
|
60
|
+
* Share-token scope kinds this plane serves. ABSENT means a share-link
|
|
61
61
|
* token is refused here (403), whatever `access` says: a share link is a
|
|
62
62
|
* bearer credential for one view of a few devices, not a session, and a
|
|
63
63
|
* plane that never read the scope headers would serve every device to it.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* - the data-plane listener binds `127.0.0.1` behind a per-listener secret that
|
|
11
11
|
* **only the hub** presents, and the hub's `/addon/<id>/…` proxy in front of
|
|
12
|
-
* it takes a session cookie, a
|
|
12
|
+
* it takes a session cookie, a token scoped `{type:'addon'}` or a JWT
|
|
13
13
|
* — an addon holds none of those;
|
|
14
14
|
* - `ctx.api.<cap>.subscribe` is refused on an addon caller by design, so a
|
|
15
15
|
* streaming cap method is not available either;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LogReadCapabilities, LogReadQuery, LogReadResult } from '../capabilities/log-destination.cap.js';
|
|
1
2
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
3
|
/**
|
|
3
4
|
* Severity ordering. Declared once here because it had already been re-declared
|
|
@@ -75,6 +76,13 @@ export interface LogTags {
|
|
|
75
76
|
readonly [key: string]: string | number | undefined;
|
|
76
77
|
}
|
|
77
78
|
export interface LogEntry {
|
|
79
|
+
/**
|
|
80
|
+
* `<bootId>.<seq>`, minted by the LogManager that FIRST accepted the line
|
|
81
|
+
* on this process (D898). Identical in the in-memory tail, the live
|
|
82
|
+
* subscription and the rotated file, so a page read from disk and a line
|
|
83
|
+
* pushed live dedupe exactly. Absent only on an entry built by hand.
|
|
84
|
+
*/
|
|
85
|
+
id?: string;
|
|
78
86
|
timestamp: Date;
|
|
79
87
|
level: LogLevel;
|
|
80
88
|
/** Single free-form label (e.g. 'EventPersistence', 'rtsp', 'AddonRegistry').
|
|
@@ -98,7 +106,14 @@ export interface ILogDestination {
|
|
|
98
106
|
initialize(): Promise<void>;
|
|
99
107
|
shutdown(): Promise<void>;
|
|
100
108
|
write(entry: LogEntry): void;
|
|
101
|
-
|
|
109
|
+
/** Absent ⇒ this destination only ships lines (D898). */
|
|
110
|
+
describeRead?(): Promise<LogReadCapabilities>;
|
|
111
|
+
read?(query: LogReadQuery): Promise<LogReadResult>;
|
|
112
|
+
cancelRead?(input: {
|
|
113
|
+
readonly requestId: string;
|
|
114
|
+
}): Promise<{
|
|
115
|
+
readonly cancelled: boolean;
|
|
116
|
+
}>;
|
|
102
117
|
}
|
|
103
118
|
/**
|
|
104
119
|
* Inline, per-call extras passed to every `IScopedLogger` method.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* media-image — the ONE media choice of a notification rule (D897).
|
|
3
|
+
*
|
|
4
|
+
* A rule used to state its picture as three fields — `attach` (which stored
|
|
5
|
+
* kind to look for), `frame` (cropped / full / boxed) and `zoneCrop` — and the
|
|
6
|
+
* ladders those fed picked a STORED kind, so one rule shipped a subject crop on
|
|
7
|
+
* one event and a boxed scene on the next depending on what had landed. The
|
|
8
|
+
* picture is now rendered at send time from a clean frame, and the rule says
|
|
9
|
+
* only what it wants to SEE: `image` (`scene-boxes` | `crop` | `clean` |
|
|
10
|
+
* `none`) plus `showTriggerZone`.
|
|
11
|
+
*
|
|
12
|
+
* This module is the only reader of the legacy triple. The rule store applies
|
|
13
|
+
* {@link normalizeNcMediaPolicy} on load (a READ projection, like the retired
|
|
14
|
+
* delivery fields of D692) and on every write, so a stored rule converges on
|
|
15
|
+
* `image` the first time it is saved, and an editor that still sends the
|
|
16
|
+
* triple (the viewer, until it follows) is folded on the way in.
|
|
17
|
+
*/
|
|
18
|
+
import type { NcConditions, NcMediaImage, NcMediaPolicy } from '../capabilities/notification-rules.cap.js';
|
|
19
|
+
import { type NcRuleKind, type NcRuleSectionSubject } from './rule-kinds.js';
|
|
20
|
+
/** Every mode, in the order an editor offers them. */
|
|
21
|
+
export declare const NC_MEDIA_IMAGE_MODES: readonly NcMediaImage[];
|
|
22
|
+
/**
|
|
23
|
+
* The modes a rule of this kind can honour. A kind that carries no media gets
|
|
24
|
+
* none (its row ships text, or — an alarm — its SOURCE rule's picture); a kind
|
|
25
|
+
* whose subject has no region of the frame (a sound) is never offered `crop`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function imageModesForKind(kind: NcRuleKind): readonly NcMediaImage[];
|
|
28
|
+
/**
|
|
29
|
+
* The zone ids that FIRE a rule: its `zones` condition, or an occupancy rule's
|
|
30
|
+
* own scoped zone. Empty when the trigger is not a zone — and then
|
|
31
|
+
* `showTriggerZone` has nothing to draw and is refused on save.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ruleTriggerZoneIds(conditions: NcConditions): readonly string[];
|
|
34
|
+
/**
|
|
35
|
+
* What the legacy triple MEANT, as a mode. `zoneCrop` forced the clean
|
|
36
|
+
* keyFrame ladder and dropped `frame`, so it is `clean` whatever else was set;
|
|
37
|
+
* `frame` decided over `attach` when present; `keyFrame` was the clean scene;
|
|
38
|
+
* every other still (`best`, `best-matching`, the default) was the subject.
|
|
39
|
+
*/
|
|
40
|
+
export declare function legacyImageMode(media: NcMediaPolicy): NcMediaImage;
|
|
41
|
+
/**
|
|
42
|
+
* The mode a rule's picture is rendered in. `image` when stored; else what the
|
|
43
|
+
* legacy triple meant — and, for a SENSOR rule written before D897, `clean`
|
|
44
|
+
* whatever it stored (even `attach: 'none'`), because its stored triple was
|
|
45
|
+
* ignored and one plain snapshot always shipped (operator ruling, 2026-10-01):
|
|
46
|
+
* the migration keeps what the rule actually DID. Clamped to what the kind can
|
|
47
|
+
* honour.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveNcMediaImage(media: NcMediaPolicy, kind: NcRuleKind): NcMediaImage;
|
|
50
|
+
/** The rule fields the normalisation reads. */
|
|
51
|
+
export interface NcMediaRuleSubject extends NcRuleSectionSubject {
|
|
52
|
+
readonly conditions: NcConditions;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The stored shape of a media policy: `image` set, the legacy triple gone.
|
|
56
|
+
* `showTriggerZone` survives only where it can be drawn — a zone trigger and a
|
|
57
|
+
* mode other than `crop`/`none`; a legacy `zoneCrop` on a zone rule becomes it.
|
|
58
|
+
* Every other field (gif, clip, rolls, speed, profile, linked cameras) is
|
|
59
|
+
* carried through untouched. Pure; never throws.
|
|
60
|
+
*/
|
|
61
|
+
export declare function normalizeNcMediaPolicy(media: NcMediaPolicy, rule: NcMediaRuleSubject): NcMediaPolicy;
|
|
62
|
+
/**
|
|
63
|
+
* Why a media policy cannot be SAVED on this rule, or null. Server-side and
|
|
64
|
+
* editor alike: `showTriggerZone` on a rule whose trigger is not a zone, and a
|
|
65
|
+
* mode the rule's kind cannot honour.
|
|
66
|
+
*/
|
|
67
|
+
export declare function ncMediaPolicyError(media: NcMediaPolicy, rule: NcMediaRuleSubject): string | null;
|
|
@@ -22,7 +22,7 @@ import { DeviceType } from '../device/device-type.js';
|
|
|
22
22
|
* `super_admin` — collapsed onto the single boolean because every
|
|
23
23
|
* non-admin caller is governed by the same scope-check rules; the
|
|
24
24
|
* distinction was only ever used to route role-specific procedures
|
|
25
|
-
* which we no longer have. CLI / webhook integrations are `
|
|
25
|
+
* which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
|
|
26
26
|
* with `isAdmin: false` + an explicit scope list.
|
|
27
27
|
*/
|
|
28
28
|
/** Per-method access flavour. Materialised on every cap method via codegen. */
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-user ACCOUNT preferences (D894): the hub-side half of the viewer's two
|
|
3
|
+
* settings levels.
|
|
4
|
+
*
|
|
5
|
+
* - DEVICE settings never leave the phone.
|
|
6
|
+
* - ACCOUNT settings live here: one row per `(user, namespace)`, private to
|
|
7
|
+
* that user, synced across every device signed in as them, last write wins
|
|
8
|
+
* unless the writer sends the revision it based its edit on.
|
|
9
|
+
*
|
|
10
|
+
* A setting lives in exactly ONE level; there are no overrides. The caller
|
|
11
|
+
* never names a user: the hub stamps the principal's own id, admin included.
|
|
12
|
+
*
|
|
13
|
+
* The contract the client codes against is the `preferences.*` tRPC router
|
|
14
|
+
* (`server/backend/src/api/core/preferences.router.ts`).
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
/** `viewer.app`, `viewer.cameras`, `viewer.grids` … — lowercase, dot/dash separated. */
|
|
18
|
+
export declare const PREFERENCES_NAMESPACE_PATTERN: RegExp;
|
|
19
|
+
/** One row's value, measured as UTF-8 JSON. */
|
|
20
|
+
export declare const PREFERENCES_MAX_VALUE_BYTES: number;
|
|
21
|
+
/** Namespaces one user may hold. */
|
|
22
|
+
export declare const PREFERENCES_MAX_NAMESPACES = 32;
|
|
23
|
+
/** The opaque client id a writer stamps (`updatedByDevice`). */
|
|
24
|
+
export declare const PREFERENCES_MAX_DEVICE_ID_LENGTH = 64;
|
|
25
|
+
export declare const PreferenceNamespaceSchema: z.ZodString;
|
|
26
|
+
export type PreferenceNamespace = z.infer<typeof PreferenceNamespaceSchema>;
|
|
27
|
+
/** A namespace's value: a JSON object, opaque to the hub. */
|
|
28
|
+
export declare const PreferenceValueSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
29
|
+
export type PreferenceValue = z.infer<typeof PreferenceValueSchema>;
|
|
30
|
+
export declare const PreferenceDeviceIdSchema: z.ZodString;
|
|
31
|
+
/** A stored row, as the owner reads it. */
|
|
32
|
+
export declare const PreferenceRowSchema: z.ZodObject<{
|
|
33
|
+
namespace: z.ZodString;
|
|
34
|
+
value: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
35
|
+
revision: z.ZodNumber;
|
|
36
|
+
updatedAt: z.ZodNumber;
|
|
37
|
+
updatedByDevice: z.ZodNullable<z.ZodString>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
export type PreferenceRow = z.infer<typeof PreferenceRowSchema>;
|
|
40
|
+
export declare const PreferencesGetInputSchema: z.ZodObject<{
|
|
41
|
+
namespaces: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
export type PreferencesGetInput = z.infer<typeof PreferencesGetInputSchema>;
|
|
44
|
+
export declare const PreferencesGetOutputSchema: z.ZodObject<{
|
|
45
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
46
|
+
namespace: z.ZodString;
|
|
47
|
+
value: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
48
|
+
revision: z.ZodNumber;
|
|
49
|
+
updatedAt: z.ZodNumber;
|
|
50
|
+
updatedByDevice: z.ZodNullable<z.ZodString>;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
export type PreferencesGetOutput = z.infer<typeof PreferencesGetOutputSchema>;
|
|
54
|
+
export declare const PreferencesPutInputSchema: z.ZodObject<{
|
|
55
|
+
namespace: z.ZodString;
|
|
56
|
+
value: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
57
|
+
baseRevision: z.ZodOptional<z.ZodNumber>;
|
|
58
|
+
deviceId: z.ZodOptional<z.ZodString>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
export type PreferencesPutInput = z.infer<typeof PreferencesPutInputSchema>;
|
|
61
|
+
export declare const PreferencesPutOutputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
62
|
+
status: z.ZodLiteral<"saved">;
|
|
63
|
+
row: z.ZodObject<{
|
|
64
|
+
namespace: z.ZodString;
|
|
65
|
+
value: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
66
|
+
revision: z.ZodNumber;
|
|
67
|
+
updatedAt: z.ZodNumber;
|
|
68
|
+
updatedByDevice: z.ZodNullable<z.ZodString>;
|
|
69
|
+
}, z.core.$strip>;
|
|
70
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
71
|
+
status: z.ZodLiteral<"conflict">;
|
|
72
|
+
current: z.ZodNullable<z.ZodObject<{
|
|
73
|
+
namespace: z.ZodString;
|
|
74
|
+
value: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
75
|
+
revision: z.ZodNumber;
|
|
76
|
+
updatedAt: z.ZodNumber;
|
|
77
|
+
updatedByDevice: z.ZodNullable<z.ZodString>;
|
|
78
|
+
}, z.core.$strip>>;
|
|
79
|
+
}, z.core.$strip>], "status">;
|
|
80
|
+
export type PreferencesPutOutput = z.infer<typeof PreferencesPutOutputSchema>;
|
|
81
|
+
export declare const PreferencesDeleteInputSchema: z.ZodObject<{
|
|
82
|
+
namespace: z.ZodString;
|
|
83
|
+
}, z.core.$strip>;
|
|
84
|
+
export type PreferencesDeleteInput = z.infer<typeof PreferencesDeleteInputSchema>;
|
|
85
|
+
export declare const PreferencesDeleteOutputSchema: z.ZodObject<{
|
|
86
|
+
deleted: z.ZodBoolean;
|
|
87
|
+
}, z.core.$strip>;
|
|
88
|
+
export type PreferencesDeleteOutput = z.infer<typeof PreferencesDeleteOutputSchema>;
|
|
89
|
+
export declare const PreferencesChangedSinceInputSchema: z.ZodObject<{
|
|
90
|
+
revisionByNamespace: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
91
|
+
}, z.core.$strip>;
|
|
92
|
+
export type PreferencesChangedSinceInput = z.infer<typeof PreferencesChangedSinceInputSchema>;
|
|
93
|
+
export declare const PreferencesChangedSinceOutputSchema: z.ZodObject<{
|
|
94
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
95
|
+
namespace: z.ZodString;
|
|
96
|
+
value: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
97
|
+
revision: z.ZodNumber;
|
|
98
|
+
updatedAt: z.ZodNumber;
|
|
99
|
+
updatedByDevice: z.ZodNullable<z.ZodString>;
|
|
100
|
+
}, z.core.$strip>>;
|
|
101
|
+
deleted: z.ZodArray<z.ZodString>;
|
|
102
|
+
}, z.core.$strip>;
|
|
103
|
+
export type PreferencesChangedSinceOutput = z.infer<typeof PreferencesChangedSinceOutputSchema>;
|
|
@@ -2804,9 +2804,9 @@ var DisposerChain = class {
|
|
|
2804
2804
|
*/
|
|
2805
2805
|
var DATAPLANE_SECRET_HEADER = "x-camstack-dataplane-secret";
|
|
2806
2806
|
/**
|
|
2807
|
-
* The share-view scope kinds a
|
|
2808
|
-
* and validates them (`
|
|
2809
|
-
* list); a data plane names the kinds it ACCEPTS in `share`.
|
|
2807
|
+
* The share-view scope kinds a share-link token can carry. The hub mints
|
|
2808
|
+
* and validates them (`ShareViewGrantSchema` builds its
|
|
2809
|
+
* enum from this list); a data plane names the kinds it ACCEPTS in `share`.
|
|
2810
2810
|
*/
|
|
2811
2811
|
var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
|
|
2812
2812
|
//#endregion
|
|
@@ -4203,6 +4203,20 @@ function parseSettingsArrayAdoptsFrom(from) {
|
|
|
4203
4203
|
function isRecord(value) {
|
|
4204
4204
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4205
4205
|
}
|
|
4206
|
+
/** RFC 7396: objects merge key by key, `null` removes, anything else replaces. */
|
|
4207
|
+
function mergePatch(target, patch) {
|
|
4208
|
+
if (!isRecord(patch)) return target;
|
|
4209
|
+
const out = { ...target };
|
|
4210
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
4211
|
+
if (value === null) {
|
|
4212
|
+
delete out[key];
|
|
4213
|
+
continue;
|
|
4214
|
+
}
|
|
4215
|
+
const current = out[key];
|
|
4216
|
+
out[key] = isRecord(value) && isRecord(current) ? mergePatch(current, value) : value;
|
|
4217
|
+
}
|
|
4218
|
+
return out;
|
|
4219
|
+
}
|
|
4206
4220
|
function markersOf(decl, body) {
|
|
4207
4221
|
const out = /* @__PURE__ */ new Map();
|
|
4208
4222
|
mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => {
|
|
@@ -4384,7 +4398,20 @@ function makeInMemoryRecords(owner = "spec") {
|
|
|
4384
4398
|
releasedRefs: released
|
|
4385
4399
|
};
|
|
4386
4400
|
},
|
|
4387
|
-
patch: async () =>
|
|
4401
|
+
patch: async ({ kind, id, data, at, ifRev }) => {
|
|
4402
|
+
const prev = table(kind).get(id);
|
|
4403
|
+
if (prev === void 0) throw new Error(`${kind}/${id}: no such record`);
|
|
4404
|
+
if (ifRev !== void 0 && prev.rev !== ifRev) throw new Error("stale ifRev");
|
|
4405
|
+
const { rev, released } = write(kind, {
|
|
4406
|
+
id,
|
|
4407
|
+
...at !== void 0 && at !== null ? { at } : prev.at !== null ? { at: prev.at } : {},
|
|
4408
|
+
data: mergePatch(prev.data, data)
|
|
4409
|
+
});
|
|
4410
|
+
return {
|
|
4411
|
+
rev,
|
|
4412
|
+
releasedRefs: released
|
|
4413
|
+
};
|
|
4414
|
+
},
|
|
4388
4415
|
delete: async ({ kind, id }) => {
|
|
4389
4416
|
if (writesFail) throw new Error("records engine unreachable");
|
|
4390
4417
|
const row = table(kind).get(id);
|
|
@@ -5375,7 +5402,9 @@ var HISTORY_UNIT_LABELS = {
|
|
|
5375
5402
|
ms: "ms",
|
|
5376
5403
|
s: "s",
|
|
5377
5404
|
days: "days",
|
|
5378
|
-
bytes: "bytes"
|
|
5405
|
+
bytes: "bytes",
|
|
5406
|
+
kbps: "kbps",
|
|
5407
|
+
fps: "fps"
|
|
5379
5408
|
};
|
|
5380
5409
|
/** Capture floor (ms) applied to `gauge` / `counter` series when a field states none. */
|
|
5381
5410
|
var HISTORY_DEFAULT_MIN_INTERVAL_MS = 1e4;
|
|
@@ -2804,9 +2804,9 @@ var DisposerChain = class {
|
|
|
2804
2804
|
*/
|
|
2805
2805
|
var DATAPLANE_SECRET_HEADER = "x-camstack-dataplane-secret";
|
|
2806
2806
|
/**
|
|
2807
|
-
* The share-view scope kinds a
|
|
2808
|
-
* and validates them (`
|
|
2809
|
-
* list); a data plane names the kinds it ACCEPTS in `share`.
|
|
2807
|
+
* The share-view scope kinds a share-link token can carry. The hub mints
|
|
2808
|
+
* and validates them (`ShareViewGrantSchema` builds its
|
|
2809
|
+
* enum from this list); a data plane names the kinds it ACCEPTS in `share`.
|
|
2810
2810
|
*/
|
|
2811
2811
|
var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
|
|
2812
2812
|
//#endregion
|
|
@@ -4203,6 +4203,20 @@ function parseSettingsArrayAdoptsFrom(from) {
|
|
|
4203
4203
|
function isRecord(value) {
|
|
4204
4204
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4205
4205
|
}
|
|
4206
|
+
/** RFC 7396: objects merge key by key, `null` removes, anything else replaces. */
|
|
4207
|
+
function mergePatch(target, patch) {
|
|
4208
|
+
if (!isRecord(patch)) return target;
|
|
4209
|
+
const out = { ...target };
|
|
4210
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
4211
|
+
if (value === null) {
|
|
4212
|
+
delete out[key];
|
|
4213
|
+
continue;
|
|
4214
|
+
}
|
|
4215
|
+
const current = out[key];
|
|
4216
|
+
out[key] = isRecord(value) && isRecord(current) ? mergePatch(current, value) : value;
|
|
4217
|
+
}
|
|
4218
|
+
return out;
|
|
4219
|
+
}
|
|
4206
4220
|
function markersOf(decl, body) {
|
|
4207
4221
|
const out = /* @__PURE__ */ new Map();
|
|
4208
4222
|
mapSecretLeaves(body, decl.secretPaths, decl.secretArrayKeys, (leaf) => {
|
|
@@ -4384,7 +4398,20 @@ function makeInMemoryRecords(owner = "spec") {
|
|
|
4384
4398
|
releasedRefs: released
|
|
4385
4399
|
};
|
|
4386
4400
|
},
|
|
4387
|
-
patch: async () =>
|
|
4401
|
+
patch: async ({ kind, id, data, at, ifRev }) => {
|
|
4402
|
+
const prev = table(kind).get(id);
|
|
4403
|
+
if (prev === void 0) throw new Error(`${kind}/${id}: no such record`);
|
|
4404
|
+
if (ifRev !== void 0 && prev.rev !== ifRev) throw new Error("stale ifRev");
|
|
4405
|
+
const { rev, released } = write(kind, {
|
|
4406
|
+
id,
|
|
4407
|
+
...at !== void 0 && at !== null ? { at } : prev.at !== null ? { at: prev.at } : {},
|
|
4408
|
+
data: mergePatch(prev.data, data)
|
|
4409
|
+
});
|
|
4410
|
+
return {
|
|
4411
|
+
rev,
|
|
4412
|
+
releasedRefs: released
|
|
4413
|
+
};
|
|
4414
|
+
},
|
|
4388
4415
|
delete: async ({ kind, id }) => {
|
|
4389
4416
|
if (writesFail) throw new Error("records engine unreachable");
|
|
4390
4417
|
const row = table(kind).get(id);
|
|
@@ -5375,7 +5402,9 @@ var HISTORY_UNIT_LABELS = {
|
|
|
5375
5402
|
ms: "ms",
|
|
5376
5403
|
s: "s",
|
|
5377
5404
|
days: "days",
|
|
5378
|
-
bytes: "bytes"
|
|
5405
|
+
bytes: "bytes",
|
|
5406
|
+
kbps: "kbps",
|
|
5407
|
+
fps: "fps"
|
|
5379
5408
|
};
|
|
5380
5409
|
/** Capture floor (ms) applied to `gauge` / `counter` series when a field states none. */
|
|
5381
5410
|
var HISTORY_DEFAULT_MIN_INTERVAL_MS = 1e4;
|