@tomorrowos/sdk 1.1.6 → 1.1.7

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/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export { getSdkPackageVersion } from "./sdk-version.js";
6
6
  export type { DeviceOnOffTimer, DevicePlaylistAssignment, DeviceRegistryRecord, PairedDeviceRecord, PendingCodeEntry, PendingCodeRecord, DeviceRegistryEntry, PlaylistItemRecord, PlaylistItemSchedule, PlaylistItemTagRule, PlaylistSchedule, PublishedPlaylistSnapshot, StoredPlaylist, TomorrowOSDataSnapshot, TomorrowOSMigratableStore, TomorrowOSStore } from "./store/types.js";
7
7
  export { PlaylistCatalog } from "./playlist-catalog.js";
8
8
  export { filterPolicyForScreen, itemMatchesScreen, itemScheduleActive, parseItemSchedule, parseTagRule, ScreenTagStore } from "./screen-tags.js";
9
+ export { parseScreenReferences, policyWithScreenReferences, ScreenReferenceStore } from "./screen-references.js";
10
+ export type { ScreenReferenceHost, ScreenReferences } from "./screen-references.js";
9
11
  export type { ItemSchedule, ScreenTagHost, ScreenTagHttpDeps, TagRule, TagRuleOp } from "./screen-tags.js";
10
12
  export type { BuiltDevicePolicy, SavePlaylistInput } from "./playlist-catalog.js";
11
13
  export { DEFAULT_PAIRING_CODE_SECRET, generateDeterministicPairingCode, generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, resolvePairingCodeSecret } from "./pairing-code.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,OAAO,EACP,SAAS,EACV,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EACL,2BAA2B,EAC3B,gCAAgC,EAChC,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,4BAA4B,EAC5B,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACpF,YAAY,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,OAAO,EACP,SAAS,EACV,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EACL,2BAA2B,EAC3B,gCAAgC,EAChC,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,4BAA4B,EAC5B,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export { buildServerStatus } from "./server-status.js";
3
3
  export { getSdkPackageVersion } from "./sdk-version.js";
4
4
  export { PlaylistCatalog } from "./playlist-catalog.js";
5
5
  export { filterPolicyForScreen, itemMatchesScreen, itemScheduleActive, parseItemSchedule, parseTagRule, ScreenTagStore } from "./screen-tags.js";
6
+ export { parseScreenReferences, policyWithScreenReferences, ScreenReferenceStore } from "./screen-references.js";
6
7
  export { DEFAULT_PAIRING_CODE_SECRET, generateDeterministicPairingCode, generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, resolvePairingCodeSecret } from "./pairing-code.js";
7
8
  export { MemoryStore } from "./store/memory-store.js";
8
9
  export { PostgresStore } from "./store/postgres-store.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Per-screen key/value references.
3
+ *
4
+ * Stored in screen-references.json beside the database. Each setPolicy for a
5
+ * screen includes that screen's references. The shared playlist is unchanged.
6
+ * The default CMS panel does not edit these; a product UI calls the HTTP routes.
7
+ */
8
+ import type { IncomingMessage, ServerResponse } from "http";
9
+ export type ScreenReferences = Record<string, string>;
10
+ export interface ScreenReferenceHost {
11
+ pushLatestPolicyToDevice(deviceId: string): Promise<{
12
+ pushed: boolean;
13
+ }>;
14
+ }
15
+ export declare function parseScreenReferences(raw: unknown): ScreenReferences;
16
+ /** Copy a policy and add this screen's references. Does not mutate the input. */
17
+ export declare function policyWithScreenReferences(policy: unknown, references: ScreenReferences): unknown;
18
+ export declare class ScreenReferenceStore {
19
+ private readonly filePath;
20
+ constructor(filePath: string);
21
+ get(deviceId: string): Promise<ScreenReferences>;
22
+ all(): Promise<Record<string, ScreenReferences>>;
23
+ replace(deviceId: string, references: ScreenReferences): Promise<ScreenReferences>;
24
+ removeKey(deviceId: string, key: string): Promise<ScreenReferences>;
25
+ deleteDevice(deviceId: string): Promise<void>;
26
+ private read;
27
+ private write;
28
+ }
29
+ export interface ScreenReferenceHttpDeps {
30
+ host: ScreenReferenceHost;
31
+ store: {
32
+ getPairedDevice(deviceId: string): Promise<unknown>;
33
+ };
34
+ references: ScreenReferenceStore;
35
+ }
36
+ export declare function handleScreenReferenceHttp(req: IncomingMessage, res: ServerResponse, deps: ScreenReferenceHttpDeps): Promise<boolean>;
37
+ //# sourceMappingURL=screen-references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen-references.d.ts","sourceRoot":"","sources":["../src/screen-references.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAO5D,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAMtD,MAAM,WAAW,mBAAmB;IAClC,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CA0BpE;AAED,iFAAiF;AACjF,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,gBAAgB,GAC3B,OAAO,CAMT;AAED,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAEvC,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAKhD,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAShD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQlF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAUnE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAOrC,IAAI;YAuBJ,KAAK;CAMpB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,KAAK,EAAE;QAAE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IAC/D,UAAU,EAAE,oBAAoB,CAAC;CAClC;AAyDD,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,OAAO,CAAC,CA4DlB"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Per-screen key/value references.
3
+ *
4
+ * Stored in screen-references.json beside the database. Each setPolicy for a
5
+ * screen includes that screen's references. The shared playlist is unchanged.
6
+ * The default CMS panel does not edit these; a product UI calls the HTTP routes.
7
+ */
8
+ import { mkdir, readFile, rename, writeFile } from "fs/promises";
9
+ import { dirname } from "path";
10
+ const KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
11
+ const MAX_KEYS = 32;
12
+ const MAX_VALUE_LENGTH = 500;
13
+ export function parseScreenReferences(raw) {
14
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
15
+ throw new Error("references must be an object of string values");
16
+ }
17
+ const entries = Object.entries(raw);
18
+ if (entries.length > MAX_KEYS) {
19
+ throw new Error(`At most ${MAX_KEYS} references`);
20
+ }
21
+ const out = {};
22
+ for (const [key, value] of entries) {
23
+ const name = key.trim();
24
+ if (!KEY_PATTERN.test(name)) {
25
+ throw new Error(`Invalid reference key “${key}”. Use a letter, then letters, numbers, or underscores.`);
26
+ }
27
+ if (typeof value !== "string") {
28
+ throw new Error(`Reference “${name}” must be a string`);
29
+ }
30
+ const text = value.trim();
31
+ if (!text || text.length > MAX_VALUE_LENGTH) {
32
+ throw new Error(`Reference “${name}” must be 1–${MAX_VALUE_LENGTH} characters`);
33
+ }
34
+ out[name] = text;
35
+ }
36
+ return out;
37
+ }
38
+ /** Copy a policy and add this screen's references. Does not mutate the input. */
39
+ export function policyWithScreenReferences(policy, references) {
40
+ if (!policy || typeof policy !== "object" || Array.isArray(policy))
41
+ return policy;
42
+ return {
43
+ ...policy,
44
+ references: { ...references }
45
+ };
46
+ }
47
+ export class ScreenReferenceStore {
48
+ filePath;
49
+ constructor(filePath) {
50
+ this.filePath = filePath;
51
+ }
52
+ async get(deviceId) {
53
+ const file = await this.read();
54
+ return { ...(file.devices[deviceId] ?? {}) };
55
+ }
56
+ async all() {
57
+ const file = await this.read();
58
+ const out = {};
59
+ for (const [deviceId, references] of Object.entries(file.devices)) {
60
+ out[deviceId] = { ...references };
61
+ }
62
+ return out;
63
+ }
64
+ async replace(deviceId, references) {
65
+ const file = await this.read();
66
+ if (Object.keys(references).length === 0)
67
+ delete file.devices[deviceId];
68
+ else
69
+ file.devices[deviceId] = references;
70
+ await this.write(file);
71
+ return { ...references };
72
+ }
73
+ async removeKey(deviceId, key) {
74
+ const file = await this.read();
75
+ const current = { ...(file.devices[deviceId] ?? {}) };
76
+ delete current[key];
77
+ if (Object.keys(current).length === 0)
78
+ delete file.devices[deviceId];
79
+ else
80
+ file.devices[deviceId] = current;
81
+ await this.write(file);
82
+ return current;
83
+ }
84
+ async deleteDevice(deviceId) {
85
+ const file = await this.read();
86
+ if (!file.devices[deviceId])
87
+ return;
88
+ delete file.devices[deviceId];
89
+ await this.write(file);
90
+ }
91
+ async read() {
92
+ try {
93
+ const raw = JSON.parse(await readFile(this.filePath, "utf8"));
94
+ const devices = {};
95
+ if (raw?.devices && typeof raw.devices === "object") {
96
+ for (const [deviceId, references] of Object.entries(raw.devices)) {
97
+ try {
98
+ devices[deviceId] = parseScreenReferences(references);
99
+ }
100
+ catch {
101
+ devices[deviceId] = {};
102
+ }
103
+ }
104
+ }
105
+ return { devices };
106
+ }
107
+ catch (err) {
108
+ const code = err.code;
109
+ if (code === "ENOENT")
110
+ return { devices: {} };
111
+ throw err;
112
+ }
113
+ }
114
+ async write(file) {
115
+ await mkdir(dirname(this.filePath), { recursive: true });
116
+ const tmp = `${this.filePath}.${process.pid}.tmp`;
117
+ await writeFile(tmp, JSON.stringify(file, null, 2), "utf8");
118
+ await rename(tmp, this.filePath);
119
+ }
120
+ }
121
+ function sendJson(res, status, body) {
122
+ res.writeHead(status, {
123
+ "Content-Type": "application/json; charset=utf-8",
124
+ "Cache-Control": "no-store"
125
+ });
126
+ res.end(JSON.stringify(body));
127
+ }
128
+ function pathnameOf(req) {
129
+ const url = new URL(req.url || "/", "http://localhost");
130
+ let pathname = url.pathname || "/";
131
+ if (pathname.length > 1 && pathname.endsWith("/"))
132
+ pathname = pathname.slice(0, -1);
133
+ return pathname;
134
+ }
135
+ async function readJson(req) {
136
+ const chunks = [];
137
+ let size = 0;
138
+ for await (const chunk of req) {
139
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
140
+ size += buf.length;
141
+ if (size > 1_000_000)
142
+ throw new Error("Body too large");
143
+ chunks.push(buf);
144
+ }
145
+ if (chunks.length === 0)
146
+ return {};
147
+ const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
148
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
149
+ throw new Error("JSON object required");
150
+ }
151
+ return parsed;
152
+ }
153
+ async function requirePaired(deps, deviceId, res) {
154
+ const paired = await deps.store.getPairedDevice(deviceId);
155
+ if (paired)
156
+ return true;
157
+ sendJson(res, 404, { status: "failed", error: "Device not found" });
158
+ return false;
159
+ }
160
+ async function pushReferences(deps, deviceId) {
161
+ try {
162
+ const result = await deps.host.pushLatestPolicyToDevice(deviceId);
163
+ return result.pushed;
164
+ }
165
+ catch {
166
+ return false;
167
+ }
168
+ }
169
+ export async function handleScreenReferenceHttp(req, res, deps) {
170
+ const method = String(req.method || "GET").toUpperCase();
171
+ const pathname = pathnameOf(req);
172
+ if (method === "GET" && pathname === "/screen-references") {
173
+ sendJson(res, 200, {
174
+ status: "success",
175
+ referencesByDevice: await deps.references.all()
176
+ });
177
+ return true;
178
+ }
179
+ const collection = /^\/device\/([^/]+)\/references$/.exec(pathname);
180
+ if (collection && method === "GET") {
181
+ const deviceId = decodeURIComponent(collection[1]);
182
+ if (!(await requirePaired(deps, deviceId, res)))
183
+ return true;
184
+ sendJson(res, 200, {
185
+ status: "success",
186
+ deviceId,
187
+ references: await deps.references.get(deviceId)
188
+ });
189
+ return true;
190
+ }
191
+ if (collection && method === "PUT") {
192
+ const deviceId = decodeURIComponent(collection[1]);
193
+ if (!(await requirePaired(deps, deviceId, res)))
194
+ return true;
195
+ let references;
196
+ try {
197
+ const body = await readJson(req);
198
+ references = parseScreenReferences(body.references);
199
+ }
200
+ catch (err) {
201
+ sendJson(res, 400, {
202
+ status: "failed",
203
+ error: err instanceof Error ? err.message : "Invalid references"
204
+ });
205
+ return true;
206
+ }
207
+ const saved = await deps.references.replace(deviceId, references);
208
+ const pushed = await pushReferences(deps, deviceId);
209
+ sendJson(res, 200, { status: "success", deviceId, references: saved, pushed });
210
+ return true;
211
+ }
212
+ const oneKey = /^\/device\/([^/]+)\/references\/([^/]+)$/.exec(pathname);
213
+ if (oneKey && method === "DELETE") {
214
+ const deviceId = decodeURIComponent(oneKey[1]);
215
+ const key = decodeURIComponent(oneKey[2]);
216
+ if (!KEY_PATTERN.test(key)) {
217
+ sendJson(res, 400, { status: "failed", error: "Invalid reference key" });
218
+ return true;
219
+ }
220
+ if (!(await requirePaired(deps, deviceId, res)))
221
+ return true;
222
+ const references = await deps.references.removeKey(deviceId, key);
223
+ const pushed = await pushReferences(deps, deviceId);
224
+ sendJson(res, 200, { status: "success", deviceId, references, pushed });
225
+ return true;
226
+ }
227
+ return false;
228
+ }
@@ -116,6 +116,7 @@ export declare class TomorrowOS extends EventEmitter {
116
116
  /** Port passed to listen(); used for suggested LAN CMS URL. */
117
117
  private listenPort;
118
118
  private readonly screenTags;
119
+ private readonly screenReferences;
119
120
  private scheduleRefreshStarted;
120
121
  constructor(options: TomorrowOSOptions);
121
122
  /** Push all device assignments using latest playlist definitions (e.g. after reboot). */
@@ -1 +1 @@
1
- {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import { fileURLToPath } from "url";
7
7
  import { WebSocket, WebSocketServer } from "ws";
8
8
  import { generateDeterministicPairingCode, generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, resolvePairingCodeSecret } from "./pairing-code.js";
9
9
  import { PlaylistCatalog } from "./playlist-catalog.js";
10
+ import { handleScreenReferenceHttp, policyWithScreenReferences, ScreenReferenceStore } from "./screen-references.js";
10
11
  import { filterPolicyForScreen, handleScreenTagHttp, ScreenTagStore, startItemScheduleRefresher } from "./screen-tags.js";
11
12
  import { MemoryStore } from "./store/memory-store.js";
12
13
  import { resolveBrandLogoPath, syncProjectAssetsToStaticRoot } from "./brand-assets.js";
@@ -237,12 +238,12 @@ function sendJson(res, status, body) {
237
238
  res.writeHead(status, { "Content-Type": "application/json" });
238
239
  res.end(JSON.stringify(body));
239
240
  }
240
- function screenTagFilePath(store) {
241
+ function screenDataFilePath(store, fileName) {
241
242
  const databasePath = store.databasePath;
242
243
  if (typeof databasePath === "string" && databasePath && databasePath !== ":memory:") {
243
- return path.join(path.dirname(databasePath), "screen-tags.json");
244
+ return path.join(path.dirname(databasePath), fileName);
244
245
  }
245
- return path.join(process.cwd(), "data", "screen-tags.json");
246
+ return path.join(process.cwd(), "data", fileName);
246
247
  }
247
248
  function parseDevicePath(pathname) {
248
249
  const base = /^\/device\/([^/]+)\/(.+)$/.exec(pathname);
@@ -271,13 +272,15 @@ export class TomorrowOS extends EventEmitter {
271
272
  /** Port passed to listen(); used for suggested LAN CMS URL. */
272
273
  listenPort = null;
273
274
  screenTags;
275
+ screenReferences;
274
276
  scheduleRefreshStarted = false;
275
277
  constructor(options) {
276
278
  super();
277
279
  this.brand = options.brand;
278
280
  this.store = options.store ?? new MemoryStore();
279
281
  this.playlists = new PlaylistCatalog(this.store);
280
- this.screenTags = new ScreenTagStore(screenTagFilePath(this.store));
282
+ this.screenTags = new ScreenTagStore(screenDataFilePath(this.store, "screen-tags.json"));
283
+ this.screenReferences = new ScreenReferenceStore(screenDataFilePath(this.store, "screen-references.json"));
281
284
  }
282
285
  /** Push all device assignments using latest playlist definitions (e.g. after reboot). */
283
286
  async pushLatestPolicyToDevice(deviceId) {
@@ -321,9 +324,10 @@ export class TomorrowOS extends EventEmitter {
321
324
  return params;
322
325
  }
323
326
  const tags = await this.screenTags.get(deviceId);
327
+ const references = await this.screenReferences.get(deviceId);
324
328
  return {
325
329
  ...params,
326
- policy: filterPolicyForScreen(params.policy, tags)
330
+ policy: policyWithScreenReferences(filterPolicyForScreen(params.policy, tags), references)
327
331
  };
328
332
  }
329
333
  /** Verify a 6-character alphanumeric pairing code (POST /pairing/verify). */
@@ -414,6 +418,7 @@ export class TomorrowOS extends EventEmitter {
414
418
  }
415
419
  await this.store.deletePairedDevice(id);
416
420
  await this.screenTags.deleteDevice(id);
421
+ await this.screenReferences.deleteDevice(id);
417
422
  this.pendingDeviceMeta.delete(id);
418
423
  if (screenshotAssetId) {
419
424
  await this.deleteUploadedAssetIfUnreferenced(screenshotAssetId);
@@ -1724,6 +1729,13 @@ export class TomorrowOS extends EventEmitter {
1724
1729
  });
1725
1730
  if (screenTagsHandled)
1726
1731
  return;
1732
+ const screenReferencesHandled = await handleScreenReferenceHttp(req, res, {
1733
+ host: this,
1734
+ store: this.store,
1735
+ references: this.screenReferences
1736
+ });
1737
+ if (screenReferencesHandled)
1738
+ return;
1727
1739
  /** Same-origin brand for TomorrowOS players (e.g. GET /brand.json + applyBrand). */
1728
1740
  if (method === "GET" && pathname === "/brand.json") {
1729
1741
  res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "Server SDK for building and self-hosting digital signage CMS products with TomorrowOS players.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "my-cms",
9
- "version": "1.1.6",
9
+ "version": "1.1.7",
10
10
  "dependencies": {
11
- "@tomorrowos/sdk": "^1.1.6",
11
+ "@tomorrowos/sdk": "^1.1.7",
12
12
  "dotenv": "^17.2.3",
13
13
  "tsx": "^4.19.0"
14
14
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
5
5
  "private": true,
6
6
  "type": "module",
@@ -12,7 +12,7 @@
12
12
  "start": "tsx server.ts"
13
13
  },
14
14
  "dependencies": {
15
- "@tomorrowos/sdk": "^1.1.6",
15
+ "@tomorrowos/sdk": "^1.1.7",
16
16
  "dotenv": "^17.2.3",
17
17
  "tsx": "^4.19.0"
18
18
  },
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "my-cms",
9
- "version": "1.1.6",
9
+ "version": "1.1.7",
10
10
  "dependencies": {
11
- "@tomorrowos/sdk": "^1.1.6",
11
+ "@tomorrowos/sdk": "^1.1.7",
12
12
  "dotenv": "^17.2.3",
13
13
  "tsx": "^4.19.0"
14
14
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "TomorrowOS CMS for Vercel / v0 Publish (Fluid Function + WebSockets + optional Next Preview).",
5
5
  "private": true,
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  "build": "node -e \"process.exit(0)\""
17
17
  },
18
18
  "dependencies": {
19
- "@tomorrowos/sdk": "^1.1.6",
19
+ "@tomorrowos/sdk": "^1.1.7",
20
20
  "dotenv": "^17.2.3",
21
21
  "tsx": "^4.19.0"
22
22
  },