@nebulahome/package-sdk 0.0.0-stage → 1.0.1

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/server.js ADDED
@@ -0,0 +1,17 @@
1
+ import { t as SDK_VERSION } from "./chunks/version.js";
2
+ //#region src/server/index.ts
3
+ /**
4
+ * Declares a package's server: the default export of its entry module.
5
+ *
6
+ * @param server - Its settings, if it reads them, and its `start`.
7
+ * @returns The server, stamped with the SDK version it was built with.
8
+ */
9
+ function defineServer(server) {
10
+ return {
11
+ ...server,
12
+ kind: "nebula.server",
13
+ sdk: SDK_VERSION
14
+ };
15
+ }
16
+ //#endregion
17
+ export { defineServer };
@@ -0,0 +1,549 @@
1
+ /* @nebulahome/package-sdk/styles.css: @reference it; it draws nothing. */
2
+ @import 'tailwindcss/theme.css' layer(theme);
3
+
4
+ /*
5
+ * The design system's tokens and utilities, and nothing that draws.
6
+ *
7
+ * Apart from `styles.css` so that what is not the interface - a package's stylesheet, through
8
+ * `@nebulahome/package-sdk/styles.css` - can `@reference` the tokens without the interface's
9
+ * fonts, base styles and `@source`, which would make it emit every class the interface uses.
10
+ */
11
+
12
+ /*
13
+ * The design tokens: the Nebula system (`design/tokens.json`, the source of truth).
14
+ *
15
+ * Dark is the home theme. The neutrals lean indigo (hue ~268), the way the logo does, and the
16
+ * accent is the logo's own hue. Surfaces are flat fills separated by 1px lines: depth comes from
17
+ * the step between grounds - canvas, rail, surface, surface-raised, surface-high - never from a
18
+ * gradient or a shadow. The only resting shadow belongs to a dialog. Light is a counterpart of
19
+ * each token, set in `styles.css`, never an inversion.
20
+ *
21
+ * Every colour in the application resolves through one of these. A hard-coded colour in a
22
+ * component is a review failure (RULES.md 15.3), and so is a pixel value: the sizes, the radii
23
+ * and the type steps are tokens for the same reason the colours are.
24
+ *
25
+ * `static`: every token is on the page as a CSS variable, whether the interface uses it or not,
26
+ * because a package's own stylesheet reads them - `var(--color-primary)` - and a token missing
27
+ * from the page would leave its rule with nothing (PACKAGES_DOCS.md 6.2).
28
+ */
29
+
30
+ @theme static {
31
+ /* --- grounds, darkest to lightest -------------------------------------------------- */
32
+
33
+ /** The page. Near-black with an indigo lean; the sky of sign-in is painted straight onto it. */
34
+ --color-canvas: #05060c;
35
+
36
+ /** The sidebar, one step darker than the page, and a disabled field. */
37
+ --color-rail: #07080f;
38
+
39
+ /** Cards, panels, dialogs: anything that holds content. Flat, with a 1px `border`. */
40
+ --color-surface: #0c0e19;
41
+
42
+ /**
43
+ * Things sitting on a surface: fields, ghost buttons, the active nav row, icon chips, hovered
44
+ * rows, the track of a fat slider.
45
+ */
46
+ --color-surface-raised: #141729;
47
+
48
+ /**
49
+ * The one step above raised: the chosen segment, thin tracks, nested tiles, a disabled primary.
50
+ * Keep `foreground-muted` or brighter on it.
51
+ */
52
+ --color-surface-high: #1b1f35;
53
+
54
+ /** The off track of a switch. Nothing else. */
55
+ --color-control: #23273d;
56
+
57
+ /* --- lines --------------------------------------------------------------------------- */
58
+
59
+ /** Edges of cards and panels, dividers between rows, the rail's edge. It separates. */
60
+ --color-border: #1c2036;
61
+
62
+ /**
63
+ * Edges of controls: fields, ghost buttons, pills, outlined badges, dialogs, the active nav row.
64
+ * The fill step and the shape carry a control; the edge only finishes it.
65
+ */
66
+ --color-border-strong: #262b45;
67
+
68
+ /* --- text ---------------------------------------------------------------------------- */
69
+
70
+ /** Body text and headings. */
71
+ --color-foreground: #eceefb;
72
+
73
+ /** Labels, inactive navigation, field labels, secondary sentences. */
74
+ --color-foreground-muted: #a4a8c6;
75
+
76
+ /**
77
+ * Captions, counts, timestamps, hints, group labels, placeholders. 5.28:1 on `surface`, 4.87:1
78
+ * on `surface-raised`; 4.46:1 on `surface-high`, so not for small text there.
79
+ */
80
+ --color-foreground-subtle: #8084a6;
81
+
82
+ /** Disabled text only, never a placeholder. */
83
+ --color-foreground-disabled: #4b5072;
84
+
85
+ /* --- accent ---------------------------------------------------------------------------- */
86
+
87
+ /** The logo's hue: the one primary action, an on-state, focus, the active nav icon. */
88
+ --color-primary: #7c86ff;
89
+ --color-primary-hover: #9aa3ff;
90
+
91
+ /** Text and glyphs on top of the accent. */
92
+ --color-primary-foreground: #05060c;
93
+
94
+ /** A selection's tint, and an accent note's ground. */
95
+ --color-primary-soft: rgb(124 134 255 / 0.1);
96
+
97
+ /** The focus halo of a field. */
98
+ --color-primary-ring: rgb(124 134 255 / 0.25);
99
+
100
+ /**
101
+ * The handle of a switch that is on, and of a slider: the lightest thing on a control in both
102
+ * themes, so the part a finger moves never sinks into its track. Off, a switch's knob is
103
+ * `foreground-muted`.
104
+ */
105
+ --color-knob: #ffffff;
106
+
107
+ /* --- entities: what kind of thing a card is about ---------------------------------------- */
108
+
109
+ /** A light's warmth, never a warning: a lit lamp, the level a slider fills to. */
110
+ --color-lamp: #ffc247;
111
+ --color-lamp-soft: rgb(255 194 71 / 0.1);
112
+
113
+ /** Heating. */
114
+ --color-heat: #ff8a4c;
115
+
116
+ /** Scenes, aliases and computed things; the If lane of an automation. */
117
+ --color-violet: #a78bfa;
118
+
119
+ /** Sensors, charts, live scanning; the When lane of an automation. */
120
+ --color-cyan: #4fd0ee;
121
+
122
+ /* --- states ------------------------------------------------------------------------------ */
123
+
124
+ --color-success: #52cd86;
125
+ --color-warning: #edb345;
126
+ --color-danger: #f75d59;
127
+
128
+ /** The tinted grounds of a state: a health card that needs attention, a soft note. */
129
+ --color-success-soft: rgb(82 205 134 / 0.12);
130
+ --color-warning-soft: rgb(237 179 69 / 0.12);
131
+ --color-danger-soft: rgb(247 93 89 / 0.1);
132
+
133
+ /** The edge of something dangerous or waiting: a danger button, a warning note. */
134
+ --color-danger-line: rgb(247 93 89 / 0.45);
135
+ --color-warning-line: rgb(237 179 69 / 0.4);
136
+
137
+ /* --- glass: only for what floats over the sky or the page ----------------------------------- */
138
+
139
+ /** The card on the sky. */
140
+ --color-glass: rgb(12 14 25 / 0.78);
141
+
142
+ /** Fields on glass. */
143
+ --color-veil: rgb(5 6 12 / 0.55);
144
+
145
+ /** Behind a dialog. */
146
+ --color-scrim: rgb(5 6 12 / 0.72);
147
+
148
+ /*
149
+ * --- tag palette --------------------------------------------------------------------------
150
+ * Twelve hues with one meaning between them: a tag the owner made, or a vendor's monogram. They
151
+ * are the only colours here that carry no verdict, which is why a tag is a chip of its own and
152
+ * never a badge.
153
+ */
154
+ --color-tag-red: #ff7a70;
155
+ --color-tag-orange: #ffa057;
156
+ --color-tag-amber: #ffc247;
157
+ --color-tag-yellow: #f2d94b;
158
+ --color-tag-lime: #b8e04a;
159
+ --color-tag-green: #52cd86;
160
+ --color-tag-teal: #43d6b8;
161
+ --color-tag-cyan: #4fd0ee;
162
+ --color-tag-blue: #62a9ff;
163
+ --color-tag-indigo: #8b96ff;
164
+ --color-tag-violet: #b48cff;
165
+ --color-tag-pink: #ff7ac8;
166
+
167
+ /*
168
+ * --- energy -----------------------------------------------------------------------------
169
+ * The three sources of a house's power, each drawn in its own colour wherever its power flows:
170
+ * the panels green, the battery blue, the grid yellow. Then the house the energy card draws,
171
+ * which is night in the dark theme - dark walls, lit windows - and day in the light one.
172
+ */
173
+ --color-energy-solar: #52cd86;
174
+ --color-energy-battery: #62a9ff;
175
+ --color-energy-grid: #f2d94b;
176
+
177
+ --color-house-wall: #161a2c;
178
+ --color-house-wall-shade: #111423;
179
+ --color-house-roof: #1b1f35;
180
+ --color-house-roof-edge: #262b45;
181
+ --color-house-panel: #1a2244;
182
+ --color-house-panel-line: #34406e;
183
+ --color-house-window: #f1e2bf;
184
+ --color-house-window-frame: #383e5c;
185
+ --color-house-wire: #2a2f4a;
186
+ --color-house-ground: #0a0c17;
187
+ --color-house-device: #c9cde2;
188
+
189
+ /* The details a style adds: tiles, trim, shutters, siding, a garage, a sand-coloured house. */
190
+ --color-house-trim: #2f3553;
191
+ --color-house-plinth: #10132a;
192
+ --color-house-interior: #05060c;
193
+ --color-house-panel-frame: #565e82;
194
+ --color-house-panel-cell: #090c1c;
195
+ --color-house-panel-glare: #8fa3dc;
196
+
197
+ /* --- shape ---------------------------------------------------------------------------- */
198
+ /*
199
+ * A pill is a control; a rounded rectangle holds things. A control inside a card takes the step
200
+ * below the card so the curves stay concentric.
201
+ */
202
+
203
+ --radius-check: 5px;
204
+ --radius-chip: 8px;
205
+ --radius-field: 10px;
206
+ --radius-tile: 12px;
207
+ --radius-inner: 14px;
208
+ --radius-card: 16px;
209
+ --radius-panel: 18px;
210
+ --radius-dialog: 22px;
211
+ --radius-pill: 9999px;
212
+
213
+ /* --- type ------------------------------------------------------------------------------ */
214
+ /*
215
+ * Named for the job, not the size. Each step carries its own line height and tracking:
216
+ * tracking tightens as size grows and opens only for `label` and `code`.
217
+ */
218
+
219
+ /**
220
+ * The interface raising its voice: group labels, breadcrumbs, card tops, "STEP 3 OF 7". Mono,
221
+ * uppercase, `foreground-subtle` - always with `font-mono uppercase`.
222
+ */
223
+ --text-label: 11px;
224
+ --text-label--line-height: 1.3;
225
+ --text-label--letter-spacing: 0.08em;
226
+ --text-label--font-weight: 400;
227
+
228
+ /** Hints, counts and timestamps; a field's label at weight 500. */
229
+ --text-caption: 12px;
230
+ --text-caption--line-height: 1.45;
231
+
232
+ /** Secondary sentences, compact buttons, option labels in dense lists. */
233
+ --text-ui-sm: 13px;
234
+ --text-ui-sm--line-height: 1.45;
235
+
236
+ /** Body text and the label of every button, field and nav row. The default. */
237
+ --text-ui: 14px;
238
+ --text-ui--line-height: 1.45;
239
+ --text-ui--letter-spacing: -0.006em;
240
+
241
+ /** A row's title, a card's name, a tile's name. */
242
+ --text-title: 15px;
243
+ --text-title--line-height: 1.35;
244
+ --text-title--letter-spacing: -0.01em;
245
+
246
+ /** A panel's heading. */
247
+ --text-subhead: 16px;
248
+ --text-subhead--line-height: 1.3;
249
+ --text-subhead--letter-spacing: -0.014em;
250
+
251
+ /** A dialog's title. */
252
+ --text-headline-sm: 18px;
253
+ --text-headline-sm--line-height: 1.25;
254
+ --text-headline-sm--letter-spacing: -0.018em;
255
+
256
+ /** The sign-in card's title; the lockup's name at weight 600. */
257
+ --text-headline: 22px;
258
+ --text-headline--line-height: 1.25;
259
+ --text-headline--letter-spacing: -0.02em;
260
+
261
+ /** The page title, one per screen, with its meta beside it in `mono-ui`. */
262
+ --text-display: 30px;
263
+ --text-display--line-height: 1.15;
264
+ --text-display--letter-spacing: -0.03em;
265
+
266
+ /** The number an entity card is about; its unit follows at half size in `foreground-subtle`. */
267
+ --text-reading: 32px;
268
+ --text-reading--line-height: 1;
269
+ --text-reading--letter-spacing: -0.03em;
270
+
271
+ /** A state spelled in words on a card: Locked, Open, Paused. */
272
+ --text-reading-sm: 22px;
273
+ --text-reading-sm--line-height: 1.1;
274
+ --text-reading-sm--letter-spacing: -0.02em;
275
+
276
+ /** Versions, addresses, ids. With `font-mono`. */
277
+ --text-mono-caption: 12px;
278
+ --text-mono-caption--line-height: 1.45;
279
+
280
+ /** The meta beside a page title; keys and values in tables. With `font-mono`. */
281
+ --text-mono-ui: 13px;
282
+ --text-mono-ui--line-height: 1.45;
283
+
284
+ /** The clock card. With `font-mono`. */
285
+ --text-mono-reading: 40px;
286
+ --text-mono-reading--line-height: 1;
287
+ --text-mono-reading--letter-spacing: -0.04em;
288
+
289
+ /**
290
+ * A code read one character at a time: the six digits of a second factor, one per box. Opened
291
+ * right out, because a person is copying them across from a phone. With `font-mono`.
292
+ */
293
+ --text-code: 20px;
294
+ --text-code--line-height: 1.2;
295
+ --text-code--letter-spacing: 0.12em;
296
+
297
+ --tracking-code: 0.12em;
298
+
299
+ --font-sans: Geist, 'Helvetica Neue', Arial, sans-serif;
300
+ --font-mono: 'Geist Mono', ui-monospace, monospace;
301
+
302
+ /* --- control heights -------------------------------------------------------------------- */
303
+ /*
304
+ * So that a button and the field beside it line up without anybody measuring.
305
+ *
306
+ * Deliberately *not* `--spacing-control`, even though that is the namespace they belong to by
307
+ * meaning. Naming a value inside `--spacing-*` replaces the whole spacing namespace, which
308
+ * takes the numeric scale down with it: `p-2`, `gap-4` and `h-16` stop being generated
309
+ * everywhere in the application, and nothing reports it - the classes are simply absent and
310
+ * every margin collapses to zero. They are plain variables read by the `h-control` utilities
311
+ * below instead, which leaves Tailwind's own scale alone.
312
+ */
313
+
314
+ /** Compact buttons, icon buttons, a field in a dense row. */
315
+ --control-height-sm: 30px;
316
+
317
+ /** Buttons, search. */
318
+ --control-height: 36px;
319
+
320
+ /** Form fields. */
321
+ --control-height-field: 38px;
322
+
323
+ /** Sign-in fields. */
324
+ --control-height-lg: 44px;
325
+
326
+ /** The one button of an auth screen. */
327
+ --control-height-xl: 46px;
328
+
329
+ /* --- depth -------------------------------------------------------------------------------- */
330
+ /*
331
+ * Flat. A panel has no resting shadow; an entity card has the faint lit top edge of `edge`. A
332
+ * dialog and the sign-in card take `dialog`, a menu and a dragged card `float`, a focused
333
+ * field `focus`.
334
+ */
335
+
336
+ --shadow-edge: inset 0 1px 0 rgb(255 255 255 / 0.04);
337
+ --shadow-focus: 0 0 0 3px rgb(124 134 255 / 0.25);
338
+ --shadow-float: 0 24px 48px -12px rgb(0 0 0 / 0.7);
339
+ --shadow-dialog: 0 30px 80px -20px rgb(0 0 0 / 0.9);
340
+
341
+ /* --- motion ---------------------------------------------------------------------------- */
342
+
343
+ /**
344
+ * The orbit, while something is loading. One turn every 1.2 seconds.
345
+ *
346
+ * The interface holds the opening frame for a whole number of these, so that the mark comes to
347
+ * rest with its notch where it started rather than snapping there from wherever the animation
348
+ * had got to. `ORBIT_PERIOD_MS` in the web interface is this number, and a test keeps them
349
+ * together.
350
+ */
351
+ --animate-orbit: orbit 1.2s linear infinite;
352
+
353
+ /** The sky's layers: far clouds, near clouds and stars, each its own slow loop, there and back. */
354
+ --animate-sky-far: sky-far 95s ease-in-out infinite alternate;
355
+ --animate-sky-near: sky-near 70s ease-in-out infinite alternate;
356
+ --animate-sky-stars: sky-stars 120s ease-in-out infinite alternate;
357
+
358
+ /**
359
+ * A thing that has just arrived.
360
+ *
361
+ * Ease-out from an already-visible default, so a dropped frame leaves the element in place
362
+ * rather than invisible. Short enough that nobody waits for it.
363
+ */
364
+ --animate-rise: rise 160ms cubic-bezier(0.16, 1, 0.3, 1);
365
+ --animate-fade-in: fade-in 120ms ease-out;
366
+
367
+ /**
368
+ * Power moving along a wire of the energy card: its dashes travel one period of their pattern
369
+ * per turn. How long a turn takes is the card's to say, by the power on the wire, and which way
370
+ * the dashes go by `animation-direction`.
371
+ */
372
+ --animate-energy-flow: energy-flow 1.6s linear infinite;
373
+ }
374
+
375
+ /* One period of a wire's dash pattern, which is 12 units long: 2 drawn, 10 gap. */
376
+ @keyframes energy-flow {
377
+ to {
378
+ stroke-dashoffset: -12;
379
+ }
380
+ }
381
+
382
+ /*
383
+ * One turn about the mark's centre.
384
+ *
385
+ * The whole mark turns, not the outer body alone. The ring has a notch cut where that body sits,
386
+ * and spinning the body out of its notch would take the logo apart rather than animate it.
387
+ */
388
+ @keyframes orbit {
389
+ to {
390
+ transform: rotate(360deg);
391
+ }
392
+ }
393
+
394
+ /* The sky's layers drift a little each way and back: parallax, the near layer furthest. */
395
+ @keyframes sky-far {
396
+ from {
397
+ transform: translate3d(1.5%, 0.5%, 0) scale(1.05);
398
+ }
399
+ to {
400
+ transform: translate3d(-2%, -1.5%, 0) scale(1.01);
401
+ }
402
+ }
403
+
404
+ @keyframes sky-near {
405
+ from {
406
+ transform: translate3d(-1.5%, 1%, 0) scale(1.02);
407
+ }
408
+ to {
409
+ transform: translate3d(1.5%, -1%, 0) scale(1.06);
410
+ }
411
+ }
412
+
413
+ @keyframes sky-stars {
414
+ from {
415
+ transform: translate3d(0, 0, 0);
416
+ }
417
+ to {
418
+ transform: translate3d(-0.6%, 0.4%, 0);
419
+ }
420
+ }
421
+
422
+ /* A dropdown or a dialog arriving: it starts almost where it ends. */
423
+ @keyframes rise {
424
+ from {
425
+ opacity: 0;
426
+ transform: translateY(-4px);
427
+ }
428
+ }
429
+
430
+ @keyframes fade-in {
431
+ from {
432
+ opacity: 0;
433
+ }
434
+ }
435
+
436
+ /*
437
+ * Turning an SVG group about the middle of its own view box.
438
+ *
439
+ * A utility rather than an inline style, which RULES.md 15 does not allow, and Tailwind has no
440
+ * `transform-box` of its own. Without it the browser may measure the origin from the element's
441
+ * bounding box - and the group's bounding box is not the mark's centre, so the logo would orbit
442
+ * around a point slightly off itself.
443
+ */
444
+ @utility origin-view-box {
445
+ transform-box: view-box;
446
+ transform-origin: center;
447
+ }
448
+
449
+ /*
450
+ * The control heights, as utilities rather than as spacing tokens.
451
+ *
452
+ * See the note beside `--control-height` for why they cannot live in `--spacing-*`.
453
+ */
454
+ @utility h-control-sm {
455
+ height: var(--control-height-sm);
456
+ }
457
+
458
+ @utility h-control {
459
+ height: var(--control-height);
460
+ }
461
+
462
+ @utility h-control-field {
463
+ height: var(--control-height-field);
464
+ }
465
+
466
+ @utility h-control-lg {
467
+ height: var(--control-height-lg);
468
+ }
469
+
470
+ @utility h-control-xl {
471
+ height: var(--control-height-xl);
472
+ }
473
+
474
+ @utility size-control-sm {
475
+ width: var(--control-height-sm);
476
+ height: var(--control-height-sm);
477
+ }
478
+
479
+ @utility size-control {
480
+ width: var(--control-height);
481
+ height: var(--control-height);
482
+ }
483
+
484
+ /*
485
+ * A strip that still scrolls but draws no bar: a row of pills, or the narrow rail, where a bar
486
+ * would take its room out of the very things it scrolls.
487
+ */
488
+ @utility scrollbar-none {
489
+ scrollbar-width: none;
490
+ }
491
+
492
+ /*
493
+ * The scrollbar's room kept whether or not one is drawn, so that content measured from its
494
+ * width - the dashboard's grid - does not narrow, and slide, the moment one appears.
495
+ */
496
+ @utility scrollbar-stable {
497
+ scrollbar-gutter: stable;
498
+ }
499
+
500
+ /* The catalogue's grid: as many 220px tiles as fit, sharing what is left over. */
501
+ @utility grid-tiles {
502
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
503
+ }
504
+
505
+ /*
506
+ * An entity card's ground: a faint two-stop wash, and - when its entity is on - a 14% glow of
507
+ * the entity's colour at the top-left, the one place colour is allowed to spread. The colour is
508
+ * `--glow`, set by the card from its kind (`[--glow:var(--color-lamp)]`); unset, no glow.
509
+ */
510
+ @utility entity-wash {
511
+ background-image:
512
+ radial-gradient(
513
+ 120% 90% at 0% 0%,
514
+ color-mix(in srgb, var(--glow, transparent) 14%, transparent) 0%,
515
+ transparent 60%
516
+ ),
517
+ linear-gradient(
518
+ 180deg,
519
+ color-mix(in srgb, var(--color-surface-raised) 60%, var(--color-surface)) 0%,
520
+ var(--color-surface) 55%
521
+ );
522
+ box-shadow: var(--shadow-edge);
523
+ }
524
+
525
+ /*
526
+ * A word marked inside running text - a formula's variable - without moving a letter.
527
+ *
528
+ * Padding would shift every glyph after it, and in the formula field that is fatal: the
529
+ * coloured words are drawn under a transparent input, and the caret belongs to the input. So the
530
+ * mark is a tint behind the word and the same tint spread two pixels round it as a shadow,
531
+ * which reads as a padded chip and takes no room at all. Drawn in the word's own colour, so one
532
+ * utility serves every colour of the palette.
533
+ */
534
+ @utility token-halo {
535
+ border-radius: calc(var(--radius-chip) / 2);
536
+ background-color: color-mix(in srgb, currentColor 15%, transparent);
537
+ box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 15%, transparent);
538
+ box-decoration-break: clone;
539
+ }
540
+
541
+ /**
542
+ * Figures that hold their column.
543
+ *
544
+ * A reading that changes in place must not move the layout, and a column of numbers must line
545
+ * up. Both are the same font feature.
546
+ */
547
+ @utility tabular {
548
+ font-variant-numeric: tabular-nums;
549
+ }
@@ -0,0 +1,117 @@
1
+ import { V as CapabilityCommand, et as ReportedCapabilityState, i as SettingsDefinition, lt as EntityId, r as JsonValue, t as JsonObject } from "./chunks/json.js";
2
+ import { C as StateChange, _ as ServerContext, f as ReportOptions, h as RpcCaller, l as EntitySnapshot, o as DeviceInput, t as Awaitable } from "./chunks/context.js";
3
+ //#region src/testing/index.d.ts
4
+ /** What a test context starts with. */
5
+ export type TestContextOptions<TSettings extends SettingsDefinition | undefined> = {
6
+ /** The package's id: `test-package` when not said. */
7
+ readonly id?: string;
8
+ /** The release: `0.0.0` when not said. */
9
+ readonly version?: string;
10
+ /** The package's settings declaration, whose defaults apply. */
11
+ readonly definition?: TSettings;
12
+ /** What the owner saved. */
13
+ readonly settings?: JsonObject;
14
+ /** Entities of the house `ctx.entities` reads. */
15
+ readonly entities?: readonly EntitySnapshot[];
16
+ readonly dataDir?: string;
17
+ readonly cacheDir?: string;
18
+ };
19
+ /** One report the package made. */
20
+ export type RecordedReport = {
21
+ readonly entityId: EntityId;
22
+ readonly state: ReportedCapabilityState;
23
+ readonly options?: ReportOptions;
24
+ };
25
+ /** One line the package logged. */
26
+ export type RecordedLog = {
27
+ readonly level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
28
+ readonly fields: Readonly<Record<string, unknown>>;
29
+ readonly message: string | undefined;
30
+ };
31
+ /** A context with no platform behind it, and what the package did with it. */
32
+ export type TestContext<TSettings extends SettingsDefinition | undefined> = {
33
+ /** The context to hand `start`. */
34
+ readonly ctx: ServerContext<TSettings>;
35
+ /** The last list `devices.sync` was given. */
36
+ readonly synced: () => readonly DeviceInput[] | undefined;
37
+ readonly reports: {
38
+ /** Every report, in order. */
39
+ readonly all: readonly RecordedReport[];
40
+ /**
41
+ * The newest state reported for one entity.
42
+ *
43
+ * @param entityId - The entity.
44
+ * @returns Its state, or undefined when it was never reported.
45
+ */
46
+ readonly last: (entityId: EntityId) => ReportedCapabilityState | undefined;
47
+ };
48
+ /** Every line logged. */
49
+ readonly logs: readonly RecordedLog[];
50
+ /**
51
+ * Routes a command as the platform would: to the entity type's handler for a custom one, to
52
+ * `devices.onCommand` otherwise.
53
+ *
54
+ * @param command - The command.
55
+ * @returns Once handled; rejects with the handler's failure.
56
+ */
57
+ readonly sendCommand: (command: CapabilityCommand) => Promise<void>;
58
+ /**
59
+ * Calls one of the package's methods, through its input schema.
60
+ *
61
+ * @param method - The method.
62
+ * @param input - What it is handed.
63
+ * @param caller - Who calls; a test user when not said.
64
+ * @returns What it answered.
65
+ */
66
+ readonly callRpc: (method: string, input?: JsonValue, caller?: RpcCaller) => Promise<JsonValue | undefined>;
67
+ /**
68
+ * Calls one of the services the package provides.
69
+ *
70
+ * @param name - The service.
71
+ * @param input - What it is handed.
72
+ * @param caller - The calling package's id; `test` when not said.
73
+ * @returns What it answered.
74
+ */
75
+ readonly callService: (name: string, input?: unknown, caller?: string) => Promise<JsonValue | undefined>;
76
+ /**
77
+ * Changes settings as the owner would: when every field changed is live, the process hears
78
+ * it; otherwise the platform would restart it, which the test does if it wants to.
79
+ *
80
+ * @param patch - What changes.
81
+ * @returns Whether the platform would restart the package.
82
+ */
83
+ readonly changeSettings: (patch: JsonObject) => Promise<{
84
+ readonly isRestart: boolean;
85
+ }>;
86
+ /**
87
+ * Puts an entity of the house where `ctx.entities` reads it.
88
+ *
89
+ * @param snapshot - The entity.
90
+ */
91
+ readonly setEntity: (snapshot: EntitySnapshot) => void;
92
+ /**
93
+ * Changes an entity of the house, as `ctx.entities.subscribe` hears it.
94
+ *
95
+ * @param change - The change.
96
+ * @returns Once every handler ran.
97
+ */
98
+ readonly emitStateChange: (change: StateChange) => Promise<void>;
99
+ /**
100
+ * Answers a service the package calls.
101
+ *
102
+ * @param target - The package or service called.
103
+ * @param name - The service.
104
+ * @param handler - What it answers.
105
+ */
106
+ readonly answerService: (target: string, name: string, handler: (input: JsonValue | undefined) => Awaitable<unknown>) => void;
107
+ /** Asks the package to stop: aborts `ctx.signal`. */
108
+ readonly stop: () => void;
109
+ };
110
+ /**
111
+ * Builds a context with no platform behind it.
112
+ *
113
+ * @param options - Its id, settings and the house it reads.
114
+ * @returns The context, and what the package does with it.
115
+ */
116
+ export declare function createTestContext<TSettings extends SettingsDefinition | undefined = undefined>(options?: TestContextOptions<TSettings>): TestContext<TSettings>;
117
+ //#endregion