Skip to content

Commit 05ef5bf

Browse files
committed
Add HDSModelAppStreams: resolve app-contextual sub-streams from data model
1 parent cb77efd commit 05ef5bf

3 files changed

Lines changed: 107 additions & 1 deletion

File tree

ts/HDSModel/HDSModel-AppStreams.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { HDSModel } from './HDSModel.ts';
2+
3+
export interface AppStreamDef {
4+
key: string;
5+
suffix: string;
6+
eventType: string;
7+
label: { [lang: string]: string };
8+
description: { [lang: string]: string };
9+
display: string;
10+
}
11+
12+
/**
13+
* AppStreams - Extension of HDSModel
14+
*
15+
* Manages app-contextual stream definitions.
16+
* Each app/bridge access declares `clientData.appStreamId` (e.g. "bridge-mira-app").
17+
* AppStreams definitions declare sub-streams by suffix (e.g. suffix "notes" → "bridge-mira-app-notes").
18+
*/
19+
export class HDSModelAppStreams {
20+
#model: HDSModel;
21+
#defs: AppStreamDef[] | null;
22+
23+
constructor (model: HDSModel) {
24+
this.#model = model;
25+
this.#defs = null;
26+
}
27+
28+
/** Get all app stream definitions */
29+
getAll (): AppStreamDef[] {
30+
if (!this.#defs) {
31+
this.#defs = [];
32+
const raw = this.#model.modelData.appStreams || {};
33+
for (const [key, def] of Object.entries(raw)) {
34+
const d = def as any;
35+
this.#defs.push({
36+
key,
37+
suffix: d.suffix,
38+
eventType: d.eventType,
39+
label: d.label || {},
40+
description: d.description || {},
41+
display: d.display || 'diary',
42+
});
43+
}
44+
}
45+
return this.#defs;
46+
}
47+
48+
/** Get an app stream definition by key (e.g. "notes", "chat") */
49+
forKey (key: string): AppStreamDef | null {
50+
return this.getAll().find(d => d.key === key) || null;
51+
}
52+
53+
/**
54+
* Resolve the full stream ID for an app stream definition given an appStreamId.
55+
* E.g. resolveStreamId("bridge-mira-app", "notes") → "bridge-mira-app-notes"
56+
*/
57+
resolveStreamId (appStreamId: string, key: string): string | null {
58+
const def = this.forKey(key);
59+
if (!def) return null;
60+
return `${appStreamId}-${def.suffix}`;
61+
}
62+
63+
/**
64+
* Resolve all app sub-stream IDs for a given appStreamId.
65+
* Returns a map of key → full stream ID.
66+
* E.g. resolveAll("bridge-mira-app") → { notes: "bridge-mira-app-notes", chat: "bridge-mira-app-chat" }
67+
*/
68+
resolveAll (appStreamId: string): Record<string, string> {
69+
const result: Record<string, string> = {};
70+
for (const def of this.getAll()) {
71+
result[def.key] = `${appStreamId}-${def.suffix}`;
72+
}
73+
return result;
74+
}
75+
76+
/**
77+
* Check if a streamId belongs to an app stream.
78+
* Returns the app stream definition key if matched, null otherwise.
79+
* E.g. matchStream("bridge-mira-app-notes", "bridge-mira-app") → "notes"
80+
*/
81+
matchStream (streamId: string, appStreamId: string): string | null {
82+
for (const def of this.getAll()) {
83+
if (streamId === `${appStreamId}-${def.suffix}`) return def.key;
84+
}
85+
return null;
86+
}
87+
88+
/**
89+
* Extract appStreamId from an access's clientData.
90+
* Returns null if not set.
91+
*/
92+
static getAppStreamId (access: { clientData?: Record<string, any> }): string | null {
93+
return access?.clientData?.appStreamId || null;
94+
}
95+
}

ts/HDSModel/HDSModel.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { HDSModelDatasources } from './HDSModel-Datasources.ts';
88
import { HDSModelConversions } from './HDSModel-Conversions.ts';
99
import { HDSModelConverters } from './HDSModel-Converters.ts';
1010
import { HDSModelPreferred } from './HDSModel-Preferred.ts';
11+
import { HDSModelAppStreams } from './HDSModel-AppStreams.ts';
1112

1213
export class HDSModel {
1314
/**
@@ -143,6 +144,14 @@ export class HDSModel {
143144
}
144145
return this.laziliyLoadedMap.preferred;
145146
}
147+
148+
get appStreams (): HDSModelAppStreams {
149+
if (!this.isLoaded) throwNotLoadedError();
150+
if (!this.laziliyLoadedMap.appStreams) {
151+
this.laziliyLoadedMap.appStreams = new HDSModelAppStreams(this);
152+
}
153+
return this.laziliyLoadedMap.appStreams;
154+
}
146155
}
147156

148157
function throwNotLoadedError (): never {

ts/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { HDSProfile, PROFILE_FIELDS } from './settings/HDSProfile.ts';
1616
import { HDSModelConversions } from './HDSModel/HDSModel-Conversions.ts';
1717
import { HDSModelConverters } from './HDSModel/HDSModel-Converters.ts';
1818
import { HDSModelPreferred, getPreferredInput, getPreferredDisplay } from './HDSModel/HDSModel-Preferred.ts';
19+
import { HDSModelAppStreams } from './HDSModel/HDSModel-AppStreams.ts';
1920
import { EuclidianDistanceEngine } from './converters/EuclidianDistanceEngine.ts';
2021
import { HDSLibError } from './errors.ts';
2122
export type { MonitorScopeConfig, MonitorScopeCallbacks } from './MonitorScope.ts';
@@ -25,10 +26,11 @@ export type { SettingKey, SettingsValues, DateFormat, UnitSystem, Theme } from '
2526
export type { ProfileKey, ProfileValues } from './settings/HDSProfile.ts';
2627
export type { ConverterPack, ConversionResult as ConverterConversionResult, ObservationVector, SourceBlock } from './converters/types.ts';
2728
export type { PreferredConfig } from './HDSModel/HDSModel-Preferred.ts';
29+
export type { AppStreamDef } from './HDSModel/HDSModel-AppStreams.ts';
2830

2931
export const getHDSModel = HDSModelInitAndSingleton.getModel;
3032
export const initHDSModel = HDSModelInitAndSingleton.initHDSModel;
31-
export { pryv, settings, HDSService, HDSModel, appTemplates, localizeText, localizeText as l, toolkit, logger, durationToSeconds, durationToLabel, computeReminders, eventToShortText, formatEventDate, MonitorScope, HDSSettings, SETTING_TYPES, HDSProfile, PROFILE_FIELDS, HDSModelConversions, HDSModelConverters, HDSModelPreferred, getPreferredInput, getPreferredDisplay, EuclidianDistanceEngine, HDSLibError };
33+
export { pryv, settings, HDSService, HDSModel, appTemplates, localizeText, localizeText as l, toolkit, logger, durationToSeconds, durationToLabel, computeReminders, eventToShortText, formatEventDate, MonitorScope, HDSSettings, SETTING_TYPES, HDSProfile, PROFILE_FIELDS, HDSModelConversions, HDSModelConverters, HDSModelPreferred, getPreferredInput, getPreferredDisplay, HDSModelAppStreams, EuclidianDistanceEngine, HDSLibError };
3234

3335
// also exporting default for typescript to capture HDSLib.. there is surely a nicer way to do
3436
const HDSLib = {

0 commit comments

Comments
 (0)