@tomorrowos/sdk 0.1.2 → 0.1.4

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.
@@ -58,6 +58,7 @@ export declare class TomorrowOS extends EventEmitter {
58
58
  private tryServeStatic;
59
59
  private handleHttp;
60
60
  private handleDeviceHttp;
61
+ private sendBrandSnapshot;
61
62
  private handleConnection;
62
63
  }
63
64
  //# sourceMappingURL=tomorrowos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,IAAI,MAAM,MAAM,CAAC;AAKxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmDD,qBAAa,UAAW,SAAQ,YAAY;IAC1C,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAgB;gBAE3B,OAAO,EAAE,iBAAiB;IAMtC,oEAAoE;IAC9D,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAiChE,OAAO;uBACU,MAAM;sBAlCgC,MAAM;;MAmC3D;IAEF,MAAM,CAAC,QAAQ,EAAE,MAAM;oBAGD,CAAC,oBACT,MAAM,WACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;IAU5E,OAAO,CAAC,mBAAmB;IA6D3B,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC,MAAM;YAgD7B,cAAc;YAmCd,UAAU;YAgDV,gBAAgB;IAgE9B,OAAO,CAAC,gBAAgB;CA8EzB"}
1
+ {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,IAAI,MAAM,MAAM,CAAC;AAKxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmDD,qBAAa,UAAW,SAAQ,YAAY;IAC1C,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAgB;gBAE3B,OAAO,EAAE,iBAAiB;IAMtC,oEAAoE;IAC9D,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAiChE,OAAO;uBACU,MAAM;sBAlCgC,MAAM;;MAmC3D;IAEF,MAAM,CAAC,QAAQ,EAAE,MAAM;oBAGD,CAAC,oBACT,MAAM,WACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;IAU5E,OAAO,CAAC,mBAAmB;IA6D3B,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC,MAAM;YAgD7B,cAAc;YAmCd,UAAU;YAgDV,gBAAgB;IAgE9B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,gBAAgB;CAgFzB"}
@@ -310,6 +310,15 @@ export class TomorrowOS extends EventEmitter {
310
310
  sendJson(res, 500, { status: "failed", error: msg });
311
311
  }
312
312
  }
313
+ sendBrandSnapshot(ws) {
314
+ if (ws.readyState !== WebSocket.OPEN)
315
+ return;
316
+ ws.send(JSON.stringify({
317
+ type: "brand.snapshot",
318
+ method: "tomorrowos.brand.snapshot",
319
+ brand: this.brand
320
+ }));
321
+ }
313
322
  handleConnection(ws) {
314
323
  ws.on("message", (raw) => {
315
324
  let msg;
@@ -337,6 +346,7 @@ export class TomorrowOS extends EventEmitter {
337
346
  code,
338
347
  deviceId
339
348
  }));
349
+ this.sendBrandSnapshot(ws);
340
350
  this.emit("device.online", { deviceId });
341
351
  return;
342
352
  }
@@ -359,6 +369,7 @@ export class TomorrowOS extends EventEmitter {
359
369
  method: "tomorrowos.pairing.resume",
360
370
  deviceId
361
371
  }));
372
+ this.sendBrandSnapshot(ws);
362
373
  this.emit("device.online", { deviceId });
363
374
  })();
364
375
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "TomorrowOS CMS server SDK — WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,4 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="160" height="40" viewBox="0 0 160 40" role="img" aria-label="Logo placeholder">
2
- <rect width="160" height="40" rx="6" fill="#FF8A3D"/>
3
- <text x="80" y="26" text-anchor="middle" fill="#ffffff" font-family="system-ui,sans-serif" font-size="14" font-weight="600">Your logo</text>
4
- </svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="160" height="40" viewBox="0 0 160 40" role="img" aria-label="Logo placeholder">
2
+ <rect width="160" height="40" rx="6" fill="#FF8A3D"/>
3
+ <text x="80" y="26" text-anchor="middle" fill="#ffffff" font-family="system-ui,sans-serif" font-size="14" font-weight="600">Your logo</text>
4
+ </svg>
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "my-tomorrowos-cms",
3
- "version": "0.1.2",
2
+ "name": "my-cms",
3
+ "version": "0.1.3",
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",
@@ -10,7 +10,7 @@
10
10
  "build-player": "tomorrowos build --platform tizen"
11
11
  },
12
12
  "dependencies": {
13
- "@tomorrowos/sdk": "^0.1.2"
13
+ "@tomorrowos/sdk": "^0.1.3"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "^20.0.0",
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>TomorrowOS SDK Smoke</title>
6
+ </head>
7
+ <body style="font-family: sans-serif; padding: 40px;">
8
+ <h1>TomorrowOS SDK Smoke Panel</h1>
9
+ <p>Same-origin API as this server — open this page after <code>npm start</code>.</p>
10
+
11
+ <h2>Pair Device</h2>
12
+ <input id="code" maxlength="6" placeholder="Enter 6 digit code" />
13
+ <button onclick="verify()">Verify</button>
14
+ <input type="hidden" id="deviceId" />
15
+
16
+ <h2>Get Device Info</h2>
17
+ <button onclick="getInfo()">Get Info</button>
18
+
19
+ <h2>Get Capabilities</h2>
20
+ <button onclick="getCapabilities()">Get Capabilities</button>
21
+
22
+ <h2>Reboot Device</h2>
23
+ <button onclick="reboot()">Reboot</button>
24
+
25
+ <h2>Set Content</h2>
26
+ <button onclick="setContent()">Set</button>
27
+
28
+ <h3>Set Policy JSON (required)</h3>
29
+ <textarea
30
+ id="policyJson"
31
+ rows="16"
32
+ cols="100"
33
+ placeholder='{
34
+ "policy": {
35
+ "playlists": [
36
+ {
37
+ "id": "default",
38
+ "items": [
39
+ { "url": "https://example.com/a.jpg", "type": "image", "durationMs": 8000 },
40
+ { "url": "https://example.com/b.mp4", "type": "video", "durationMs": 30000 }
41
+ ]
42
+ }
43
+ ],
44
+ "fallback": { "type": "brand" }
45
+ }
46
+ }'></textarea>
47
+
48
+ <h2>Clear Content</h2>
49
+ <button onclick="clearContent()">Clear</button>
50
+
51
+ <br />
52
+ <br />
53
+
54
+ <pre id="result"></pre>
55
+
56
+ <script src="./methods.js" defer></script>
57
+ </body>
58
+ </html>
@@ -0,0 +1,124 @@
1
+ async function verify() {
2
+ const code = document.getElementById("code").value;
3
+
4
+ const res = await fetch("/pairing/verify", {
5
+ method: "POST",
6
+ headers: { "Content-Type": "application/json" },
7
+ body: JSON.stringify({ code })
8
+ });
9
+
10
+ const data = await res.json();
11
+
12
+ document.getElementById("result").textContent = JSON.stringify(data, null, 2);
13
+
14
+ if (data.deviceId) {
15
+ document.getElementById("deviceId").value = data.deviceId;
16
+ }
17
+ }
18
+
19
+ async function getInfo() {
20
+ const deviceId = document.getElementById("deviceId").value;
21
+
22
+ if (!deviceId) {
23
+ alert("Please pair a device first.");
24
+ return;
25
+ }
26
+
27
+ const res = await fetch("/device/" + deviceId + "/get-info", {
28
+ method: "POST"
29
+ });
30
+
31
+ const data = await res.json();
32
+
33
+ document.getElementById("result").textContent = JSON.stringify(data, null, 2);
34
+ }
35
+
36
+ async function getCapabilities() {
37
+ const deviceId = document.getElementById("deviceId").value;
38
+
39
+ if (!deviceId) {
40
+ alert("Please pair a device first.");
41
+ return;
42
+ }
43
+
44
+ const res = await fetch(`/device/${deviceId}/get-capabilities`, {
45
+ method: "POST"
46
+ });
47
+
48
+ const data = await res.json();
49
+ document.getElementById("result").textContent = JSON.stringify(data, null, 2);
50
+ }
51
+
52
+ async function reboot() {
53
+ const deviceId = document.getElementById("deviceId").value;
54
+
55
+ if (!deviceId) {
56
+ alert("Please pair a device first.");
57
+ return;
58
+ }
59
+
60
+ if (!confirm("Are you sure you want to reboot this device?")) {
61
+ return;
62
+ }
63
+
64
+ const res = await fetch("/device/" + deviceId + "/reboot", {
65
+ method: "POST"
66
+ });
67
+
68
+ const data = await res.json();
69
+
70
+ document.getElementById("result").textContent = JSON.stringify(data, null, 2);
71
+ }
72
+
73
+ async function setContent() {
74
+ const deviceId = document.getElementById("deviceId").value;
75
+ const policyJsonText = document.getElementById("policyJson")?.value?.trim();
76
+
77
+ if (!deviceId) {
78
+ alert("Please pair a device first.");
79
+ return;
80
+ }
81
+
82
+ if (!policyJsonText) {
83
+ alert("Please enter policy JSON object.");
84
+ return;
85
+ }
86
+
87
+ let payload = null;
88
+ try {
89
+ payload = JSON.parse(policyJsonText);
90
+ } catch (err) {
91
+ alert("Policy JSON is invalid: " + err.message);
92
+ return;
93
+ }
94
+
95
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
96
+ alert("Policy payload must be a JSON object.");
97
+ return;
98
+ }
99
+
100
+ const res = await fetch(`/device/${deviceId}/content/set-policy`, {
101
+ method: "POST",
102
+ headers: { "Content-Type": "application/json" },
103
+ body: JSON.stringify(payload)
104
+ });
105
+
106
+ const data = await res.json();
107
+ document.getElementById("result").textContent = JSON.stringify(data, null, 2);
108
+ }
109
+
110
+ async function clearContent() {
111
+ const deviceId = document.getElementById("deviceId").value;
112
+
113
+ if (!deviceId) {
114
+ alert("Please pair a device first.");
115
+ return;
116
+ }
117
+
118
+ const res = await fetch(`/device/${deviceId}/content/clear`, {
119
+ method: "POST"
120
+ });
121
+
122
+ const data = await res.json();
123
+ document.getElementById("result").textContent = JSON.stringify(data, null, 2);
124
+ }
@@ -15,7 +15,8 @@ const tomorrowos = new TomorrowOS({ brand });
15
15
 
16
16
  tomorrowos.listen({
17
17
  port: Number(process.env.PORT) || 3000,
18
- host: "0.0.0.0"
18
+ host: "0.0.0.0",
19
+ staticRoot: join(__dirname,"public"),
19
20
  });
20
21
 
21
22
  tomorrowos.on("device.paired", (event) => {