@tomorrowos/sdk 0.9.70 → 0.9.72
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/LICENSE +201 -0
- package/NOTICE +50 -0
- package/PLAYER_INSTALL.md +181 -123
- package/README.md +87 -346
- package/REPLIT_SETUP.md +219 -197
- package/VERCEL_SETUP.md +37 -8
- package/dist/cli.js +9 -5
- package/dist/playlist-catalog.d.ts +0 -3
- package/dist/playlist-catalog.d.ts.map +1 -1
- package/dist/playlist-catalog.js +0 -1
- package/package.json +22 -3
- package/templates/cms-starter/.env.example +19 -0
- package/templates/cms-starter/package.json +3 -4
- package/templates/cms-starter/policy.example.json +1 -2
- package/templates/cms-starter/public/index.html +7 -3
- package/templates/cms-starter/public/methods.js +21 -11
- package/templates/cms-starter/public/panel.css +10 -0
- package/templates/cms-starter-v0/.env.example +19 -0
- package/templates/cms-starter-v0/cms-panel/index.html +7 -3
- package/templates/cms-starter-v0/cms-panel/methods.js +21 -11
- package/templates/cms-starter-v0/cms-panel/panel.css +10 -0
- package/templates/cms-starter-v0/package.json +3 -4
- package/templates/cms-starter-v0/policy.example.json +1 -2
package/VERCEL_SETUP.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
>
|
|
6
6
|
> **On Vercel, this file is the setup questionnaire** (not `REPLIT_SETUP.md`).
|
|
7
7
|
>
|
|
8
|
-
> Protocol id: `vercel-setup/1.
|
|
8
|
+
> Protocol id: `vercel-setup/1.15` - pairs with `@tomorrowos/sdk` **0.9.70+** (`templates/cms-starter-v0`, Fluid Functions WebSockets).
|
|
9
9
|
>
|
|
10
10
|
> **Questions source of truth:** `VERCEL_QUESTIONS.md` - Agents must **open that file and paste each Q block verbatim**. Do not paraphrase.
|
|
11
11
|
> **Q1/Q2 = choice questions. Q3 = form only:** open **all seven optional inputs at once**, then **HARD STOP and WAIT** for submit or "skip". Never auto-skip because fields are optional. Never ask a branding choice first. Never show only Name + Primary colour. Logo = **Upload** above **Logo URL**.
|
|
@@ -921,7 +921,32 @@ Tell the user:
|
|
|
921
921
|
|
|
922
922
|
- **Control Panel (Publish):** `https://YOUR-PROJECT.vercel.app`
|
|
923
923
|
- **TV CMS endpoint:** same HTTPS origin (players use `wss://`)
|
|
924
|
-
- **Preview:** Next shell is for v0 only
|
|
924
|
+
- **Preview:** Next shell is for v0 only — do not pair devices to Preview
|
|
925
|
+
|
|
926
|
+
Then **you must tell the user how to install a player and pair**. Do **not** only link a file — spell out the steps:
|
|
927
|
+
|
|
928
|
+
#### Samsung Tizen (6.5 and 7.0)
|
|
929
|
+
|
|
930
|
+
1. On the display, open **App Management** → install via **Custom App** URL:
|
|
931
|
+
|
|
932
|
+
```txt
|
|
933
|
+
https://tmr.sh/tizen
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
Or use Control Panel → **Download Players → Samsung** and install via USB.
|
|
937
|
+
2. Choose orientation, then enter the **Production** CMS URL: `https://YOUR-PROJECT.vercel.app/` (never Preview, never `localhost`).
|
|
938
|
+
3. Enter the **six-character** pairing code in Control Panel → **Pair**.
|
|
939
|
+
|
|
940
|
+
#### BrightSign (Series 3-6)
|
|
941
|
+
|
|
942
|
+
1. On the **Production** Control Panel → **Download Players → BrightSign** (preferred — `cmsEndpoint` is filled for this CMS),
|
|
943
|
+
or download `https://tmr.sh/app/brightsign/brightsign_package.zip` and set `cmsEndpoint` in `config.js` to `https://YOUR-PROJECT.vercel.app/`.
|
|
944
|
+
2. Unzip and copy the **contents** to the SD card root (`autorun.brs`, `config.js`, player files).
|
|
945
|
+
3. Power-cycle the player, wait ~10s through the black boot window, then pair with the six-character code.
|
|
946
|
+
|
|
947
|
+
4. Create a playlist, upload media, **Publish** to the device.
|
|
948
|
+
|
|
949
|
+
More detail: https://docs.tomorrowos.org/docs/os/tizen and https://docs.tomorrowos.org/docs/os/brightsign
|
|
925
950
|
|
|
926
951
|
### E. Minimal verification only
|
|
927
952
|
|
|
@@ -987,25 +1012,27 @@ Tell the user:
|
|
|
987
1012
|
|
|
988
1013
|
---
|
|
989
1014
|
|
|
990
|
-
## Final summary template (Agent
|
|
1015
|
+
## Final summary template (Agent — human)
|
|
991
1016
|
|
|
992
1017
|
After setup, report:
|
|
993
1018
|
|
|
994
1019
|
1. **Live URL** (Production Publish)
|
|
995
|
-
2. **Publish health:** Framework = Other; Output
|
|
1020
|
+
2. **Publish health:** Framework = Other; Output — `public`; `GET /status` — JSON; `GET /` OK
|
|
996
1021
|
3. **Preview note:** Next proxy shell used / not needed
|
|
997
|
-
4. **Env Vars set** (names only
|
|
1022
|
+
4. **Env Vars set** (names only — never values); note which were auto-set (`TOMORROWOS_STORE`, `DATABASE_SSL`)
|
|
998
1023
|
5. **Store:** Supabase pooler or Neon pooled
|
|
999
1024
|
6. **Media:** Cloudinary or Vercel Blob
|
|
1000
1025
|
7. **Brand:** name + `hostingTarget: vercel` (from optional Q3 fields; blanks = starter defaults)
|
|
1001
|
-
8. **Runtime split:** Preview =
|
|
1026
|
+
8. **Runtime split:** Preview = …; Publish = Node TomorrowOS (confirm **not** Next)
|
|
1002
1027
|
9. **Open action:** if Database still ERROR, paste the pooler instruction again
|
|
1028
|
+
10. **Connect a screen:** include the Tizen Custom App URL / BrightSign SD install + six-character pairing steps from section **D. Deploy** above (required — do not skip)
|
|
1003
1029
|
|
|
1004
1030
|
Protocol complete when:
|
|
1005
1031
|
|
|
1006
1032
|
- **Preview** shows the Control Panel at `/` (via Next proxy if required), **and**
|
|
1007
1033
|
- **Publish** returns Control Panel at `/` **and** `/status` JSON from pure Node `TomorrowOS.listen` with Fluid (not static `public/`, not `404: NOT_FOUND`, not `Unexpected token 'T'`), **and**
|
|
1008
|
-
- Q1
|
|
1034
|
+
- Q1–Q3 configuration is saved, **and**
|
|
1035
|
+
- the user has been told how to install Tizen and/or BrightSign and pair
|
|
1009
1036
|
|
|
1010
1037
|
? even if a sandbox DB probe still flakes **after** the pooled URL is correctly set for Production.
|
|
1011
1038
|
|
|
@@ -1013,7 +1040,9 @@ Protocol complete when:
|
|
|
1013
1040
|
|
|
1014
1041
|
## Protocol version
|
|
1015
1042
|
|
|
1016
|
-
`vercel-setup/1.
|
|
1043
|
+
`vercel-setup/1.15` - pairs with `@tomorrowos/sdk` 0.9.70+ and `VERCEL_QUESTIONS.md` 1.5.
|
|
1044
|
+
|
|
1045
|
+
**Changelog 1.15:** After Publish is healthy, agents **must** tell the user how to install Tizen (Custom App `https://tmr.sh/tizen`) and BrightSign (CMS zip → SD root) and pair against the **Production** URL. Final summary requires this screen-connect step.
|
|
1017
1046
|
|
|
1018
1047
|
**Changelog 1.14:** Vercel Blob is **SDK-native** (`BLOB_READ_WRITE_TOKEN` + `TOMORROWOS_MEDIA=vercel-blob`). No project Blob bridge. Status providers use display names (Neon, Supabase, Blob, Cloudinary, Replit Object Storage). Forbidden marketing status copy about blob URL patterns.
|
|
1019
1048
|
|
package/dist/cli.js
CHANGED
|
@@ -85,6 +85,7 @@ function copyStarter(destDir, force, hosting) {
|
|
|
85
85
|
console.log(`[tomorrowos] Template: ${templateName} (--hosting ${hosting})`);
|
|
86
86
|
console.log(`[tomorrowos] @tomorrowos/sdk dependency: ^${sdkVer}`);
|
|
87
87
|
console.log(`[tomorrowos] Initialized SQLite database: ${dbPath}`);
|
|
88
|
+
console.log(`[tomorrowos] Env template: ${path.join(resolved, ".env.example")}`);
|
|
88
89
|
if (hosting === "replit") {
|
|
89
90
|
console.log("Next: npm install, then npm start (see REPLIT_SETUP.md on Replit)");
|
|
90
91
|
}
|
|
@@ -102,10 +103,12 @@ function parseHostingFlag(argv) {
|
|
|
102
103
|
}
|
|
103
104
|
function cmdBuild(argv) {
|
|
104
105
|
const platformIdx = argv.indexOf("--platform");
|
|
105
|
-
const platform = platformIdx >= 0 && argv[platformIdx + 1] ? argv[platformIdx + 1] : "
|
|
106
|
-
console.
|
|
107
|
-
console.
|
|
108
|
-
|
|
106
|
+
const platform = platformIdx >= 0 && argv[platformIdx + 1] ? argv[platformIdx + 1] : "(unspecified)";
|
|
107
|
+
console.error(`[tomorrowos] "tomorrowos build" does not package players. No file was produced for platform "${platform}".`);
|
|
108
|
+
console.error("Download a verified prebuilt player from your running Control Panel (Download Players), or from the player repositories.");
|
|
109
|
+
console.error("Tizen: Control Panel → Download Players → Samsung (or https://tmr.sh/app/tizen/). BrightSign: Control Panel → Download Players → BrightSign (GET /players/brightsign.zip).");
|
|
110
|
+
console.error("See PLAYER_INSTALL.md for install and pairing steps.");
|
|
111
|
+
process.exit(1);
|
|
109
112
|
}
|
|
110
113
|
function optionValue(argv, name) {
|
|
111
114
|
const withEquals = `${name}=`;
|
|
@@ -194,7 +197,6 @@ function printHelp() {
|
|
|
194
197
|
Usage:
|
|
195
198
|
tomorrowos init [directory] Copy cms-starter template (default: Replit / Railway)
|
|
196
199
|
tomorrowos migrate [options] Migrate TomorrowOS data between supported databases
|
|
197
|
-
tomorrowos build --platform … Placeholder; player packaging lives in the player repo
|
|
198
200
|
|
|
199
201
|
Options:
|
|
200
202
|
--hosting replit|v0|vercel init template: replit (default) or Vercel/v0 (cms-starter-v0)
|
|
@@ -205,6 +207,8 @@ Examples:
|
|
|
205
207
|
npx @tomorrowos/sdk@latest init ./my-cms --hosting replit
|
|
206
208
|
npx @tomorrowos/sdk@latest init ./my-cms --hosting v0
|
|
207
209
|
npx @tomorrowos/sdk@latest migrate --from sqlite --from-sqlite ./data/tomorrowos.db --to supabase --to-database-url "$DATABASE_URL"
|
|
210
|
+
|
|
211
|
+
Player packages are not built by this CLI. Use Control Panel → Download Players, or see PLAYER_INSTALL.md.
|
|
208
212
|
`);
|
|
209
213
|
}
|
|
210
214
|
function printMigrateHelp() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playlist-catalog.d.ts","sourceRoot":"","sources":["../src/playlist-catalog.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE;QACN,SAAS,EAAE,yBAAyB,EAAE,CAAC;QACvC,QAAQ,
|
|
1
|
+
{"version":3,"file":"playlist-catalog.d.ts","sourceRoot":"","sources":["../src/playlist-catalog.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE;QACN,SAAS,EAAE,yBAAyB,EAAE,CAAC;QACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;KAClC,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyDD,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,eAAe;IAE7C,aAAa,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAK1C,6BAA6B,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAI1D,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAI5D,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;IA8B/D,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAcnD,oBAAoB,CACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,wBAAwB,EAAE,CAAC;IAIhC,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC;IAiEvB,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAO7B,mFAAmF;IAC7E,6BAA6B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAKjF;;;OAGG;IACG,+BAA+B,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,iBAAiB,CAAA;KAAE,CAAC;IA4BrD,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC;YAKf,0BAA0B;IA+BxC,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGpE"}
|
package/dist/playlist-catalog.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomorrowos/sdk",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.9.72",
|
|
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",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
"dist",
|
|
19
19
|
"templates",
|
|
20
20
|
"README.md",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"NOTICE",
|
|
21
23
|
"REPLIT_SETUP.md",
|
|
22
24
|
"VERCEL_SETUP.md",
|
|
23
25
|
"VERCEL_QUESTIONS.md",
|
|
@@ -32,7 +34,7 @@
|
|
|
32
34
|
"prepublishOnly": "npm run build"
|
|
33
35
|
},
|
|
34
36
|
"engines": {
|
|
35
|
-
"node": ">=
|
|
37
|
+
"node": ">=20"
|
|
36
38
|
},
|
|
37
39
|
"dependencies": {
|
|
38
40
|
"@replit/object-storage": "^1.0.0",
|
|
@@ -50,5 +52,22 @@
|
|
|
50
52
|
"@types/ws": "^8.5.10",
|
|
51
53
|
"typescript": "^5.5.0"
|
|
52
54
|
},
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/TomorrowOS/TomorrowOS_SDK"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://docs.tomorrowos.org",
|
|
60
|
+
"bugs": {
|
|
61
|
+
"url": "https://github.com/TomorrowOS/TomorrowOS_SDK/issues"
|
|
62
|
+
},
|
|
63
|
+
"keywords": [
|
|
64
|
+
"digital-signage",
|
|
65
|
+
"cms",
|
|
66
|
+
"tizen",
|
|
67
|
+
"brightsign",
|
|
68
|
+
"device-management",
|
|
69
|
+
"websocket",
|
|
70
|
+
"typescript"
|
|
71
|
+
],
|
|
53
72
|
"license": "Apache-2.0"
|
|
54
73
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Default: SQLite.
|
|
2
|
+
# TOMORROWOS_STORE=sqlite
|
|
3
|
+
# TOMORROWOS_DB_PATH=./data/tomorrowos.db
|
|
4
|
+
|
|
5
|
+
# Supabase/Postgres.
|
|
6
|
+
# On Replit use SUPABASE_URL — DATABASE_URL is often a reserved Secret.
|
|
7
|
+
# TOMORROWOS_STORE=supabase
|
|
8
|
+
# SUPABASE_URL=postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres
|
|
9
|
+
# DATABASE_SSL=true
|
|
10
|
+
# DATABASE_URL=postgresql://... # optional fallback outside Replit
|
|
11
|
+
|
|
12
|
+
# Optional: upload media to Cloudinary instead of local / Object Storage.
|
|
13
|
+
# CLOUDINARY_CLOUD_NAME=
|
|
14
|
+
# CLOUDINARY_API_KEY=
|
|
15
|
+
# CLOUDINARY_API_SECRET=
|
|
16
|
+
# CLOUDINARY_FOLDER=tomorrowos
|
|
17
|
+
|
|
18
|
+
# Optional: override the default deterministic pairing-code secret.
|
|
19
|
+
# PAIRING_CODE_SECRET=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-cms",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.72",
|
|
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",
|
|
@@ -9,11 +9,10 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"dev": "tsx watch server.ts",
|
|
12
|
-
"start": "tsx server.ts"
|
|
13
|
-
"build-player": "tomorrowos build --platform tizen"
|
|
12
|
+
"start": "tsx server.ts"
|
|
14
13
|
},
|
|
15
14
|
"dependencies": {
|
|
16
|
-
"@tomorrowos/sdk": "^0.9.
|
|
15
|
+
"@tomorrowos/sdk": "^0.9.72",
|
|
17
16
|
"dotenv": "^17.2.3",
|
|
18
17
|
"tsx": "^4.19.0"
|
|
19
18
|
},
|
|
@@ -231,11 +231,15 @@
|
|
|
231
231
|
<p class="hint">Current installed SDK version:</p>
|
|
232
232
|
<p class="update-sdk-version" id="updateSdkVersionLabel">Loading…</p>
|
|
233
233
|
<p class="hint">
|
|
234
|
-
To upgrade on AI agent platforms
|
|
234
|
+
To upgrade on AI agent platforms, paste the matching prompt into the Agent chat:
|
|
235
235
|
</p>
|
|
236
|
-
<
|
|
236
|
+
<p class="update-sdk-prompt-label">Replit</p>
|
|
237
|
+
<pre class="update-sdk-prompt" id="updateSdkPromptReplit">Follow NPM package @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.</pre>
|
|
238
|
+
<p class="update-sdk-prompt-label">Vercel</p>
|
|
239
|
+
<pre class="update-sdk-prompt" id="updateSdkPromptVercel">Follow NPM package @tomorrowos/sdk VERCEL_UPGRADE.md to upgrade my CMS with the latest SDK.</pre>
|
|
237
240
|
<div class="modal-actions update-sdk-modal-actions">
|
|
238
|
-
<button type="button" id="
|
|
241
|
+
<button type="button" id="copyUpdateSdkPromptReplitBtn" class="primary">Copy Replit prompt</button>
|
|
242
|
+
<button type="button" id="copyUpdateSdkPromptVercelBtn" class="primary">Copy Vercel prompt</button>
|
|
239
243
|
<button type="button" data-close-update-sdk-modal="1">Close</button>
|
|
240
244
|
</div>
|
|
241
245
|
</div>
|
|
@@ -33,8 +33,10 @@ let cachedSdkVersion = "";
|
|
|
33
33
|
/** @type {number|null} CMS server boot time (ms) from GET /devices. */
|
|
34
34
|
let serverStartedAtMs = null;
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
"Follow @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.";
|
|
36
|
+
const UPDATE_SDK_PROMPT_REPLIT =
|
|
37
|
+
"Follow NPM package @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.";
|
|
38
|
+
const UPDATE_SDK_PROMPT_VERCEL =
|
|
39
|
+
"Follow NPM package @tomorrowos/sdk VERCEL_UPGRADE.md to upgrade my CMS with the latest SDK.";
|
|
38
40
|
/** @type {ReturnType<typeof setTimeout>|null} */
|
|
39
41
|
let reconnectGraceTimer = null;
|
|
40
42
|
let uploadQueue = [];
|
|
@@ -2364,8 +2366,10 @@ function setUpdateSdkVersionLabel(version) {
|
|
|
2364
2366
|
|
|
2365
2367
|
async function openUpdateSdkModal() {
|
|
2366
2368
|
const modal = document.getElementById("updateSdkModal");
|
|
2367
|
-
const
|
|
2368
|
-
|
|
2369
|
+
const replitEl = document.getElementById("updateSdkPromptReplit");
|
|
2370
|
+
const vercelEl = document.getElementById("updateSdkPromptVercel");
|
|
2371
|
+
if (replitEl) replitEl.textContent = UPDATE_SDK_PROMPT_REPLIT;
|
|
2372
|
+
if (vercelEl) vercelEl.textContent = UPDATE_SDK_PROMPT_VERCEL;
|
|
2369
2373
|
setUpdateSdkVersionLabel(cachedSdkVersion || "Loading…");
|
|
2370
2374
|
modal?.classList.remove("hidden");
|
|
2371
2375
|
|
|
@@ -2379,18 +2383,21 @@ function closeUpdateSdkModal() {
|
|
|
2379
2383
|
document.getElementById("updateSdkModal")?.classList.add("hidden");
|
|
2380
2384
|
}
|
|
2381
2385
|
|
|
2382
|
-
async function copyUpdateSdkPrompt() {
|
|
2386
|
+
async function copyUpdateSdkPrompt(which) {
|
|
2387
|
+
const isVercel = which === "vercel";
|
|
2383
2388
|
const text =
|
|
2384
|
-
document.getElementById("
|
|
2385
|
-
|
|
2389
|
+
document.getElementById(isVercel ? "updateSdkPromptVercel" : "updateSdkPromptReplit")
|
|
2390
|
+
?.textContent?.trim() ||
|
|
2391
|
+
(isVercel ? UPDATE_SDK_PROMPT_VERCEL : UPDATE_SDK_PROMPT_REPLIT);
|
|
2392
|
+
const btnId = isVercel ? "copyUpdateSdkPromptVercelBtn" : "copyUpdateSdkPromptReplitBtn";
|
|
2386
2393
|
try {
|
|
2387
2394
|
await navigator.clipboard.writeText(text);
|
|
2388
|
-
const btn = document.getElementById(
|
|
2395
|
+
const btn = document.getElementById(btnId);
|
|
2389
2396
|
if (btn) {
|
|
2390
2397
|
const prev = btn.textContent;
|
|
2391
2398
|
btn.textContent = "Copied";
|
|
2392
2399
|
setTimeout(() => {
|
|
2393
|
-
btn.textContent = prev || "Copy prompt";
|
|
2400
|
+
btn.textContent = prev || (isVercel ? "Copy Vercel prompt" : "Copy Replit prompt");
|
|
2394
2401
|
}, 1200);
|
|
2395
2402
|
}
|
|
2396
2403
|
} catch {
|
|
@@ -2679,8 +2686,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
2679
2686
|
el.addEventListener("click", closeUpdateSdkModal);
|
|
2680
2687
|
});
|
|
2681
2688
|
document
|
|
2682
|
-
.getElementById("
|
|
2683
|
-
?.addEventListener("click", () => void copyUpdateSdkPrompt());
|
|
2689
|
+
.getElementById("copyUpdateSdkPromptReplitBtn")
|
|
2690
|
+
?.addEventListener("click", () => void copyUpdateSdkPrompt("replit"));
|
|
2691
|
+
document
|
|
2692
|
+
.getElementById("copyUpdateSdkPromptVercelBtn")
|
|
2693
|
+
?.addEventListener("click", () => void copyUpdateSdkPrompt("vercel"));
|
|
2684
2694
|
|
|
2685
2695
|
document.getElementById("addAssetBtn")?.addEventListener("click", () => {
|
|
2686
2696
|
if (uploadInProgress) return;
|
|
@@ -1034,6 +1034,14 @@ button.danger {
|
|
|
1034
1034
|
color: #0a0908;
|
|
1035
1035
|
}
|
|
1036
1036
|
|
|
1037
|
+
.update-sdk-prompt-label {
|
|
1038
|
+
margin: 0.85rem 0 0.35rem;
|
|
1039
|
+
font-size: 0.8rem;
|
|
1040
|
+
font-weight: 600;
|
|
1041
|
+
letter-spacing: 0.02em;
|
|
1042
|
+
color: #5d554d;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1037
1045
|
.update-sdk-prompt {
|
|
1038
1046
|
margin: 0;
|
|
1039
1047
|
padding: 0.75rem 0.85rem;
|
|
@@ -1049,6 +1057,8 @@ button.danger {
|
|
|
1049
1057
|
|
|
1050
1058
|
.update-sdk-modal-actions {
|
|
1051
1059
|
justify-content: flex-end;
|
|
1060
|
+
flex-wrap: wrap;
|
|
1061
|
+
gap: 0.5rem;
|
|
1052
1062
|
}
|
|
1053
1063
|
|
|
1054
1064
|
.download-players-modal-card {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Default: SQLite.
|
|
2
|
+
# TOMORROWOS_STORE=sqlite
|
|
3
|
+
# TOMORROWOS_DB_PATH=./data/tomorrowos.db
|
|
4
|
+
|
|
5
|
+
# Supabase/Postgres.
|
|
6
|
+
# On Replit use SUPABASE_URL — DATABASE_URL is often a reserved Secret.
|
|
7
|
+
# TOMORROWOS_STORE=supabase
|
|
8
|
+
# SUPABASE_URL=postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres
|
|
9
|
+
# DATABASE_SSL=true
|
|
10
|
+
# DATABASE_URL=postgresql://... # optional fallback outside Replit
|
|
11
|
+
|
|
12
|
+
# Optional: upload media to Cloudinary instead of local / Object Storage.
|
|
13
|
+
# CLOUDINARY_CLOUD_NAME=
|
|
14
|
+
# CLOUDINARY_API_KEY=
|
|
15
|
+
# CLOUDINARY_API_SECRET=
|
|
16
|
+
# CLOUDINARY_FOLDER=tomorrowos
|
|
17
|
+
|
|
18
|
+
# Optional: override the default deterministic pairing-code secret.
|
|
19
|
+
# PAIRING_CODE_SECRET=
|
|
@@ -231,11 +231,15 @@
|
|
|
231
231
|
<p class="hint">Current installed SDK version:</p>
|
|
232
232
|
<p class="update-sdk-version" id="updateSdkVersionLabel">Loading…</p>
|
|
233
233
|
<p class="hint">
|
|
234
|
-
To upgrade on AI agent platforms
|
|
234
|
+
To upgrade on AI agent platforms, paste the matching prompt into the Agent chat:
|
|
235
235
|
</p>
|
|
236
|
-
<
|
|
236
|
+
<p class="update-sdk-prompt-label">Replit</p>
|
|
237
|
+
<pre class="update-sdk-prompt" id="updateSdkPromptReplit">Follow NPM package @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.</pre>
|
|
238
|
+
<p class="update-sdk-prompt-label">Vercel</p>
|
|
239
|
+
<pre class="update-sdk-prompt" id="updateSdkPromptVercel">Follow NPM package @tomorrowos/sdk VERCEL_UPGRADE.md to upgrade my CMS with the latest SDK.</pre>
|
|
237
240
|
<div class="modal-actions update-sdk-modal-actions">
|
|
238
|
-
<button type="button" id="
|
|
241
|
+
<button type="button" id="copyUpdateSdkPromptReplitBtn" class="primary">Copy Replit prompt</button>
|
|
242
|
+
<button type="button" id="copyUpdateSdkPromptVercelBtn" class="primary">Copy Vercel prompt</button>
|
|
239
243
|
<button type="button" data-close-update-sdk-modal="1">Close</button>
|
|
240
244
|
</div>
|
|
241
245
|
</div>
|
|
@@ -33,8 +33,10 @@ let cachedSdkVersion = "";
|
|
|
33
33
|
/** @type {number|null} CMS server boot time (ms) from GET /devices. */
|
|
34
34
|
let serverStartedAtMs = null;
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
"Follow @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.";
|
|
36
|
+
const UPDATE_SDK_PROMPT_REPLIT =
|
|
37
|
+
"Follow NPM package @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.";
|
|
38
|
+
const UPDATE_SDK_PROMPT_VERCEL =
|
|
39
|
+
"Follow NPM package @tomorrowos/sdk VERCEL_UPGRADE.md to upgrade my CMS with the latest SDK.";
|
|
38
40
|
/** @type {ReturnType<typeof setTimeout>|null} */
|
|
39
41
|
let reconnectGraceTimer = null;
|
|
40
42
|
let uploadQueue = [];
|
|
@@ -2364,8 +2366,10 @@ function setUpdateSdkVersionLabel(version) {
|
|
|
2364
2366
|
|
|
2365
2367
|
async function openUpdateSdkModal() {
|
|
2366
2368
|
const modal = document.getElementById("updateSdkModal");
|
|
2367
|
-
const
|
|
2368
|
-
|
|
2369
|
+
const replitEl = document.getElementById("updateSdkPromptReplit");
|
|
2370
|
+
const vercelEl = document.getElementById("updateSdkPromptVercel");
|
|
2371
|
+
if (replitEl) replitEl.textContent = UPDATE_SDK_PROMPT_REPLIT;
|
|
2372
|
+
if (vercelEl) vercelEl.textContent = UPDATE_SDK_PROMPT_VERCEL;
|
|
2369
2373
|
setUpdateSdkVersionLabel(cachedSdkVersion || "Loading…");
|
|
2370
2374
|
modal?.classList.remove("hidden");
|
|
2371
2375
|
|
|
@@ -2379,18 +2383,21 @@ function closeUpdateSdkModal() {
|
|
|
2379
2383
|
document.getElementById("updateSdkModal")?.classList.add("hidden");
|
|
2380
2384
|
}
|
|
2381
2385
|
|
|
2382
|
-
async function copyUpdateSdkPrompt() {
|
|
2386
|
+
async function copyUpdateSdkPrompt(which) {
|
|
2387
|
+
const isVercel = which === "vercel";
|
|
2383
2388
|
const text =
|
|
2384
|
-
document.getElementById("
|
|
2385
|
-
|
|
2389
|
+
document.getElementById(isVercel ? "updateSdkPromptVercel" : "updateSdkPromptReplit")
|
|
2390
|
+
?.textContent?.trim() ||
|
|
2391
|
+
(isVercel ? UPDATE_SDK_PROMPT_VERCEL : UPDATE_SDK_PROMPT_REPLIT);
|
|
2392
|
+
const btnId = isVercel ? "copyUpdateSdkPromptVercelBtn" : "copyUpdateSdkPromptReplitBtn";
|
|
2386
2393
|
try {
|
|
2387
2394
|
await navigator.clipboard.writeText(text);
|
|
2388
|
-
const btn = document.getElementById(
|
|
2395
|
+
const btn = document.getElementById(btnId);
|
|
2389
2396
|
if (btn) {
|
|
2390
2397
|
const prev = btn.textContent;
|
|
2391
2398
|
btn.textContent = "Copied";
|
|
2392
2399
|
setTimeout(() => {
|
|
2393
|
-
btn.textContent = prev || "Copy prompt";
|
|
2400
|
+
btn.textContent = prev || (isVercel ? "Copy Vercel prompt" : "Copy Replit prompt");
|
|
2394
2401
|
}, 1200);
|
|
2395
2402
|
}
|
|
2396
2403
|
} catch {
|
|
@@ -2679,8 +2686,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
2679
2686
|
el.addEventListener("click", closeUpdateSdkModal);
|
|
2680
2687
|
});
|
|
2681
2688
|
document
|
|
2682
|
-
.getElementById("
|
|
2683
|
-
?.addEventListener("click", () => void copyUpdateSdkPrompt());
|
|
2689
|
+
.getElementById("copyUpdateSdkPromptReplitBtn")
|
|
2690
|
+
?.addEventListener("click", () => void copyUpdateSdkPrompt("replit"));
|
|
2691
|
+
document
|
|
2692
|
+
.getElementById("copyUpdateSdkPromptVercelBtn")
|
|
2693
|
+
?.addEventListener("click", () => void copyUpdateSdkPrompt("vercel"));
|
|
2684
2694
|
|
|
2685
2695
|
document.getElementById("addAssetBtn")?.addEventListener("click", () => {
|
|
2686
2696
|
if (uploadInProgress) return;
|
|
@@ -1034,6 +1034,14 @@ button.danger {
|
|
|
1034
1034
|
color: #0a0908;
|
|
1035
1035
|
}
|
|
1036
1036
|
|
|
1037
|
+
.update-sdk-prompt-label {
|
|
1038
|
+
margin: 0.85rem 0 0.35rem;
|
|
1039
|
+
font-size: 0.8rem;
|
|
1040
|
+
font-weight: 600;
|
|
1041
|
+
letter-spacing: 0.02em;
|
|
1042
|
+
color: #5d554d;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1037
1045
|
.update-sdk-prompt {
|
|
1038
1046
|
margin: 0;
|
|
1039
1047
|
padding: 0.75rem 0.85rem;
|
|
@@ -1049,6 +1057,8 @@ button.danger {
|
|
|
1049
1057
|
|
|
1050
1058
|
.update-sdk-modal-actions {
|
|
1051
1059
|
justify-content: flex-end;
|
|
1060
|
+
flex-wrap: wrap;
|
|
1061
|
+
gap: 0.5rem;
|
|
1052
1062
|
}
|
|
1053
1063
|
|
|
1054
1064
|
.download-players-modal-card {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-cms",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.72",
|
|
4
4
|
"description": "TomorrowOS CMS for Vercel / v0 Publish (Fluid Function + WebSockets + optional Next Preview).",
|
|
5
5
|
"private": true,
|
|
6
6
|
"type": "module",
|
|
@@ -13,11 +13,10 @@
|
|
|
13
13
|
"dev:next": "cd preview && next dev -p 3000",
|
|
14
14
|
"dev:preview": "concurrently -k \"npm:dev:tomorrowos\" \"npm:dev:next\"",
|
|
15
15
|
"start": "tsx server.ts",
|
|
16
|
-
"build": "node -e \"process.exit(0)\""
|
|
17
|
-
"build-player": "tomorrowos build --platform tizen"
|
|
16
|
+
"build": "node -e \"process.exit(0)\""
|
|
18
17
|
},
|
|
19
18
|
"dependencies": {
|
|
20
|
-
"@tomorrowos/sdk": "^0.9.
|
|
19
|
+
"@tomorrowos/sdk": "^0.9.72",
|
|
21
20
|
"dotenv": "^17.2.3",
|
|
22
21
|
"tsx": "^4.19.0"
|
|
23
22
|
},
|