@camstack/types 1.1.20 → 1.1.21

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.
@@ -0,0 +1,14 @@
1
+ import { type ExpressionEvalHooks } from './builtins.js';
2
+ import type { ExpressionNode, ExpressionValue } from './ast.js';
3
+ export interface ExpressionEvalOptions {
4
+ readonly hooks?: ExpressionEvalHooks;
5
+ readonly maxSteps?: number;
6
+ }
7
+ /** Build a null-prototype scope from own-enumerable binding entries. Inherited
8
+ * keys of the input (e.g. from a `{__proto__: {...}}` payload) are NOT copied,
9
+ * so nothing smuggles in via the prototype chain. */
10
+ export declare function createExpressionScope(bindings: Readonly<Record<string, ExpressionValue>>): Record<string, ExpressionValue>;
11
+ /** Evaluate an AST node against a scope. Throws `ExpressionEvalError` on any
12
+ * runtime failure (unknown identifier, type mismatch, non-finite result,
13
+ * step-budget exhaustion). */
14
+ export declare function evaluateAst(node: ExpressionNode, scope: Record<string, ExpressionValue>, opts?: ExpressionEvalOptions): ExpressionValue;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Safe expression engine — public surface. A non-Turing-complete infix
3
+ * mini-language (tokenizer → Pratt parser → whitelisted-AST interpreter) with
4
+ * NO eval / new Function / node:vm, NO member access, NO loops/lambdas, and
5
+ * hard resource bounds. Powers the `expression` DeviceLinkSource kind.
6
+ *
7
+ * This is the module barrel; leaf files inside @camstack/types MUST import from
8
+ * the deep modules (e.g. `../expression/compile.js`), never through this file
9
+ * OR the root barrel (see biome-plugins/no-types-barrel-leaf-import.grit).
10
+ */
11
+ export type { ExpressionValue, ExpressionNode, ExpressionLiteralNode, ExpressionIdentifierNode, ExpressionUnaryNode, ExpressionBinaryNode, ExpressionLogicalNode, ExpressionConditionalNode, ExpressionCallNode, ExpressionBinaryOperator, ExpressionLogicalOperator, ExpressionUnaryOperator, } from './ast.js';
12
+ export { ExpressionParseError, ExpressionEvalError } from './errors.js';
13
+ export { MAX_EXPRESSION_SOURCE_LENGTH, MAX_EXPRESSION_AST_NODES, MAX_EXPRESSION_EVAL_STEPS, MAX_EXPRESSION_BINDINGS, MAX_EXPRESSION_CALL_ARGS, EXPRESSION_COMPILE_CACHE_CAPACITY, EXPRESSION_IDENTIFIER_RE, RESERVED_BINDING_NAMES, } from './limits.js';
14
+ export { tokenize } from './tokenizer.js';
15
+ export type { Token, Punctuator, Keyword } from './tokenizer.js';
16
+ export { parseExpression } from './parser.js';
17
+ export type { ParsedExpression } from './parser.js';
18
+ export { EXPRESSION_BUILTINS, EXPRESSION_BUILTIN_NAMES, } from './builtins.js';
19
+ export type { ExpressionBuiltin, ExpressionEvalHooks } from './builtins.js';
20
+ export { createExpressionScope, evaluateAst } from './evaluator.js';
21
+ export type { ExpressionEvalOptions } from './evaluator.js';
22
+ export { compileExpression, compileExpressionSafe } from './compile.js';
23
+ export type { CompileResult } from './compile.js';
24
+ export { EXPRESSION_INJECTED_NOW, toExpressionValue, validateExpressionSource, evaluateLinkExpression, } from './link-expression.js';
25
+ export type { ExpressionSourceInput, EvaluateLinkExpressionResult, } from './link-expression.js';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resource-bound constants for the safe expression engine.
3
+ *
4
+ * Every bound is defense-in-depth: the grammar is non-Turing-complete (no
5
+ * loops, recursion, lambdas or member access — see `ast.ts`), so evaluation is
6
+ * O(nodeCount) by construction. These caps merely put a hard ceiling on the
7
+ * work a single author-supplied expression can request, so a hostile or
8
+ * accidental pathological string can never spend unbounded CPU/memory.
9
+ */
10
+ /** Max source length (chars) — checked BEFORE tokenizing so a huge string is
11
+ * rejected without allocation. */
12
+ export declare const MAX_EXPRESSION_SOURCE_LENGTH = 2048;
13
+ /** Max AST nodes — checked during parse; a deeply nested grouping that exceeds
14
+ * this is rejected as "expression too complex". */
15
+ export declare const MAX_EXPRESSION_AST_NODES = 256;
16
+ /** Defense-in-depth walker step budget — one increment per node visit during
17
+ * evaluation. The grammar guarantees O(nodeCount) walks, so this can only trip
18
+ * on a crafted maximum-size AST. */
19
+ export declare const MAX_EXPRESSION_EVAL_STEPS = 4096;
20
+ /** Max named bindings on one `DeviceLinkExpressionSource`. */
21
+ export declare const MAX_EXPRESSION_BINDINGS = 32;
22
+ /** Max positional arguments to any builtin call. */
23
+ export declare const MAX_EXPRESSION_CALL_ARGS = 16;
24
+ /** LRU compile-cache capacity (parsed ASTs keyed by raw source string). */
25
+ export declare const EXPRESSION_COMPILE_CACHE_CAPACITY = 256;
26
+ /** A legal binding / identifier name. */
27
+ export declare const EXPRESSION_IDENTIFIER_RE: RegExp;
28
+ /** Binding names an author may NOT use: `now` is auto-injected; the literal
29
+ * keywords lex as values, not identifiers, so binding to them is meaningless. */
30
+ export declare const RESERVED_BINDING_NAMES: ReadonlySet<string>;
@@ -0,0 +1,44 @@
1
+ import { type ExpressionEvalOptions } from './evaluator.js';
2
+ import type { ExpressionValue } from './ast.js';
3
+ /** The `now` epoch-ms binding is auto-injected into every evaluation and is a
4
+ * reserved binding name (authors may not rebind it). */
5
+ export declare const EXPRESSION_INJECTED_NOW = "now";
6
+ /**
7
+ * Coerce an untrusted `getByPath` / mirror read to an `ExpressionValue`.
8
+ * Non-primitive values (objects, arrays, `undefined`, functions, bigint,
9
+ * symbol) and non-finite numbers become `undefined` so the caller can apply
10
+ * its binding-miss policy (→ `null`). `null` itself is a valid value.
11
+ */
12
+ export declare function toExpressionValue(raw: unknown): ExpressionValue | undefined;
13
+ /** Shape the author-time validator accepts (structural subset of a
14
+ * `DeviceLinkExpressionSource`). */
15
+ export interface ExpressionSourceInput {
16
+ readonly expr: string;
17
+ readonly bindings: Readonly<Record<string, unknown>>;
18
+ }
19
+ /**
20
+ * Author-time validation. Returns `null` when the source is valid, else a
21
+ * human-readable error message. Checks: the expression compiles; binding count
22
+ * is within `MAX_EXPRESSION_BINDINGS`; every binding name is a legal identifier,
23
+ * is not reserved (`now`/keywords) and does not shadow a builtin; and every
24
+ * FREE identifier of the AST is covered by a binding or the injected `now`.
25
+ */
26
+ export declare function validateExpressionSource(src: ExpressionSourceInput): string | null;
27
+ /** Result of a link-expression evaluation — `ok` carries the value, the error
28
+ * branch carries a reason the async channel can log while the sync channel
29
+ * silently skips. */
30
+ export type EvaluateLinkExpressionResult = {
31
+ readonly ok: true;
32
+ readonly value: ExpressionValue;
33
+ } | {
34
+ readonly ok: false;
35
+ readonly error: string;
36
+ };
37
+ /**
38
+ * Shared read-path evaluation for BOTH resolver channels. Builds a null-proto
39
+ * scope from `bindingValues` plus the injected `now` (supplied by the caller
40
+ * for determinism/testability), compiles via the LRU, and evaluates. Any
41
+ * failure (parse or eval) returns `{ ok: false }` — the caller treats that as
42
+ * "skip this link".
43
+ */
44
+ export declare function evaluateLinkExpression(expr: string, bindingValues: Readonly<Record<string, ExpressionValue>>, now: number, opts?: ExpressionEvalOptions): EvaluateLinkExpressionResult;
@@ -0,0 +1,12 @@
1
+ import type { ExpressionNode } from './ast.js';
2
+ export interface ParsedExpression {
3
+ readonly ast: ExpressionNode;
4
+ /** Free identifiers referenced by the expression (NOT callees). */
5
+ readonly identifiers: ReadonlySet<string>;
6
+ /** Builtin function names called by the expression. */
7
+ readonly callees: ReadonlySet<string>;
8
+ readonly nodeCount: number;
9
+ }
10
+ /** Tokenize + parse `source` into a validated `ParsedExpression`. Throws
11
+ * `ExpressionParseError` on any lexical or grammatical failure. */
12
+ export declare function parseExpression(source: string): ParsedExpression;
@@ -0,0 +1,38 @@
1
+ /** The fixed punctuator set of the language. */
2
+ export type Punctuator = '(' | ')' | ',' | '?' | ':' | '+' | '-' | '*' | '/' | '%' | '!' | '<' | '<=' | '>' | '>=' | '==' | '!=' | '&&' | '||';
3
+ /** The three value keywords. */
4
+ export type Keyword = 'true' | 'false' | 'null';
5
+ export interface NumberToken {
6
+ readonly type: 'number';
7
+ readonly value: number;
8
+ readonly pos: number;
9
+ }
10
+ export interface StringToken {
11
+ readonly type: 'string';
12
+ readonly value: string;
13
+ readonly pos: number;
14
+ }
15
+ export interface IdentifierToken {
16
+ readonly type: 'identifier';
17
+ readonly name: string;
18
+ readonly pos: number;
19
+ }
20
+ export interface KeywordToken {
21
+ readonly type: 'keyword';
22
+ readonly keyword: Keyword;
23
+ readonly pos: number;
24
+ }
25
+ export interface PunctToken {
26
+ readonly type: 'punct';
27
+ readonly punct: Punctuator;
28
+ readonly pos: number;
29
+ }
30
+ export interface EofToken {
31
+ readonly type: 'eof';
32
+ readonly pos: number;
33
+ }
34
+ export type Token = NumberToken | StringToken | IdentifierToken | KeywordToken | PunctToken | EofToken;
35
+ /** Tokenize `source` into a flat token list ending with a single `eof` token.
36
+ * Throws `ExpressionParseError` on any illegal character or unterminated
37
+ * string. */
38
+ export declare function tokenize(source: string): readonly Token[];
@@ -4109,6 +4109,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4109
4109
  sourceStableId: string;
4110
4110
  cap: string;
4111
4111
  fieldPath: string;
4112
+ } | {
4113
+ kind: "expression";
4114
+ expr: string;
4115
+ bindings: Record<string, {
4116
+ sourceKey: string;
4117
+ cap: string;
4118
+ fieldPath: string;
4119
+ kind?: "field" | undefined;
4120
+ } | {
4121
+ kind: "literal";
4122
+ value: string | number | boolean | null;
4123
+ } | {
4124
+ kind: "global";
4125
+ sourceStableId: string;
4126
+ cap: string;
4127
+ fieldPath: string;
4128
+ }>;
4112
4129
  };
4113
4130
  target: {
4114
4131
  cap: string;
@@ -4129,6 +4146,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4129
4146
  } | undefined;
4130
4147
  }[] | undefined;
4131
4148
  role?: string | null | undefined;
4149
+ display?: {
4150
+ icon?: string | undefined;
4151
+ label?: string | undefined;
4152
+ unit?: string | undefined;
4153
+ precision?: number | undefined;
4154
+ hidden?: boolean | undefined;
4155
+ perCap?: Record<string, {
4156
+ unit?: string | undefined;
4157
+ precision?: number | undefined;
4158
+ }> | undefined;
4159
+ } | undefined;
4132
4160
  } | null;
4133
4161
  meta: object;
4134
4162
  }>;
@@ -4219,6 +4247,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4219
4247
  sourceStableId: string;
4220
4248
  cap: string;
4221
4249
  fieldPath: string;
4250
+ } | {
4251
+ kind: "expression";
4252
+ expr: string;
4253
+ bindings: Record<string, {
4254
+ sourceKey: string;
4255
+ cap: string;
4256
+ fieldPath: string;
4257
+ kind?: "field" | undefined;
4258
+ } | {
4259
+ kind: "literal";
4260
+ value: string | number | boolean | null;
4261
+ } | {
4262
+ kind: "global";
4263
+ sourceStableId: string;
4264
+ cap: string;
4265
+ fieldPath: string;
4266
+ }>;
4222
4267
  };
4223
4268
  target: {
4224
4269
  cap: string;
@@ -4242,6 +4287,50 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4242
4287
  output: void;
4243
4288
  meta: object;
4244
4289
  }>;
4290
+ setDisplay: import("@trpc/server").TRPCMutationProcedure<{
4291
+ input: {
4292
+ [x: string]: unknown;
4293
+ deviceId: number;
4294
+ display: {
4295
+ icon?: string | undefined;
4296
+ label?: string | undefined;
4297
+ unit?: string | undefined;
4298
+ precision?: number | undefined;
4299
+ hidden?: boolean | undefined;
4300
+ perCap?: Record<string, {
4301
+ unit?: string | undefined;
4302
+ precision?: number | undefined;
4303
+ }> | undefined;
4304
+ } | null;
4305
+ };
4306
+ output: void;
4307
+ meta: object;
4308
+ }>;
4309
+ getRoleDisplayDefaults: import("@trpc/server").TRPCQueryProcedure<{
4310
+ input: {
4311
+ [x: string]: unknown;
4312
+ };
4313
+ output: {
4314
+ defaults: Record<string, {
4315
+ unit?: string | undefined;
4316
+ precision?: number | undefined;
4317
+ icon?: string | undefined;
4318
+ }>;
4319
+ };
4320
+ meta: object;
4321
+ }>;
4322
+ setRoleDisplayDefaults: import("@trpc/server").TRPCMutationProcedure<{
4323
+ input: {
4324
+ [x: string]: unknown;
4325
+ defaults: Record<string, {
4326
+ unit?: string | undefined;
4327
+ precision?: number | undefined;
4328
+ icon?: string | undefined;
4329
+ }>;
4330
+ };
4331
+ output: void;
4332
+ meta: object;
4333
+ }>;
4245
4334
  getWireableFields: import("@trpc/server").TRPCQueryProcedure<{
4246
4335
  input: {
4247
4336
  [x: string]: unknown;
@@ -4398,6 +4487,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4398
4487
  sourceStableId: string;
4399
4488
  cap: string;
4400
4489
  fieldPath: string;
4490
+ } | {
4491
+ kind: "expression";
4492
+ expr: string;
4493
+ bindings: Record<string, {
4494
+ sourceKey: string;
4495
+ cap: string;
4496
+ fieldPath: string;
4497
+ kind?: "field" | undefined;
4498
+ } | {
4499
+ kind: "literal";
4500
+ value: string | number | boolean | null;
4501
+ } | {
4502
+ kind: "global";
4503
+ sourceStableId: string;
4504
+ cap: string;
4505
+ fieldPath: string;
4506
+ }>;
4401
4507
  };
4402
4508
  target: {
4403
4509
  cap: string;
@@ -4417,6 +4523,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4417
4523
  clamp?: readonly [number, number] | undefined;
4418
4524
  } | undefined;
4419
4525
  }[] | undefined;
4526
+ display?: {
4527
+ icon?: string | undefined;
4528
+ label?: string | undefined;
4529
+ unit?: string | undefined;
4530
+ precision?: number | undefined;
4531
+ hidden?: boolean | undefined;
4532
+ perCap?: Record<string, {
4533
+ unit?: string | undefined;
4534
+ precision?: number | undefined;
4535
+ }> | undefined;
4536
+ } | undefined;
4420
4537
  }[];
4421
4538
  meta: object;
4422
4539
  }>;
@@ -4471,6 +4588,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4471
4588
  sourceStableId: string;
4472
4589
  cap: string;
4473
4590
  fieldPath: string;
4591
+ } | {
4592
+ kind: "expression";
4593
+ expr: string;
4594
+ bindings: Record<string, {
4595
+ sourceKey: string;
4596
+ cap: string;
4597
+ fieldPath: string;
4598
+ kind?: "field" | undefined;
4599
+ } | {
4600
+ kind: "literal";
4601
+ value: string | number | boolean | null;
4602
+ } | {
4603
+ kind: "global";
4604
+ sourceStableId: string;
4605
+ cap: string;
4606
+ fieldPath: string;
4607
+ }>;
4474
4608
  };
4475
4609
  target: {
4476
4610
  cap: string;
@@ -4490,6 +4624,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4490
4624
  clamp?: readonly [number, number] | undefined;
4491
4625
  } | undefined;
4492
4626
  }[] | undefined;
4627
+ display?: {
4628
+ icon?: string | undefined;
4629
+ label?: string | undefined;
4630
+ unit?: string | undefined;
4631
+ precision?: number | undefined;
4632
+ hidden?: boolean | undefined;
4633
+ perCap?: Record<string, {
4634
+ unit?: string | undefined;
4635
+ precision?: number | undefined;
4636
+ }> | undefined;
4637
+ } | undefined;
4493
4638
  } | null;
4494
4639
  meta: object;
4495
4640
  }>;
@@ -4544,6 +4689,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4544
4689
  sourceStableId: string;
4545
4690
  cap: string;
4546
4691
  fieldPath: string;
4692
+ } | {
4693
+ kind: "expression";
4694
+ expr: string;
4695
+ bindings: Record<string, {
4696
+ sourceKey: string;
4697
+ cap: string;
4698
+ fieldPath: string;
4699
+ kind?: "field" | undefined;
4700
+ } | {
4701
+ kind: "literal";
4702
+ value: string | number | boolean | null;
4703
+ } | {
4704
+ kind: "global";
4705
+ sourceStableId: string;
4706
+ cap: string;
4707
+ fieldPath: string;
4708
+ }>;
4547
4709
  };
4548
4710
  target: {
4549
4711
  cap: string;
@@ -4563,6 +4725,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
4563
4725
  clamp?: readonly [number, number] | undefined;
4564
4726
  } | undefined;
4565
4727
  }[] | undefined;
4728
+ display?: {
4729
+ icon?: string | undefined;
4730
+ label?: string | undefined;
4731
+ unit?: string | undefined;
4732
+ precision?: number | undefined;
4733
+ hidden?: boolean | undefined;
4734
+ perCap?: Record<string, {
4735
+ unit?: string | undefined;
4736
+ precision?: number | undefined;
4737
+ }> | undefined;
4738
+ } | undefined;
4566
4739
  }[];
4567
4740
  meta: object;
4568
4741
  }>;
@@ -18184,6 +18357,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18184
18357
  sourceStableId: string;
18185
18358
  cap: string;
18186
18359
  fieldPath: string;
18360
+ } | {
18361
+ kind: "expression";
18362
+ expr: string;
18363
+ bindings: Record<string, {
18364
+ sourceKey: string;
18365
+ cap: string;
18366
+ fieldPath: string;
18367
+ kind?: "field" | undefined;
18368
+ } | {
18369
+ kind: "literal";
18370
+ value: string | number | boolean | null;
18371
+ } | {
18372
+ kind: "global";
18373
+ sourceStableId: string;
18374
+ cap: string;
18375
+ fieldPath: string;
18376
+ }>;
18187
18377
  };
18188
18378
  target: {
18189
18379
  cap: string;
@@ -18204,6 +18394,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18204
18394
  } | undefined;
18205
18395
  }[] | undefined;
18206
18396
  role?: string | null | undefined;
18397
+ display?: {
18398
+ icon?: string | undefined;
18399
+ label?: string | undefined;
18400
+ unit?: string | undefined;
18401
+ precision?: number | undefined;
18402
+ hidden?: boolean | undefined;
18403
+ perCap?: Record<string, {
18404
+ unit?: string | undefined;
18405
+ precision?: number | undefined;
18406
+ }> | undefined;
18407
+ } | undefined;
18207
18408
  } | null;
18208
18409
  meta: object;
18209
18410
  }>;
@@ -18294,6 +18495,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18294
18495
  sourceStableId: string;
18295
18496
  cap: string;
18296
18497
  fieldPath: string;
18498
+ } | {
18499
+ kind: "expression";
18500
+ expr: string;
18501
+ bindings: Record<string, {
18502
+ sourceKey: string;
18503
+ cap: string;
18504
+ fieldPath: string;
18505
+ kind?: "field" | undefined;
18506
+ } | {
18507
+ kind: "literal";
18508
+ value: string | number | boolean | null;
18509
+ } | {
18510
+ kind: "global";
18511
+ sourceStableId: string;
18512
+ cap: string;
18513
+ fieldPath: string;
18514
+ }>;
18297
18515
  };
18298
18516
  target: {
18299
18517
  cap: string;
@@ -18317,6 +18535,50 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18317
18535
  output: void;
18318
18536
  meta: object;
18319
18537
  }>;
18538
+ setDisplay: import("@trpc/server").TRPCMutationProcedure<{
18539
+ input: {
18540
+ [x: string]: unknown;
18541
+ deviceId: number;
18542
+ display: {
18543
+ icon?: string | undefined;
18544
+ label?: string | undefined;
18545
+ unit?: string | undefined;
18546
+ precision?: number | undefined;
18547
+ hidden?: boolean | undefined;
18548
+ perCap?: Record<string, {
18549
+ unit?: string | undefined;
18550
+ precision?: number | undefined;
18551
+ }> | undefined;
18552
+ } | null;
18553
+ };
18554
+ output: void;
18555
+ meta: object;
18556
+ }>;
18557
+ getRoleDisplayDefaults: import("@trpc/server").TRPCQueryProcedure<{
18558
+ input: {
18559
+ [x: string]: unknown;
18560
+ };
18561
+ output: {
18562
+ defaults: Record<string, {
18563
+ unit?: string | undefined;
18564
+ precision?: number | undefined;
18565
+ icon?: string | undefined;
18566
+ }>;
18567
+ };
18568
+ meta: object;
18569
+ }>;
18570
+ setRoleDisplayDefaults: import("@trpc/server").TRPCMutationProcedure<{
18571
+ input: {
18572
+ [x: string]: unknown;
18573
+ defaults: Record<string, {
18574
+ unit?: string | undefined;
18575
+ precision?: number | undefined;
18576
+ icon?: string | undefined;
18577
+ }>;
18578
+ };
18579
+ output: void;
18580
+ meta: object;
18581
+ }>;
18320
18582
  getWireableFields: import("@trpc/server").TRPCQueryProcedure<{
18321
18583
  input: {
18322
18584
  [x: string]: unknown;
@@ -18473,6 +18735,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18473
18735
  sourceStableId: string;
18474
18736
  cap: string;
18475
18737
  fieldPath: string;
18738
+ } | {
18739
+ kind: "expression";
18740
+ expr: string;
18741
+ bindings: Record<string, {
18742
+ sourceKey: string;
18743
+ cap: string;
18744
+ fieldPath: string;
18745
+ kind?: "field" | undefined;
18746
+ } | {
18747
+ kind: "literal";
18748
+ value: string | number | boolean | null;
18749
+ } | {
18750
+ kind: "global";
18751
+ sourceStableId: string;
18752
+ cap: string;
18753
+ fieldPath: string;
18754
+ }>;
18476
18755
  };
18477
18756
  target: {
18478
18757
  cap: string;
@@ -18492,6 +18771,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18492
18771
  clamp?: readonly [number, number] | undefined;
18493
18772
  } | undefined;
18494
18773
  }[] | undefined;
18774
+ display?: {
18775
+ icon?: string | undefined;
18776
+ label?: string | undefined;
18777
+ unit?: string | undefined;
18778
+ precision?: number | undefined;
18779
+ hidden?: boolean | undefined;
18780
+ perCap?: Record<string, {
18781
+ unit?: string | undefined;
18782
+ precision?: number | undefined;
18783
+ }> | undefined;
18784
+ } | undefined;
18495
18785
  }[];
18496
18786
  meta: object;
18497
18787
  }>;
@@ -18546,6 +18836,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18546
18836
  sourceStableId: string;
18547
18837
  cap: string;
18548
18838
  fieldPath: string;
18839
+ } | {
18840
+ kind: "expression";
18841
+ expr: string;
18842
+ bindings: Record<string, {
18843
+ sourceKey: string;
18844
+ cap: string;
18845
+ fieldPath: string;
18846
+ kind?: "field" | undefined;
18847
+ } | {
18848
+ kind: "literal";
18849
+ value: string | number | boolean | null;
18850
+ } | {
18851
+ kind: "global";
18852
+ sourceStableId: string;
18853
+ cap: string;
18854
+ fieldPath: string;
18855
+ }>;
18549
18856
  };
18550
18857
  target: {
18551
18858
  cap: string;
@@ -18565,6 +18872,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18565
18872
  clamp?: readonly [number, number] | undefined;
18566
18873
  } | undefined;
18567
18874
  }[] | undefined;
18875
+ display?: {
18876
+ icon?: string | undefined;
18877
+ label?: string | undefined;
18878
+ unit?: string | undefined;
18879
+ precision?: number | undefined;
18880
+ hidden?: boolean | undefined;
18881
+ perCap?: Record<string, {
18882
+ unit?: string | undefined;
18883
+ precision?: number | undefined;
18884
+ }> | undefined;
18885
+ } | undefined;
18568
18886
  } | null;
18569
18887
  meta: object;
18570
18888
  }>;
@@ -18619,6 +18937,23 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18619
18937
  sourceStableId: string;
18620
18938
  cap: string;
18621
18939
  fieldPath: string;
18940
+ } | {
18941
+ kind: "expression";
18942
+ expr: string;
18943
+ bindings: Record<string, {
18944
+ sourceKey: string;
18945
+ cap: string;
18946
+ fieldPath: string;
18947
+ kind?: "field" | undefined;
18948
+ } | {
18949
+ kind: "literal";
18950
+ value: string | number | boolean | null;
18951
+ } | {
18952
+ kind: "global";
18953
+ sourceStableId: string;
18954
+ cap: string;
18955
+ fieldPath: string;
18956
+ }>;
18622
18957
  };
18623
18958
  target: {
18624
18959
  cap: string;
@@ -18638,6 +18973,17 @@ export type AppRouter = import("@trpc/server/unstable-core-do-not-import").Route
18638
18973
  clamp?: readonly [number, number] | undefined;
18639
18974
  } | undefined;
18640
18975
  }[] | undefined;
18976
+ display?: {
18977
+ icon?: string | undefined;
18978
+ label?: string | undefined;
18979
+ unit?: string | undefined;
18980
+ precision?: number | undefined;
18981
+ hidden?: boolean | undefined;
18982
+ perCap?: Record<string, {
18983
+ unit?: string | undefined;
18984
+ precision?: number | undefined;
18985
+ }> | undefined;
18986
+ } | undefined;
18641
18987
  }[];
18642
18988
  meta: object;
18643
18989
  }>;
@@ -254,7 +254,7 @@ export interface DeviceProxy {
254
254
  readonly cameraPipelineConfig: Pick<InferDeviceProxyCap<typeof cameraPipelineConfigCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
255
255
  readonly deviceAdoption: Pick<InferDeviceProxyCap<typeof deviceAdoptionCapability>, 'getStatus'>;
256
256
  readonly deviceExport: Pick<InferDeviceProxyCap<typeof deviceExportCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
257
- readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDeviceLinks' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>;
257
+ readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDeviceLinks' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'getAllBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate'>;
258
258
  readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice'>;
259
259
  readonly faceGallery: Pick<InferDeviceProxyCap<typeof faceGalleryCapability>, 'getFaceByTrack'>;
260
260
  readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 724 method paths across 110 capabilities.
9
+ * Coverage: 727 method paths across 110 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {