@tomorrowos/sdk 0.5.9 → 0.6.0
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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/pairing-code.d.ts +6 -0
- package/dist/pairing-code.d.ts.map +1 -1
- package/dist/pairing-code.js +19 -1
- package/dist/tomorrowos.d.ts.map +1 -1
- package/dist/tomorrowos.js +6 -2
- package/package.json +1 -1
- package/templates/cms-starter/.env.example +7 -3
- package/templates/cms-starter/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type { DeviceListItem, ListenOptions, TomorrowOSBrand, TomorrowOSOptions
|
|
|
3
3
|
export type { DevicePlaylistAssignment, DeviceRegistryRecord, PairedDeviceRecord, PendingCodeEntry, PendingCodeRecord, DeviceRegistryEntry, PlaylistItemRecord, PlaylistSchedule, PublishedPlaylistSnapshot, StoredPlaylist, TomorrowOSDataSnapshot, TomorrowOSMigratableStore, TomorrowOSStore } from "./store/types.js";
|
|
4
4
|
export { PlaylistCatalog } from "./playlist-catalog.js";
|
|
5
5
|
export type { BuiltDevicePolicy, SavePlaylistInput } from "./playlist-catalog.js";
|
|
6
|
-
export { generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH } from "./pairing-code.js";
|
|
6
|
+
export { DEFAULT_PAIRING_CODE_SECRET, generateDeterministicPairingCode, generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, resolvePairingCodeSecret } from "./pairing-code.js";
|
|
7
7
|
export { MemoryStore } from "./store/memory-store.js";
|
|
8
8
|
export { PostgresStore } from "./store/postgres-store.js";
|
|
9
9
|
export type { PostgresStoreOptions } from "./store/postgres-store.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,
|
|
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,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { TomorrowOS } from "./tomorrowos.js";
|
|
2
2
|
export { PlaylistCatalog } from "./playlist-catalog.js";
|
|
3
|
-
export { generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH } from "./pairing-code.js";
|
|
3
|
+
export { DEFAULT_PAIRING_CODE_SECRET, generateDeterministicPairingCode, generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, resolvePairingCodeSecret } from "./pairing-code.js";
|
|
4
4
|
export { MemoryStore } from "./store/memory-store.js";
|
|
5
5
|
export { PostgresStore } from "./store/postgres-store.js";
|
|
6
6
|
export { SQLiteStore } from "./store/sqlite-store.js";
|
package/dist/pairing-code.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/** 0-9 and A-Z — 36 characters per digit position. */
|
|
2
2
|
export declare const PAIRING_CODE_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
3
3
|
export declare const PAIRING_CODE_LENGTH = 6;
|
|
4
|
+
export declare const DEFAULT_PAIRING_CODE_SECRET = "TomorrowOSDefaultPairingV1";
|
|
4
5
|
export declare function normalizePairingCode(raw: string): string;
|
|
5
6
|
export declare function isValidPairingCodeFormat(code: string): boolean;
|
|
6
7
|
/** Random 6-character code; each position is digit or uppercase letter. */
|
|
7
8
|
export declare function generateRandomPairingCode(): string;
|
|
9
|
+
export declare function resolvePairingCodeSecret(env?: NodeJS.ProcessEnv): string;
|
|
10
|
+
export declare function generateDeterministicPairingCode(identity: string, options?: {
|
|
11
|
+
secret?: string;
|
|
12
|
+
attempt?: number;
|
|
13
|
+
}): string;
|
|
8
14
|
//# sourceMappingURL=pairing-code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing-code.d.ts","sourceRoot":"","sources":["../src/pairing-code.ts"],"names":[],"mappings":"AAEA,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,yCAAyC,CAAC;AAE5E,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK9D;AAED,2EAA2E;AAC3E,wBAAgB,yBAAyB,IAAI,MAAM,CAOlD"}
|
|
1
|
+
{"version":3,"file":"pairing-code.d.ts","sourceRoot":"","sources":["../src/pairing-code.ts"],"names":[],"mappings":"AAEA,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,yCAAyC,CAAC;AAE5E,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,eAAO,MAAM,2BAA2B,+BAA+B,CAAC;AAExE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK9D;AAED,2EAA2E;AAC3E,wBAAgB,yBAAyB,IAAI,MAAM,CAOlD;AAED,wBAAgB,wBAAwB,CACtC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAGR;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GACL,MAAM,CAaR"}
|
package/dist/pairing-code.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { randomBytes } from "crypto";
|
|
1
|
+
import { createHmac, randomBytes } from "crypto";
|
|
2
2
|
/** 0-9 and A-Z — 36 characters per digit position. */
|
|
3
3
|
export const PAIRING_CODE_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
4
4
|
export const PAIRING_CODE_LENGTH = 6;
|
|
5
|
+
export const DEFAULT_PAIRING_CODE_SECRET = "TomorrowOSDefaultPairingV1";
|
|
5
6
|
export function normalizePairingCode(raw) {
|
|
6
7
|
return String(raw || "")
|
|
7
8
|
.trim()
|
|
@@ -21,3 +22,20 @@ export function generateRandomPairingCode() {
|
|
|
21
22
|
}
|
|
22
23
|
return out;
|
|
23
24
|
}
|
|
25
|
+
export function resolvePairingCodeSecret(env = process.env) {
|
|
26
|
+
const configured = String(env.PAIRING_CODE_SECRET || "").trim();
|
|
27
|
+
return configured || DEFAULT_PAIRING_CODE_SECRET;
|
|
28
|
+
}
|
|
29
|
+
export function generateDeterministicPairingCode(identity, options = {}) {
|
|
30
|
+
const normalizedIdentity = String(identity || "").trim().toUpperCase();
|
|
31
|
+
const secret = options.secret || DEFAULT_PAIRING_CODE_SECRET;
|
|
32
|
+
const attempt = Number.isInteger(options.attempt) ? options.attempt : 0;
|
|
33
|
+
const digest = createHmac("sha256", secret)
|
|
34
|
+
.update(`${normalizedIdentity}:${attempt}`)
|
|
35
|
+
.digest();
|
|
36
|
+
let out = "";
|
|
37
|
+
for (let i = 0; i < PAIRING_CODE_LENGTH; i += 1) {
|
|
38
|
+
out += PAIRING_CODE_ALPHABET[digest[i] % PAIRING_CODE_ALPHABET.length];
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
package/dist/tomorrowos.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"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"}
|
package/dist/tomorrowos.js
CHANGED
|
@@ -4,7 +4,7 @@ import fs from "fs/promises";
|
|
|
4
4
|
import http from "http";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { WebSocket, WebSocketServer } from "ws";
|
|
7
|
-
import { generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode } from "./pairing-code.js";
|
|
7
|
+
import { generateDeterministicPairingCode, generateRandomPairingCode, isValidPairingCodeFormat, normalizePairingCode, resolvePairingCodeSecret } from "./pairing-code.js";
|
|
8
8
|
import { PlaylistCatalog } from "./playlist-catalog.js";
|
|
9
9
|
import { MemoryStore } from "./store/memory-store.js";
|
|
10
10
|
import { resolveBrandLogoPath, syncProjectAssetsToStaticRoot } from "./brand-assets.js";
|
|
@@ -393,8 +393,12 @@ export class TomorrowOS extends EventEmitter {
|
|
|
393
393
|
});
|
|
394
394
|
return existing.permanentPairingCode;
|
|
395
395
|
}
|
|
396
|
+
const stableIdentity = String(serialNumber || deviceId || "").trim();
|
|
397
|
+
const secret = resolvePairingCodeSecret();
|
|
396
398
|
for (let attempt = 0; attempt < 32; attempt += 1) {
|
|
397
|
-
const code =
|
|
399
|
+
const code = stableIdentity
|
|
400
|
+
? generateDeterministicPairingCode(stableIdentity, { secret, attempt })
|
|
401
|
+
: generateRandomPairingCode();
|
|
398
402
|
const collision = await this.store.getDeviceRegistryByCode(code);
|
|
399
403
|
if (collision && collision.deviceId !== deviceId)
|
|
400
404
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomorrowos/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
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",
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
# DATABASE_URL=postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres
|
|
4
4
|
# DATABASE_SSL=true
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
# Optional: override the default deterministic pairing-code secret.
|
|
7
|
+
# PAIRING_CODE_SECRET=
|
|
8
|
+
|
|
9
|
+
# Optional: upload media to Cloudinary instead of local storage.
|
|
10
|
+
# CLOUDINARY_CLOUD_NAME=
|
|
11
|
+
# CLOUDINARY_API_KEY=
|
|
12
|
+
# CLOUDINARY_API_SECRET=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
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.
|
|
13
|
+
"@tomorrowos/sdk": "^0.6.0",
|
|
14
14
|
"dotenv": "^17.2.3"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|