@tomorrowos/sdk 0.9.31 → 0.9.33
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/README.md +196 -197
- package/VERCEL_SETUP.md +171 -178
- package/package.json +51 -51
- package/templates/cms-starter/package.json +25 -25
- package/templates/cms-starter-v0/README.md +25 -10
- package/templates/cms-starter-v0/package.json +35 -35
- package/templates/cms-starter-v0/preview/app/layout.tsx +11 -0
- package/templates/cms-starter-v0/preview/app/page.tsx +3 -0
- package/templates/cms-starter-v0/preview/next-env.d.ts +2 -0
- package/templates/cms-starter-v0/preview/next.config.mjs +18 -0
- package/templates/cms-starter-v0/preview/tsconfig.json +20 -0
- package/templates/cms-starter-v0/tsconfig.json +1 -2
- package/templates/cms-starter-v0/app/[[...slug]]/route.ts +0 -89
- package/templates/cms-starter-v0/app/layout.tsx +0 -15
- package/templates/cms-starter-v0/next-env.d.ts +0 -4
- package/templates/cms-starter-v0/next.config.mjs +0 -15
package/package.json
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@tomorrowos/sdk",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "TomorrowOS CMS server SDK - WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.js"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"bin": {
|
|
15
|
-
"tomorrowos": "./dist/cli.js"
|
|
16
|
-
},
|
|
17
|
-
"files": [
|
|
18
|
-
"dist",
|
|
19
|
-
"templates",
|
|
20
|
-
"README.md",
|
|
21
|
-
"LLM_PROMPT.md",
|
|
22
|
-
"REPLIT_SETUP.md",
|
|
23
|
-
"VERCEL_SETUP.md",
|
|
24
|
-
"REPLIT_UPGRADE.md",
|
|
25
|
-
"BUILD_GUARDRAILS.md",
|
|
26
|
-
"PLAYER_INSTALL.md",
|
|
27
|
-
"brand.schema.json",
|
|
28
|
-
"brand.example.json"
|
|
29
|
-
],
|
|
30
|
-
"scripts": {
|
|
31
|
-
"build": "tsc",
|
|
32
|
-
"prepublishOnly": "npm run build"
|
|
33
|
-
},
|
|
34
|
-
"engines": {
|
|
35
|
-
"node": ">=18"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"better-sqlite3": "^12.11.1",
|
|
39
|
-
"cloudinary": "^2.10.0",
|
|
40
|
-
"pg": "^8.22.0",
|
|
41
|
-
"ws": "^8.21.0"
|
|
42
|
-
},
|
|
43
|
-
"devDependencies": {
|
|
44
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
45
|
-
"@types/node": "^20.19.41",
|
|
46
|
-
"@types/pg": "^8.20.0",
|
|
47
|
-
"@types/ws": "^8.5.10",
|
|
48
|
-
"typescript": "^5.5.0"
|
|
49
|
-
},
|
|
50
|
-
"license": "Apache-2.0"
|
|
51
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@tomorrowos/sdk",
|
|
3
|
+
"version": "0.9.33",
|
|
4
|
+
"description": "TomorrowOS CMS server SDK - WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"tomorrowos": "./dist/cli.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"templates",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LLM_PROMPT.md",
|
|
22
|
+
"REPLIT_SETUP.md",
|
|
23
|
+
"VERCEL_SETUP.md",
|
|
24
|
+
"REPLIT_UPGRADE.md",
|
|
25
|
+
"BUILD_GUARDRAILS.md",
|
|
26
|
+
"PLAYER_INSTALL.md",
|
|
27
|
+
"brand.schema.json",
|
|
28
|
+
"brand.example.json"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"better-sqlite3": "^12.11.1",
|
|
39
|
+
"cloudinary": "^2.10.0",
|
|
40
|
+
"pg": "^8.22.0",
|
|
41
|
+
"ws": "^8.21.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
45
|
+
"@types/node": "^20.19.41",
|
|
46
|
+
"@types/pg": "^8.20.0",
|
|
47
|
+
"@types/ws": "^8.5.10",
|
|
48
|
+
"typescript": "^5.5.0"
|
|
49
|
+
},
|
|
50
|
+
"license": "Apache-2.0"
|
|
51
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "my-cms",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
|
|
5
|
-
"private": true,
|
|
6
|
-
"type": "module",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=20"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"dev": "tsx watch server.ts",
|
|
12
|
-
"start": "tsx server.ts",
|
|
13
|
-
"build-player": "tomorrowos build --platform tizen"
|
|
14
|
-
},
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"@tomorrowos/sdk": "^0.9.
|
|
17
|
-
"dotenv": "^17.2.3",
|
|
18
|
-
"tsx": "^4.19.0"
|
|
19
|
-
},
|
|
20
|
-
"devDependencies": {
|
|
21
|
-
"@types/node": "^20.0.0",
|
|
22
|
-
"typescript": "^5.5.0"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "my-cms",
|
|
3
|
+
"version": "0.9.33",
|
|
4
|
+
"description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "tsx watch server.ts",
|
|
12
|
+
"start": "tsx server.ts",
|
|
13
|
+
"build-player": "tomorrowos build --platform tizen"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@tomorrowos/sdk": "^0.9.33",
|
|
17
|
+
"dotenv": "^17.2.3",
|
|
18
|
+
"tsx": "^4.19.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^20.0.0",
|
|
22
|
+
"typescript": "^5.5.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# TomorrowOS CMS Starter (Vercel / v0)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
This starter is for **Vercel Publish** and **v0**. It follows
|
|
4
|
+
[Vercel Functions WebSockets](https://vercel.com/docs/functions/websockets):
|
|
5
|
+
|
|
6
|
+
- **`cms-app.ts`** — shared `TomorrowOS.listen` + `export const server`
|
|
7
|
+
- **`api/index.ts`** — Production Function: `export default server` (Fluid)
|
|
8
|
+
- **`server.ts`** — local / Preview: same server (`npm start`)
|
|
9
|
+
- **`cms-panel/`** — Control Panel static files (not `public/`)
|
|
10
|
+
- **`preview/`** — Next.js shell for v0 Preview only
|
|
11
|
+
- **`vercel.json`** — `fluid`, rewrites → `/api`, `maxDuration`
|
|
6
12
|
|
|
7
13
|
## Scaffold
|
|
8
14
|
|
|
@@ -10,26 +16,35 @@
|
|
|
10
16
|
npx @tomorrowos/sdk init my-cms --hosting v0
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
## Local
|
|
19
|
+
## Local development
|
|
14
20
|
|
|
15
21
|
```bash
|
|
16
22
|
npm install
|
|
17
23
|
npm run dev
|
|
18
24
|
```
|
|
19
25
|
|
|
20
|
-
`
|
|
26
|
+
Open `http://localhost:3000`. Pairing uses `ws://localhost:3000/` (root path).
|
|
27
|
+
|
|
28
|
+
### v0-style Preview
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm run dev:preview
|
|
32
|
+
```
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
2. Next on `http://localhost:3000` → proxies `/` to TomorrowOS
|
|
34
|
+
Pair devices against the **Publish URL**, not Preview.
|
|
24
35
|
|
|
25
|
-
|
|
36
|
+
## Production acceptance
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
1. `GET /status` → JSON
|
|
39
|
+
2. `GET /` → Control Panel
|
|
40
|
+
3. WebSocket upgrade on `/` or `/api` → **101** (not 200 HTML)
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
TV endpoint: `https://YOUR.vercel.app/` (players also try `/api` on `*.vercel.app`).
|
|
30
43
|
|
|
31
44
|
## Replit / Railway
|
|
32
45
|
|
|
46
|
+
Use the default starter (unchanged Node listen, no `api/` Function):
|
|
47
|
+
|
|
33
48
|
```bash
|
|
34
49
|
npx @tomorrowos/sdk init my-cms --hosting replit
|
|
35
50
|
```
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "my-cms",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "TomorrowOS CMS for Vercel / v0 (Fluid Function
|
|
5
|
-
"private": true,
|
|
6
|
-
"type": "module",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=20"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"dev": "
|
|
12
|
-
"dev:tomorrowos": "cross-env TOMORROWOS_INTERNAL_PORT=3001 tsx watch server.ts",
|
|
13
|
-
"dev:next": "next dev -p 3000",
|
|
14
|
-
"dev:preview": "concurrently -k
|
|
15
|
-
"start": "tsx server.ts",
|
|
16
|
-
"build": "node -e \"process.exit(0)\"",
|
|
17
|
-
"build-player": "tomorrowos build --platform tizen"
|
|
18
|
-
},
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"@tomorrowos/sdk": "^0.9.
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"react
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"typescript": "^5.5.0"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "my-cms",
|
|
3
|
+
"version": "0.9.33",
|
|
4
|
+
"description": "TomorrowOS CMS for Vercel / v0 Publish (Fluid Function + WebSockets + optional Next Preview).",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"dev": "tsx watch server.ts",
|
|
12
|
+
"dev:tomorrowos": "cross-env TOMORROWOS_INTERNAL_PORT=3001 tsx watch server.ts",
|
|
13
|
+
"dev:next": "cd preview && next dev -p 3000",
|
|
14
|
+
"dev:preview": "concurrently -k \"npm:dev:tomorrowos\" \"npm:dev:next\"",
|
|
15
|
+
"start": "tsx server.ts",
|
|
16
|
+
"build": "node -e \"process.exit(0)\"",
|
|
17
|
+
"build-player": "tomorrowos build --platform tizen"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@tomorrowos/sdk": "^0.9.33",
|
|
21
|
+
"dotenv": "^17.2.3",
|
|
22
|
+
"tsx": "^4.19.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^20.0.0",
|
|
26
|
+
"@types/react": "^19.0.0",
|
|
27
|
+
"@types/react-dom": "^19.0.0",
|
|
28
|
+
"concurrently": "^9.1.2",
|
|
29
|
+
"cross-env": "^7.0.3",
|
|
30
|
+
"next": "^15.1.0",
|
|
31
|
+
"react": "^19.0.0",
|
|
32
|
+
"react-dom": "^19.0.0",
|
|
33
|
+
"typescript": "^5.5.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const internalUrl =
|
|
2
|
+
process.env.TOMORROWOS_INTERNAL_URL || "http://127.0.0.1:3001";
|
|
3
|
+
|
|
4
|
+
/** @type {import('next').NextConfig} */
|
|
5
|
+
const nextConfig = {
|
|
6
|
+
async rewrites() {
|
|
7
|
+
return {
|
|
8
|
+
fallback: [
|
|
9
|
+
{
|
|
10
|
+
source: "/:path*",
|
|
11
|
+
destination: `${internalUrl}/:path*`
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default nextConfig;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [{ "name": "next" }]
|
|
17
|
+
},
|
|
18
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
|
19
|
+
"exclude": ["node_modules"]
|
|
20
|
+
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* v0 / local Preview shell — proxies all HTTP to TomorrowOS on :3001.
|
|
3
|
-
* Production Publish does NOT use this file; traffic goes to api/index.ts (Fluid).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const INTERNAL =
|
|
7
|
-
process.env.TOMORROWOS_INTERNAL_URL || "http://127.0.0.1:3001";
|
|
8
|
-
|
|
9
|
-
const HOP_BY_HOP = new Set([
|
|
10
|
-
"connection",
|
|
11
|
-
"keep-alive",
|
|
12
|
-
"proxy-authenticate",
|
|
13
|
-
"proxy-authorization",
|
|
14
|
-
"te",
|
|
15
|
-
"trailers",
|
|
16
|
-
"transfer-encoding",
|
|
17
|
-
"upgrade",
|
|
18
|
-
"host",
|
|
19
|
-
"content-length"
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
async function proxyToTomorrowOS(req: Request): Promise<Response> {
|
|
23
|
-
const incoming = new URL(req.url);
|
|
24
|
-
const target = new URL(incoming.pathname + incoming.search, INTERNAL);
|
|
25
|
-
|
|
26
|
-
const headers = new Headers();
|
|
27
|
-
req.headers.forEach((value, key) => {
|
|
28
|
-
if (!HOP_BY_HOP.has(key.toLowerCase())) headers.set(key, value);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const init: RequestInit = {
|
|
32
|
-
method: req.method,
|
|
33
|
-
headers,
|
|
34
|
-
redirect: "manual"
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
38
|
-
init.body = req.body;
|
|
39
|
-
// @ts-expect-error Node fetch duplex for streaming bodies
|
|
40
|
-
init.duplex = "half";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const upstream = await fetch(target, init);
|
|
45
|
-
const outHeaders = new Headers();
|
|
46
|
-
upstream.headers.forEach((value, key) => {
|
|
47
|
-
if (!HOP_BY_HOP.has(key.toLowerCase())) outHeaders.set(key, value);
|
|
48
|
-
});
|
|
49
|
-
return new Response(upstream.body, {
|
|
50
|
-
status: upstream.status,
|
|
51
|
-
statusText: upstream.statusText,
|
|
52
|
-
headers: outHeaders
|
|
53
|
-
});
|
|
54
|
-
} catch {
|
|
55
|
-
const html = `<!DOCTYPE html>
|
|
56
|
-
<html lang="en">
|
|
57
|
-
<head>
|
|
58
|
-
<meta charset="utf-8" />
|
|
59
|
-
<title>TomorrowOS Preview</title>
|
|
60
|
-
<style>
|
|
61
|
-
body { font-family: system-ui, sans-serif; max-width: 40rem; margin: 3rem auto; padding: 0 1rem; line-height: 1.5; }
|
|
62
|
-
code { background: #f4f4f5; padding: 0.1em 0.35em; border-radius: 4px; }
|
|
63
|
-
</style>
|
|
64
|
-
</head>
|
|
65
|
-
<body>
|
|
66
|
-
<h1>TomorrowOS Preview</h1>
|
|
67
|
-
<p>The Next.js shell is running, but TomorrowOS is not reachable at <code>${INTERNAL}</code>.</p>
|
|
68
|
-
<p>Start both processes:</p>
|
|
69
|
-
<pre><code>npm run dev</code></pre>
|
|
70
|
-
<p>(runs TomorrowOS on :3001 and Next on :3000). Publish / Production does not use this shell.</p>
|
|
71
|
-
</body>
|
|
72
|
-
</html>`;
|
|
73
|
-
return new Response(html, {
|
|
74
|
-
status: 502,
|
|
75
|
-
headers: { "content-type": "text/html; charset=utf-8" }
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const dynamic = "force-dynamic";
|
|
81
|
-
export const runtime = "nodejs";
|
|
82
|
-
|
|
83
|
-
export const GET = proxyToTomorrowOS;
|
|
84
|
-
export const POST = proxyToTomorrowOS;
|
|
85
|
-
export const PUT = proxyToTomorrowOS;
|
|
86
|
-
export const PATCH = proxyToTomorrowOS;
|
|
87
|
-
export const DELETE = proxyToTomorrowOS;
|
|
88
|
-
export const HEAD = proxyToTomorrowOS;
|
|
89
|
-
export const OPTIONS = proxyToTomorrowOS;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal layout so the App Router can boot for v0 Preview.
|
|
3
|
-
* All real UI is proxied from TomorrowOS via app/[[...slug]]/route.ts.
|
|
4
|
-
*/
|
|
5
|
-
export default function RootLayout({
|
|
6
|
-
children
|
|
7
|
-
}: {
|
|
8
|
-
children: React.ReactNode;
|
|
9
|
-
}) {
|
|
10
|
-
return (
|
|
11
|
-
<html lang="en">
|
|
12
|
-
<body style={{ margin: 0 }}>{children}</body>
|
|
13
|
-
</html>
|
|
14
|
-
);
|
|
15
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Preview-only Next config. Production Publish ignores this
|
|
3
|
-
* (`vercel.json` → framework: null + api/index.ts Fluid Function).
|
|
4
|
-
*
|
|
5
|
-
* HTTP proxy lives in `app/[[...slug]]/route.ts` (not rewrites) so POST
|
|
6
|
-
* uploads and custom 502 pages work when TomorrowOS is down.
|
|
7
|
-
*
|
|
8
|
-
* @type {import('next').NextConfig}
|
|
9
|
-
*/
|
|
10
|
-
const nextConfig = {
|
|
11
|
-
// Do not add a root page.tsx that returns null — v0 shows
|
|
12
|
-
// "Your v0 generation will show here" instead of the Control Panel.
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default nextConfig;
|