@tomorrowos/sdk 0.8.0 → 0.8.2

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/REPLIT_SETUP.md CHANGED
@@ -12,7 +12,7 @@ When a human pastes a prompt like this, **read this file and start Question 1 im
12
12
  ```text
13
13
  Follow @tomorrowos/sdk REPLIT_SETUP.md and set up my TomorrowOS CMS.
14
14
  Ask only the questions listed in REPLIT_SETUP.md, in order. Do not use LLM_PROMPT.md.
15
- After all setup questions are answered (including Cloudinary Secrets if you chose Cloudinary), configure and start — minimal verification only (Web app type + Preview at /). No Supabase or WebSocket tests.
15
+ After all setup questions are answered (including Cloudinary Secrets if you chose Cloudinary), configure and start — minimal verification only (Web app type + Preview at /). **Never test Supabase connection** — save `SUPABASE_URL` and move on. No Supabase or WebSocket tests.
16
16
  Do not skip steps.
17
17
  ```
18
18
 
@@ -35,16 +35,15 @@ Replit Agent must ask **only** the questions defined in **this file**, in **this
35
35
  |------|---------|------|
36
36
  | 1 | **Question 1** — How many screens / devices? | Always |
37
37
  | 2 | **Question 2** — Supabase connection | Only if answer to Q1 is **> 5** |
38
- | 3 | **Question 3** — Media storage (Cloudinary vs Object Storage) | Always (after Q1 or Q2) |
39
- | 3b | **Question 3b** — Cloudinary credentials (Secrets) | **Mandatory** if Q3 answer is Cloudinary / yes — **before Q4** |
38
+ | 3 | **Question 3** — Media storage (+ Cloudinary Secrets if chosen) | Always (after Q1 or Q2) |
40
39
  | 4 | **Question 4** — Brand / TomorrowOS app look | Always last, before execution |
41
40
 
42
- **That is the complete list.** There are no other setup questions.
41
+ **That is the complete list.** There are no other setup questions. There is **no** “Question 3b” — Cloudinary credentials are collected **inside Question 3**, immediately after the user chooses Cloudinary.
43
42
 
44
- **Critical:** Question 3 is **not complete** when the user says “Cloudinary” or “yes”. You **must** run **Question 3b** and collect `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_API_SECRET` (as Replit Secrets) **before** asking Question 4. Do **not** skip to branding with placeholder or invented credentials.
43
+ **Critical:** Question 3 is **not complete** when the user says “Cloudinary” or “yes”. You **must** immediately show the Cloudinary Secrets input (same step — do **not** label a new question) and collect `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_API_SECRET` **before** Question 4. Do **not** skip to branding with placeholder or invented credentials.
45
44
 
46
45
 
47
- If the user volunteers extra info early (e.g. brand name before Q4), **record it** and still ask the current question’s required fields you do not yet have. Do not skip ahead to execution until Q1–Q4 (or Q1, Q3, Q3b, Q4 if ≤5 screens and Cloudinary) are complete.
46
+ If the user volunteers extra info early (e.g. brand name before Q4), **record it** and still ask the current question’s required fields you do not yet have. Do not skip ahead to execution until Q1–Q4 are complete (Question 3 includes Cloudinary Secrets when applicable).
48
47
 
49
48
  If the user says “just set it up, don’t ask questions,” respond:
50
49
 
@@ -56,21 +55,22 @@ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
56
55
 
57
56
  ## Hard rules
58
57
 
59
- 1. **Ask only REPLIT_SETUP.md questions 1–4 and 3b when required** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
60
- 2. **One question at a time.** Wait for the user’s answer before asking the next question (unless they already answered several in one message). **Exception:** Question 3b may ask for all three Cloudinary Secrets in one messagestill **stop and wait** for the user’s values before Question 4.
58
+ 1. **Ask only REPLIT_SETUP.md questions 1–4** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
59
+ 2. **One question at a time.** Wait for the user’s answer before asking the next question (unless they already answered several in one message). **Exception:** If the user chooses Cloudinary in Question 3, **stay on Question 3** and immediately show the Secrets formdo **not** open a separate “3b” step or announce a new question number.
61
60
  3. **Do not invent** screen counts, Cloudinary credentials, Supabase URLs, or brand colours.
62
61
  4. **Do not use Replit’s reserved `DATABASE_URL` Secret for Supabase.** On Replit, `DATABASE_URL` is often pre-claimed. Always use **`SUPABASE_URL`** for TomorrowOS ↔ Supabase.
63
62
  5. **Prefer `npx @tomorrowos/sdk init`** (or the package’s `templates/cms-starter`) as the project seed. Do not rebuild pairing, WebSocket, or playlist APIs from scratch.
64
63
  6. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
65
64
  7. After Q&A, **configure and start** — do **not** run a long test suite (see **Post-Q&A: minimal verification only**).
66
65
  8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
66
+ 9. **Supabase: configure only — never test.** Save `SUPABASE_URL` + `TOMORROWOS_STORE=supabase` and proceed. **Do not** ping Postgres, run `psql`, start the server solely to verify DB connectivity, or treat log errors like `ENOTFOUND` / `database connection failure` in **Replit dev / Preview** as a failed setup. Supabase often works only after **Publish** (production networking), not in the dev shell.
67
67
 
68
68
  **Question order after Q1:**
69
69
 
70
- - If **≤ 5 screens:** Q1 → Q3 → (Q3b if Cloudinary) → Q4 → execution checklist
71
- - If **> 5 screens:** Q1 → Q2 → Q3 → (Q3b if Cloudinary) → Q4 → execution checklist
70
+ - If **≤ 5 screens:** Q1 → Q3 → Q4 → execution checklist
71
+ - If **> 5 screens:** Q1 → Q2 → Q3 → Q4 → execution checklist
72
72
 
73
- Never insert extra questions between these steps. **Never skip Question 3b** when the user chose Cloudinary.
73
+ Never insert extra questions between these steps. When the user chooses Cloudinary, **Question 3 continues** with the Secrets form immediately — then proceed to Q4 only after secrets are saved.
74
74
 
75
75
  ---
76
76
 
@@ -201,7 +201,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
201
201
  "node": ">=20"
202
202
  },
203
203
  "dependencies": {
204
- "@tomorrowos/sdk": "^0.8.0",
204
+ "@tomorrowos/sdk": "^0.8.2",
205
205
  "dotenv": "^17.2.3",
206
206
  "tsx": "^4.19.0"
207
207
  },
@@ -301,6 +301,22 @@ Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.re
301
301
 
302
302
  After Questions 1–4, **configure → `npm install` → `npm run start` → done.**
303
303
 
304
+ ### Supabase: never test in Replit dev (mandatory)
305
+
306
+ When the user chose Supabase (>5 screens), setup is **save credentials + wire `server.ts` + start** — **nothing else**.
307
+
308
+ **Forbidden after Q&A (and after Question 2):**
309
+
310
+ - ❌ “Testing Supabase connection…”
311
+ - ❌ `psql`, `pg`, Prisma `db pull`, or any one-off DB probe script
312
+ - ❌ Restarting / debugging the server **because** logs show `database connection failure`, `getaddrinfo ENOTFOUND`, or `db.*.supabase.co can't be resolved`
313
+ - ❌ Telling the user their Supabase URL is wrong **only** because dev Preview cannot resolve the host
314
+ - ❌ Blocking setup completion on Supabase connectivity
315
+
316
+ **Expected in Replit dev:** Supabase host may **not resolve** in the dev environment. That is **normal**. The Control Panel at `/` can still load. Mark setup **complete** when Web app type is correct and Preview shows the Control Panel — **even if** Supabase errors appear in logs.
317
+
318
+ **When Supabase actually gets validated:** after the user **Publishes** the Repl and uses the live URL — not during the setup wizard.
319
+
304
320
  ### Do (maximum)
305
321
 
306
322
  1. Confirm **Web app** artifact (not API) — **most important**.
@@ -311,7 +327,7 @@ After Questions 1–4, **configure → `npm install` → `npm run start` → don
311
327
 
312
328
  ### Do NOT run after setup (unless user asks or Publish fails)
313
329
 
314
- - ❌ **Supabase connection test** (no `psql`, no DB ping, no “testing Supabase connection…”)
330
+ - ❌ **Supabase connection test** — **never**, including after `npm run start` (no `psql`, no DB ping, no “verifying database…”, no retry loops for `ENOTFOUND`)
315
331
  - ❌ **Cloudinary upload test**
316
332
  - ❌ **`curl` / `fetch` on `/brand.json`** as a formal gate
317
333
  - ❌ **Browser WebSocket console snippet** as a formal gate
@@ -319,7 +335,7 @@ After Questions 1–4, **configure → `npm install` → `npm run start` → don
319
335
  - ❌ **Long troubleshooting loops** when Preview already shows the Control Panel
320
336
  - ❌ Re-running the full **Publish readiness checklist** item-by-item in chat
321
337
 
322
- If Preview shows the Control Panel and the project is **Web app** type, **stop testing** and give the user their URL and next steps.
338
+ If Preview shows the Control Panel and the project is **Web app** type, **stop testing** and give the user their URL and next steps — **even when using Supabase and dev logs show DB connection errors**.
323
339
 
324
340
  ### Only if Preview is empty or Publish fails
325
341
 
@@ -402,7 +418,7 @@ DATABASE_SSL=true
402
418
  ```
403
419
 
404
420
  5. **Do not** write the real password into committed files.
405
- 6. **Do not** test the Supabase connection after saving the Secret — configuration only.
421
+ 6. **Do not** test the Supabase connection after saving the Secret — **configuration only**. No probe, no `npm run start` just to verify DB, no fixing “connection failure” in dev. Saving `SUPABASE_URL` completes Question 2.
406
422
 
407
423
  If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit is fragile for fleets, then offer SQLite only after they confirm.
408
424
 
@@ -410,6 +426,8 @@ If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit i
410
426
 
411
427
  ## Question 3 — Media storage (uploads / thumbnails)
412
428
 
429
+ ### Step A — Ask storage choice
430
+
413
431
  **Ask exactly:**
414
432
 
415
433
  > How should playlist media (images/videos) be stored?
@@ -422,47 +440,38 @@ If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit i
422
440
  >
423
441
  > Do you want me to set up **Cloudinary**? (yes / no)
424
442
 
425
- ### If YES Cloudinary go to Question 3b (do not ask Question 4 yet)
443
+ ### Step B — If YES / Cloudinary (same Question 3 no “3b”, no extra question)
426
444
 
427
- Choosing Cloudinary **does not finish** Question 3. Immediately continue to **Question 3b** below.
445
+ **Do this immediately** when the user chooses Cloudinary. **Do not** say “Question 3b”, “next step”, or “Great — I’ll use Cloudinary” as a separate message before the form. **Go straight to the Secrets input.**
428
446
 
429
- ---
430
-
431
- ## Question 3b — Cloudinary credentials (mandatory if Q3 = Cloudinary)
447
+ **Preferred on Replit:** open the **Replit Secrets** UI with fields for:
432
448
 
433
- > **Ask this before Question 4.** Do not jump to `brand.json` until the user has provided credentials or confirmed they are saved as Replit Secrets.
449
+ - `CLOUDINARY_CLOUD_NAME`
450
+ - `CLOUDINARY_API_KEY`
451
+ - `CLOUDINARY_API_SECRET`
452
+ - Optional: `CLOUDINARY_FOLDER` (e.g. `tomorrowos`)
434
453
 
435
- **Ask exactly (copy wording):**
454
+ **If Secrets UI is unavailable, ask exactly (one message with all fields):**
436
455
 
437
- > Great I’ll use **Cloudinary** for media uploads.
438
- >
439
- > Please paste your Cloudinary credentials (from [cloudinary.com/console](https://cloudinary.com/console) → Dashboard → **API Keys**). I will store them as Replit **Secrets** — never in committed files:
440
- >
441
- > 1. **`CLOUDINARY_CLOUD_NAME`** — your cloud name (e.g. `dxyz123abc`)
442
- > 2. **`CLOUDINARY_API_KEY`** — API Key
443
- > 3. **`CLOUDINARY_API_SECRET`** — API Secret
456
+ > Paste your Cloudinary credentials (from [cloudinary.com/console](https://cloudinary.com/console) → Dashboard → **API Keys**). I will store them as Replit **Secrets**:
444
457
  >
445
- > Optional: **`CLOUDINARY_FOLDER`** (e.g. `tomorrowos`) — say if you want a folder prefix.
458
+ > 1. **`CLOUDINARY_CLOUD_NAME`**
459
+ > 2. **`CLOUDINARY_API_KEY`**
460
+ > 3. **`CLOUDINARY_API_SECRET`**
446
461
  >
447
- > You can paste all three in one reply, or use Replit’s Secrets panel and tell me when each Secret is set.
462
+ > Optional: **`CLOUDINARY_FOLDER`**
448
463
 
449
464
  **You must then:**
450
465
 
451
- 1. Create / update Replit Secrets:
452
- - `CLOUDINARY_CLOUD_NAME=<user value>`
453
- - `CLOUDINARY_API_KEY=<user value>`
454
- - `CLOUDINARY_API_SECRET=<user value>`
455
- - Optional: `CLOUDINARY_FOLDER=<user value>`
456
- 2. **Do not** write real secrets into `.env` files that are committed to git. Replit Secrets only (or `.env` that is gitignored and references env vars).
457
- 3. **Do not** invent or placeholder Cloudinary credentials.
466
+ 1. Save Replit Secrets: `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, `CLOUDINARY_API_SECRET` (and optional `CLOUDINARY_FOLDER`).
467
+ 2. **Do not** write real secrets into committed files.
468
+ 3. **Do not** invent or placeholder credentials.
458
469
  4. **Do not** proceed to Question 4 until all three required Secrets exist.
459
470
  5. **Do not** run a Cloudinary upload test — configuration only.
460
471
 
461
- Tell the user:
472
+ **If the user does not have a Cloudinary account yet:** tell them to sign up at cloudinary.com and return with API keys. **Wait** on Question 3 — do not skip to Question 4.
462
473
 
463
- > After Cloudinary Secrets are set, we’ll finish branding and start the CMS. New uploads will return `https://res.cloudinary.com/...` URLs.
464
-
465
- **If the user does not have a Cloudinary account yet:** tell them to sign up at cloudinary.com, create API keys, then return with the three values. **Wait** — do not skip to Question 4.
474
+ The SDK auto-detects these env vars and uploads media to Cloudinary. New uploads will return `https://res.cloudinary.com/...` URLs.
466
475
 
467
476
  ### If NO — Replit Object Storage (or local)
468
477
 
@@ -600,13 +609,13 @@ npm run start
600
609
 
601
610
  (Use `npm run dev` only for local edit/watch. **Publish / Deploy / Replit Run must use `npm run start`.**)
602
611
 
603
- **Minimal check:** logs contain `[TomorrowOS] listening on http://0.0.0.0:...` and Preview shows Control Panel at `/`. Then proceed to **G** — no further tests.
612
+ **Minimal check:** logs contain `[TomorrowOS] listening on http://0.0.0.0:...` and Preview shows Control Panel at `/`. Then proceed to **G** — no further tests. **Ignore** Supabase `ENOTFOUND` / `database connection failure` in dev logs; do not debug DB for that reason alone.
604
613
 
605
614
  ### F. Done — skip extended verification
606
615
 
607
616
  If the **three-item Publish readiness checklist** passes (especially **Web app, not API**), mark setup complete.
608
617
 
609
- **Do not** run WebSocket console tests, Supabase connection tests, or `brand.json` curl checks here.
618
+ **Do not** run WebSocket console tests, Supabase connection tests, or `brand.json` curl checks here. **Supabase `ENOTFOUND` in dev is not a setup failure** — tell the user DB will connect after Publish if needed.
610
619
 
611
620
  Only investigate further if Preview is empty, server crashed, or user reports Publish failure.
612
621
 
@@ -641,7 +650,8 @@ Do **not**:
641
650
  - Change the production start command away from `tsx server.ts` / `npm run start`
642
651
  - Point Supabase at Replit’s reserved `DATABASE_URL` when `SUPABASE_URL` should be used
643
652
  - Skip Cloudinary recommendation without stating the persistence tradeoff
644
- - **Skip Question 3b** after the user chooses Cloudinary — always collect `CLOUDINARY_*` Secrets before Question 4
653
+ - **Skip Cloudinary Secrets** after the user chooses Cloudinary — always collect `CLOUDINARY_*` inside Question 3 before Question 4
654
+ - **Announce “Question 3b”** or a separate follow-up question — show the Secrets form immediately instead
645
655
  - Claim uploads are “permanent” on Replit local disk without Object Storage or Cloudinary
646
656
  - Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
647
657
  - Use Canvas preview as the primary CMS verification surface
@@ -649,6 +659,7 @@ Do **not**:
649
659
  - Create the Repl as **API-only** or publish with **Static Deployment** only
650
660
  - Omit `[[ports]]` / `deploymentTarget` from `.replit` when setting up for Publish
651
661
  - Run **Supabase connection tests**, **WebSocket console tests**, or other post-setup smoke tests unless Preview fails or the user asks
662
+ - **Debug or “fix” Supabase** because dev logs show `getaddrinfo ENOTFOUND` or `database connection failure` — save config and finish setup instead
652
663
 
653
664
  ---
654
665
 
@@ -682,15 +693,20 @@ TOMORROWOS_STORE=sqlite
682
693
  | `EADDRINUSE` on start | Old process holding port | Stop stale processes, clear background tasks, restart Repl |
683
694
  | Upload: `storage.objects.create` denied | Replit Object Storage IAM | Fix Object Storage permissions **or** switch to Cloudinary |
684
695
  | Upload OK then thumbnails vanish later | Non-persistent `public/uploads` | Object Storage or Cloudinary |
685
- | Supabase connection errors | Wrong URL or using reserved `DATABASE_URL` | Use `SUPABASE_URL` + `TOMORROWOS_STORE=supabase` |
696
+ | Supabase `ENOTFOUND` / `can't be resolved` in **dev** logs after setup | Replit dev network cannot reach Supabase host | **Not a setup failure.** Finish wizard; user validates DB after **Publish** |
697
+ | Supabase connection errors on **published** URL | Wrong URL or using reserved `DATABASE_URL` | Use `SUPABASE_URL` + `TOMORROWOS_STORE=supabase`; pooler URL `*.pooler.supabase.com:6543` |
686
698
  | Pairing works on one Repl but not another | That Repl’s WS/backend only | Compare Run command and logs with a known-good Repl |
687
699
 
688
700
  ---
689
701
 
690
702
  ## Protocol version
691
703
 
692
- `replit-setup/1.4` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
704
+ `replit-setup/1.6` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
705
+
706
+ **Changelog 1.6:** **Never test Supabase** in Replit dev — `ENOTFOUND` / connection errors in Preview logs are expected; setup completes when Control Panel loads.
707
+
708
+ **Changelog 1.5:** Cloudinary Secrets collected **inside Question 3** — no separate “3b” step; show Secrets form immediately when user picks Cloudinary.
693
709
 
694
- **Changelog 1.4:** **Question 3b** — mandatory Cloudinary credential collection (Replit Secrets) before Question 4; fixes agents skipping secrets after “yes” to Cloudinary.
710
+ **Changelog 1.4:** mandatory Cloudinary credential collection before Question 4 (superseded by 1.5 flow).
695
711
 
696
712
  **Changelog 1.3:** minimal post-Q&A verification — no Supabase/WS smoke tests; prioritize **Web app vs API** only.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
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,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
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",
@@ -13,7 +13,7 @@
13
13
  "build-player": "tomorrowos build --platform tizen"
14
14
  },
15
15
  "dependencies": {
16
- "@tomorrowos/sdk": "^0.8.0",
16
+ "@tomorrowos/sdk": "^0.8.2",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },