liveblocks 1.0.5 → 1.0.6
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 +32 -2
- package/dist/dev-server-FYKFAPQC.js +363 -0
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/dist/dev-server-TYPUD5KO.js +0 -303
package/README.md
CHANGED
|
@@ -2,13 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
Liveblocks command line interface.
|
|
4
4
|
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
### `liveblocks dev`
|
|
8
|
+
|
|
9
|
+
Start the local Liveblocks dev server (requires [Bun](https://bun.sh)):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx liveblocks dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
|
|
17
|
+
| Flag | Description | Default |
|
|
18
|
+
| -------------- | ----------------- | ----------- |
|
|
19
|
+
| `-p`, `--port` | Port to listen on | `1153` |
|
|
20
|
+
| `--host` | Host to bind to | `localhost` |
|
|
21
|
+
| `-h`, `--help` | Show help | |
|
|
22
|
+
|
|
23
|
+
### `liveblocks upgrade`
|
|
24
|
+
|
|
25
|
+
Upgrade all `@liveblocks/*` packages in your project to the same version:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx liveblocks upgrade # upgrades to "latest"
|
|
29
|
+
npx liveblocks upgrade 2.15.0 # upgrades to a specific version
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Automatically detects your package manager (npm, yarn, pnpm, or bun).
|
|
33
|
+
|
|
5
34
|
## Run with Docker
|
|
6
35
|
|
|
7
36
|
```bash
|
|
8
|
-
docker run -
|
|
37
|
+
docker run -p 1153:1153 ghcr.io/liveblocks/cli dev
|
|
9
38
|
```
|
|
10
39
|
|
|
11
|
-
See [DOCKER.md](./DOCKER.md) for configuration, volume mounts, and image
|
|
40
|
+
See [DOCKER.md](./DOCKER.md) for configuration, volume mounts, and image
|
|
41
|
+
signature verification.
|
|
12
42
|
|
|
13
43
|
## License
|
|
14
44
|
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import{parse as Lt}from"@bomb.sh/args";import{WebsocketCloseCodes as Rt}from"@liveblocks/core";import{ZenRelay as Nt}from"@liveblocks/zenrouter";import kt from"bun";function P(e){return`\x1B[33m${e}\x1B[0m`}function Q(e){return`\x1B[34m${e}\x1B[0m`}function D(e){return`\x1B[35m${e}\x1B[0m`}function L(e){return`\x1B[32m${e}\x1B[0m`}function V(e){return`\x1B[31m${e}\x1B[0m`}function j(e){return`\x1B[1m${e}\x1B[0m`}function T(e){return`\x1B[2m${e}\x1B[0m`}import{nanoid as De,Permission as Ae}from"@liveblocks/core";import{ProtocolVersion as re}from"@liveblocks/server";import{nanoid as Pe}from"@liveblocks/core";function ee(e){return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function te(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),o=t+"=".repeat((4-t.length%4)%4);return atob(o)}function oe(e){let t=Math.floor(Date.now()/1e3),o={...e,iat:t,exp:t+60*60,jti:Pe(12)},s=ee(JSON.stringify({alg:"none",typ:"JWT"})),i=ee(JSON.stringify(o));return`${s}.${i}.`}function $(e){let t=e.split(".");if(t.length!==3)return null;let[o,s,i]=t;try{if(JSON.parse(te(o)).alg!=="none")return null}catch{return null}let d;try{d=JSON.parse(te(s))}catch{return null}if(i!==""||d.pid!=="localdev")return null;let u=d.exp;return typeof u=="number"&&u<Math.floor(Date.now()/1e3)?null:d}function Ue(e,t){if(t[e])return t[e];for(let[o,s]of Object.entries(t))if(o.endsWith("*")){let i=o.slice(0,-1);if(e.startsWith(i))return s}return[]}function se(e){let t=new URL(e.url),o=t.pathname==="/v7"?re.V7:t.pathname==="/v8"?re.V8:null;if(o===null)return{ok:!1};let s=t.searchParams.get("roomId");if(!s)return{ok:!1};let i=t.searchParams.get("tok");if(i!==null){let u=$(i);if(!u)return{ok:!1};if(u.k==="acc"){let c=Ue(s,u.perms);return c.length===0?{ok:!1}:{ok:!0,roomId:s,ticketData:{version:o,id:u.uid,info:u.ui,scopes:c}}}else if(u.k==="id")return{ok:!0,roomId:s,ticketData:{version:o,id:u.uid,info:u.ui,scopes:[Ae.Write]}};return{ok:!1}}let d=t.searchParams.get("pubkey");return d!==null?d!=="pk_localdev"?{ok:!1,xwarn:"You can only use 'pk_localdev' as the public key"}:{ok:!0,roomId:s,ticketData:{version:o,anonymousId:De(),scopes:["room:write"]}}:{ok:!1}}import{DefaultMap as Ke,Room as Fe}from"@liveblocks/server";import{mkdirSync as ue,readdirSync as Xe}from"fs";import{resolve as ce}from"path";import{asPos as je,CrdtType as x,nn as Me}from"@liveblocks/core";import{makeInMemorySnapshot as Be,NestedMap as Je,plainLsonToNodeStream as Ye,quote as y}from"@liveblocks/server";import{Database as Ge}from"bun:sqlite";function R(e){try{return e!==void 0?JSON.parse(e):void 0}catch{return}}function ae(e){if(e>512)throw new Error("More than 512 params not supported");return new Array(e).fill("?").join(",")}function Ve(e){return Array.isArray(e)?e:Array.from(e)}function $e(e){return e.query("SELECT node_id, crdt_json FROM nodes").values().map(([t,o])=>[t,R(o)])}function M(e,t){let o=e.prepare(`INSERT INTO nodes (node_id, crdt_json)
|
|
2
|
+
VALUES (?, ?)
|
|
3
|
+
ON CONFLICT (node_id) DO UPDATE SET crdt_json = ?`);e.transaction(i=>{for(let[d,u]of i){let c=JSON.stringify(u);o.run(d,c,c)}})(t)}function de(e,t){let o=Ve(t),s=o.length;e.query(`DELETE FROM nodes WHERE node_id IN (${ae(s)})`).run(...o)}function ne(e){let t=new Je;for(let[o,s]of e){if(s.parentId===void 0)continue;let i=t.get(s.parentId,s.parentKey);(i===void 0||o>i)&&t.set(s.parentId,s.parentKey,o)}return t}function ze(e,t){let o=new Map($e(e));o.has("root")||o.set("root",{type:x.OBJECT,data:{}});let s=new Set,i=["root"],d=new Map,u=ne(o);for(;i.length>0;){let p=i.pop(),f=Me(o.get(p));if(f.type===x.OBJECT)for(let I of u.keysAt(p))Object.prototype.hasOwnProperty.call(f.data,I)&&(delete f.data[I],s.add(p),t.warn(`[integrity] Found data key ${y(I)} from ${y(p)} (conflicted with child node)`));if(f.type!==x.REGISTER)i.push(...u.valuesAt(p));else if(o.get(f.parentId)?.type===x.OBJECT)continue;d.set(p,f)}let c=new Set;for(let[p,f]of o)d.has(p)||(f.parentId!==void 0&&d.has(f.parentId)?d.get(f.parentId)?.type===x.REGISTER?t.warn(`[integrity] Found unreachable node ${y(p)} (child of live register)`):t.warn(`[integrity] Found conflicting sibling ${y(p)} (conflicted with ${y(u.get(f.parentId,f.parentKey))} at ${y(f.parentKey)})`):t.warn(`[integrity] Found orphan ${y(p)}`),c.add(p),s.delete(p));if(s.size>0||c.size>0){if(s.size>0){let p=new Map;for(let f of s){let I=d.get(f);I!==void 0&&p.set(f,I)}M(e,p)}c.size>0&&de(e,c)}let v=c.size===0?u:ne(d);return{nodes:d,revNodes:v}}function ie(e,t){return e?.type===x.OBJECT&&Object.prototype.hasOwnProperty.call(e.data,t)&&e.data[t]!==void 0}var z=class{db;constructor(t){let o=new Ge(t,{create:!0});o.run("PRAGMA journal_mode = WAL"),o.run("PRAGMA case_sensitive_like = ON"),o.run(`CREATE TABLE IF NOT EXISTS system (
|
|
4
|
+
setting TEXT NOT NULL,
|
|
5
|
+
jval TEXT NOT NULL,
|
|
6
|
+
PRIMARY KEY (setting)
|
|
7
|
+
)`),o.run(`CREATE TABLE IF NOT EXISTS nodes (
|
|
8
|
+
node_id TEXT NOT NULL,
|
|
9
|
+
crdt_json TEXT NOT NULL,
|
|
10
|
+
PRIMARY KEY (node_id)
|
|
11
|
+
)`),o.run(`CREATE TABLE IF NOT EXISTS metadata (
|
|
12
|
+
key TEXT NOT NULL,
|
|
13
|
+
jval TEXT NOT NULL,
|
|
14
|
+
PRIMARY KEY (key)
|
|
15
|
+
)`),o.run(`CREATE TABLE IF NOT EXISTS ydocs (
|
|
16
|
+
doc_id TEXT NOT NULL,
|
|
17
|
+
key TEXT NOT NULL,
|
|
18
|
+
data BLOB NOT NULL,
|
|
19
|
+
PRIMARY KEY (doc_id, key)
|
|
20
|
+
)`),o.run(`CREATE TABLE IF NOT EXISTS leased_sessions (
|
|
21
|
+
session_id TEXT NOT NULL PRIMARY KEY,
|
|
22
|
+
jpresence TEXT NOT NULL,
|
|
23
|
+
updated_at INTEGER NOT NULL,
|
|
24
|
+
juserinfo TEXT NOT NULL,
|
|
25
|
+
ttl INTEGER NOT NULL,
|
|
26
|
+
actor_id INTEGER NOT NULL
|
|
27
|
+
)`),o.run("CREATE INDEX IF NOT EXISTS idx_leased_sessions_expiry ON leased_sessions(updated_at, ttl)"),this.db=o}load_nodes_api(t){let o=this.db,{nodes:s,revNodes:i}=ze(o,t),d=l=>s.get(l),u=(l,m)=>i.get(l,m),c=(l,m)=>i.has(l,m);function v(l,m){let g;for(let h of i.keysAt(l)){let b=je(h);b>m&&(g===void 0||b<g)&&(g=b)}return g}function p(l,m,g=!1){let h=d(m.parentId);if(h===void 0)throw new Error(`No such parent ${y(m.parentId)}`);if(m.type===x.REGISTER&&h.type===x.OBJECT)throw new Error("Cannot add register under object");let b=u(m.parentId,m.parentKey);if(b!==l){let w=ie(h,m.parentKey);if(b!==void 0||w)if(g)G(m.parentId,m.parentKey);else throw new Error(`Key ${y(m.parentKey)} already exists`);i.set(m.parentId,m.parentKey,l)}s.set(l,m),M(o,[[l,m]])}function f(l,m){let g=d(l);if(g?.parentId===void 0)return;if(c(g.parentId,m))throw new Error(`Pos ${y(m)} already taken`);i.delete(g.parentId,g.parentKey);let h={...g,parentKey:m};s.set(l,h),i.set(g.parentId,m,l),M(o,[[l,h]])}function I(l,m,g=!1){let h=d(l);if(h?.type!==x.OBJECT)return;for(let w of Object.keys(m)){let k=u(l,w);if(k!==void 0)if(g)C(k);else throw new Error(`Child node already exists under ${w}`)}let b={...h,data:{...h.data,...m}};s.set(l,b),M(o,[[l,b]])}function C(l){let m=d(l);if(m?.parentId===void 0)return;i.delete(m.parentId,m.parentKey);let g=[],h=[l];for(;h.length>0;){let b=h.pop();h.push(...i.valuesAt(b)),s.delete(b),i.deleteAll(b),g.push(b)}de(o,g)}function G(l,m){let g=d(l);if(ie(g,m)){let{[m]:b,...w}=g.data,k={...g,data:w};s.set(l,k),M(o,[[l,k]])}let h=u(l,m);h!==void 0&&C(h)}return{get_node:d,iter_nodes:()=>s.entries(),has_node:l=>s.has(l),get_child_at:u,has_child_at:c,get_next_sibling:v,set_child:p,move_sibling:f,delete_node:C,delete_child_key:G,set_object_data:I,get_snapshot(l){return Be(s)}}}DANGEROUSLY_reset_nodes(t){let o=this.db.prepare("DELETE FROM nodes"),s=this.db.prepare("INSERT INTO nodes (node_id, crdt_json) VALUES (?, ?)");this.db.transaction(()=>{o.run();for(let[d,u]of Ye(t))s.run(d,JSON.stringify(u))})()}raw_iter_nodes(){return this.db.query("SELECT node_id, crdt_json FROM nodes").values().map(([t,o])=>[t,R(o)])}get_meta(t){let s=this.db.query("SELECT jval FROM metadata WHERE key = ?").get(t)?.jval;if(s!==void 0)return R(s)??null}put_meta(t,o){let s=JSON.stringify(o);this.db.run(`INSERT INTO metadata (key, jval)
|
|
28
|
+
VALUES (?, ?)
|
|
29
|
+
ON CONFLICT (key) DO UPDATE SET jval = ?
|
|
30
|
+
`,[t,s,s])}delete_meta(t){this.db.query("DELETE FROM metadata WHERE key = ?").run(t)}next_actor(){let t=this.db.query(`INSERT INTO system (setting, jval)
|
|
31
|
+
VALUES ('last_actor_id', '0')
|
|
32
|
+
ON CONFLICT (setting) DO UPDATE SET jval = json(CAST(jval AS INTEGER) + 1)
|
|
33
|
+
RETURNING jval`).get();return JSON.parse(t.jval)}iter_y_updates(t){return this.db.query("SELECT key, data FROM ydocs WHERE doc_id = ?").values(t)}write_y_updates(t,o,s){this.db.query(`INSERT INTO ydocs
|
|
34
|
+
VALUES (?, ?, ?)
|
|
35
|
+
ON CONFLICT (doc_id, key) DO UPDATE SET data = ?`).run(t,o,s,s)}delete_y_updates(t,o){let s=o.length;this.db.query(`DELETE FROM ydocs WHERE doc_id = ? AND key IN (${ae(s)})`).run(t,...o)}DANGEROUSLY_wipe_all_y_updates(){this.db.query("DELETE FROM ydocs").run()}list_leased_sessions(){let t=this.db.query("SELECT session_id, jpresence, updated_at, juserinfo, ttl, actor_id FROM leased_sessions").all();return Array.from(t,o=>[o.session_id,{sessionId:o.session_id,presence:R(o.jpresence)??null,updatedAt:o.updated_at,info:R(o.juserinfo)??{name:""},ttl:o.ttl,actorId:o.actor_id}])}get_leased_session(t){let o=this.db.query("SELECT session_id, jpresence, updated_at, juserinfo, ttl, actor_id FROM leased_sessions WHERE session_id = ?").get(t);if(o!=null)return{sessionId:o.session_id,presence:R(o.jpresence)??null,updatedAt:o.updated_at,info:R(o.juserinfo)??{name:""},ttl:o.ttl,actorId:o.actor_id}}put_leased_session(t){this.db.query(`INSERT INTO leased_sessions (session_id, jpresence, updated_at, juserinfo, ttl, actor_id)
|
|
36
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
37
|
+
ON CONFLICT (session_id) DO UPDATE SET
|
|
38
|
+
jpresence = excluded.jpresence,
|
|
39
|
+
updated_at = excluded.updated_at,
|
|
40
|
+
juserinfo = excluded.juserinfo,
|
|
41
|
+
ttl = excluded.ttl,
|
|
42
|
+
actor_id = excluded.actor_id`).run(t.sessionId,JSON.stringify(t.presence),t.updatedAt,JSON.stringify(t.info),t.ttl,t.actorId)}delete_leased_session(t){this.db.query("DELETE FROM leased_sessions WHERE session_id = ?").run(t)}close(){this.db.close()}};var B=".liveblocks/v1/rooms",K=new Ke(e=>{ue(B,{recursive:!0});let t=new z(H(e));return new Fe(e,{storage:t})});function H(e){let t=ce(B,`${encodeURIComponent(e)}.db`);if(!t.startsWith(ce(B)+"/"))throw new Error("Invalid room ID");return t}function O(e){return K.getOrCreate(e)}async function S(e){let t=H(e);return await Bun.file(t).exists()}function le(){try{return ue(B,{recursive:!0}),Xe(B).filter(o=>o.endsWith(".db")).map(o=>decodeURIComponent(o.replace(/\.db$/,"")))}catch{return[]}}async function me(e){if(await S(e))throw new Error(`Room with id "${e}" already exists`);let t=K.getOrCreate(e);await t.load();let o={liveblocksType:"LiveObject",data:{}};await t.driver.DANGEROUSLY_reset_nodes(o),t.unload()}async function pe(e){K.get(e)?.unload(),K.delete(e);let t=H(e);try{await Bun.write(t,""),await Bun.file(t).unlink()}catch{}}function He(e){return e.trim().split(`
|
|
43
|
+
`).filter(Boolean).map(t=>{let o=t.match(/^(.+?):(\d+):(.*)$/);return o?{file:o[1],line:parseInt(o[2],10),text:o[3]}:null}).filter(t=>t!==null)}async function ge(...e){try{let t=["git","grep","-nF",...e.flatMap(i=>["-e",i]),"--","."],o=Bun.spawn(t,{stdout:"pipe",stderr:"pipe"}),s=await new Response(o.stdout).text();return await o.exited,He(s)}catch{return[]}}function We(e){let t=e.trim();return t.startsWith("#")||t.startsWith("//")||t.startsWith("*")||t.startsWith("/*")}var qe=[{pattern:"<LiveblocksProvider",expected:"baseUrl=",fixSnippet:e=>`${D("baseUrl")}=${L(`"${e}"`)}`,closePattern:">"},{pattern:"createClient(",expected:"baseUrl:",fixSnippet:e=>`${D("baseUrl")}: ${L(`"${e}"`)}`,closePattern:")"},{pattern:"new Liveblocks(",expected:"baseUrl:",fixSnippet:e=>`${D("baseUrl")}: ${L(`"${e}"`)}`,closePattern:")"}];async function he(e){let t=`http://localhost:${e}`,o=[];for(let s of qe){let i=(await ge(s.pattern)).filter(c=>!We(c.text));if(i.length===0)continue;let d=await ge(s.expected),u=new Set(d.map(c=>c.file));for(let c of i)u.has(c.file)||o.push({match:c,check:s})}if(o.length>0){console.log(),console.warn(P("\u26A0 Your project may not be configured for the local dev server.")),console.log(),console.log(` Missing baseUrl in the following location(s):
|
|
44
|
+
`);for(let{match:s,check:i}of o)console.log(` ${Q(`${s.file}:${s.line}`)}`),console.log(` To fix, add ${i.fixSnippet(t)} to ${D(i.pattern)}${D(i.closePattern)}`),console.log();console.log(T(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")),console.log(T(" \u2502 \u{1F4A1} ")+"Press "+j("p")+" to copy an AI fix prompt to your clipboard"+T(" \u2502")),console.log(T(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F")),console.log()}return o}var Ze={"<LiveblocksProvider":"baseUrl={...}","createClient(":"baseUrl: ...","new Liveblocks(":"baseUrl: ..."};function ve(e,t){let o=e.map(({match:s,check:i})=>{let d=Ze[i.pattern]??"baseUrl: ...";return` - In \`${s.file}\` at line ${s.line}, add \`${d}\` to the \`${i.pattern}\` call`}).join(`
|
|
45
|
+
`);return`# Set up Liveblocks dev server
|
|
46
|
+
|
|
47
|
+
1. Check which system the application is using for environment variables, then
|
|
48
|
+
add a new environment variable called \`USE_LIVEBLOCKS_DEV_SERVER="true"\`.
|
|
49
|
+
This will be used to enable the dev server. It needs to be available on the client, so it may need to be called
|
|
50
|
+
\`NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER\` or similar. Do not rename or modify existing variables.
|
|
51
|
+
2. You must use \`"${t}"\` as a \`baseUrl\` when the dev server is
|
|
52
|
+
enabled. In the following files add a \`baseUrl\` property for this when the
|
|
53
|
+
dev server is enabled, otherwise set \`baseUrl\` to \`undefined\`:
|
|
54
|
+
${o}
|
|
55
|
+
|
|
56
|
+
3. Identify if the user is using \`publicApiKey\` in \`LiveblocksProvider\` or
|
|
57
|
+
\`secret\` in \`new Liveblocks\`. Edit the existing property to use "pk_localdev"
|
|
58
|
+
(for \`publicApikey\`) or "sk_localdev" (for \`secret\`) when the dev server is
|
|
59
|
+
enabled.
|
|
60
|
+
|
|
61
|
+
## Examples
|
|
62
|
+
|
|
63
|
+
Remember to keep the user's current system for environment variables and names.
|
|
64
|
+
In the following snippets, I have given the following names, but the user's
|
|
65
|
+
system may work differently: \`process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_KEY\`
|
|
66
|
+
and \`process.env.LIVEBLOCKS_SECRET_KEY\`.
|
|
67
|
+
|
|
68
|
+
### Public key example
|
|
69
|
+
|
|
70
|
+
If the user is already using the public key with \`publicApKey\`:
|
|
71
|
+
|
|
72
|
+
\`\`\`env file=".env.local"
|
|
73
|
+
NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER="true"
|
|
74
|
+
\`\`\`
|
|
75
|
+
|
|
76
|
+
\`\`\`tsx file="src/app/Providers.tsx"
|
|
77
|
+
<LiveblocksProvider
|
|
78
|
+
baseUrl={process.env.NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER === "true" ? "${t}" : undefined}
|
|
79
|
+
publicApiKey={process.env.NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER === "true" ? "pk_localdev" : process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_KEY}
|
|
80
|
+
\`\`\`
|
|
81
|
+
|
|
82
|
+
### Secret key example
|
|
83
|
+
|
|
84
|
+
If the user is already using their secret key with \`secret\`:
|
|
85
|
+
|
|
86
|
+
\`\`\`env file=".env.local"
|
|
87
|
+
NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER="true"
|
|
88
|
+
\`\`\`
|
|
89
|
+
|
|
90
|
+
\`\`\`tsx file="src/app/Providers.tsx"
|
|
91
|
+
<LiveblocksProvider
|
|
92
|
+
baseUrl={process.env.NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER === "true" ? "${t}" : undefined}
|
|
93
|
+
\`\`\`
|
|
94
|
+
|
|
95
|
+
\`\`\`ts file="src/app/api/liveblocks-auth/route.ts"
|
|
96
|
+
new Liveblocks({
|
|
97
|
+
baseUrl={process.env.NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER === "true" ? "${t}" : undefined}
|
|
98
|
+
secret={process.env.NEXT_PUBLIC_USE_LIVEBLOCKS_DEV_SERVER === "true" ? "sk_localdev" : process.env.LIVEBLOCKS_SECRET_KEY}
|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
## Follow up
|
|
102
|
+
|
|
103
|
+
Explain to the user that you've enabled the Liveblocks dev server by adding a an
|
|
104
|
+
environment variable to the application, and share which file it is in. Explain
|
|
105
|
+
that the user can disable this by setting it to "false".`}import{execSync as Qe}from"node:child_process";function Ie(e){let t=process.platform==="darwin"?"pbcopy":process.platform==="win32"?"clip.exe":"xclip -selection clipboard";Qe(t,{input:e})}import et from"bun";function Ee(e,t){let{promise:o,resolve:s}=Promise.withResolvers();return et.connect({hostname:t,port:e,socket:{data(){},open(i){i.end(),s(!0)},error(){s(!1)},connectError(){s(!1)}}}),o}function W(e,t=!1){e&&console.log((t?V:P)(` \u26A0 ${e}`))}import{Permission as rt}from"@liveblocks/core";import{ZenRouter as st}from"@liveblocks/zenrouter";import{array as nt,enum_ as it,object as at,optional as dt,record as ct,string as ut}from"decoders";import{json as tt}from"@liveblocks/zenrouter";import{json as be}from"@liveblocks/zenrouter";function J(e,t,o){return be(e,t,{"X-LB-Warn":o})}function _(e,t,o="This is a dummy response."){return J(e,t,o)}function r(e="This endpoint isn't implemented in the Liveblocks dev server."){return be({error:"Not implemented",message:e},501,{"X-LB-Warn":e})}function F(e){let t=e.headers.get("Authorization");if(t==="Bearer sk_localdev")return!0;if(!t)throw tt({error:"Unauthorized",message:"Missing secret key"},401);if(t.startsWith("Bearer "))throw J({error:"Forbidden",message:"Invalid secret key. You can only use 'sk_localdev' as a secret key"},403,"You can only use 'sk_localdev' as the secret key");return!1}import{inexact as ot,optional as Te,string as ye}from"decoders";var Se=ot({name:Te(ye),avatar:Te(ye)}).refineType();var lt=it(rt),Y=new st({authorize:({req:e})=>F(e)});Y.route("POST /v2/authorize-user",at({userId:ut,userInfo:dt(Se),permissions:ct(nt(lt))}),({body:e})=>({token:oe({k:"acc",pid:"localdev",uid:e.userId,perms:e.permissions,ui:e.userInfo})}));Y.route("POST /v2/identify-user",()=>r("ID tokens are not supported in the Liveblocks dev server. To develop locally, use access tokens instead (via POST /v2/authorize-user)"));import{ZenRouter as mt}from"@liveblocks/zenrouter";var a=new mt({cors:{allowCredentials:!0,maxAge:600,exposeHeaders:["X-LB-Warn"]},authorize:({req:e})=>{let t=e.headers.get("Authorization");if(!t?.startsWith("Bearer "))return!1;let o=t.slice(7);return $(o)!==null}});a.route("GET /v2/c/threads",()=>_({threads:[],inboxNotifications:[],subscriptions:[],meta:{nextCursor:null,requestedAt:new Date().toISOString(),permissionHints:{}}}));a.route("GET /v2/c/threads/delta",()=>_({threads:[],inboxNotifications:[],subscriptions:[],meta:{requestedAt:new Date().toISOString(),permissionHints:{}}}));a.route("GET /v2/c/inbox-notifications",()=>_({inboxNotifications:[],threads:[],subscriptions:[],groups:[],meta:{nextCursor:null,requestedAt:new Date().toISOString()}}));a.route("GET /v2/c/inbox-notifications/count",()=>_({count:0}));a.route("GET /v2/c/inbox-notifications/delta",()=>_({inboxNotifications:[],threads:[],subscriptions:[],groups:[],deletedInboxNotifications:[],deletedThreads:[],deletedSubscriptions:[],meta:{requestedAt:new Date().toISOString()}}));a.route("GET /v2/c/rooms/<roomId>/threads",()=>_({data:[],inboxNotifications:[],subscriptions:[],meta:{nextCursor:null,requestedAt:new Date().toISOString(),permissionHints:{}}}));a.route("GET /v2/c/rooms/<roomId>/threads/delta",()=>_({data:[],inboxNotifications:[],subscriptions:[],deletedThreads:[],deletedInboxNotifications:[],deletedSubscriptions:[],meta:{requestedAt:new Date().toISOString(),permissionHints:{}}}));a.route("POST /v2/c/rooms/<roomId>/text-metadata",()=>_({status:"ok"}));a.route("PUT /v2/c/rooms/<roomId>/attachments/<attachmentId>/upload/<name>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<name>",()=>r()),a.route("PUT /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<uploadId>/<partNumber>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<uploadId>/complete",()=>r()),a.route("DELETE /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<uploadId>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/attachments/presigned-urls",()=>r()),a.route("POST /v2/c/rooms/<roomId>/send-message",()=>r()),a.route("GET /v2/c/rooms/<roomId>/storage",()=>r()),a.route("POST /v2/c/rooms/<roomId>/version",()=>r()),a.route("GET /v2/c/rooms/<roomId>/y-version/<version>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/ai/contextual-prompt",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/search",()=>r()),a.route("DELETE /v2/c/rooms/<roomId>/threads/<threadId>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/metadata",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/mark-as-resolved",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/mark-as-unresolved",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/subscribe",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/unsubscribe",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments",()=>r()),a.route("GET /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>/metadata",()=>r()),a.route("DELETE /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>/reactions",()=>r()),a.route("DELETE /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>/reactions/<emoji>",()=>r()),a.route("GET /v2/c/rooms/<roomId>/threads/comments/search",()=>r()),a.route("GET /v2/c/rooms/<roomId>/threads/<threadId>/participants",()=>r()),a.route("GET /v2/c/rooms/<roomId>/notification-settings",()=>r()),a.route("GET /v2/c/rooms/<roomId>/subscription-settings",()=>r()),a.route("POST /v2/c/rooms/<roomId>/notification-settings",()=>r()),a.route("POST /v2/c/rooms/<roomId>/subscription-settings",()=>r()),a.route("DELETE /v2/c/inbox-notifications",()=>r()),a.route("POST /v2/c/inbox-notifications/read",()=>r()),a.route("DELETE /v2/c/inbox-notifications/<inboxNotificationId>",()=>r()),a.route("POST /v2/c/rooms/<roomId>/inbox-notifications/read",()=>r()),a.route("POST /v2/c/rooms/<roomId>/text-mentions",()=>r()),a.route("DELETE /v2/c/rooms/<roomId>/text-mentions/<mentionId>",()=>r()),a.route("GET /v2/c/notification-settings",()=>r()),a.route("POST /v2/c/notification-settings",()=>r()),a.route("GET /v2/c/rooms/<roomId>/thread-with-notification/<threadId>",()=>r()),a.route("GET /v2/c/urls/metadata",()=>r()),a.route("GET /v2/c/rooms/<roomId>/versions",()=>r()),a.route("GET /v2/c/rooms/<roomId>/versions/delta",()=>r()),a.route("POST /v2/c/groups/find",()=>r());import{abort as xe,html as ft,json as gt,ZenRouter as ht}from"@liveblocks/zenrouter";var Ce=`<!doctype html>
|
|
106
|
+
<html lang="en">
|
|
107
|
+
<head>
|
|
108
|
+
<meta charset="UTF-8" />
|
|
109
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
110
|
+
<title>Liveblocks dev server</title>
|
|
111
|
+
<style>
|
|
112
|
+
* {
|
|
113
|
+
box-sizing: border-box;
|
|
114
|
+
margin: 0;
|
|
115
|
+
padding: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
:root {
|
|
119
|
+
--bg: #f9f9f9;
|
|
120
|
+
--fg: #202020;
|
|
121
|
+
--fg-secondary: #646464;
|
|
122
|
+
--code-bg: #fcfcfc;
|
|
123
|
+
--shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.06),
|
|
124
|
+
0px 1px 2px -1px rgba(0, 0, 0, 0.06),
|
|
125
|
+
0px 2px 4px 0px rgba(0, 0, 0, 0.04);
|
|
126
|
+
--shadow-hover: 0px 0px 0px 1px rgba(0, 0, 0, 0.08),
|
|
127
|
+
0px 1px 2px -1px rgba(0, 0, 0, 0.08),
|
|
128
|
+
0px 2px 4px 0px rgba(0, 0, 0, 0.06);
|
|
129
|
+
--pill-bg: #171717;
|
|
130
|
+
--pill-fg: #e5e7eb;
|
|
131
|
+
--green: #05df72;
|
|
132
|
+
--green-glow: rgba(5, 223, 114, 0.4);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@media (prefers-color-scheme: dark) {
|
|
136
|
+
:root {
|
|
137
|
+
--bg: #111;
|
|
138
|
+
--fg: #e5e5e5;
|
|
139
|
+
--fg-secondary: #a0a0a0;
|
|
140
|
+
--code-bg: #1a1a1a;
|
|
141
|
+
--shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.08),
|
|
142
|
+
0px 1px 2px -1px rgba(0, 0, 0, 0.4),
|
|
143
|
+
0px 2px 4px 0px rgba(0, 0, 0, 0.3);
|
|
144
|
+
--shadow-hover: 0px 0px 0px 1px rgba(255, 255, 255, 0.12),
|
|
145
|
+
0px 1px 2px -1px rgba(0, 0, 0, 0.5),
|
|
146
|
+
0px 2px 4px 0px rgba(0, 0, 0, 0.4);
|
|
147
|
+
--pill-bg: #f5f5f5;
|
|
148
|
+
--pill-fg: #202020;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
body {
|
|
153
|
+
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
|
|
154
|
+
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
155
|
+
background: var(--bg);
|
|
156
|
+
color: var(--fg);
|
|
157
|
+
min-height: 100vh;
|
|
158
|
+
-webkit-font-smoothing: antialiased;
|
|
159
|
+
-moz-osx-font-smoothing: grayscale;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
main {
|
|
163
|
+
position: relative;
|
|
164
|
+
min-height: 100vh;
|
|
165
|
+
overflow: hidden;
|
|
166
|
+
padding: 2rem 1.5rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.logo {
|
|
170
|
+
position: absolute;
|
|
171
|
+
left: 50%;
|
|
172
|
+
top: 2rem;
|
|
173
|
+
transform: translateX(-50%);
|
|
174
|
+
animation: fade-in 0.6s ease-out both;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.logo svg {
|
|
178
|
+
height: 1.5rem;
|
|
179
|
+
width: auto;
|
|
180
|
+
color: var(--fg);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.center {
|
|
184
|
+
position: absolute;
|
|
185
|
+
inset: 0;
|
|
186
|
+
z-index: 10;
|
|
187
|
+
display: flex;
|
|
188
|
+
flex-direction: column;
|
|
189
|
+
align-items: center;
|
|
190
|
+
justify-content: center;
|
|
191
|
+
text-align: center;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
h1 {
|
|
195
|
+
margin-bottom: 0.25rem;
|
|
196
|
+
font-weight: 500;
|
|
197
|
+
font-size: 1rem;
|
|
198
|
+
animation: fade-in 0.6s ease-out 0.1s both;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.description {
|
|
202
|
+
margin-bottom: 1rem;
|
|
203
|
+
max-width: 20rem;
|
|
204
|
+
font-size: 0.875rem;
|
|
205
|
+
line-height: 1.625;
|
|
206
|
+
color: var(--fg-secondary);
|
|
207
|
+
animation: fade-in 0.6s ease-out 0.2s both;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.description code {
|
|
211
|
+
white-space: nowrap;
|
|
212
|
+
border-radius: 0.25rem;
|
|
213
|
+
background: var(--code-bg);
|
|
214
|
+
padding: 0.125rem 0.375rem;
|
|
215
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
216
|
+
monospace;
|
|
217
|
+
box-shadow: var(--shadow);
|
|
218
|
+
font-size: 0.75rem;
|
|
219
|
+
color: var(--fg);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.docs-link {
|
|
223
|
+
display: inline-flex;
|
|
224
|
+
align-items: center;
|
|
225
|
+
justify-content: center;
|
|
226
|
+
border-radius: 0.375rem;
|
|
227
|
+
font-size: 0.875rem;
|
|
228
|
+
font-weight: 500;
|
|
229
|
+
background: var(--code-bg);
|
|
230
|
+
box-shadow: var(--shadow);
|
|
231
|
+
height: 2.25rem;
|
|
232
|
+
padding: 0.5rem 1rem;
|
|
233
|
+
color: var(--fg);
|
|
234
|
+
text-decoration: none;
|
|
235
|
+
transition: box-shadow 0.15s;
|
|
236
|
+
animation: fade-in 0.6s ease-out 0.3s both;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.docs-link:hover {
|
|
240
|
+
box-shadow: var(--shadow-hover);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.status {
|
|
244
|
+
position: absolute;
|
|
245
|
+
bottom: 2rem;
|
|
246
|
+
left: 50%;
|
|
247
|
+
transform: translateX(-50%);
|
|
248
|
+
animation: fade-in 0.6s ease-out 0.4s both;
|
|
249
|
+
display: inline-flex;
|
|
250
|
+
align-items: center;
|
|
251
|
+
gap: 0.5rem;
|
|
252
|
+
border-radius: 9999px;
|
|
253
|
+
background: var(--pill-bg);
|
|
254
|
+
color: var(--pill-fg);
|
|
255
|
+
box-shadow: var(--shadow);
|
|
256
|
+
padding: 0.5rem 0.75rem 0.5rem 0.625rem;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.status-dot {
|
|
260
|
+
position: relative;
|
|
261
|
+
width: 0.75rem;
|
|
262
|
+
height: 0.75rem;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.status-dot .glow {
|
|
266
|
+
position: absolute;
|
|
267
|
+
inset: 0;
|
|
268
|
+
background: var(--green-glow);
|
|
269
|
+
border-radius: 9999px;
|
|
270
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.status-dot .dot {
|
|
274
|
+
position: absolute;
|
|
275
|
+
width: 0.25rem;
|
|
276
|
+
height: 0.25rem;
|
|
277
|
+
left: 50%;
|
|
278
|
+
top: 50%;
|
|
279
|
+
transform: translate(-50%, -50%);
|
|
280
|
+
background: var(--green);
|
|
281
|
+
border-radius: 9999px;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.status-text {
|
|
285
|
+
font-size: 0.75rem;
|
|
286
|
+
font-weight: 500;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@keyframes fade-in {
|
|
290
|
+
from {
|
|
291
|
+
opacity: 0;
|
|
292
|
+
}
|
|
293
|
+
to {
|
|
294
|
+
opacity: 1;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@keyframes pulse {
|
|
299
|
+
50% {
|
|
300
|
+
opacity: 0.5;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
</style>
|
|
304
|
+
</head>
|
|
305
|
+
<body>
|
|
306
|
+
<main>
|
|
307
|
+
<div class="logo">
|
|
308
|
+
<svg
|
|
309
|
+
width="384"
|
|
310
|
+
height="72"
|
|
311
|
+
viewBox="0 0 128 24"
|
|
312
|
+
fill="none"
|
|
313
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
314
|
+
>
|
|
315
|
+
<path
|
|
316
|
+
fill-rule="evenodd"
|
|
317
|
+
clip-rule="evenodd"
|
|
318
|
+
d="M28.8316 3.21884H26L26.0007 19.9974H28.8316V3.21884ZM34.0855 8.01549H31.2547V19.9974H34.0855V8.01549ZM34.0855 3.08984H31.2547V6.14356H34.0855V3.08984ZM38.2401 8.01549H35.1978L39.4807 19.9974H42.6398L46.9226 8.01549H43.9269L42.1367 13.6908C42.0901 13.8384 41.9224 14.416 41.6336 15.4222L41.0602 17.3529C40.7213 16.1277 40.3665 14.9069 39.996 13.6908L38.2401 8.01549ZM58.5185 11.7601C58.2841 10.9567 57.9408 10.2737 57.4879 9.71184C56.9805 9.08118 56.3376 8.59313 55.5579 8.24984C54.7853 7.89868 53.9274 7.72381 52.9836 7.72381C51.1897 7.72381 49.7542 8.28496 48.6778 9.40798C48.1408 9.9882 47.7303 10.6737 47.4723 11.4211C47.2072 12.1929 47.0746 13.0472 47.0746 13.9832C47.0746 15.9877 47.6092 17.5364 48.6785 18.6286C49.7621 19.7359 51.2055 20.2898 53.0072 20.2898C54.5517 20.2898 55.803 19.943 56.7633 19.2485C57.723 18.5541 58.3586 17.5249 58.6704 16.1597L55.909 15.949C55.7765 16.69 55.4719 17.244 54.996 17.6102C54.5201 17.9693 53.8493 18.1492 52.9836 18.1492C51.0027 18.1492 49.9886 17.0333 49.942 14.8023H58.8575L58.8696 14.4046C58.8696 13.445 58.7521 12.5635 58.5185 11.7601ZM50.5734 10.918C51.0729 10.2157 51.8763 9.86449 52.9836 9.86449C53.5218 9.86449 53.9747 9.93831 54.341 10.0867C54.7079 10.235 55.024 10.4729 55.2891 10.8005C55.4953 11.0547 55.6539 11.3441 55.7571 11.6547C55.8734 11.9788 55.9443 12.3174 55.9678 12.6609H49.9649C50.0352 11.9665 50.238 11.3853 50.5734 10.918ZM69.8685 8.48419C69.0651 7.96103 68.137 7.70016 67.0842 7.70016H67.0827C66.3188 7.70016 65.6207 7.85568 64.9886 8.16814C64.3667 8.4713 63.8342 8.9309 63.4435 9.50186V3.21884H60.6126V19.9974H63.4442V18.3477C63.8031 18.9405 64.3115 19.4286 64.9184 19.7631C65.5505 20.1143 66.2485 20.2898 67.0125 20.2898C68.0739 20.2898 69.0135 20.0361 69.8341 19.5295C70.6525 19.0228 71.2882 18.2968 71.7404 17.3529C72.2005 16.4012 72.4313 15.2861 72.4313 14.0068C72.4313 12.7584 72.2041 11.659 71.7526 10.7073C71.3076 9.74768 70.6797 9.00664 69.8685 8.48419ZM68.663 17.1774C68.2108 17.8639 67.4389 18.2065 66.346 18.2065C65.3627 18.2065 64.6224 17.8517 64.1236 17.1422C63.6241 16.4327 63.3747 15.395 63.3747 14.0298C63.3747 12.7111 63.5968 11.682 64.0412 10.9409C64.4941 10.192 65.2545 9.81791 66.3231 9.81791C67.4153 9.81791 68.1914 10.1612 68.6516 10.847C69.1124 11.5257 69.3417 12.5792 69.3417 14.0068C69.3417 15.4337 69.116 16.4908 68.663 17.1774ZM77.0302 3.21884H74.1986V19.9974H77.0302V3.21884ZM81.6169 19.5409C82.5379 20.0404 83.6294 20.2898 84.8936 20.2898C86.1105 20.2898 87.1791 20.0283 88.0993 19.5065C89.0131 18.9985 89.7576 18.2335 90.2407 17.3064C90.7474 16.3546 91.0011 15.2545 91.0011 14.0068C91.0011 12.8057 90.7517 11.7285 90.2522 10.7775C89.7734 9.83933 89.0341 9.05921 88.1229 8.53078C87.202 7.99256 86.1256 7.72309 84.8936 7.72309C83.653 7.72309 82.5687 7.99256 81.6406 8.53078C80.7318 9.05692 79.9926 9.83235 79.5106 10.7653C79.0197 11.7092 78.7739 12.7899 78.7739 14.0068C78.7739 15.3018 79.0154 16.4206 79.4992 17.3644C79.9697 18.2867 80.7079 19.0453 81.6169 19.5409ZM87.245 17.1895C86.7691 17.8603 85.9851 18.1957 84.8936 18.1957C84.1525 18.1957 83.5556 18.0474 83.1033 17.7507C82.6504 17.4468 82.3229 16.9903 82.12 16.3819C81.9172 15.7655 81.8162 14.9736 81.8162 14.0061C81.8162 12.5556 82.0541 11.4949 82.53 10.8241C83.0137 10.1533 83.8014 9.81791 84.8936 9.81791C85.9779 9.81791 86.7577 10.1533 87.2335 10.8241C87.7173 11.4949 87.9588 12.5556 87.9588 14.0068C87.9588 15.4574 87.7209 16.518 87.245 17.1895ZM94.8626 19.5409C95.7756 20.0404 96.8635 20.2898 98.1277 20.2898C99.1103 20.2898 99.9882 20.1186 100.76 19.7753C101.533 19.432 102.16 18.9525 102.644 18.3362C103.129 17.708 103.447 16.967 103.568 16.1826L100.842 15.9024C100.655 16.6506 100.343 17.2089 99.9058 17.5751C99.4693 17.942 98.8759 18.1255 98.1277 18.1255C97.363 18.1255 96.7625 17.9693 96.3253 17.6568C95.8888 17.3372 95.5842 16.8814 95.413 16.288C95.241 15.6874 95.1557 14.927 95.1557 14.0068C95.1557 13.1017 95.241 12.3528 95.413 11.7601C95.5842 11.1595 95.8845 10.6994 96.3138 10.3791C96.751 10.0515 97.3552 9.88814 98.1277 9.88814C98.9541 9.88814 99.5668 10.1182 99.9646 10.5783C100.37 11.0305 100.659 11.6504 100.83 12.4388L103.51 11.9586C103.253 10.6793 102.671 9.65379 101.766 8.88194C100.869 8.10938 99.6564 7.72381 98.1277 7.72381C96.8793 7.72381 95.7992 7.98898 94.8862 8.51931C93.9847 9.03823 93.2562 9.81153 92.7921 10.7424C92.3083 11.6863 92.0661 12.7742 92.0661 14.0068C92.0661 15.309 92.304 16.4327 92.7799 17.3766C93.2637 18.3204 93.9581 19.0421 94.8626 19.5409ZM107.91 15.5512L109.232 14.287L112.742 19.9974H116.007L111.151 12.4732L115.855 8.01549H112.18L107.91 12.3922V3.21884H105.078V19.9974H107.91V15.5512ZM118.488 19.8569C119.284 20.1457 120.169 20.2897 121.144 20.2897C122.634 20.2897 123.862 19.993 124.83 19.4011C125.805 18.8077 126.293 17.8402 126.293 16.4986C126.293 15.6249 126.066 14.9384 125.614 14.4396C125.162 13.9322 124.623 13.5695 123.999 13.351C123.383 13.1252 122.544 12.8952 121.484 12.6608C120.867 12.5282 120.38 12.4035 120.021 12.2867C119.662 12.1692 119.373 12.0172 119.155 11.8302C118.945 11.6424 118.839 11.4009 118.839 11.1049C118.839 10.6678 119.034 10.3367 119.424 10.1102C119.814 9.88373 120.298 9.77049 120.875 9.77049C121.639 9.77049 122.236 9.95396 122.666 10.3209C123.102 10.6878 123.336 11.2375 123.367 11.9707L125.988 11.5378C125.863 10.1962 125.337 9.22511 124.408 8.62383C123.488 8.02398 122.31 7.72298 120.875 7.72298C120.032 7.72298 119.253 7.85126 118.535 8.10926C117.825 8.35866 117.252 8.75283 116.815 9.29176C116.378 9.82926 116.16 10.5079 116.16 11.3271C116.16 12.0839 116.347 12.6959 116.721 13.1639C117.102 13.6369 117.592 14.0102 118.149 14.2518C118.726 14.5019 119.451 14.7399 120.325 14.9656L121.051 15.1412C121.535 15.256 122.015 15.3887 122.49 15.5389C122.817 15.6407 123.086 15.7812 123.297 15.9603C123.508 16.1395 123.613 16.3739 123.613 16.6627C123.613 17.1694 123.402 17.5599 122.981 17.8323C122.568 18.106 121.963 18.2422 121.168 18.2422C120.356 18.2422 119.709 18.0394 119.225 17.6338C118.742 17.2281 118.496 16.6433 118.488 15.8786L115.821 16.1825C115.851 17.1034 116.105 17.8717 116.581 18.488C117.065 19.1044 117.7 19.5602 118.488 19.8569Z"
|
|
319
|
+
fill="currentColor"
|
|
320
|
+
></path>
|
|
321
|
+
<path
|
|
322
|
+
fill-rule="evenodd"
|
|
323
|
+
clip-rule="evenodd"
|
|
324
|
+
d="M13.5 9H0L4 13V18.5L13.5 9Z"
|
|
325
|
+
fill="currentColor"
|
|
326
|
+
></path>
|
|
327
|
+
<path
|
|
328
|
+
fill-rule="evenodd"
|
|
329
|
+
clip-rule="evenodd"
|
|
330
|
+
d="M6.5 20H20L16 16V10.5L6.5 20Z"
|
|
331
|
+
fill="currentColor"
|
|
332
|
+
></path>
|
|
333
|
+
</svg>
|
|
334
|
+
</div>
|
|
335
|
+
|
|
336
|
+
<div class="center">
|
|
337
|
+
<h1>You're all set</h1>
|
|
338
|
+
<p class="description">
|
|
339
|
+
This is the Liveblocks dev server. Point your app to
|
|
340
|
+
<code>http://localhost:1153</code> and start building. This page is
|
|
341
|
+
not meant to be used directly.
|
|
342
|
+
</p>
|
|
343
|
+
<a
|
|
344
|
+
href="https://liveblocks.io/docs/tools/dev-server?from=__VERSION__"
|
|
345
|
+
target="_blank"
|
|
346
|
+
rel="noopener noreferrer"
|
|
347
|
+
class="docs-link"
|
|
348
|
+
>Read the docs</a
|
|
349
|
+
>
|
|
350
|
+
</div>
|
|
351
|
+
|
|
352
|
+
<div class="status">
|
|
353
|
+
<span class="status-dot">
|
|
354
|
+
<span class="glow" aria-hidden="true"></span>
|
|
355
|
+
<span class="dot" aria-hidden="true"></span>
|
|
356
|
+
</span>
|
|
357
|
+
<span class="status-text">Dev server is running</span>
|
|
358
|
+
</div>
|
|
359
|
+
</main>
|
|
360
|
+
</body>
|
|
361
|
+
</html>
|
|
362
|
+
`;var A=new ht({authorize:()=>!0});A.route("GET /v7",()=>xe(426));A.route("GET /v8",()=>xe(426));A.route("GET /health",()=>gt({status:"ok"}));A.route("GET /",()=>ft(Ce.replace("__VERSION__","1.0.6")));import{jsonObjectYolo as bt,ROOT_YDOC_ID as q,snapshotToLossyJson_eager as Tt,snapshotToPlainLson_eager as we}from"@liveblocks/server";import{json as yt,ZenRouter as St}from"@liveblocks/zenrouter";import{constant as Ct,enum_ as xt,object as Le,string as Ot}from"decoders";import{Base64 as _t}from"js-base64";import*as X from"yjs";import*as E from"yjs";function vt(e){return e.content instanceof E.ContentFormat||e.content instanceof E.ContentEmbed?"text":"arr"in e.content?"array":"str"in e.content?"text":"type"in e.content?"xml":"unknown"}function It(e){let t=[],o=e;for(;o!==null;){if(!o.deleted)if(o.content instanceof E.ContentType)t.push(o.content.type.toJSON());else if(o.content instanceof E.ContentString)t.push(o.content.str);else if(o.content instanceof E.ContentFormat){let{key:s,value:i}=o.content;t.push({key:s,value:i})}else o.content instanceof E.ContentEmbed&&t.push(o.content.embed);o=o.right}return t}function Oe(e,t,o,s=!1){if(!t._first&&t._map instanceof Map&&t._map.size>0)return e.getMap(o).toJSON();if(t._first!==null){let i=vt(t._first);if(i==="text")return s?It(t._first):e.getText(o).toJSON();if(i==="array")return e.getArray(o).toJSON();if(i==="xml")return e.getXmlFragment(o).toJSON()}return t.toJSON()}var Et={ytext:E.Text,yxmlfragment:E.XmlFragment,yxmltext:E.XmlText,ymap:E.Map,yarray:E.Array};function _e(e,t="",o=!1,s=""){let i={};if(t.length){if(e.share.has(t)){if(s.length){let d=Et[s];if(d)return e.get(t,d).toJSON()}return{[t]:Oe(e,e.share.get(t),t,o)}}return{[t]:""}}for(let[d,u]of e.share)i[d]=Oe(e,u,d,o);return i}var Re=(o=>(o.PlainLson="plain-lson",o.LossyJson="json",o))(Re||{}),wt=xt(Re),n=new St({authorize:({req:e})=>F(e)});function N(e){return yt({error:"ROOM_NOT_FOUND",message:`Room with id "${e}" not found.`},404)}n.route("GET /v2/rooms/<roomId>",async({p:e})=>{if(!await S(e.roomId))throw N(e.roomId);return{type:"room",id:e.roomId,createdAt:new Date().toISOString(),metadata:{},defaultAccesses:["room:write"],groupsAccesses:{},usersAccesses:{}}});n.route("GET /v2/rooms",()=>{let t=le().map(o=>({type:"room",id:o,createdAt:new Date().toISOString(),metadata:{},defaultAccesses:["room:write"],groupsAccesses:{},usersAccesses:{}}));return J({data:t,nextPage:null,nextCursor:null},200,"The Liveblocks dev server doesn't implement room permissions or pagination yet.")});n.route("POST /v2/rooms",Le({id:Ot}),async({body:e})=>{if(await S(e.id))return new Response(JSON.stringify({error:"ROOM_ALREADY_EXISTS",message:`Room with id "${e.id}" already exists.`}),{status:409,headers:{"Content-Type":"application/json"}});try{await me(e.id)}catch(o){if(o instanceof Error&&o.message.includes("already exists"))return new Response(JSON.stringify({error:"ROOM_ALREADY_EXISTS",message:`Room with id "${e.id}" already exists.`}),{status:409,headers:{"Content-Type":"application/json"}});throw o}return{type:"room",id:e.id,createdAt:new Date().toISOString(),metadata:{},defaultAccesses:["room:write"],groupsAccesses:{},usersAccesses:{}}});n.route("POST /v2/rooms/<roomId>",()=>r());n.route("DELETE /v2/rooms/<roomId>",async({p:e})=>(await pe(e.roomId),new Response(null,{status:204})));n.route("GET /v2/rooms/<roomId>/storage",async({url:e,p:t})=>{if(!await S(t.roomId))throw N(t.roomId);let s=wt.value(e.searchParams.get("format"))??"plain-lson",i=O(t.roomId);await i.load();let d=i.storage.loadedDriver.get_snapshot(!1),u=s==="json"?Tt(d):we(d);return new Response(JSON.stringify(u),{status:200,headers:{"Content-Type":"application/json"}})});n.route("POST /v2/rooms/<roomId>/storage",Le({liveblocksType:Ct("LiveObject"),data:bt}).refineType(),async({p:e,body:t})=>{if(!await S(e.roomId))throw N(e.roomId);let s=O(e.roomId);await s.load();let i=s.storage.loadedDriver.get_snapshot(!1),d=we(i);return Object.keys(d.data).length>0?new Response(JSON.stringify({error:"CANNOT_UPDATE_EXISTING_STORAGE",message:"The room already has storage data. It's only possible to initialize the storage for an empty room.",suggestion:"Create another room or clear this room storage first."}),{status:409,headers:{"Content-Type":"application/json"}}):(await s.driver.DANGEROUSLY_reset_nodes(t),s.unload(),new Response(JSON.stringify(t),{status:200,headers:{"Content-Type":"application/json"}}))});n.route("DELETE /v2/rooms/<roomId>/storage",async({p:e})=>{if(!await S(e.roomId))throw N(e.roomId);let o=O(e.roomId);await o.load();let s={liveblocksType:"LiveObject",data:{}};return await o.driver.DANGEROUSLY_reset_nodes(s),o.unload(),new Response(null,{status:204})});n.route("GET /v2/rooms/<roomId>/ydoc",async({url:e,p:t})=>{if(!await S(t.roomId))throw N(t.roomId);let s=O(t.roomId);await s.load();let i=e.searchParams.get("key")??"",d=e.searchParams.get("type")??"",u=e.searchParams.get("guid")??q,c=e.searchParams.get("formatting")!==null,v=await s.yjsStorage.getYDoc(u),p=_e(v,i,c,d);return new Response(JSON.stringify(p),{status:200,headers:{"Content-Type":"application/json"}})});n.route("PUT /v2/rooms/<roomId>/ydoc",async({req:e,url:t,p:o})=>{if(e.headers.get("content-type")!=="application/octet-stream")return new Response(JSON.stringify({error:"BAD_REQUEST",message:'Expected "Content-Type" header to be "application/octet-stream", and the HTTP body to be a valid binary Yjs update.'}),{status:400,headers:{"Content-Type":"application/json"}});if(!await S(o.roomId))throw N(o.roomId);let i=O(o.roomId);await i.load();let d=await e.arrayBuffer(),u=_t.fromUint8Array(new Uint8Array(d)),c=t.searchParams.get("guid"),p=t.searchParams.get("encoder")==="v2",f=c&&c!==q?c:void 0;try{return await i.mutex.runExclusive(()=>i.yjsStorage.addYDocUpdate({},u,f,p)),new Response(JSON.stringify({success:!0}),{status:200,headers:{"Content-Type":"application/json"}})}catch(I){return new Response(JSON.stringify({error:"UNPROCESSABLE_ENTITY",message:I instanceof Error?I.message:"Could not apply update",suggestion:"Please ensure the update is correct, and you selected the correct encoder to use (v1 or v2)."}),{status:422,headers:{"Content-Type":"application/json"}})}});n.route("GET /v2/rooms/<roomId>/ydoc-binary",async({url:e,p:t})=>{if(!await S(t.roomId))throw N(t.roomId);let s=O(t.roomId);await s.load();let i=e.searchParams.get("guid")??q,d=e.searchParams.get("encoder"),u=await s.yjsStorage.getYDoc(i),c=d==="v2"?X.encodeStateAsUpdateV2(u):X.encodeStateAsUpdate(u);return new Response(c,{status:200,headers:{"Content-Type":"application/octet-stream"}})});n.route("GET /v2/rooms/<roomId>/threads",()=>r()),n.route("POST /v2/rooms/<roomId>/upsert",()=>r()),n.route("POST /v2/rooms/<roomId>/update-room-id",()=>r()),n.route("POST /v2/rooms/<roomId>/update-tenant-id",()=>r()),n.route("POST /v2/rooms/<roomId>/update-organization-id",()=>r()),n.route("GET /v2/rooms/<roomId>/prewarm",()=>r()),n.route("POST /v2/rooms/<roomId>/request-storage-mutation",()=>r()),n.route("GET /v2/rooms/<roomId>/rippling/text-editor",()=>r()),n.route("POST /v2/rooms/<roomId>/rippling/text-editor",()=>r()),n.route("GET /v2/rooms/<roomId>/active_users",()=>r()),n.route("POST /v2/rooms/<roomId>/send-message",()=>r()),n.route("POST /v2/rooms/<roomId>/broadcast_event",()=>r()),n.route("GET /v2/rooms/<roomId>/versions",()=>r()),n.route("GET /v2/rooms/<roomId>/version/<version>",()=>r()),n.route("POST /v2/rooms/<roomId>/version",()=>r()),n.route("POST /v2/rooms/<roomId>/threads",()=>r()),n.route("GET /v2/rooms/<roomId>/threads/<threadId>",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/mark-as-resolved",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/mark-as-unresolved",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/subscribe",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/unsubscribe",()=>r()),n.route("GET /v2/rooms/<roomId>/threads/<threadId>/subscriptions",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/metadata",()=>r()),n.route("DELETE /v2/rooms/<roomId>/threads/<threadId>",()=>r()),n.route("GET /v2/rooms/<roomId>/threads/<threadId>/participants",()=>r()),n.route("GET /v2/rooms/<roomId>/threads/<threadId>/inbox-notifications",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments",()=>r()),n.route("GET /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>/metadata",()=>r()),n.route("DELETE /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>/add-reaction",()=>r()),n.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>/remove-reaction",()=>r()),n.route("GET /v2/rooms/<roomId>/users/<userId>/notification-settings",()=>r()),n.route("GET /v2/rooms/<roomId>/users/<userId>/subscription-settings",()=>r()),n.route("POST /v2/rooms/<roomId>/users/<userId>/notification-settings",()=>r()),n.route("POST /v2/rooms/<roomId>/users/<userId>/subscription-settings",()=>r()),n.route("DELETE /v2/rooms/<roomId>/users/<userId>/notification-settings",()=>r()),n.route("DELETE /v2/rooms/<roomId>/users/<userId>/subscription-settings",()=>r()),n.route("GET /v2/users/<userId>/inbox-notifications/<inboxNotificationId>",()=>r()),n.route("DELETE /v2/users/<userId>/inbox-notifications/<inboxNotificationId>",()=>r()),n.route("GET /v2/users/<userId>/inbox-notifications",()=>r()),n.route("DELETE /v2/users/<userId>/inbox-notifications",()=>r()),n.route("GET /v2/users/<userId>/notification-settings",()=>r()),n.route("POST /v2/users/<userId>/notification-settings",()=>r()),n.route("DELETE /v2/users/<userId>/notification-settings",()=>r()),n.route("GET /v2/users/<userId>/room-subscription-settings",()=>r()),n.route("GET /v2/users/<userId>/threads",()=>r()),n.route("POST /v2/inbox-notifications/trigger",()=>r()),n.route("POST /v2/inbox-notifications/<inboxNotificationId>/read",()=>r()),n.route("GET /v2/threads",()=>r()),n.route("POST /v2/groups",()=>r()),n.route("GET /v2/groups/<groupId>",()=>r()),n.route("POST /v2/groups/<groupId>/add-members",()=>r()),n.route("POST /v2/groups/<groupId>/remove-members",()=>r()),n.route("DELETE /v2/groups/<groupId>",()=>r()),n.route("GET /v2/groups",()=>r()),n.route("GET /v2/users/<userId>/groups",()=>r());function Pt(e,t,o,s){if(!e.upgrade(t,{data:{refuseConnection:{code:o,message:s}}}))return new Response("Could not upgrade to WebSocket",{status:426})}var U=new Nt;U.relay("/v2/authorize-user/*",Y);U.relay("/v2/identify-user/*",Y);U.relay("/v2/c/*",a);U.relay("/v2/*",n);U.relay("/*",A);var Ne=1153;function ke(e){if(e===void 0)return;let t=Number(e);return Number.isInteger(t)&&t>0&&t<=65535?t:void 0}var Dt={description:"Start the local Liveblocks dev server",async run(e){let t=Lt(e,{string:["port","host"],boolean:["help"],alias:{h:"help",p:"port"}});if(t.help){console.log("Usage: liveblocks dev [options]"),console.log(),console.log("Start the local Liveblocks dev server"),console.log(),console.log("Options:"),console.log(` -p, --port Port to listen on (default: ${Ne})`),console.log(" --host Host to bind to (default: localhost)"),console.log(" -h, --help Show this help message");return}let o=ke(t.port)??ke(process.env.LIVEBLOCKS_DEVSERVER_PORT)??Ne,s=t.host||process.env.LIVEBLOCKS_DEVSERVER_HOST||"localhost";await Ee(o,s)&&(console.error(`Port ${o} is already in use.
|
|
363
|
+
Is another dev server already running?`),process.exit(1));let i=kt.serve({hostname:s,port:o,async fetch(c,v){if(c.headers.get("Upgrade")==="websocket"){let l=se(c);if(!l.ok)return W(l.xwarn,!0),Pt(v,c,Rt.NOT_ALLOWED,"You have no access to this room");let{roomId:m,ticketData:g}=l,h=O(m);await h.load();let b=await h.createTicket(g),w=b.sessionKey;if(v.upgrade(c,{data:{room:h,ticket:b,sessionKey:w}})){console.log(`${L("101")} WS ${new URL(c.url).pathname}`);return}return new Response("Could not upgrade to WebSocket",{status:426})}let p=new URL(c.url),f=`${c.method} ${p.pathname}`,I=await U.fetch(c),C=I.status,G=C>=500?V(String(C)):C>=400?P(String(C)):L(String(C));console.log(`${G} ${f}`);let Z=I.headers.get("X-LB-Warn")??void 0;return W(Z,!I.ok),I},error(c){return console.error(c),new Response("An unknown error occurred",{status:500})},websocket:{async open(c){let{refuseConnection:v,room:p,ticket:f}=c.data;if(v){c.close(v.code,v.message);return}p&&f&&await p.startBrowserSession(f,c)},async message(c,v){let{room:p,sessionKey:f}=c.data;p&&f&&await p.handleData(f,v)},close(c,v,p){let{room:f,sessionKey:I}=c.data;f&&I&&f.endBrowserSession(I,v,p)}}});console.log(`Liveblocks dev server running at http://${i.hostname}:${i.port}`);let d=await he(o),u=`http://localhost:${o}`;console.log(T("Press ")+j("q")+T(" to quit, ")+j("c")+T(" to clear")),process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.on("data",c=>{let v=c.toString();if(v==="q"||v==="")i.stop().then(()=>process.exit(0));else if(v==="c")console.clear();else if(v==="p")if(d.length>0){let p=ve(d,u);Ie(p),console.log(T("Copied AI fix prompt to clipboard"))}else console.log(T("No setup issues detected"))}))}},qo=Dt;export{qo as default};
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{execFileSync as c,spawnSync as t}from"node:child_process";import{parse as l}from"@bomb.sh/args";function a(){try{return c("bun",["--version"],{stdio:"ignore"}),!0}catch{return!1}}function d(){if(a()){let e=t("bun",process.argv.slice(1),{stdio:"inherit"});process.exit(e.status??1)}else console.error("The Liveblocks local dev server requires Bun."),console.error("See https://liveblocks.io/docs/get-started/dev-server for more information."),process.exit(1)}var s=process.argv.slice(2),o=s.findIndex(e=>!e.startsWith("-")),r=l(o>=0?s.slice(0,o):s,{boolean:["help","version"],alias:{h:"help",v:"version"}}),n=o>=0?s[o]:void 0,u=o>=0?s.slice(o+1):[];async function m(e){switch(e){case"dev":return typeof Bun>"u"&&d(),(await import("./dev-server-
|
|
2
|
+
import{execFileSync as c,spawnSync as t}from"node:child_process";import{parse as l}from"@bomb.sh/args";function a(){try{return c("bun",["--version"],{stdio:"ignore"}),!0}catch{return!1}}function d(){if(a()){let e=t("bun",process.argv.slice(1),{stdio:"inherit"});process.exit(e.status??1)}else console.error("The Liveblocks local dev server requires Bun."),console.error("See https://liveblocks.io/docs/get-started/dev-server for more information."),process.exit(1)}var s=process.argv.slice(2),o=s.findIndex(e=>!e.startsWith("-")),r=l(o>=0?s.slice(0,o):s,{boolean:["help","version"],alias:{h:"help",v:"version"}}),n=o>=0?s[o]:void 0,u=o>=0?s.slice(o+1):[];async function m(e){switch(e){case"dev":return typeof Bun>"u"&&d(),(await import("./dev-server-FYKFAPQC.js")).default;case"upgrade":return(await import("./upgrade-EKOUUSAC.js")).default;default:return}}var v={dev:"Start the local Liveblocks dev server",upgrade:"Upgrade all Liveblocks packages"};function p(){console.log("liveblocks v1.0.6"),console.log(),console.log("Usage: liveblocks <command> [options]"),console.log(),console.log("Commands:");for(let[e,i]of Object.entries(v))console.log(` ${e.padEnd(12)} ${i}`);console.log(),console.log("Options:"),console.log(" -h, --help Show this help message"),console.log(" -v, --version Show version number")}async function f(){r.version&&(console.log("1.0.6"),process.exit(0)),(r.help||!n)&&(p(),process.exit(n?0:1));let e=await m(n);e?await e.run(u):(console.error(`Unknown command: ${n}`),console.error('Run "liveblocks --help" for usage.'),process.exit(1))}f();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "liveblocks",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Liveblocks command line interface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@bomb.sh/args": "^0.3.1",
|
|
42
42
|
"@liveblocks/core": "3.14.0-rc1",
|
|
43
|
-
"@liveblocks/server": "1.0.
|
|
44
|
-
"@liveblocks/zenrouter": "1.0.
|
|
43
|
+
"@liveblocks/server": "1.0.6",
|
|
44
|
+
"@liveblocks/zenrouter": "1.0.6",
|
|
45
45
|
"decoders": "^2.8.0-1",
|
|
46
46
|
"js-base64": "^3.7.5",
|
|
47
47
|
"yjs": "^13.6.10"
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import{parse as Lt}from"@bomb.sh/args";import{WebsocketCloseCodes as Nt}from"@liveblocks/core";import{ZenRelay as kt}from"@liveblocks/zenrouter";import Pt from"bun";function k(t){return`\x1B[33m${t}\x1B[0m`}function V(t){return`\x1B[34m${t}\x1B[0m`}function Y(t){return`\x1B[35m${t}\x1B[0m`}function L(t){return`\x1B[32m${t}\x1B[0m`}function q(t){return`\x1B[31m${t}\x1B[0m`}function O(t){return`\x1B[2m${t}\x1B[0m`}import{nanoid as Pe,Permission as De}from"@liveblocks/core";import{ProtocolVersion as te}from"@liveblocks/server";import{nanoid as ke}from"@liveblocks/core";function Z(t){return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Q(t){let e=t.replace(/-/g,"+").replace(/_/g,"/"),o=e+"=".repeat((4-e.length%4)%4);return atob(o)}function ee(t){let e=Math.floor(Date.now()/1e3),o={...t,iat:e,exp:e+60*60,jti:ke(12)},s=Z(JSON.stringify({alg:"none",typ:"JWT"})),n=Z(JSON.stringify(o));return`${s}.${n}.`}function $(t){let e=t.split(".");if(e.length!==3)return null;let[o,s,n]=e;try{if(JSON.parse(Q(o)).alg!=="none")return null}catch{return null}let a;try{a=JSON.parse(Q(s))}catch{return null}if(n!==""||a.pid!=="localdev")return null;let u=a.exp;return typeof u=="number"&&u<Math.floor(Date.now()/1e3)?null:a}function Ae(t,e){if(e[t])return e[t];for(let[o,s]of Object.entries(e))if(o.endsWith("*")){let n=o.slice(0,-1);if(t.startsWith(n))return s}return[]}function oe(t){let e=new URL(t.url),o=e.pathname==="/v7"?te.V7:e.pathname==="/v8"?te.V8:null;if(o===null)return{ok:!1};let s=e.searchParams.get("roomId");if(!s)return{ok:!1};let n=e.searchParams.get("tok");if(n!==null){let u=$(n);if(!u)return{ok:!1};if(u.k==="acc"){let c=Ae(s,u.perms);return c.length===0?{ok:!1}:{ok:!0,roomId:s,ticketData:{version:o,id:u.uid,info:u.ui,scopes:c}}}else if(u.k==="id")return{ok:!0,roomId:s,ticketData:{version:o,id:u.uid,info:u.ui,scopes:[De.Write]}};return{ok:!1}}let a=e.searchParams.get("pubkey");return a!==null?a!=="pk_localdev"?{ok:!1,xwarn:"You can only use 'pk_localdev' as the public key"}:{ok:!0,roomId:s,ticketData:{version:o,anonymousId:Pe(),scopes:["room:write"]}}:{ok:!1}}import{DefaultMap as Fe,Room as He}from"@liveblocks/server";import{mkdirSync as de,readdirSync as We}from"fs";import{resolve as ae}from"path";import{asPos as Me,CrdtType as x,nn as je}from"@liveblocks/core";import{makeInMemorySnapshot as Ue,NestedMap as Je,plainLsonToNodeStream as Ge,quote as b}from"@liveblocks/server";import{Database as Ye}from"bun:sqlite";function N(t){try{return t!==void 0?JSON.parse(t):void 0}catch{return}}function ne(t){if(t>512)throw new Error("More than 512 params not supported");return new Array(t).fill("?").join(",")}function $e(t){return Array.isArray(t)?t:Array.from(t)}function Be(t){return t.query("SELECT node_id, crdt_json FROM nodes").values().map(([e,o])=>[e,N(o)])}function M(t,e){let o=t.prepare(`INSERT INTO nodes (node_id, crdt_json)
|
|
2
|
-
VALUES (?, ?)
|
|
3
|
-
ON CONFLICT (node_id) DO UPDATE SET crdt_json = ?`);t.transaction(n=>{for(let[a,u]of n){let c=JSON.stringify(u);o.run(a,c,c)}})(e)}function ie(t,e){let o=$e(e),s=o.length;t.query(`DELETE FROM nodes WHERE node_id IN (${ne(s)})`).run(...o)}function re(t){let e=new Je;for(let[o,s]of t){if(s.parentId===void 0)continue;let n=e.get(s.parentId,s.parentKey);(n===void 0||o>n)&&e.set(s.parentId,s.parentKey,o)}return e}function ze(t,e){let o=new Map(Be(t));o.has("root")||o.set("root",{type:x.OBJECT,data:{}});let s=new Set,n=["root"],a=new Map,u=re(o);for(;n.length>0;){let p=n.pop(),f=je(o.get(p));if(f.type===x.OBJECT)for(let I of u.keysAt(p))Object.prototype.hasOwnProperty.call(f.data,I)&&(delete f.data[I],s.add(p),e.warn(`[integrity] Found data key ${b(I)} from ${b(p)} (conflicted with child node)`));if(f.type!==x.REGISTER)n.push(...u.valuesAt(p));else if(o.get(f.parentId)?.type===x.OBJECT)continue;a.set(p,f)}let c=new Set;for(let[p,f]of o)a.has(p)||(f.parentId!==void 0&&a.has(f.parentId)?a.get(f.parentId)?.type===x.REGISTER?e.warn(`[integrity] Found unreachable node ${b(p)} (child of live register)`):e.warn(`[integrity] Found conflicting sibling ${b(p)} (conflicted with ${b(u.get(f.parentId,f.parentKey))} at ${b(f.parentKey)})`):e.warn(`[integrity] Found orphan ${b(p)}`),c.add(p),s.delete(p));if(s.size>0||c.size>0){if(s.size>0){let p=new Map;for(let f of s){let I=a.get(f);I!==void 0&&p.set(f,I)}M(t,p)}c.size>0&&ie(t,c)}let h=c.size===0?u:re(a);return{nodes:a,revNodes:h}}function se(t,e){return t?.type===x.OBJECT&&Object.prototype.hasOwnProperty.call(t.data,e)&&t.data[e]!==void 0}var B=class{db;constructor(e){let o=new Ye(e,{create:!0});o.run("PRAGMA journal_mode = WAL"),o.run("PRAGMA case_sensitive_like = ON"),o.run(`CREATE TABLE IF NOT EXISTS system (
|
|
4
|
-
setting TEXT NOT NULL,
|
|
5
|
-
jval TEXT NOT NULL,
|
|
6
|
-
PRIMARY KEY (setting)
|
|
7
|
-
)`),o.run(`CREATE TABLE IF NOT EXISTS nodes (
|
|
8
|
-
node_id TEXT NOT NULL,
|
|
9
|
-
crdt_json TEXT NOT NULL,
|
|
10
|
-
PRIMARY KEY (node_id)
|
|
11
|
-
)`),o.run(`CREATE TABLE IF NOT EXISTS metadata (
|
|
12
|
-
key TEXT NOT NULL,
|
|
13
|
-
jval TEXT NOT NULL,
|
|
14
|
-
PRIMARY KEY (key)
|
|
15
|
-
)`),o.run(`CREATE TABLE IF NOT EXISTS ydocs (
|
|
16
|
-
doc_id TEXT NOT NULL,
|
|
17
|
-
key TEXT NOT NULL,
|
|
18
|
-
data BLOB NOT NULL,
|
|
19
|
-
PRIMARY KEY (doc_id, key)
|
|
20
|
-
)`),o.run(`CREATE TABLE IF NOT EXISTS leased_sessions (
|
|
21
|
-
session_id TEXT NOT NULL PRIMARY KEY,
|
|
22
|
-
jpresence TEXT NOT NULL,
|
|
23
|
-
updated_at INTEGER NOT NULL,
|
|
24
|
-
juserinfo TEXT NOT NULL,
|
|
25
|
-
ttl INTEGER NOT NULL,
|
|
26
|
-
actor_id INTEGER NOT NULL
|
|
27
|
-
)`),o.run("CREATE INDEX IF NOT EXISTS idx_leased_sessions_expiry ON leased_sessions(updated_at, ttl)"),this.db=o}load_nodes_api(e){let o=this.db,{nodes:s,revNodes:n}=ze(o,e),a=m=>s.get(m),u=(m,l)=>n.get(m,l),c=(m,l)=>n.has(m,l);function h(m,l){let g;for(let v of n.keysAt(m)){let y=Me(v);y>l&&(g===void 0||y<g)&&(g=y)}return g}function p(m,l,g=!1){let v=a(l.parentId);if(v===void 0)throw new Error(`No such parent ${b(l.parentId)}`);if(l.type===x.REGISTER&&v.type===x.OBJECT)throw new Error("Cannot add register under object");let y=u(l.parentId,l.parentKey);if(y!==m){let S=se(v,l.parentKey);if(y!==void 0||S)if(g)G(l.parentId,l.parentKey);else throw new Error(`Key ${b(l.parentKey)} already exists`);n.set(l.parentId,l.parentKey,m)}s.set(m,l),M(o,[[m,l]])}function f(m,l){let g=a(m);if(g?.parentId===void 0)return;if(c(g.parentId,l))throw new Error(`Pos ${b(l)} already taken`);n.delete(g.parentId,g.parentKey);let v={...g,parentKey:l};s.set(m,v),n.set(g.parentId,l,m),M(o,[[m,v]])}function I(m,l,g=!1){let v=a(m);if(v?.type!==x.OBJECT)return;for(let S of Object.keys(l)){let _=u(m,S);if(_!==void 0)if(g)E(_);else throw new Error(`Child node already exists under ${S}`)}let y={...v,data:{...v.data,...l}};s.set(m,y),M(o,[[m,y]])}function E(m){let l=a(m);if(l?.parentId===void 0)return;n.delete(l.parentId,l.parentKey);let g=[],v=[m];for(;v.length>0;){let y=v.pop();v.push(...n.valuesAt(y)),s.delete(y),n.deleteAll(y),g.push(y)}ie(o,g)}function G(m,l){let g=a(m);if(se(g,l)){let{[l]:y,...S}=g.data,_={...g,data:S};s.set(m,_),M(o,[[m,_]])}let v=u(m,l);v!==void 0&&E(v)}return{get_node:a,iter_nodes:()=>s.entries(),has_node:m=>s.has(m),get_child_at:u,has_child_at:c,get_next_sibling:h,set_child:p,move_sibling:f,delete_node:E,delete_child_key:G,set_object_data:I,get_snapshot(m){return Ue(s)}}}DANGEROUSLY_reset_nodes(e){let o=this.db.prepare("DELETE FROM nodes"),s=this.db.prepare("INSERT INTO nodes (node_id, crdt_json) VALUES (?, ?)");this.db.transaction(()=>{o.run();for(let[a,u]of Ge(e))s.run(a,JSON.stringify(u))})()}raw_iter_nodes(){return this.db.query("SELECT node_id, crdt_json FROM nodes").values().map(([e,o])=>[e,N(o)])}get_meta(e){let s=this.db.query("SELECT jval FROM metadata WHERE key = ?").get(e)?.jval;if(s!==void 0)return N(s)??null}put_meta(e,o){let s=JSON.stringify(o);this.db.run(`INSERT INTO metadata (key, jval)
|
|
28
|
-
VALUES (?, ?)
|
|
29
|
-
ON CONFLICT (key) DO UPDATE SET jval = ?
|
|
30
|
-
`,[e,s,s])}delete_meta(e){this.db.query("DELETE FROM metadata WHERE key = ?").run(e)}next_actor(){let e=this.db.query(`INSERT INTO system (setting, jval)
|
|
31
|
-
VALUES ('last_actor_id', '0')
|
|
32
|
-
ON CONFLICT (setting) DO UPDATE SET jval = json(CAST(jval AS INTEGER) + 1)
|
|
33
|
-
RETURNING jval`).get();return JSON.parse(e.jval)}iter_y_updates(e){return this.db.query("SELECT key, data FROM ydocs WHERE doc_id = ?").values(e)}write_y_updates(e,o,s){this.db.query(`INSERT INTO ydocs
|
|
34
|
-
VALUES (?, ?, ?)
|
|
35
|
-
ON CONFLICT (doc_id, key) DO UPDATE SET data = ?`).run(e,o,s,s)}delete_y_updates(e,o){let s=o.length;this.db.query(`DELETE FROM ydocs WHERE doc_id = ? AND key IN (${ne(s)})`).run(e,...o)}DANGEROUSLY_wipe_all_y_updates(){this.db.query("DELETE FROM ydocs").run()}list_leased_sessions(){let e=this.db.query("SELECT session_id, jpresence, updated_at, juserinfo, ttl, actor_id FROM leased_sessions").all();return Array.from(e,o=>[o.session_id,{sessionId:o.session_id,presence:N(o.jpresence)??null,updatedAt:o.updated_at,info:N(o.juserinfo)??{name:""},ttl:o.ttl,actorId:o.actor_id}])}get_leased_session(e){let o=this.db.query("SELECT session_id, jpresence, updated_at, juserinfo, ttl, actor_id FROM leased_sessions WHERE session_id = ?").get(e);if(o!=null)return{sessionId:o.session_id,presence:N(o.jpresence)??null,updatedAt:o.updated_at,info:N(o.juserinfo)??{name:""},ttl:o.ttl,actorId:o.actor_id}}put_leased_session(e){this.db.query(`INSERT INTO leased_sessions (session_id, jpresence, updated_at, juserinfo, ttl, actor_id)
|
|
36
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
37
|
-
ON CONFLICT (session_id) DO UPDATE SET
|
|
38
|
-
jpresence = excluded.jpresence,
|
|
39
|
-
updated_at = excluded.updated_at,
|
|
40
|
-
juserinfo = excluded.juserinfo,
|
|
41
|
-
ttl = excluded.ttl,
|
|
42
|
-
actor_id = excluded.actor_id`).run(e.sessionId,JSON.stringify(e.presence),e.updatedAt,JSON.stringify(e.info),e.ttl,e.actorId)}delete_leased_session(e){this.db.query("DELETE FROM leased_sessions WHERE session_id = ?").run(e)}close(){this.db.close()}};var j=".liveblocks/v1/rooms",ce=new Fe(t=>{de(j,{recursive:!0});let e=new B(ue(t));return new He(t,{storage:e})});function ue(t){let e=ae(j,`${encodeURIComponent(t)}.db`);if(!e.startsWith(ae(j)+"/"))throw new Error("Invalid room ID");return e}function w(t){return ce.getOrCreate(t)}async function C(t){let e=ue(t);return await Bun.file(e).exists()}function le(){try{return de(j,{recursive:!0}),We(j).filter(o=>o.endsWith(".db")).map(o=>decodeURIComponent(o.replace(/\.db$/,"")))}catch{return[]}}async function me(t){if(await C(t))throw new Error(`Room with id "${t}" already exists`);let e=ce.getOrCreate(t);await e.load();let o={liveblocksType:"LiveObject",data:{}};await e.driver.DANGEROUSLY_reset_nodes(o),e.unload()}function Ke(t){return t.trim().split(`
|
|
43
|
-
`).filter(Boolean).map(e=>{let o=e.match(/^(.+?):(\d+):(.*)$/);return o?{file:o[1],line:parseInt(o[2],10),text:o[3]}:null}).filter(e=>e!==null)}async function fe(...t){try{let e=["git","grep","-nF",...t.flatMap(n=>["-e",n]),"--","."],o=Bun.spawn(e,{stdout:"pipe",stderr:"pipe"}),s=await new Response(o.stdout).text();return await o.exited,Ke(s)}catch{return[]}}function Xe(t){let e=t.trim();return e.startsWith("#")||e.startsWith("//")||e.startsWith("*")||e.startsWith("/*")}var Ve=[{pattern:"<LiveblocksProvider",expected:"baseUrl=",fixSnippet:t=>`${Y("baseUrl")}=${L(`"${t}"`)}`},{pattern:"createClient(",expected:"baseUrl:",fixSnippet:t=>`${Y("baseUrl")}: ${L(`"${t}"`)}`},{pattern:"new Liveblocks(",expected:"baseUrl:",fixSnippet:t=>`${Y("baseUrl")}: ${L(`"${t}"`)}`}];async function ge(t){let e=`http://localhost:${t}`,o=[];for(let s of Ve){let n=(await fe(s.pattern)).filter(c=>!Xe(c.text));if(n.length===0)continue;let a=await fe(s.expected),u=new Set(a.map(c=>c.file));for(let c of n)u.has(c.file)||o.push({match:c,check:s})}if(o.length>0){console.log(),console.warn(k("\u26A0 Your project may not be configured for the local dev server.")),console.log(),console.log(` Missing baseUrl in the following location(s):
|
|
44
|
-
`);for(let{match:s,check:n}of o)console.log(` ${V(`${s.file}:${s.line}`)}`),console.log(` To fix, add ${n.fixSnippet(e)}`),console.log();console.log(O(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")),console.log(O(" \u2502 Press p to copy an AI fix prompt to your clipboard \u2502")),console.log(O(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F")),console.log()}return o}var qe={"<LiveblocksProvider":t=>`baseUrl="${t}"`,"createClient(":t=>`baseUrl: "${t}"`,"new Liveblocks(":t=>`baseUrl: "${t}"`},Ze={"<LiveblocksProvider":{prop:"publicApiKey",value:"pk_localdev"},"createClient(":{prop:"publicApiKey",value:"pk_localdev"},"new Liveblocks(":{prop:"secret",value:"sk_localdev"}};function he(t,e){let o=[`In the following file(s), the Liveblocks setup is missing a \`baseUrl\` property pointing to the local dev server at ${e}. Please add the missing configuration:`,""];for(let{match:n,check:a}of t){let u=qe[a.pattern]?.(e)??`baseUrl: "${e}"`;o.push(`- In \`${n.file}\` at line ${n.line}, add \`${u}\` to the \`${a.pattern}\` call`)}o.push("","Also make sure the API keys are set to the local dev server keys:");let s=new Set;for(let{check:n}of t){let a=Ze[n.pattern];a&&!s.has(a.value)&&(s.add(a.value),o.push(`- Set \`${a.prop}\` to \`"${a.value}"\` (either directly or via an environment variable)`))}return o.join(`
|
|
45
|
-
`)}import{execSync as Qe}from"node:child_process";function ve(t){let e=process.platform==="darwin"?"pbcopy":process.platform==="win32"?"clip.exe":"xclip -selection clipboard";Qe(e,{input:t})}import et from"bun";function Ie(t,e){let{promise:o,resolve:s}=Promise.withResolvers();return et.connect({hostname:e,port:t,socket:{data(){},open(n){n.end(),s(!0)},error(){s(!1)},connectError(){s(!1)}}}),o}var H=new Set;function W(t,e=t){e&&!H.has(e)&&(H.add(e),console.log(k(` \u26A0 ${t??e}`)))}function Te(){H.clear()}import{Permission as st}from"@liveblocks/core";import{ZenRouter as nt}from"@liveblocks/zenrouter";import{array as it,enum_ as at,object as dt,optional as ct,record as ut,string as lt}from"decoders";import{json as ot}from"@liveblocks/zenrouter";import{nanoid as tt}from"@liveblocks/core";import{json as ye}from"@liveblocks/zenrouter";function U(t,e,o,s){let n={};return n["X-LB-Warn"]=o,s&&(n["X-LB-Warn-Key"]=s),ye(t,e,n)}function R(t,e,o="This is a dummy response."){return U(t,e,o,tt())}function r(t="This endpoint isn't implemented in the Liveblocks dev server"){return ye({error:"Not implemented",message:t},501,{"X-LB-Warn":t})}function z(t){let e=t.headers.get("Authorization");if(e==="Bearer sk_localdev")return!0;if(!e)throw ot({error:"Unauthorized",message:"Missing secret key"},401);if(e.startsWith("Bearer "))throw U({error:"Forbidden",message:"Invalid secret key. You can only use 'sk_localdev' as a secret key"},403,"You can only use 'sk_localdev' as the secret key");return!1}import{inexact as rt,optional as be,string as Ee}from"decoders";var Se=rt({name:be(Ee),avatar:be(Ee)}).refineType();var mt=at(st),J=new nt({authorize:({req:t})=>z(t)});J.route("POST /v2/authorize-user",dt({userId:lt,userInfo:ct(Se),permissions:ut(it(mt))}),({body:t})=>({token:ee({k:"acc",pid:"localdev",uid:t.userId,perms:t.permissions,ui:t.userInfo})}));J.route("POST /v2/identify-user",()=>r("ID tokens are not supported in the Liveblocks dev server. To develop locally, use access tokens instead (via POST /v2/authorize-user)"));import{ZenRouter as pt}from"@liveblocks/zenrouter";var d=new pt({cors:{allowCredentials:!0,maxAge:600},authorize:({req:t})=>{let e=t.headers.get("Authorization");if(!e?.startsWith("Bearer "))return!1;let o=e.slice(7);return $(o)!==null}});d.route("GET /v2/c/threads",()=>R({threads:[],inboxNotifications:[],subscriptions:[],meta:{nextCursor:null,requestedAt:new Date().toISOString(),permissionHints:{}}}));d.route("GET /v2/c/threads/delta",()=>R({threads:[],inboxNotifications:[],subscriptions:[],meta:{requestedAt:new Date().toISOString(),permissionHints:{}}}));d.route("GET /v2/c/inbox-notifications",()=>R({inboxNotifications:[],threads:[],subscriptions:[],groups:[],meta:{nextCursor:null,requestedAt:new Date().toISOString()}}));d.route("GET /v2/c/inbox-notifications/count",()=>R({count:0}));d.route("GET /v2/c/rooms/<roomId>/threads",()=>R({data:[],inboxNotifications:[],subscriptions:[],meta:{nextCursor:null,requestedAt:new Date().toISOString(),permissionHints:{}}}));d.route("GET /v2/c/rooms/<roomId>/threads/delta",()=>R({data:[],inboxNotifications:[],subscriptions:[],deletedThreads:[],deletedInboxNotifications:[],deletedSubscriptions:[],meta:{requestedAt:new Date().toISOString(),permissionHints:{}}}));d.route("POST /v2/c/rooms/<roomId>/text-metadata",()=>R({status:"ok"}));d.route("PUT /v2/c/rooms/<roomId>/attachments/<attachmentId>/upload/<name>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<name>",()=>r()),d.route("PUT /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<uploadId>/<partNumber>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<uploadId>/complete",()=>r()),d.route("DELETE /v2/c/rooms/<roomId>/attachments/<attachmentId>/multipart/<uploadId>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/attachments/presigned-urls",()=>r()),d.route("POST /v2/c/rooms/<roomId>/send-message",()=>r()),d.route("GET /v2/c/rooms/<roomId>/storage",()=>r()),d.route("POST /v2/c/rooms/<roomId>/version",()=>r()),d.route("GET /v2/c/rooms/<roomId>/y-version/<version>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/ai/contextual-prompt",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/search",()=>r()),d.route("DELETE /v2/c/rooms/<roomId>/threads/<threadId>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/metadata",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/mark-as-resolved",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/mark-as-unresolved",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/subscribe",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/unsubscribe",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments",()=>r()),d.route("GET /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>/metadata",()=>r()),d.route("DELETE /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>/reactions",()=>r()),d.route("DELETE /v2/c/rooms/<roomId>/threads/<threadId>/comments/<commentId>/reactions/<emoji>",()=>r()),d.route("GET /v2/c/rooms/<roomId>/threads/comments/search",()=>r()),d.route("GET /v2/c/rooms/<roomId>/threads/<threadId>/participants",()=>r()),d.route("GET /v2/c/rooms/<roomId>/notification-settings",()=>r()),d.route("GET /v2/c/rooms/<roomId>/subscription-settings",()=>r()),d.route("POST /v2/c/rooms/<roomId>/notification-settings",()=>r()),d.route("POST /v2/c/rooms/<roomId>/subscription-settings",()=>r()),d.route("GET /v2/c/inbox-notifications/delta",()=>r()),d.route("DELETE /v2/c/inbox-notifications",()=>r()),d.route("POST /v2/c/inbox-notifications/read",()=>r()),d.route("DELETE /v2/c/inbox-notifications/<inboxNotificationId>",()=>r()),d.route("POST /v2/c/rooms/<roomId>/inbox-notifications/read",()=>r()),d.route("POST /v2/c/rooms/<roomId>/text-mentions",()=>r()),d.route("DELETE /v2/c/rooms/<roomId>/text-mentions/<mentionId>",()=>r()),d.route("GET /v2/c/notification-settings",()=>r()),d.route("POST /v2/c/notification-settings",()=>r()),d.route("GET /v2/c/rooms/<roomId>/thread-with-notification/<threadId>",()=>r()),d.route("GET /v2/c/urls/metadata",()=>r()),d.route("GET /v2/c/rooms/<roomId>/versions",()=>r()),d.route("GET /v2/c/rooms/<roomId>/versions/delta",()=>r()),d.route("POST /v2/c/groups/find",()=>r());import{abort as Ce,html as gt,json as ht,ZenRouter as vt}from"@liveblocks/zenrouter";var xe=`<!doctype html>
|
|
46
|
-
<html lang="en">
|
|
47
|
-
<head>
|
|
48
|
-
<meta charset="UTF-8" />
|
|
49
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
50
|
-
<title>Liveblocks dev server</title>
|
|
51
|
-
<style>
|
|
52
|
-
* {
|
|
53
|
-
box-sizing: border-box;
|
|
54
|
-
margin: 0;
|
|
55
|
-
padding: 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
:root {
|
|
59
|
-
--bg: #f9f9f9;
|
|
60
|
-
--fg: #202020;
|
|
61
|
-
--fg-secondary: #646464;
|
|
62
|
-
--code-bg: #fcfcfc;
|
|
63
|
-
--shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.06),
|
|
64
|
-
0px 1px 2px -1px rgba(0, 0, 0, 0.06),
|
|
65
|
-
0px 2px 4px 0px rgba(0, 0, 0, 0.04);
|
|
66
|
-
--shadow-hover: 0px 0px 0px 1px rgba(0, 0, 0, 0.08),
|
|
67
|
-
0px 1px 2px -1px rgba(0, 0, 0, 0.08),
|
|
68
|
-
0px 2px 4px 0px rgba(0, 0, 0, 0.06);
|
|
69
|
-
--pill-bg: #171717;
|
|
70
|
-
--pill-fg: #e5e7eb;
|
|
71
|
-
--green: #05df72;
|
|
72
|
-
--green-glow: rgba(5, 223, 114, 0.4);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@media (prefers-color-scheme: dark) {
|
|
76
|
-
:root {
|
|
77
|
-
--bg: #111;
|
|
78
|
-
--fg: #e5e5e5;
|
|
79
|
-
--fg-secondary: #a0a0a0;
|
|
80
|
-
--code-bg: #1a1a1a;
|
|
81
|
-
--shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.08),
|
|
82
|
-
0px 1px 2px -1px rgba(0, 0, 0, 0.4),
|
|
83
|
-
0px 2px 4px 0px rgba(0, 0, 0, 0.3);
|
|
84
|
-
--shadow-hover: 0px 0px 0px 1px rgba(255, 255, 255, 0.12),
|
|
85
|
-
0px 1px 2px -1px rgba(0, 0, 0, 0.5),
|
|
86
|
-
0px 2px 4px 0px rgba(0, 0, 0, 0.4);
|
|
87
|
-
--pill-bg: #f5f5f5;
|
|
88
|
-
--pill-fg: #202020;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
body {
|
|
93
|
-
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
|
|
94
|
-
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
95
|
-
background: var(--bg);
|
|
96
|
-
color: var(--fg);
|
|
97
|
-
min-height: 100vh;
|
|
98
|
-
-webkit-font-smoothing: antialiased;
|
|
99
|
-
-moz-osx-font-smoothing: grayscale;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
main {
|
|
103
|
-
position: relative;
|
|
104
|
-
min-height: 100vh;
|
|
105
|
-
overflow: hidden;
|
|
106
|
-
padding: 2rem 1.5rem;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.logo {
|
|
110
|
-
position: absolute;
|
|
111
|
-
left: 50%;
|
|
112
|
-
top: 2rem;
|
|
113
|
-
transform: translateX(-50%);
|
|
114
|
-
animation: fade-in 0.6s ease-out both;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.logo svg {
|
|
118
|
-
height: 1.5rem;
|
|
119
|
-
width: auto;
|
|
120
|
-
color: var(--fg);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.center {
|
|
124
|
-
position: absolute;
|
|
125
|
-
inset: 0;
|
|
126
|
-
z-index: 10;
|
|
127
|
-
display: flex;
|
|
128
|
-
flex-direction: column;
|
|
129
|
-
align-items: center;
|
|
130
|
-
justify-content: center;
|
|
131
|
-
text-align: center;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
h1 {
|
|
135
|
-
margin-bottom: 0.25rem;
|
|
136
|
-
font-weight: 500;
|
|
137
|
-
font-size: 1rem;
|
|
138
|
-
animation: fade-in 0.6s ease-out 0.1s both;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.description {
|
|
142
|
-
margin-bottom: 1rem;
|
|
143
|
-
max-width: 20rem;
|
|
144
|
-
font-size: 0.875rem;
|
|
145
|
-
line-height: 1.625;
|
|
146
|
-
color: var(--fg-secondary);
|
|
147
|
-
animation: fade-in 0.6s ease-out 0.2s both;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.description code {
|
|
151
|
-
white-space: nowrap;
|
|
152
|
-
border-radius: 0.25rem;
|
|
153
|
-
background: var(--code-bg);
|
|
154
|
-
padding: 0.125rem 0.375rem;
|
|
155
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
156
|
-
monospace;
|
|
157
|
-
box-shadow: var(--shadow);
|
|
158
|
-
font-size: 0.75rem;
|
|
159
|
-
color: var(--fg);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.docs-link {
|
|
163
|
-
display: inline-flex;
|
|
164
|
-
align-items: center;
|
|
165
|
-
justify-content: center;
|
|
166
|
-
border-radius: 0.375rem;
|
|
167
|
-
font-size: 0.875rem;
|
|
168
|
-
font-weight: 500;
|
|
169
|
-
background: var(--code-bg);
|
|
170
|
-
box-shadow: var(--shadow);
|
|
171
|
-
height: 2.25rem;
|
|
172
|
-
padding: 0.5rem 1rem;
|
|
173
|
-
color: var(--fg);
|
|
174
|
-
text-decoration: none;
|
|
175
|
-
transition: box-shadow 0.15s;
|
|
176
|
-
animation: fade-in 0.6s ease-out 0.3s both;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
.docs-link:hover {
|
|
180
|
-
box-shadow: var(--shadow-hover);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.status {
|
|
184
|
-
position: absolute;
|
|
185
|
-
bottom: 2rem;
|
|
186
|
-
left: 50%;
|
|
187
|
-
transform: translateX(-50%);
|
|
188
|
-
animation: fade-in 0.6s ease-out 0.4s both;
|
|
189
|
-
display: inline-flex;
|
|
190
|
-
align-items: center;
|
|
191
|
-
gap: 0.5rem;
|
|
192
|
-
border-radius: 9999px;
|
|
193
|
-
background: var(--pill-bg);
|
|
194
|
-
color: var(--pill-fg);
|
|
195
|
-
box-shadow: var(--shadow);
|
|
196
|
-
padding: 0.5rem 0.75rem 0.5rem 0.625rem;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
.status-dot {
|
|
200
|
-
position: relative;
|
|
201
|
-
width: 0.75rem;
|
|
202
|
-
height: 0.75rem;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.status-dot .glow {
|
|
206
|
-
position: absolute;
|
|
207
|
-
inset: 0;
|
|
208
|
-
background: var(--green-glow);
|
|
209
|
-
border-radius: 9999px;
|
|
210
|
-
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
.status-dot .dot {
|
|
214
|
-
position: absolute;
|
|
215
|
-
width: 0.25rem;
|
|
216
|
-
height: 0.25rem;
|
|
217
|
-
left: 50%;
|
|
218
|
-
top: 50%;
|
|
219
|
-
transform: translate(-50%, -50%);
|
|
220
|
-
background: var(--green);
|
|
221
|
-
border-radius: 9999px;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.status-text {
|
|
225
|
-
font-size: 0.75rem;
|
|
226
|
-
font-weight: 500;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
@keyframes fade-in {
|
|
230
|
-
from {
|
|
231
|
-
opacity: 0;
|
|
232
|
-
}
|
|
233
|
-
to {
|
|
234
|
-
opacity: 1;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
@keyframes pulse {
|
|
239
|
-
50% {
|
|
240
|
-
opacity: 0.5;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
</style>
|
|
244
|
-
</head>
|
|
245
|
-
<body>
|
|
246
|
-
<main>
|
|
247
|
-
<div class="logo">
|
|
248
|
-
<svg
|
|
249
|
-
width="384"
|
|
250
|
-
height="72"
|
|
251
|
-
viewBox="0 0 128 24"
|
|
252
|
-
fill="none"
|
|
253
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
254
|
-
>
|
|
255
|
-
<path
|
|
256
|
-
fill-rule="evenodd"
|
|
257
|
-
clip-rule="evenodd"
|
|
258
|
-
d="M28.8316 3.21884H26L26.0007 19.9974H28.8316V3.21884ZM34.0855 8.01549H31.2547V19.9974H34.0855V8.01549ZM34.0855 3.08984H31.2547V6.14356H34.0855V3.08984ZM38.2401 8.01549H35.1978L39.4807 19.9974H42.6398L46.9226 8.01549H43.9269L42.1367 13.6908C42.0901 13.8384 41.9224 14.416 41.6336 15.4222L41.0602 17.3529C40.7213 16.1277 40.3665 14.9069 39.996 13.6908L38.2401 8.01549ZM58.5185 11.7601C58.2841 10.9567 57.9408 10.2737 57.4879 9.71184C56.9805 9.08118 56.3376 8.59313 55.5579 8.24984C54.7853 7.89868 53.9274 7.72381 52.9836 7.72381C51.1897 7.72381 49.7542 8.28496 48.6778 9.40798C48.1408 9.9882 47.7303 10.6737 47.4723 11.4211C47.2072 12.1929 47.0746 13.0472 47.0746 13.9832C47.0746 15.9877 47.6092 17.5364 48.6785 18.6286C49.7621 19.7359 51.2055 20.2898 53.0072 20.2898C54.5517 20.2898 55.803 19.943 56.7633 19.2485C57.723 18.5541 58.3586 17.5249 58.6704 16.1597L55.909 15.949C55.7765 16.69 55.4719 17.244 54.996 17.6102C54.5201 17.9693 53.8493 18.1492 52.9836 18.1492C51.0027 18.1492 49.9886 17.0333 49.942 14.8023H58.8575L58.8696 14.4046C58.8696 13.445 58.7521 12.5635 58.5185 11.7601ZM50.5734 10.918C51.0729 10.2157 51.8763 9.86449 52.9836 9.86449C53.5218 9.86449 53.9747 9.93831 54.341 10.0867C54.7079 10.235 55.024 10.4729 55.2891 10.8005C55.4953 11.0547 55.6539 11.3441 55.7571 11.6547C55.8734 11.9788 55.9443 12.3174 55.9678 12.6609H49.9649C50.0352 11.9665 50.238 11.3853 50.5734 10.918ZM69.8685 8.48419C69.0651 7.96103 68.137 7.70016 67.0842 7.70016H67.0827C66.3188 7.70016 65.6207 7.85568 64.9886 8.16814C64.3667 8.4713 63.8342 8.9309 63.4435 9.50186V3.21884H60.6126V19.9974H63.4442V18.3477C63.8031 18.9405 64.3115 19.4286 64.9184 19.7631C65.5505 20.1143 66.2485 20.2898 67.0125 20.2898C68.0739 20.2898 69.0135 20.0361 69.8341 19.5295C70.6525 19.0228 71.2882 18.2968 71.7404 17.3529C72.2005 16.4012 72.4313 15.2861 72.4313 14.0068C72.4313 12.7584 72.2041 11.659 71.7526 10.7073C71.3076 9.74768 70.6797 9.00664 69.8685 8.48419ZM68.663 17.1774C68.2108 17.8639 67.4389 18.2065 66.346 18.2065C65.3627 18.2065 64.6224 17.8517 64.1236 17.1422C63.6241 16.4327 63.3747 15.395 63.3747 14.0298C63.3747 12.7111 63.5968 11.682 64.0412 10.9409C64.4941 10.192 65.2545 9.81791 66.3231 9.81791C67.4153 9.81791 68.1914 10.1612 68.6516 10.847C69.1124 11.5257 69.3417 12.5792 69.3417 14.0068C69.3417 15.4337 69.116 16.4908 68.663 17.1774ZM77.0302 3.21884H74.1986V19.9974H77.0302V3.21884ZM81.6169 19.5409C82.5379 20.0404 83.6294 20.2898 84.8936 20.2898C86.1105 20.2898 87.1791 20.0283 88.0993 19.5065C89.0131 18.9985 89.7576 18.2335 90.2407 17.3064C90.7474 16.3546 91.0011 15.2545 91.0011 14.0068C91.0011 12.8057 90.7517 11.7285 90.2522 10.7775C89.7734 9.83933 89.0341 9.05921 88.1229 8.53078C87.202 7.99256 86.1256 7.72309 84.8936 7.72309C83.653 7.72309 82.5687 7.99256 81.6406 8.53078C80.7318 9.05692 79.9926 9.83235 79.5106 10.7653C79.0197 11.7092 78.7739 12.7899 78.7739 14.0068C78.7739 15.3018 79.0154 16.4206 79.4992 17.3644C79.9697 18.2867 80.7079 19.0453 81.6169 19.5409ZM87.245 17.1895C86.7691 17.8603 85.9851 18.1957 84.8936 18.1957C84.1525 18.1957 83.5556 18.0474 83.1033 17.7507C82.6504 17.4468 82.3229 16.9903 82.12 16.3819C81.9172 15.7655 81.8162 14.9736 81.8162 14.0061C81.8162 12.5556 82.0541 11.4949 82.53 10.8241C83.0137 10.1533 83.8014 9.81791 84.8936 9.81791C85.9779 9.81791 86.7577 10.1533 87.2335 10.8241C87.7173 11.4949 87.9588 12.5556 87.9588 14.0068C87.9588 15.4574 87.7209 16.518 87.245 17.1895ZM94.8626 19.5409C95.7756 20.0404 96.8635 20.2898 98.1277 20.2898C99.1103 20.2898 99.9882 20.1186 100.76 19.7753C101.533 19.432 102.16 18.9525 102.644 18.3362C103.129 17.708 103.447 16.967 103.568 16.1826L100.842 15.9024C100.655 16.6506 100.343 17.2089 99.9058 17.5751C99.4693 17.942 98.8759 18.1255 98.1277 18.1255C97.363 18.1255 96.7625 17.9693 96.3253 17.6568C95.8888 17.3372 95.5842 16.8814 95.413 16.288C95.241 15.6874 95.1557 14.927 95.1557 14.0068C95.1557 13.1017 95.241 12.3528 95.413 11.7601C95.5842 11.1595 95.8845 10.6994 96.3138 10.3791C96.751 10.0515 97.3552 9.88814 98.1277 9.88814C98.9541 9.88814 99.5668 10.1182 99.9646 10.5783C100.37 11.0305 100.659 11.6504 100.83 12.4388L103.51 11.9586C103.253 10.6793 102.671 9.65379 101.766 8.88194C100.869 8.10938 99.6564 7.72381 98.1277 7.72381C96.8793 7.72381 95.7992 7.98898 94.8862 8.51931C93.9847 9.03823 93.2562 9.81153 92.7921 10.7424C92.3083 11.6863 92.0661 12.7742 92.0661 14.0068C92.0661 15.309 92.304 16.4327 92.7799 17.3766C93.2637 18.3204 93.9581 19.0421 94.8626 19.5409ZM107.91 15.5512L109.232 14.287L112.742 19.9974H116.007L111.151 12.4732L115.855 8.01549H112.18L107.91 12.3922V3.21884H105.078V19.9974H107.91V15.5512ZM118.488 19.8569C119.284 20.1457 120.169 20.2897 121.144 20.2897C122.634 20.2897 123.862 19.993 124.83 19.4011C125.805 18.8077 126.293 17.8402 126.293 16.4986C126.293 15.6249 126.066 14.9384 125.614 14.4396C125.162 13.9322 124.623 13.5695 123.999 13.351C123.383 13.1252 122.544 12.8952 121.484 12.6608C120.867 12.5282 120.38 12.4035 120.021 12.2867C119.662 12.1692 119.373 12.0172 119.155 11.8302C118.945 11.6424 118.839 11.4009 118.839 11.1049C118.839 10.6678 119.034 10.3367 119.424 10.1102C119.814 9.88373 120.298 9.77049 120.875 9.77049C121.639 9.77049 122.236 9.95396 122.666 10.3209C123.102 10.6878 123.336 11.2375 123.367 11.9707L125.988 11.5378C125.863 10.1962 125.337 9.22511 124.408 8.62383C123.488 8.02398 122.31 7.72298 120.875 7.72298C120.032 7.72298 119.253 7.85126 118.535 8.10926C117.825 8.35866 117.252 8.75283 116.815 9.29176C116.378 9.82926 116.16 10.5079 116.16 11.3271C116.16 12.0839 116.347 12.6959 116.721 13.1639C117.102 13.6369 117.592 14.0102 118.149 14.2518C118.726 14.5019 119.451 14.7399 120.325 14.9656L121.051 15.1412C121.535 15.256 122.015 15.3887 122.49 15.5389C122.817 15.6407 123.086 15.7812 123.297 15.9603C123.508 16.1395 123.613 16.3739 123.613 16.6627C123.613 17.1694 123.402 17.5599 122.981 17.8323C122.568 18.106 121.963 18.2422 121.168 18.2422C120.356 18.2422 119.709 18.0394 119.225 17.6338C118.742 17.2281 118.496 16.6433 118.488 15.8786L115.821 16.1825C115.851 17.1034 116.105 17.8717 116.581 18.488C117.065 19.1044 117.7 19.5602 118.488 19.8569Z"
|
|
259
|
-
fill="currentColor"
|
|
260
|
-
></path>
|
|
261
|
-
<path
|
|
262
|
-
fill-rule="evenodd"
|
|
263
|
-
clip-rule="evenodd"
|
|
264
|
-
d="M13.5 9H0L4 13V18.5L13.5 9Z"
|
|
265
|
-
fill="currentColor"
|
|
266
|
-
></path>
|
|
267
|
-
<path
|
|
268
|
-
fill-rule="evenodd"
|
|
269
|
-
clip-rule="evenodd"
|
|
270
|
-
d="M6.5 20H20L16 16V10.5L6.5 20Z"
|
|
271
|
-
fill="currentColor"
|
|
272
|
-
></path>
|
|
273
|
-
</svg>
|
|
274
|
-
</div>
|
|
275
|
-
|
|
276
|
-
<div class="center">
|
|
277
|
-
<h1>You're all set</h1>
|
|
278
|
-
<p class="description">
|
|
279
|
-
This is the Liveblocks dev server. Point your app to
|
|
280
|
-
<code>http://localhost:1153</code> and start building. This page is
|
|
281
|
-
not meant to be used directly.
|
|
282
|
-
</p>
|
|
283
|
-
<a
|
|
284
|
-
href="https://liveblocks.io/docs/tools/devserver?from=__VERSION__"
|
|
285
|
-
target="_blank"
|
|
286
|
-
rel="noopener noreferrer"
|
|
287
|
-
class="docs-link"
|
|
288
|
-
>Read the docs</a
|
|
289
|
-
>
|
|
290
|
-
</div>
|
|
291
|
-
|
|
292
|
-
<div class="status">
|
|
293
|
-
<span class="status-dot">
|
|
294
|
-
<span class="glow" aria-hidden="true"></span>
|
|
295
|
-
<span class="dot" aria-hidden="true"></span>
|
|
296
|
-
</span>
|
|
297
|
-
<span class="status-text">Dev server is running</span>
|
|
298
|
-
</div>
|
|
299
|
-
</main>
|
|
300
|
-
</body>
|
|
301
|
-
</html>
|
|
302
|
-
`;var P=new vt({authorize:()=>!0});P.route("GET /v7",()=>Ce(426));P.route("GET /v8",()=>Ce(426));P.route("GET /health",()=>ht({status:"ok"}));P.route("GET /",()=>gt(xe.replace("__VERSION__","1.0.5")));import{jsonObjectYolo as bt,ROOT_YDOC_ID as K,snapshotToLossyJson_eager as Et,snapshotToPlainLson_eager as Re}from"@liveblocks/server";import{json as St,ZenRouter as xt}from"@liveblocks/zenrouter";import{constant as Ct,enum_ as Ot,object as _e,string as wt}from"decoders";import{Base64 as Rt}from"js-base64";import*as F from"yjs";import*as T from"yjs";function It(t){return t.content instanceof T.ContentFormat||t.content instanceof T.ContentEmbed?"text":"arr"in t.content?"array":"str"in t.content?"text":"type"in t.content?"xml":"unknown"}function Tt(t){let e=[],o=t;for(;o!==null;){if(!o.deleted)if(o.content instanceof T.ContentType)e.push(o.content.type.toJSON());else if(o.content instanceof T.ContentString)e.push(o.content.str);else if(o.content instanceof T.ContentFormat){let{key:s,value:n}=o.content;e.push({key:s,value:n})}else o.content instanceof T.ContentEmbed&&e.push(o.content.embed);o=o.right}return e}function Oe(t,e,o,s=!1){if(!e._first&&e._map instanceof Map&&e._map.size>0)return t.getMap(o).toJSON();if(e._first!==null){let n=It(e._first);if(n==="text")return s?Tt(e._first):t.getText(o).toJSON();if(n==="array")return t.getArray(o).toJSON();if(n==="xml")return t.getXmlFragment(o).toJSON()}return e.toJSON()}var yt={ytext:T.Text,yxmlfragment:T.XmlFragment,yxmltext:T.XmlText,ymap:T.Map,yarray:T.Array};function we(t,e="",o=!1,s=""){let n={};if(e.length){if(t.share.has(e)){if(s.length){let a=yt[s];if(a)return t.get(e,a).toJSON()}return{[e]:Oe(t,t.share.get(e),e,o)}}return{[e]:""}}for(let[a,u]of t.share)n[a]=Oe(t,u,a,o);return n}var Le=(o=>(o.PlainLson="plain-lson",o.LossyJson="json",o))(Le||{}),_t=Ot(Le),i=new xt({authorize:({req:t})=>z(t)});function D(t){return St({error:"ROOM_NOT_FOUND",message:`Room with id "${t}" not found.`},404)}i.route("GET /v2/rooms/<roomId>",async({p:t})=>{if(!await C(t.roomId))throw D(t.roomId);return{type:"room",id:t.roomId,createdAt:new Date().toISOString(),metadata:{},defaultAccesses:["room:write"],groupsAccesses:{},usersAccesses:{}}});i.route("GET /v2/rooms",()=>{let e=le().map(o=>({type:"room",id:o,createdAt:new Date().toISOString(),metadata:{},defaultAccesses:["room:write"],groupsAccesses:{},usersAccesses:{}}));return U({data:e,nextPage:null,nextCursor:null},200,"The Liveblocks dev server doesn't implement room permissions or pagination yet, so all rooms are returned in a single page with nextPage set to null.","GET /v2/rooms")});i.route("POST /v2/rooms",_e({id:wt}),async({body:t})=>{if(await C(t.id))return new Response(JSON.stringify({error:"ROOM_ALREADY_EXISTS",message:`Room with id "${t.id}" already exists.`}),{status:409,headers:{"Content-Type":"application/json"}});try{await me(t.id)}catch(o){if(o instanceof Error&&o.message.includes("already exists"))return new Response(JSON.stringify({error:"ROOM_ALREADY_EXISTS",message:`Room with id "${t.id}" already exists.`}),{status:409,headers:{"Content-Type":"application/json"}});throw o}return{type:"room",id:t.id,createdAt:new Date().toISOString(),metadata:{},defaultAccesses:["room:write"],groupsAccesses:{},usersAccesses:{}}});i.route("POST /v2/rooms/<roomId>",()=>r());i.route("GET /v2/rooms/<roomId>/storage",async({url:t,p:e})=>{if(!await C(e.roomId))throw D(e.roomId);let s=_t.value(t.searchParams.get("format"))??"plain-lson",n=w(e.roomId);await n.load();let a=n.storage.loadedDriver.get_snapshot(!1),u=s==="json"?Et(a):Re(a);return new Response(JSON.stringify(u),{status:200,headers:{"Content-Type":"application/json"}})});i.route("POST /v2/rooms/<roomId>/storage",_e({liveblocksType:Ct("LiveObject"),data:bt}).refineType(),async({p:t,body:e})=>{if(!await C(t.roomId))throw D(t.roomId);let s=w(t.roomId);await s.load();let n=s.storage.loadedDriver.get_snapshot(!1),a=Re(n);return Object.keys(a.data).length>0?new Response(JSON.stringify({error:"CANNOT_UPDATE_EXISTING_STORAGE",message:"The room already has storage data. It's only possible to initialize the storage for an empty room.",suggestion:"Create another room or clear this room storage first."}),{status:409,headers:{"Content-Type":"application/json"}}):(await s.driver.DANGEROUSLY_reset_nodes(e),s.unload(),new Response(JSON.stringify(e),{status:200,headers:{"Content-Type":"application/json"}}))});i.route("GET /v2/rooms/<roomId>/ydoc",async({url:t,p:e})=>{if(!await C(e.roomId))throw D(e.roomId);let s=w(e.roomId);await s.load();let n=t.searchParams.get("key")??"",a=t.searchParams.get("type")??"",u=t.searchParams.get("guid")??K,c=t.searchParams.get("formatting")!==null,h=await s.yjsStorage.getYDoc(u),p=we(h,n,c,a);return new Response(JSON.stringify(p),{status:200,headers:{"Content-Type":"application/json"}})});i.route("PUT /v2/rooms/<roomId>/ydoc",async({req:t,url:e,p:o})=>{if(t.headers.get("content-type")!=="application/octet-stream")return new Response(JSON.stringify({error:"BAD_REQUEST",message:'Expected "Content-Type" header to be "application/octet-stream", and the HTTP body to be a valid binary Yjs update.'}),{status:400,headers:{"Content-Type":"application/json"}});if(!await C(o.roomId))throw D(o.roomId);let n=w(o.roomId);await n.load();let a=await t.arrayBuffer(),u=Rt.fromUint8Array(new Uint8Array(a)),c=e.searchParams.get("guid"),p=e.searchParams.get("encoder")==="v2",f=c&&c!==K?c:void 0;try{return await n.mutex.runExclusive(()=>n.yjsStorage.addYDocUpdate({},u,f,p)),new Response(JSON.stringify({success:!0}),{status:200,headers:{"Content-Type":"application/json"}})}catch(I){return new Response(JSON.stringify({error:"UNPROCESSABLE_ENTITY",message:I instanceof Error?I.message:"Could not apply update",suggestion:"Please ensure the update is correct, and you selected the correct encoder to use (v1 or v2)."}),{status:422,headers:{"Content-Type":"application/json"}})}});i.route("GET /v2/rooms/<roomId>/ydoc-binary",async({url:t,p:e})=>{if(!await C(e.roomId))throw D(e.roomId);let s=w(e.roomId);await s.load();let n=t.searchParams.get("guid")??K,a=t.searchParams.get("encoder"),u=await s.yjsStorage.getYDoc(n),c=a==="v2"?F.encodeStateAsUpdateV2(u):F.encodeStateAsUpdate(u);return new Response(c,{status:200,headers:{"Content-Type":"application/octet-stream"}})});i.route("DELETE /v2/rooms/<roomId>/storage",()=>r()),i.route("GET /v2/rooms/<roomId>/threads",()=>r()),i.route("POST /v2/rooms/<roomId>/upsert",()=>r()),i.route("DELETE /v2/rooms/<roomId>",()=>r()),i.route("POST /v2/rooms/<roomId>/update-room-id",()=>r()),i.route("POST /v2/rooms/<roomId>/update-tenant-id",()=>r()),i.route("POST /v2/rooms/<roomId>/update-organization-id",()=>r()),i.route("GET /v2/rooms/<roomId>/prewarm",()=>r()),i.route("POST /v2/rooms/<roomId>/request-storage-mutation",()=>r()),i.route("GET /v2/rooms/<roomId>/rippling/text-editor",()=>r()),i.route("POST /v2/rooms/<roomId>/rippling/text-editor",()=>r()),i.route("GET /v2/rooms/<roomId>/active_users",()=>r()),i.route("POST /v2/rooms/<roomId>/send-message",()=>r()),i.route("POST /v2/rooms/<roomId>/broadcast_event",()=>r()),i.route("GET /v2/rooms/<roomId>/versions",()=>r()),i.route("GET /v2/rooms/<roomId>/version/<version>",()=>r()),i.route("POST /v2/rooms/<roomId>/version",()=>r()),i.route("POST /v2/rooms/<roomId>/threads",()=>r()),i.route("GET /v2/rooms/<roomId>/threads/<threadId>",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/mark-as-resolved",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/mark-as-unresolved",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/subscribe",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/unsubscribe",()=>r()),i.route("GET /v2/rooms/<roomId>/threads/<threadId>/subscriptions",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/metadata",()=>r()),i.route("DELETE /v2/rooms/<roomId>/threads/<threadId>",()=>r()),i.route("GET /v2/rooms/<roomId>/threads/<threadId>/participants",()=>r()),i.route("GET /v2/rooms/<roomId>/threads/<threadId>/inbox-notifications",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments",()=>r()),i.route("GET /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>/metadata",()=>r()),i.route("DELETE /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>/add-reaction",()=>r()),i.route("POST /v2/rooms/<roomId>/threads/<threadId>/comments/<commentId>/remove-reaction",()=>r()),i.route("GET /v2/rooms/<roomId>/users/<userId>/notification-settings",()=>r()),i.route("GET /v2/rooms/<roomId>/users/<userId>/subscription-settings",()=>r()),i.route("POST /v2/rooms/<roomId>/users/<userId>/notification-settings",()=>r()),i.route("POST /v2/rooms/<roomId>/users/<userId>/subscription-settings",()=>r()),i.route("DELETE /v2/rooms/<roomId>/users/<userId>/notification-settings",()=>r()),i.route("DELETE /v2/rooms/<roomId>/users/<userId>/subscription-settings",()=>r()),i.route("GET /v2/users/<userId>/inbox-notifications/<inboxNotificationId>",()=>r()),i.route("DELETE /v2/users/<userId>/inbox-notifications/<inboxNotificationId>",()=>r()),i.route("GET /v2/users/<userId>/inbox-notifications",()=>r()),i.route("DELETE /v2/users/<userId>/inbox-notifications",()=>r()),i.route("GET /v2/users/<userId>/notification-settings",()=>r()),i.route("POST /v2/users/<userId>/notification-settings",()=>r()),i.route("DELETE /v2/users/<userId>/notification-settings",()=>r()),i.route("GET /v2/users/<userId>/room-subscription-settings",()=>r()),i.route("GET /v2/users/<userId>/threads",()=>r()),i.route("POST /v2/inbox-notifications/trigger",()=>r()),i.route("POST /v2/inbox-notifications/<inboxNotificationId>/read",()=>r()),i.route("GET /v2/threads",()=>r()),i.route("POST /v2/groups",()=>r()),i.route("GET /v2/groups/<groupId>",()=>r()),i.route("POST /v2/groups/<groupId>/add-members",()=>r()),i.route("POST /v2/groups/<groupId>/remove-members",()=>r()),i.route("DELETE /v2/groups/<groupId>",()=>r()),i.route("GET /v2/groups",()=>r()),i.route("GET /v2/users/<userId>/groups",()=>r());function Dt(t,e,o,s){if(!t.upgrade(e,{data:{refuseConnection:{code:o,message:s}}}))return new Response("Could not upgrade to WebSocket",{status:426})}var A=new kt;A.relay("/v2/authorize-user/*",J);A.relay("/v2/identify-user/*",J);A.relay("/v2/c/*",d);A.relay("/v2/*",i);A.relay("/*",P);var Ne=1153;function At(t){if(t===void 0)return;let e=Number(t);return Number.isInteger(e)&&e>0&&e<=65535?e:void 0}var Mt={description:"Start the local Liveblocks dev server",async run(t){let e=Lt(t,{string:["port","host"],boolean:["help"],alias:{h:"help",p:"port"}});if(e.help){console.log("Usage: liveblocks dev [options]"),console.log(),console.log("Start the local Liveblocks dev server"),console.log(),console.log("Options:"),console.log(` -p, --port Port to listen on (default: ${Ne})`),console.log(" --host Host to bind to (default: localhost)"),console.log(" -h, --help Show this help message");return}let o=At(e.port)??Ne,s=e.host||"localhost";await Ie(o,s)&&(console.error(`Port ${o} is already in use.
|
|
303
|
-
Is another dev server already running?`),process.exit(1));let n=Pt.serve({hostname:s,port:o,async fetch(c,h){if(c.headers.get("Upgrade")==="websocket"){let l=oe(c);if(!l.ok)return W(l.xwarn),Dt(h,c,Nt.NOT_ALLOWED,"You have no access to this room");let{roomId:g,ticketData:v}=l,y=w(g);await y.load();let S=await y.createTicket(v),_=S.sessionKey;if(h.upgrade(c,{data:{room:y,ticket:S,sessionKey:_}})){console.log(`${L("101")} WS ${new URL(c.url).pathname}`);return}return new Response("Could not upgrade to WebSocket",{status:426})}let p=new URL(c.url),f=`${c.method} ${p.pathname}`,I=await A.fetch(c),E=I.status,G=E>=500?q(String(E)):E>=400?k(String(E)):L(String(E));console.log(`${G} ${f}`);let X=I.headers.get("X-LB-Warn")??void 0,m=I.headers.get("X-LB-Warn-Key")??void 0;return W(X,m),I},error(c){return console.error(c),new Response("An unknown error occurred",{status:500})},websocket:{async open(c){let{refuseConnection:h,room:p,ticket:f}=c.data;if(h){c.close(h.code,h.message);return}p&&f&&await p.startBrowserSession(f,c)},async message(c,h){let{room:p,sessionKey:f}=c.data;p&&f&&await p.handleData(f,h)},close(c,h,p){let{room:f,sessionKey:I}=c.data;f&&I&&f.endBrowserSession(I,h,p)}}});console.log(`Liveblocks dev server running at http://${n.hostname}:${n.port}`);let a=await ge(o),u=`http://localhost:${o}`;console.log(O("Press q to quit, c to clear")),process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.on("data",c=>{let h=c.toString();if(h==="q"||h==="")n.stop().then(()=>process.exit(0));else if(h==="c")console.clear(),Te();else if(h==="p")if(a.length>0){let p=he(a,u);ve(p),console.log(O("Copied AI fix prompt to clipboard"))}else console.log(O("No setup issues detected"))}))}},tr=Mt;export{tr as default};
|