@camstack/types 1.2.432 → 1.2.433

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/CHANGELOG.md CHANGED
@@ -7,11 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.433] - 2026-10-28
11
+
12
+ ### Changed
13
+
14
+ - Unknown event kinds, state words and class names read as words instead of raw ids
15
+
10
16
  ## [1.2.432] - 2026-10-28
11
17
 
12
18
  ### Changed
13
19
 
14
20
  - The vendor login proxy is served on one shared vendor-login prefix that cannot shadow an addon's own routes
21
+ - Unknown event kinds and state words now read as a humanized label ("Delivery truck") instead of the raw id
15
22
 
16
23
  ## [1.2.431] - 2026-10-27
17
24
 
package/dist/client.js CHANGED
@@ -32032,7 +32032,41 @@ function packagePickerItems(packages) {
32032
32032
  return [...pinned, ...addons];
32033
32033
  }
32034
32034
  //#endregion
32035
+ //#region src/i18n/humanize-id.ts
32036
+ /**
32037
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
32038
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
32039
+ * translation — the words stay the id's own, only separators and the first
32040
+ * letter change. An empty id stays empty.
32041
+ */
32042
+ function humanizeId(id) {
32043
+ const spaced = id.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
32044
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
32045
+ }
32046
+ //#endregion
32035
32047
  //#region src/i18n/state-labels.ts
32048
+ /**
32049
+ * ONE dictionary of human labels for the state words the rule editors show
32050
+ * (R7, D690).
32051
+ *
32052
+ * A device-state gate offers the words the engine compares against —
32053
+ * `armed_away`, `not_home`, `unlocking` — and both rule editors printed them
32054
+ * verbatim. The words are the WIRE vocabulary and must stay what they are (a
32055
+ * rule stores them); what the operator reads is a label, and two editors that
32056
+ * each translate on their own are two editors that disagree. Both the admin UI
32057
+ * and the viewer resolve through {@link stateLabel}.
32058
+ *
32059
+ * Keys are the raw values themselves, flat: the vocabularies are disjoint where
32060
+ * they differ and agree where they overlap (`open` is the same word on a cover
32061
+ * and on a contact). An OPEN vocabulary (a presence zone the operator named,
32062
+ * a cover state a new integration invents) falls back to the raw word — never
32063
+ * an exception, never an empty chip.
32064
+ *
32065
+ * Covered, and held to their sources by the spec: the alarm panel's states,
32066
+ * the cover's, the lock's, the boolean readers' words
32067
+ * (`DEVICE_STATE_READERS`), presence's canonical `home`/`not_home`, and the
32068
+ * scene gate's verdicts and read modes.
32069
+ */
32036
32070
  /** Every key the dictionary answers for, in a stable order. */
32037
32071
  var STATE_LABEL_KEYS = [
32038
32072
  "disarmed",
@@ -32193,7 +32227,7 @@ function isStateLabelKey(key) {
32193
32227
  * dictionary does not know it. Never throws.
32194
32228
  */
32195
32229
  function stateLabel(key, locale) {
32196
- return isStateLabelKey(key) ? STATE_LABELS[key][locale] : key;
32230
+ return isStateLabelKey(key) ? STATE_LABELS[key][locale] : humanizeId(key);
32197
32231
  }
32198
32232
  //#endregion
32199
32233
  //#region src/notification/timelapse-rule.ts
package/dist/client.mjs CHANGED
@@ -32031,7 +32031,41 @@ function packagePickerItems(packages) {
32031
32031
  return [...pinned, ...addons];
32032
32032
  }
32033
32033
  //#endregion
32034
+ //#region src/i18n/humanize-id.ts
32035
+ /**
32036
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
32037
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
32038
+ * translation — the words stay the id's own, only separators and the first
32039
+ * letter change. An empty id stays empty.
32040
+ */
32041
+ function humanizeId(id) {
32042
+ const spaced = id.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
32043
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
32044
+ }
32045
+ //#endregion
32034
32046
  //#region src/i18n/state-labels.ts
32047
+ /**
32048
+ * ONE dictionary of human labels for the state words the rule editors show
32049
+ * (R7, D690).
32050
+ *
32051
+ * A device-state gate offers the words the engine compares against —
32052
+ * `armed_away`, `not_home`, `unlocking` — and both rule editors printed them
32053
+ * verbatim. The words are the WIRE vocabulary and must stay what they are (a
32054
+ * rule stores them); what the operator reads is a label, and two editors that
32055
+ * each translate on their own are two editors that disagree. Both the admin UI
32056
+ * and the viewer resolve through {@link stateLabel}.
32057
+ *
32058
+ * Keys are the raw values themselves, flat: the vocabularies are disjoint where
32059
+ * they differ and agree where they overlap (`open` is the same word on a cover
32060
+ * and on a contact). An OPEN vocabulary (a presence zone the operator named,
32061
+ * a cover state a new integration invents) falls back to the raw word — never
32062
+ * an exception, never an empty chip.
32063
+ *
32064
+ * Covered, and held to their sources by the spec: the alarm panel's states,
32065
+ * the cover's, the lock's, the boolean readers' words
32066
+ * (`DEVICE_STATE_READERS`), presence's canonical `home`/`not_home`, and the
32067
+ * scene gate's verdicts and read modes.
32068
+ */
32035
32069
  /** Every key the dictionary answers for, in a stable order. */
32036
32070
  var STATE_LABEL_KEYS = [
32037
32071
  "disarmed",
@@ -32192,7 +32226,7 @@ function isStateLabelKey(key) {
32192
32226
  * dictionary does not know it. Never throws.
32193
32227
  */
32194
32228
  function stateLabel(key, locale) {
32195
- return isStateLabelKey(key) ? STATE_LABELS[key][locale] : key;
32229
+ return isStateLabelKey(key) ? STATE_LABELS[key][locale] : humanizeId(key);
32196
32230
  }
32197
32231
  //#endregion
32198
32232
  //#region src/notification/timelapse-rule.ts
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
3
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
4
+ * translation — the words stay the id's own, only separators and the first
5
+ * letter change. An empty id stays empty.
6
+ */
7
+ export declare function humanizeId(id: string): string;
package/dist/index.js CHANGED
@@ -113507,7 +113507,41 @@ function packagePickerItems(packages) {
113507
113507
  return [...pinned, ...addons];
113508
113508
  }
113509
113509
  //#endregion
113510
+ //#region src/i18n/humanize-id.ts
113511
+ /**
113512
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
113513
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
113514
+ * translation — the words stay the id's own, only separators and the first
113515
+ * letter change. An empty id stays empty.
113516
+ */
113517
+ function humanizeId(id) {
113518
+ const spaced = id.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
113519
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
113520
+ }
113521
+ //#endregion
113510
113522
  //#region src/i18n/state-labels.ts
113523
+ /**
113524
+ * ONE dictionary of human labels for the state words the rule editors show
113525
+ * (R7, D690).
113526
+ *
113527
+ * A device-state gate offers the words the engine compares against —
113528
+ * `armed_away`, `not_home`, `unlocking` — and both rule editors printed them
113529
+ * verbatim. The words are the WIRE vocabulary and must stay what they are (a
113530
+ * rule stores them); what the operator reads is a label, and two editors that
113531
+ * each translate on their own are two editors that disagree. Both the admin UI
113532
+ * and the viewer resolve through {@link stateLabel}.
113533
+ *
113534
+ * Keys are the raw values themselves, flat: the vocabularies are disjoint where
113535
+ * they differ and agree where they overlap (`open` is the same word on a cover
113536
+ * and on a contact). An OPEN vocabulary (a presence zone the operator named,
113537
+ * a cover state a new integration invents) falls back to the raw word — never
113538
+ * an exception, never an empty chip.
113539
+ *
113540
+ * Covered, and held to their sources by the spec: the alarm panel's states,
113541
+ * the cover's, the lock's, the boolean readers' words
113542
+ * (`DEVICE_STATE_READERS`), presence's canonical `home`/`not_home`, and the
113543
+ * scene gate's verdicts and read modes.
113544
+ */
113511
113545
  /** Every key the dictionary answers for, in a stable order. */
113512
113546
  var STATE_LABEL_KEYS = [
113513
113547
  "disarmed",
@@ -113668,11 +113702,23 @@ function isStateLabelKey(key) {
113668
113702
  * dictionary does not know it. Never throws.
113669
113703
  */
113670
113704
  function stateLabel(key, locale) {
113671
- return isStateLabelKey(key) ? STATE_LABELS[key][locale] : key;
113705
+ return isStateLabelKey(key) ? STATE_LABELS[key][locale] : humanizeId(key);
113672
113706
  }
113673
113707
  //#endregion
113674
113708
  //#region src/i18n/event-kind-labels.ts
113675
113709
  /**
113710
+ * ONE dictionary of human labels for event kinds (detection macros/subs,
113711
+ * sensors, audio macros, …) — the same vocabulary the viewer filters and the
113712
+ * notification centre speak (R7).
113713
+ *
113714
+ * Wire ids stay raw (`cat`, `animal`, `audio-dog`). What a human reads is a
113715
+ * label, and a surface that translates on its own is a surface that disagrees
113716
+ * with the next one. Admin UI, viewer and NC resolve through {@link eventKindLabel}.
113717
+ *
113718
+ * Keys match {@link EVENT_TAXONOMY}. An OPEN kind (a custom model class) falls
113719
+ * back to the raw word — never an exception, never an empty chip.
113720
+ */
113721
+ /**
113676
113722
  * Every kind the dictionary answers for. Order is stable; the set is held to
113677
113723
  * {@link EVENT_TAXONOMY} by the spec.
113678
113724
  */
@@ -114042,7 +114088,7 @@ function isEventKindLabelKey(key) {
114042
114088
  */
114043
114089
  function eventKindLabel(kind, locale) {
114044
114090
  const key = kind.trim().toLowerCase();
114045
- return isEventKindLabelKey(key) ? EVENT_KIND_LABELS[key][locale] : kind;
114091
+ return isEventKindLabelKey(key) ? EVENT_KIND_LABELS[key][locale] : humanizeId(kind);
114046
114092
  }
114047
114093
  //#endregion
114048
114094
  //#region src/i18n/translation.ts
package/dist/index.mjs CHANGED
@@ -113506,7 +113506,41 @@ function packagePickerItems(packages) {
113506
113506
  return [...pinned, ...addons];
113507
113507
  }
113508
113508
  //#endregion
113509
+ //#region src/i18n/humanize-id.ts
113510
+ /**
113511
+ * Make a raw wire id readable when no dictionary knows it: `delivery_truck`
113512
+ * becomes "Delivery truck", `open-door` becomes "Open door". It invents no
113513
+ * translation — the words stay the id's own, only separators and the first
113514
+ * letter change. An empty id stays empty.
113515
+ */
113516
+ function humanizeId(id) {
113517
+ const spaced = id.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
113518
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
113519
+ }
113520
+ //#endregion
113509
113521
  //#region src/i18n/state-labels.ts
113522
+ /**
113523
+ * ONE dictionary of human labels for the state words the rule editors show
113524
+ * (R7, D690).
113525
+ *
113526
+ * A device-state gate offers the words the engine compares against —
113527
+ * `armed_away`, `not_home`, `unlocking` — and both rule editors printed them
113528
+ * verbatim. The words are the WIRE vocabulary and must stay what they are (a
113529
+ * rule stores them); what the operator reads is a label, and two editors that
113530
+ * each translate on their own are two editors that disagree. Both the admin UI
113531
+ * and the viewer resolve through {@link stateLabel}.
113532
+ *
113533
+ * Keys are the raw values themselves, flat: the vocabularies are disjoint where
113534
+ * they differ and agree where they overlap (`open` is the same word on a cover
113535
+ * and on a contact). An OPEN vocabulary (a presence zone the operator named,
113536
+ * a cover state a new integration invents) falls back to the raw word — never
113537
+ * an exception, never an empty chip.
113538
+ *
113539
+ * Covered, and held to their sources by the spec: the alarm panel's states,
113540
+ * the cover's, the lock's, the boolean readers' words
113541
+ * (`DEVICE_STATE_READERS`), presence's canonical `home`/`not_home`, and the
113542
+ * scene gate's verdicts and read modes.
113543
+ */
113510
113544
  /** Every key the dictionary answers for, in a stable order. */
113511
113545
  var STATE_LABEL_KEYS = [
113512
113546
  "disarmed",
@@ -113667,11 +113701,23 @@ function isStateLabelKey(key) {
113667
113701
  * dictionary does not know it. Never throws.
113668
113702
  */
113669
113703
  function stateLabel(key, locale) {
113670
- return isStateLabelKey(key) ? STATE_LABELS[key][locale] : key;
113704
+ return isStateLabelKey(key) ? STATE_LABELS[key][locale] : humanizeId(key);
113671
113705
  }
113672
113706
  //#endregion
113673
113707
  //#region src/i18n/event-kind-labels.ts
113674
113708
  /**
113709
+ * ONE dictionary of human labels for event kinds (detection macros/subs,
113710
+ * sensors, audio macros, …) — the same vocabulary the viewer filters and the
113711
+ * notification centre speak (R7).
113712
+ *
113713
+ * Wire ids stay raw (`cat`, `animal`, `audio-dog`). What a human reads is a
113714
+ * label, and a surface that translates on its own is a surface that disagrees
113715
+ * with the next one. Admin UI, viewer and NC resolve through {@link eventKindLabel}.
113716
+ *
113717
+ * Keys match {@link EVENT_TAXONOMY}. An OPEN kind (a custom model class) falls
113718
+ * back to the raw word — never an exception, never an empty chip.
113719
+ */
113720
+ /**
113675
113721
  * Every kind the dictionary answers for. Order is stable; the set is held to
113676
113722
  * {@link EVENT_TAXONOMY} by the spec.
113677
113723
  */
@@ -114041,7 +114087,7 @@ function isEventKindLabelKey(key) {
114041
114087
  */
114042
114088
  function eventKindLabel(kind, locale) {
114043
114089
  const key = kind.trim().toLowerCase();
114044
- return isEventKindLabelKey(key) ? EVENT_KIND_LABELS[key][locale] : kind;
114090
+ return isEventKindLabelKey(key) ? EVENT_KIND_LABELS[key][locale] : humanizeId(kind);
114045
114091
  }
114046
114092
  //#endregion
114047
114093
  //#region src/i18n/translation.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.432",
3
+ "version": "1.2.433",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",