@camstack/types 1.2.179 → 1.2.181

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,90 @@
1
+ /**
2
+ * The one place a media key is built and read.
3
+ *
4
+ * A media key addresses a file by its OWNER, in one grammar:
5
+ *
6
+ * ```
7
+ * <ownerType>:<ownerId>:<fileKind>[:<timestampMs>]
8
+ * ```
9
+ *
10
+ * The owner type is a TABLE. That is already true of every owner on the live
11
+ * hub - `track`, `summary`, `face`, `identity`, `plate` - and the exception was
12
+ * `event`, which covered three tables at once. While event ids were UUIDs the
13
+ * ambiguity cost nothing, because a UUID is unique across tables. D474 made an
14
+ * event id a SQLite rowid alias, so each table numbers from 1 and `event:5`
15
+ * stopped naming one row. Splitting `event` into `motion` / `object` / `audio`
16
+ * restores uniqueness without a fifth segment and without a magic numbering
17
+ * offset, which would have hidden the same invariant somewhere nobody reads.
18
+ *
19
+ * Why this module exists at all, rather than a `split(':')` at each call site:
20
+ * the key is built in the addon, in `ui-library` and in the notification
21
+ * dispatcher, and read positionally in admin-ui (`split(':')[1]` for an owner
22
+ * id). Positional reads are silently wrong the moment a segment moves, and
23
+ * there is no compiler that notices. It lives in `@camstack/types` because both
24
+ * an addon and the UI packages must reach it, and addons may not import each
25
+ * other.
26
+ *
27
+ * `parseMediaOwnerKey` returns `null` for anything it cannot read, and never
28
+ * throws: it sits on the media READ path, where an exception takes out every
29
+ * thumbnail and a guess puts the wrong image on screen. A legacy `event:` key
30
+ * is therefore unreadable BY DESIGN - on this hub the 299 883 resolvable ones
31
+ * are rewritten by the D474 data migration, and the 676 that remain were
32
+ * already orphaned, their event having aged out before it.
33
+ */
34
+ /**
35
+ * Owner types, i.e. the tables that own media.
36
+ *
37
+ * `motion` / `object` / `audio` are the three event tables; `event` is
38
+ * deliberately absent and must not be re-added - it is the ambiguity this
39
+ * module exists to remove.
40
+ *
41
+ * This list must cover `OWNER_KINDS` in
42
+ * `addon-post-analysis/src/pipeline-analytics/store/media-store.ts`, which is
43
+ * the AUTHORITY on what may own media. I first derived it from the prefixes
44
+ * actually present on the live hub and so omitted `vehicle` and `scene`: both
45
+ * are declared owner kinds with no rows today, and the parser would have
46
+ * rejected their keys the day one appeared. A list derived from data is a list
47
+ * that is correct until the data changes.
48
+ */
49
+ export declare const MEDIA_OWNER_TYPES: readonly ["track", "summary", "face", "identity", "plate", "vehicle", "scene", "motion", "object", "audio"];
50
+ export type MediaOwnerType = (typeof MEDIA_OWNER_TYPES)[number];
51
+ /** A parsed media key. `timestampMs` is absent for the three-segment form. */
52
+ export interface MediaOwnerKey {
53
+ readonly ownerType: MediaOwnerType;
54
+ readonly ownerId: string;
55
+ readonly fileKind: string;
56
+ readonly timestampMs?: number;
57
+ }
58
+ /**
59
+ * What a caller may hand `formatMediaOwnerKey`. `ownerId` widens to `number`
60
+ * because an event id IS a number now (D474) and stringifying at every call
61
+ * site is how the old `String(id)` sprawl started.
62
+ */
63
+ export interface MediaOwnerKeyInput {
64
+ readonly ownerType: MediaOwnerType;
65
+ readonly ownerId: string | number;
66
+ readonly fileKind: string;
67
+ readonly timestampMs?: number;
68
+ }
69
+ /**
70
+ * Read a media key. `null` when it is not one - an unknown owner type, a legacy
71
+ * `event:` key, a missing segment, or a fourth segment that is not a timestamp.
72
+ *
73
+ * `fileKind` is returned as a plain string rather than validated against
74
+ * `MediaFileKindEnum`: kinds have been RETIRED over time (`crop`,
75
+ * `fullFrameBoxed`) and rows carrying them still exist, so a parser that
76
+ * rejected them would make historical media unreadable while claiming the key
77
+ * was malformed.
78
+ */
79
+ export declare function parseMediaOwnerKey(key: string): MediaOwnerKey | null;
80
+ /** Build a media key. The timestamp segment is omitted when there is none. */
81
+ export declare function formatMediaOwnerKey(key: MediaOwnerKeyInput): string;
82
+ /**
83
+ * The owner types that are event tables, in the order the event-media resolver
84
+ * should consider them. Exported so a consumer asking "is this key an event?"
85
+ * does not re-spell the list and drift from it.
86
+ */
87
+ export declare const EVENT_OWNER_TYPES: readonly ["motion", "object", "audio"];
88
+ export type EventOwnerType = (typeof EVENT_OWNER_TYPES)[number];
89
+ /** True when this key's owner is one of the three event tables. */
90
+ export declare function isEventOwnerType(ownerType: MediaOwnerType): ownerType is EventOwnerType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.179",
3
+ "version": "1.2.181",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",