Compare commits

...

76 Commits

Author SHA1 Message Date
Anselm Eickhoff
e4fcafd576 Merge pull request #857 from garden-co/changeset-release/main
Version Packages
2024-11-22 15:46:42 +00:00
github-actions[bot]
a9cff03bcb Version Packages 2024-11-22 15:35:56 +00:00
Anselm Eickhoff
26324d4b1e Merge pull request #853 from garden-co/fix/improve-peers-close
fix: clean the queues on peers close
2024-11-22 15:32:43 +00:00
Anselm Eickhoff
bd022ffd5e Merge pull request #854 from garden-co/fix/offline-support-and-faster-load
fix: restore offline support and faster load when storage is active
2024-11-22 15:32:31 +00:00
Guido D'Orsi
dcc9c2e376 chore: changeset 2024-11-22 15:53:14 +01:00
Guido D'Orsi
48edcaff37 fix: clean the queues on peers close 2024-11-22 15:49:42 +01:00
Guido D'Orsi
7780346208 fix(jazz-browser): fix unitialized variable when loading offline 2024-11-22 15:36:02 +01:00
Guido D'Orsi
699553fe9f chore: changeset 2024-11-22 10:11:30 +01:00
Guido D'Orsi
bdd5ad7eb1 fix: restore offline support and faster load when storage is active 2024-11-22 10:09:56 +01:00
Guido D'Orsi
a6942030d4 Merge pull request #848 from garden-co/benjamin-jazz-528
Chore: Bump turbo to v2
2024-11-21 18:21:05 +01:00
Benjamin S. Leveritt
905c6b312b Chore: Bump turbo to v2 2024-11-21 17:00:10 +00:00
Trisha Lim
fc845cc930 Fix url for sharing in chat demo 2024-11-20 21:39:26 +00:00
Trisha Lim
0e6ea3f762 Fix chat demo opens 2 different chat rooms 2024-11-20 21:20:09 +00:00
Anselm Eickhoff
f0060e0355 Merge pull request #836 from garden-co/changeset-release/main
Version Packages
2024-11-20 18:42:06 +00:00
github-actions[bot]
9e9788395c Version Packages 2024-11-20 18:41:39 +00:00
Anselm Eickhoff
6371c7689f Merge pull request #835 from garden-co/covalue-state-fix
Send empty known state on all states except available
2024-11-20 18:40:16 +00:00
Anselm
605734c71c Add changeset 2024-11-20 18:39:40 +00:00
Anselm
db5227b463 Send empty known state on all states except available 2024-11-20 18:39:28 +00:00
Anselm Eickhoff
7ed748a0f6 Merge pull request #828 from garden-co/changeset-release/main
Version Packages
2024-11-20 15:55:22 +00:00
github-actions[bot]
8492dd9501 Version Packages 2024-11-20 15:54:55 +00:00
Anselm Eickhoff
b957085e02 Merge pull request #827 from garden-co/gudorsi-jazz-519
fix(coValueState): once a coValue is loaded send the known state to the rest of the peers
2024-11-20 15:53:43 +00:00
Guido D'Orsi
75fdff431a chore: changeset 2024-11-20 16:40:17 +01:00
Guido D'Orsi
a5559529ae fix(coValueState): once a coValue is loaded send the known state to the rest of the peers 2024-11-20 16:39:16 +01:00
Anselm Eickhoff
2c74fdaa71 Merge pull request #824 from garden-co/changeset-release/main
Version Packages
2024-11-20 15:03:53 +00:00
github-actions[bot]
2b16a97f7a Version Packages 2024-11-20 14:10:12 +00:00
Anselm Eickhoff
e5f135b82a Merge pull request #748 from garden-co/trishalim-jazz-193
Show two chat demos side by side
2024-11-20 14:09:00 +00:00
Anselm Eickhoff
0fa0cb2338 Merge pull request #822 from garden-co/changeset-release/main
Version Packages
2024-11-20 14:01:40 +00:00
github-actions[bot]
7e7b6b981a Version Packages 2024-11-20 13:59:34 +00:00
Anselm Eickhoff
f762afd361 Merge pull request #821 from garden-co/fix-sqlite-new-piece
fix(sqlite): reference piece.new instead of piece
2024-11-20 13:58:27 +00:00
pax-k
63d46c985c chore: changeset 2024-11-20 15:57:43 +02:00
pax-k
e5b89e2f96 fix(sqlite): reference piece.new instead of piece 2024-11-20 15:52:45 +02:00
Trisha Lim
eae724a9f3 Build fix 2024-11-20 12:48:59 +00:00
Trisha Lim
b14eb2106a Add chat url with copy button 2024-11-20 12:33:37 +00:00
Trisha Lim
379e56efe9 Fix missing key 2024-11-20 12:33:19 +00:00
Trisha Lim
caf682fecd Move testimonial out of chat demo section 2024-11-20 12:33:19 +00:00
Anselm
2f6d3ac8e6 Better approach to hide logout button in demo 2024-11-20 12:33:19 +00:00
Trisha Lim
ed80b52ad3 Cover log out button with a div 2024-11-20 12:33:19 +00:00
Trisha Lim
a64690e5f3 dont hide logout 2024-11-20 12:33:19 +00:00
Trisha Lim
3bcacecbad Revert "return username to DemoAuthState"
This reverts commit 71a49763b0c4ad4209ce224822d31960fbbaa8df.
2024-11-20 12:33:19 +00:00
Trisha Lim
01e3e8a954 Revert "DemoAuth: logout if logged in user doesnt match user param"
This reverts commit 3966d58197557aa3834da7caafb6e63cf792e078.
2024-11-20 12:33:19 +00:00
Trisha Lim
9adcfc2cd9 DemoAuth: logout if logged in user doesnt match user param 2024-11-20 12:33:19 +00:00
Trisha Lim
738bf3a1bb return username to DemoAuthState 2024-11-20 12:33:19 +00:00
Trisha Lim
59d37df8a2 add changeset 2024-11-20 12:33:19 +00:00
Trisha Lim
8b63994048 hide demo-specific logic in chat example 2024-11-20 12:33:18 +00:00
Trisha Lim
f1a7478331 increase font size in chat app 2024-11-20 12:33:18 +00:00
Trisha Lim
a713d4ad51 Move retrieving of user from url into DemoAuthBasicUI 2024-11-20 12:33:18 +00:00
Trisha Lim
f33aa5c28a Hide log out button 2024-11-20 12:33:18 +00:00
Trisha Lim
2ec7e5f287 Set different color on message bubble for sender 2024-11-20 12:33:18 +00:00
Trisha Lim
e7d96c9c76 Name chat users Alice and Bob 2024-11-20 12:33:18 +00:00
Trisha Lim
c1e49fe727 Remove renderCodeSamples.mjs 2024-11-20 12:33:18 +00:00
Trisha Lim
812b13ecbd Clean up 2024-11-20 12:33:18 +00:00
Trisha Lim
0e6eb7a592 Rename component 2024-11-20 12:33:18 +00:00
Trisha Lim
9f8506fe76 Styling for chat demo section 2024-11-20 12:33:18 +00:00
Guido D'Orsi
f62f227e14 fix: remove async 2024-11-20 12:33:18 +00:00
Guido D'Orsi
3e17c0e221 fix: improve chat loading 2024-11-20 12:33:18 +00:00
Trisha Lim
1af61c8895 add logs 2024-11-20 12:33:18 +00:00
Trisha Lim
0c781d28f7 fix window is undefined 2024-11-20 12:33:18 +00:00
Trisha Lim
a93db84530 rename component 2024-11-20 12:33:18 +00:00
Guido D'Orsi
b529ae3c55 fix: hack a solution for the chat rooms sync 2024-11-20 12:33:18 +00:00
Trisha Lim
a6780401b5 pass user 2024-11-20 12:33:18 +00:00
Trisha Lim
b7ef6db1f6 simplify 2024-11-20 12:33:18 +00:00
Trisha Lim
9d089ab94f remove listener 2024-11-20 12:33:18 +00:00
Anselm Eickhoff
3b7a5c0e9d Merge pull request #820 from garden-co/changeset-release/main
Version Packages
2024-11-20 12:28:37 +00:00
github-actions[bot]
7dc2a2828e Version Packages 2024-11-20 12:15:10 +00:00
Anselm Eickhoff
ea93cacd45 Merge pull request #819 from garden-co/fuzzyobject-jazz-501
fix: 'ErrorLoadingCoValueCore',  IndexedDB peer doesn't deliver dependencies
2024-11-20 12:13:48 +00:00
Anselm Eickhoff
162da453ca Update .changeset/cool-readers-share.md 2024-11-20 12:13:35 +00:00
Marina Orlova
e17e959307 Add changeset 2024-11-20 13:08:39 +01:00
Marina Orlova
0d43b2edbc Fix Error - 'ErrorLoadingCoValueCore' 2024-11-20 12:44:19 +01:00
pax-k
9b220b17de fix(docs): updated docs for SchemaUnion 2024-11-20 13:43:10 +02:00
Anselm Eickhoff
d4a1aab5d5 Merge pull request #797 from garden-co/benjamin-jazz-503
Add minimal PasskeyAuth example
2024-11-20 11:28:50 +00:00
Benjamin S. Leveritt
32b258a966 Remove MinimalAccount for ultra-minimalism 2024-11-20 11:19:08 +00:00
Benjamin S. Leveritt
6846f74bc5 Chore: Update pnpm lock 2024-11-20 11:11:19 +00:00
Benjamin S. Leveritt
5fc3e7b700 Add biome formatter 2024-11-20 11:08:42 +00:00
Benjamin S. Leveritt
6a799b0d65 Update readme 2024-11-20 11:08:42 +00:00
Benjamin S. Leveritt
0a88aeb5a9 Finish really minimal example 2024-11-20 11:08:42 +00:00
Benjamin S. Leveritt
28ae36391b Add new minimal passkey auth example 2024-11-20 11:08:42 +00:00
111 changed files with 2289 additions and 491 deletions

View File

@@ -1,5 +1,46 @@
# @jazz-e2e/binarycostream
## 0.0.106
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.105
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.104
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.103
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.102
### Patch Changes
- jazz-react@0.8.24
## 0.0.101
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "@jazz-e2e/filestream",
"private": true,
"version": "0.0.101",
"version": "0.0.106",
"type": "module",
"scripts": {
"dev": "vite",
@@ -13,11 +13,11 @@
"test:ui": "playwright test --ui"
},
"dependencies": {
"cojson": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"hash-slash": "workspace:0.2.1",
"is-ci": "^3.0.1",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},

View File

@@ -1,5 +1,46 @@
# @jazz-e2e/covalues
## 0.0.105
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.104
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.103
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.102
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.101
### Patch Changes
- jazz-react@0.8.24
## 0.0.100
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "@jazz-e2e/covalues",
"private": true,
"version": "0.0.100",
"version": "0.0.105",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,43 @@
# jazz-example-book-shelf
## 0.1.21
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
- jazz-browser-media-images@0.8.29
## 0.1.20
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
- jazz-browser-media-images@0.8.28
## 0.1.19
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
- jazz-browser-media-images@0.8.27
## 0.1.18
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.1.17
### Patch Changes
- jazz-browser-media-images@0.8.24
- jazz-react@0.8.24
## 0.1.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-example-book-shelf",
"version": "0.1.16",
"version": "0.1.21",
"private": true,
"scripts": {
"dev": "next dev",
@@ -11,9 +11,9 @@
},
"dependencies": {
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.8.23",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-browser-media-images": "workspace:0.8.29",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"next": "14.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0"

View File

@@ -1,5 +1,51 @@
# jazz-example-chat
## 0.0.105
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-react@0.8.29
- jazz-react-auth-clerk@0.8.29
- jazz-tools@0.8.29
## 0.0.104
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-react@0.8.28
- jazz-react-auth-clerk@0.8.28
- jazz-tools@0.8.28
## 0.0.103
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-react@0.8.27
- jazz-react-auth-clerk@0.8.27
- jazz-tools@0.8.27
## 0.0.102
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
- jazz-react-auth-clerk@0.8.26
## 0.0.101
### Patch Changes
- jazz-react@0.8.24
- jazz-react-auth-clerk@0.8.24
## 0.0.100
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat-clerk",
"private": true,
"version": "0.0.100",
"version": "0.0.105",
"type": "module",
"scripts": {
"dev": "vite",
@@ -17,11 +17,11 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"hash-slash": "workspace:0.2.1",
"jazz-react": "workspace:0.8.23",
"jazz-react-auth-clerk": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-react": "workspace:0.8.29",
"jazz-react-auth-clerk": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",

View File

@@ -1,5 +1,44 @@
# chat-rn-clerk
## 1.0.21
### Patch Changes
- jazz-react-native@0.8.29
- jazz-react-auth-clerk@0.8.29
- jazz-tools@0.8.29
- jazz-react-native-media-images@0.8.21
## 1.0.20
### Patch Changes
- jazz-react-auth-clerk@0.8.28
- jazz-react-native@0.8.28
- jazz-tools@0.8.28
- jazz-react-native-media-images@0.8.20
## 1.0.19
### Patch Changes
- jazz-react-auth-clerk@0.8.27
- jazz-react-native@0.8.27
- jazz-tools@0.8.27
- jazz-react-native-media-images@0.8.19
## 1.0.18
### Patch Changes
- jazz-react-auth-clerk@0.8.26
## 1.0.17
### Patch Changes
- jazz-react-auth-clerk@0.8.24
## 1.0.16
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-clerk",
"main": "index.js",
"version": "1.0.16",
"version": "1.0.21",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",

View File

@@ -1,5 +1,26 @@
# chat-rn
## 1.0.20
### Patch Changes
- jazz-react-native@0.8.29
- jazz-tools@0.8.29
## 1.0.19
### Patch Changes
- jazz-react-native@0.8.28
- jazz-tools@0.8.28
## 1.0.18
### Patch Changes
- jazz-react-native@0.8.27
- jazz-tools@0.8.27
## 1.0.17
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.17",
"version": "1.0.20",
"main": "index.js",
"scripts": {
"build": "expo export -p ios",

View File

@@ -1,5 +1,36 @@
# chat-vue
## 0.0.12
### Patch Changes
- jazz-browser@0.8.29
- jazz-tools@0.8.29
- jazz-vue@0.8.17
## 0.0.11
### Patch Changes
- jazz-browser@0.8.28
- jazz-tools@0.8.28
- jazz-vue@0.8.16
## 0.0.10
### Patch Changes
- jazz-browser@0.8.27
- jazz-tools@0.8.27
- jazz-vue@0.8.15
## 0.0.9
### Patch Changes
- jazz-browser@0.8.24
- jazz-vue@0.8.14
## 0.0.8
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-vue",
"version": "0.0.8",
"version": "0.0.12",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,47 @@
# jazz-example-chat
## 0.0.107
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.106
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.105
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.104
### Patch Changes
- 59d37df: add autologin option to DemoAuth to skip login
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.103
### Patch Changes
- jazz-react@0.8.24
## 0.0.102
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.102",
"version": "0.0.107",
"type": "module",
"scripts": {
"dev": "vite",
@@ -18,10 +18,10 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"hash-slash": "workspace:0.2.1",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",

View File

@@ -1,3 +1,4 @@
import { inIframe, onChatLoad } from "@/util.ts";
import { useIframeHashRouter } from "hash-slash";
import { Group, ID } from "jazz-tools";
import { ChatScreen } from "./chatScreen.tsx";
@@ -15,12 +16,16 @@ export function App() {
group.addMember("everyone", "writer");
const chat = Chat.create([], { owner: group });
router.navigate("/#/chat/" + chat.id);
// for https://jazz.tools marketing site demo only
onChatLoad(chat, me);
};
return (
<AppContainer>
<TopBar>
<p>{me?.profile?.name}</p> · <button onClick={logOut}>Log out</button>
<p>{me?.profile?.name}</p>
{!inIframe && <button onClick={logOut}>Log out</button>}
</TopBar>
{router.route({
"/": () => createChat() as never,

View File

@@ -48,10 +48,11 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
function ChatBubble(props: { msg: Message }) {
const lastEdit = props.msg._edits.text;
const fromMe = lastEdit.by?.isMe;
return (
<BubbleContainer fromMe={lastEdit.by?.isMe}>
<BubbleBody>{props.msg.text}</BubbleBody>
<BubbleContainer fromMe={fromMe}>
<BubbleBody fromMe={fromMe}>{props.msg.text}</BubbleBody>
<BubbleInfo by={lastEdit.by?.profile?.name} madeAt={lastEdit.madeAt} />
</BubbleContainer>
);

View File

@@ -1,3 +1,4 @@
import clsx from "clsx";
import { useId } from "react";
export function AppContainer(props: { children: React.ReactNode }) {
@@ -10,7 +11,7 @@ export function AppContainer(props: { children: React.ReactNode }) {
export function TopBar(props: { children: React.ReactNode }) {
return (
<div className="p-3 bg-white w-full flex justify-end gap-1 text-xs border-b dark:bg-transparent dark:border-stone-800">
<div className="p-3 bg-white w-full flex justify-between gap-2 border-b dark:bg-transparent dark:border-stone-800">
{props.children}
</div>
);
@@ -29,7 +30,7 @@ export function ChatBody(props: { children: React.ReactNode }) {
export function EmptyChatMessage() {
return (
<div className="h-full text-base text-stone-500 flex items-center justify-center px-3 md:text-xl">
<div className="h-full text-base text-stone-500 flex items-center justify-center px-3 text-lg md:text-2xl">
Start a conversation below.
</div>
);
@@ -41,15 +42,26 @@ export function BubbleContainer(props: {
}) {
const align = props.fromMe ? "items-end" : "items-start";
return (
<div className={`${align} flex flex-col m-2`} role="row">
<div className={`${align} flex flex-col m-3`} role="row">
{props.children}
</div>
);
}
export function BubbleBody(props: { children: React.ReactNode }) {
export function BubbleBody(props: {
children: React.ReactNode;
fromMe: boolean | undefined;
}) {
return (
<div className="rounded-2xl text-sm line-clamp-10 text-ellipsis bg-white max-w-full whitespace-pre-wrap dark:bg-stone-700 dark:text-white py-1 px-3 shadow-sm">
<div
className={clsx(
"line-clamp-10 text-ellipsis whitespace-pre-wrap",
"rounded-2xl max-w-full py-1 px-3 shadow-sm",
props.fromMe
? "bg-white dark:bg-stone-700 dark:text-white"
: "bg-blue text-white",
)}
>
{props.children}
</div>
);
@@ -73,7 +85,7 @@ export function ChatInput(props: { onSubmit: (text: string) => void }) {
</label>
<input
id={inputId}
className="rounded-full py-2 px-4 text-sm border block w-full dark:bg-black dark:text-white dark:border-stone-700"
className="rounded-full py-2 px-4 border block w-full dark:bg-black dark:text-white dark:border-stone-700"
placeholder="Type a message and press Enter"
maxLength={2048}
onKeyDown={({ key, currentTarget: input }) => {

27
examples/chat/src/util.ts Normal file
View File

@@ -0,0 +1,27 @@
// This is only for demo purposes for https://jazz.tools
// This is NOT needed to make the chat work
import { Chat } from "@/schema.ts";
import { Account, CoValue, ID } from "jazz-tools";
export function waitForUpload(id: ID<CoValue>, me: Account) {
const syncManager = me._raw.core.node.syncManager;
const peers = syncManager.getPeers();
return Promise.all(
peers.map((peer) => syncManager.waitForUploadIntoPeer(peer.id, id)),
);
}
export function onChatLoad(chat: Chat, me: Account) {
if (window.parent) {
waitForUpload(chat.id, me).then(() => {
window.parent.postMessage(
{ type: "chat-load", id: "/chat/" + chat.id },
"*",
);
});
}
}
export const inIframe = window.self !== window.top;

View File

@@ -16,6 +16,10 @@ module.exports = {
},
extend: {
colors: {
blue: {
700: "#3313F7",
DEFAULT: "#3313F7",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",

View File

@@ -20,10 +20,6 @@ export class ChatPage {
await this.messageInput.press("Enter");
}
async expectLoaded() {
await expect(this.messageInput).toBeVisible();
}
async expectMessageRow(message: string) {
await expect(this.page.getByText(message)).toBeVisible();
}

View File

@@ -1,5 +1,30 @@
# jazz-example-inspector
## 0.0.77
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson-transport-ws@0.8.29
- cojson@0.8.29
## 0.0.76
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- cojson-transport-ws@0.8.28
## 0.0.75
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- cojson-transport-ws@0.8.27
## 0.0.74
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector",
"private": true,
"version": "0.0.74",
"version": "0.0.77",
"type": "module",
"scripts": {
"dev": "vite",
@@ -16,8 +16,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.23",
"cojson-transport-ws": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"cojson-transport-ws": "workspace:0.8.29",
"hash-slash": "workspace:0.2.1",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",

View File

@@ -1,5 +1,44 @@
# minimal-auth-clerk
## 0.0.6
### Patch Changes
- jazz-react@0.8.29
- jazz-react-auth-clerk@0.8.29
- jazz-tools@0.8.29
## 0.0.5
### Patch Changes
- jazz-react@0.8.28
- jazz-react-auth-clerk@0.8.28
- jazz-tools@0.8.28
## 0.0.4
### Patch Changes
- jazz-react@0.8.27
- jazz-react-auth-clerk@0.8.27
- jazz-tools@0.8.27
## 0.0.3
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
- jazz-react-auth-clerk@0.8.26
## 0.0.2
### Patch Changes
- jazz-react@0.8.24
- jazz-react-auth-clerk@0.8.24
## 0.0.1
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "minimal-auth-clerk",
"private": true,
"version": "0.0.1",
"version": "0.0.6",
"type": "module",
"scripts": {
"dev": "vite",
@@ -14,7 +14,7 @@
"@clerk/clerk-react": "^5.4.1",
"jazz-tools": "workspace:*",
"jazz-react": "workspace:*",
"jazz-react-auth-clerk": "workspace:0.8.23",
"jazz-react-auth-clerk": "workspace:0.8.29",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},

View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,35 @@
# minimal-auth-passkey
## 0.0.5
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.4
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.3
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.2
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.1
### Patch Changes
- jazz-react@0.8.24

View File

@@ -0,0 +1,4 @@
# Minimal Jazz Passkey Auth Example
This is a minimal example of how to use passkey authentication with Jazz.

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jazz | Minimal Auth Passkey Example</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,28 @@
{
"name": "minimal-auth-passkey",
"private": true,
"version": "0.0.5",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
},
"dependencies": {
"jazz-tools": "workspace:*",
"jazz-react": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"globals": "^15.11.0",
"typescript": "~5.6.2",
"vite": "^5.4.10"
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,42 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

View File

@@ -0,0 +1,16 @@
import "./App.css";
import { useAccount } from "./main";
function App() {
const { me, logOut } = useAccount();
return (
<>
<h1>You're logged in</h1>
<p>Welcome back, {me?.profile?.name}</p>
<button onClick={() => logOut()}>Logout</button>
</>
);
}
export default App;

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1,68 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View File

@@ -0,0 +1,39 @@
import {
PasskeyAuthBasicUI,
createJazzReactApp,
usePasskeyAuth,
} from "jazz-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
const Jazz = createJazzReactApp();
export const { useAccount, useCoState } = Jazz;
function JazzAndAuth({ children }: { children: React.ReactNode }) {
const [auth, state] = usePasskeyAuth({
appName: "Jazz Minimal Auth Passkey Example",
});
return (
<>
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=minimal-auth-passkey-example@gcmp.io"
>
{children}
</Jazz.Provider>
<PasskeyAuthBasicUI state={state} />
</>
);
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<JazzAndAuth>
<App />
</JazzAndAuth>
</StrictMode>,
);

View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2023", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,7 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -1,5 +1,39 @@
# jazz-example-musicplayer
## 0.0.27
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.26
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.25
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.24
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.23
### Patch Changes
- jazz-react@0.8.24
## 0.0.22
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.22",
"version": "0.0.27",
"type": "module",
"scripts": {
"dev": "vite",
@@ -18,8 +18,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"lucide-react": "^0.274.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",

View File

@@ -1,5 +1,43 @@
# jazz-example-onboarding
## 0.0.8
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
- jazz-browser-media-images@0.8.29
## 0.0.7
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
- jazz-browser-media-images@0.8.28
## 0.0.6
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
- jazz-browser-media-images@0.8.27
## 0.0.5
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.4
### Patch Changes
- jazz-browser-media-images@0.8.24
- jazz-react@0.8.24
## 0.0.3
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-onboarding",
"private": true,
"version": "0.0.3",
"version": "0.0.8",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,39 @@
# jazz-password-manager
## 0.0.26
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.25
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.24
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.23
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.22
### Patch Changes
- jazz-react@0.8.24
## 0.0.21
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.21",
"version": "0.0.26",
"type": "module",
"scripts": {
"dev": "vite",
@@ -12,8 +12,8 @@
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
},
"dependencies": {
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.41.5",

View File

@@ -1,5 +1,43 @@
# jazz-example-pets
## 0.0.124
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
- jazz-browser-media-images@0.8.29
## 0.0.123
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
- jazz-browser-media-images@0.8.28
## 0.0.122
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
- jazz-browser-media-images@0.8.27
## 0.0.121
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.120
### Patch Changes
- jazz-browser-media-images@0.8.24
- jazz-react@0.8.24
## 0.0.119
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.119",
"version": "0.0.124",
"type": "module",
"scripts": {
"dev": "vite",
@@ -19,9 +19,9 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.8.23",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-browser-media-images": "workspace:0.8.29",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
@@ -41,7 +41,7 @@
"@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.14",
"is-ci": "^3.0.1",
"jazz-run": "workspace:0.8.23",
"jazz-run": "workspace:0.8.29",
"postcss": "^8.4.27",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",

View File

@@ -1,5 +1,36 @@
# todo-vue
## 0.0.10
### Patch Changes
- jazz-browser@0.8.29
- jazz-tools@0.8.29
- jazz-vue@0.8.17
## 0.0.9
### Patch Changes
- jazz-browser@0.8.28
- jazz-tools@0.8.28
- jazz-vue@0.8.16
## 0.0.8
### Patch Changes
- jazz-browser@0.8.27
- jazz-tools@0.8.27
- jazz-vue@0.8.15
## 0.0.7
### Patch Changes
- jazz-browser@0.8.24
- jazz-vue@0.8.14
## 0.0.6
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "todo-vue",
"version": "0.0.6",
"version": "0.0.10",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,39 @@
# jazz-example-todo
## 0.0.123
### Patch Changes
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.0.122
### Patch Changes
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.0.121
### Patch Changes
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.0.120
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.0.119
### Patch Changes
- jazz-react@0.8.24
## 0.0.118
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.118",
"version": "0.0.123",
"type": "module",
"scripts": {
"dev": "vite",
@@ -16,8 +16,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",

View File

@@ -6,17 +6,18 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "tertiary";
size?: "sm" | "md" | "lg";
href?: string;
newTab?: boolean;
}
export function Button(props: ButtonProps) {
const {
type = "button",
className,
children,
size = "md",
variant = "primary",
href,
disabled,
newTab,
} = props;
const sizeClasses = {
@@ -43,14 +44,18 @@ export function Button(props: ButtonProps) {
if (href) {
return (
<Link href={href} className={classNames}>
<Link
href={href}
target={newTab ? "_blank" : undefined}
className={classNames}
>
{children}
</Link>
);
}
return (
<button className={classNames} {...props}>
<button {...props} className={classNames}>
{children}
</button>
);

View File

@@ -5,7 +5,7 @@ import { Prose } from "./Prose";
function H2Sub({ children }: { children: React.ReactNode }) {
return (
<Prose size="lg" className="max-w-3xl">
<Prose size="lg" className="text-balance max-w-3xl">
{children}
</Prose>
);

View File

@@ -1,26 +1,45 @@
import clsx from "clsx";
export function Testimonial({
children,
name,
role,
className,
size = "md",
}: {
children: React.ReactNode;
name: string;
role: string;
className?: string;
size?: "sm" | "md";
}) {
return (
<figure className="max-w-2xl">
<figure className={clsx("max-w-2xl", className)}>
<svg
className="size-8 text-blue"
className={clsx("text-blue", {
"size-8": size === "md",
"size-6": size === "sm",
})}
fill="currentColor"
viewBox="0 0 32 32"
aria-hidden="true"
>
<path d="M9.352 4C4.456 7.456 1 13.12 1 19.36c0 5.088 3.072 8.064 6.624 8.064 3.36 0 5.856-2.688 5.856-5.856 0-3.168-2.208-5.472-5.088-5.472-.576 0-1.344.096-1.536.192.48-3.264 3.552-7.104 6.624-9.024L9.352 4zm16.512 0c-4.8 3.456-8.256 9.12-8.256 15.36 0 5.088 3.072 8.064 6.624 8.064 3.264 0 5.856-2.688 5.856-5.856 0-3.168-2.304-5.472-5.184-5.472-.576 0-1.248.096-1.44.192.48-3.264 3.456-7.104 6.528-9.024L25.864 4z"></path>
</svg>
<blockquote className="mt-6 text-balance font-medium leading-8 text-stone-900 sm:text-lg dark:text-white">
<blockquote
className={clsx("text-balance text-stone-900 dark:text-white", {
"mt-6 font-medium sm:text-lg leading-8 space-y-3": size === "md",
"mt-4 leading-relaxed space-y-3": size === "sm",
})}
>
{children}
</blockquote>
<figcaption className="mt-6 flex items-center gap-x-6">
<figcaption
className={clsx("flex items-center gap-x-6", {
"mt-6": size === "md",
"mt-4": size === "sm",
})}
>
<div className="text-sm leading-6 sm:text-base">
<div className="font-semibold text-stone-900 dark:text-white">
{name}

View File

@@ -92,6 +92,7 @@ function NavItem({
href={href}
aria-label={title}
as={Link}
key={href}
>
{icon}
<div className="grid gap-1.5 mt-px">

View File

@@ -1,4 +1,4 @@
import { CodeExampleSection } from "@/components/home/CodeExampleSection";
import { ChatDemoSection } from "@/components/home/ChatDemoSection";
import { CollaborationFeaturesSection } from "@/components/home/CollaborationFeaturesSection";
import { ComingSoonSection } from "@/components/home/ComingSoonSection";
import { EarlyAdopterSection } from "@/components/home/EarlyAdopterSection";
@@ -32,6 +32,8 @@ export default function Home() {
</p>
</Testimonial>
<ChatDemoSection />
<LocalFirstFeaturesSection />
<CollaborationFeaturesSection />
@@ -49,8 +51,6 @@ export default function Home() {
<FeaturesSection />
<CodeExampleSection />
<SupportedEnvironmentsSection />
<ComingSoonSection />

View File

@@ -1,97 +0,0 @@
"use client";
import { CopyIcon } from "lucide-react";
import { IframeHTMLAttributes, useLayoutEffect, useRef, useState } from "react";
export function ResponsiveIframe(
props: IframeHTMLAttributes<HTMLIFrameElement> & { localsrc: string },
) {
const containerRef = useRef<HTMLDivElement>(null);
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
const [url, setUrl] = useState<string | undefined>();
const [src, setSrc] = useState<string | undefined>();
useLayoutEffect(() => {
const listener = (e: MessageEvent) => {
console.log(e);
if (e.data.type === "navigate" && src?.startsWith(e.origin)) {
setUrl(e.data.url);
}
};
window.addEventListener("message", listener);
return () => {
window.removeEventListener("message", listener);
};
}, [src]);
useLayoutEffect(() => {
if (!containerRef.current) return;
const observer = new ResizeObserver(() => {
if (!containerRef.current) return;
setDimensions({
width: containerRef.current.offsetWidth,
height: containerRef.current.offsetHeight,
});
});
observer.observe(containerRef.current);
return () => {
observer.disconnect();
};
}, [containerRef]);
useLayoutEffect(() => {
setSrc(
window.location.hostname === "localhost" ? props.localsrc : props.src,
);
setUrl(
window.location.hostname === "localhost" ? props.localsrc : props.src,
);
}, [props.src, props.localsrc]);
const copyUrl = () => {
if (url) {
navigator.clipboard.writeText(url);
}
};
return (
<>
<div className="bg-white flex gap-3 border-b text-xs dark:bg-stone-925">
<input
className="flex-1 font-mono bg-transparent overflow-hidden text-ellipsis py-2 px-3"
value={url?.replace("http://", "").replace("https://", "")}
onClick={(e) => e.currentTarget.select()}
onBlur={(e) => e.currentTarget.setSelectionRange(0, 0)}
readOnly
/>
{url?.includes("/#/chat/") && (
<button
type="button"
className="text-blue-600 flex items-center gap-1.5 py-2 px-3"
onClick={copyUrl}
>
<CopyIcon className="hidden sm:inline" size={12} />
<span>
Copy URL{" "}
<span className="hidden sm:inline">to invite others</span>
</span>
</button>
)}
</div>
<div className="flex-1 bg-stone-100 flex items-stretch justify-center p-2 sm:p-6 dark:bg-stone-925">
<div className="border rounded-lg overflow-hidden shadow-2xl w-[20rem] min-h-[30rem]">
<div className="h-full" ref={containerRef}>
<iframe
{...props}
src={src}
className="dark:bg-black w-full"
{...dimensions}
allowFullScreen
/>
</div>
</div>
</div>
</>
);
}

View File

@@ -5,15 +5,6 @@ import {
import { CodeGroup as CodeGroupClient } from "gcmp-design-system/src/app/components/molecules/CodeGroup";
import { IframeHTMLAttributes } from "react";
import { ResponsiveIframe as ResponsiveIframeClient } from "./ResponsiveIframe";
export function ResponsiveIframe(
props: IframeHTMLAttributes<HTMLIFrameElement> & { localsrc: string },
) {
return <ResponsiveIframeClient {...props} />;
}
export function CodeExampleTabs(props: CodeExampleTabsProps) {
return <CodeExampleTabsClient {...props} />;
}

View File

@@ -0,0 +1,192 @@
"use client";
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
import { CheckIcon, CopyIcon } from "lucide-react";
import Link from "next/link";
import QRCode from "qrcode";
import {
IframeHTMLAttributes,
useEffect,
useLayoutEffect,
useMemo,
useState,
} from "react";
function Iframe(
props: IframeHTMLAttributes<HTMLIFrameElement> & {
user: string;
},
) {
const { src, user } = props;
return (
<div className="relative col-span-2 w-full border rounded-xl shadow-sm overflow-hidden lg:col-span-2 dark:bg-black">
<iframe
{...props}
src={src}
className="w-full"
width="200"
height="390"
allowFullScreen
/>
</div>
);
}
export function ChatDemoSection() {
const [chatId, setChatId] = useState<string | undefined>();
const user1 = "Alice";
const user2 = "Bob";
const [server1, setServer1] = useState<string | null>();
const [server2, setServer2] = useState<string | null>();
const [shareUrl, setShareUrl] = useState<string | null>();
const [qrCode, setQrCode] = useState<string | null>();
let [copyCount, setCopyCount] = useState(0);
let copied = copyCount > 0;
useEffect(() => {
if (copyCount > 0) {
let timeout = setTimeout(() => setCopyCount(0), 1000);
return () => {
clearTimeout(timeout);
};
}
}, [copyCount]);
useLayoutEffect(() => {
if (typeof window === "undefined") return;
const isLocal = window.location.hostname === "localhost";
if (chatId) {
const shareServer = isLocal
? "http://localhost:5173"
: "https://chat.jazz.tools";
const url = `${shareServer}/${chatId}`;
setShareUrl(url);
QRCode.toDataURL(url, {
errorCorrectionLevel: "L",
}).then((dataUrl) => {
setQrCode(dataUrl);
});
return; // Once the chatId is set, we don't need to listen for messages anymore
}
setServer1(
(isLocal ? "http://localhost:5173" : "https://jazz-chat-1.vercel.app") +
`?user=${user1}`,
);
setServer2(
(isLocal ? "http://localhost:5174" : "https://jazz-chat-2.vercel.app") +
`?user=${user2}`,
);
if (!server1 || !server2) return;
const server1Url = new URL(server1);
const listener = (e: MessageEvent) => {
const isValidOrigin = e.origin === server1Url.origin;
if (e.data.type === "navigate" && isValidOrigin) {
setChatId(new URL(e.data.url).hash);
}
};
window.addEventListener("message", listener);
return () => {
window.removeEventListener("message", listener);
};
}, [chatId, server1, server2]);
const server2WithSameChatId = useMemo(() => {
if (chatId && server2) {
const server2Url = new URL(server2);
server2Url.hash = chatId;
return server2Url.toString();
}
return null;
}, [chatId, server2]);
if (!server1) return null;
const copyUrl = () => {
if (shareUrl) {
navigator.clipboard.writeText(shareUrl).then(() => {
setCopyCount((count) => count + 1);
});
}
};
return (
<div>
<SectionHeader
kicker="Demo"
title="See it for yourself"
slogan={
<>
A chat app in 174 lines of client-side code.{" "}
<Link href="https://github.com/gardencmp/jazz/tree/main/examples/chat">
View code
</Link>
</>
}
/>
<GappedGrid className="gap-y-8">
<Iframe src={server1} user={user1} />
{server2WithSameChatId && (
<Iframe src={server2WithSameChatId} user={user2} />
)}
<div className="col-span-2 md:col-span-full lg:col-span-2">
{chatId && shareUrl && (
<div className="flex h-full flex-col justify-between gap-3 text-center md:gap-5">
<H3 className="font-medium text-stone-900 dark:text-white !mb-0">
Join the chat
</H3>
<p>Scan the QR code</p>
{qrCode && (
<img
src={qrCode}
className="size-48 border mx-auto rounded-lg"
/>
)}
<div className="flex items-center gap-2">
<div className="h-px w-full border-t" />
<p className="whitespace-nowrap">or copy the URL</p>
<div className="h-px w-full border-t" />
</div>
<div>
<div className="border rounded shadow-sm p-2 overflow-hidden leading-none flex-1 flex gap-2">
<input
className="flex-1"
type="text"
value={shareUrl}
onClick={(e) => e.currentTarget.select()}
onBlur={(e) => e.currentTarget.setSelectionRange(0, 0)}
readOnly
/>
<button
type="button"
className="text-blue dark:text-blue-400"
onClick={copyUrl}
>
{copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}
<span className="sr-only">Copy URL</span>
</button>
</div>
</div>
</div>
)}
</div>
</GappedGrid>
</div>
);
}

View File

@@ -1,58 +0,0 @@
import {
App_tsx,
ChatScreen_tsx,
Main_tsx,
Schema_ts,
Ui_tsx,
} from "@/codeSamples/examples/chat/src";
import { CodeExampleTabs, ResponsiveIframe } from "@/components/forMdx";
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
export function CodeExampleSection() {
return (
<div>
<SectionHeader
title="See it for yourself"
slogan="A chat app in 174 lines of code."
/>
<div className="flex flex-col md:grid md:grid-cols-2 md:divide-x border rounded-sm overflow-hidden shadow-sm dark:divide-stone-900">
<CodeExampleTabs
tabs={[
{
name: "main.tsx",
content: <Main_tsx />,
},
{
name: "app.tsx",
content: <App_tsx />,
},
{
name: "schema.ts",
content: <Schema_ts />,
},
{
name: "chatScreen.tsx",
content: <ChatScreen_tsx />,
},
{
name: "ui.tsx",
content: <Ui_tsx />,
},
]}
/>
<div className="border-b order-first md:order-last flex flex-col md:border-b-0">
<div className="flex border-b overflow-x-auto overflow-y-hidden bg-white dark:bg-stone-900">
<p className="items-center -mb-px transition-colors px-3 pb-1.5 pt-2 block text-xs border-b-2 border-blue-700 text-stone-700 dark:bg-stone-925 dark:text-blue-500 dark:border-blue-500">
result
</p>
</div>
<ResponsiveIframe
src="https://chat.jazz.tools"
localsrc="http://localhost:5173"
/>
</div>
</div>
</div>
);
}

View File

@@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "NODE_OPTIONS=--max-old-space-size=8192 next dev",
"build": "node genDocs.mjs --build && node renderCodeSamples.mjs && next build",
"build": "node genDocs.mjs --build && next build",
"start": "next start",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
@@ -28,6 +28,7 @@
"mdast-util-mdx": "^3.0.0",
"micromark-extension-mdxjs": "^3.0.0",
"next": "13.5.4",
"qrcode": "^1.5.4",
"react": "^18",
"react-dom": "^18",
"rehype-slug": "^6.0.0",

View File

@@ -1,104 +0,0 @@
import path from "path";
import { mkdir, readFile, readdir, rm, writeFile } from "fs/promises";
import {
createShikiHighlighter,
renderCodeToHTML,
runTwoSlash,
} from "shiki-twoslash";
const targetDoc = "components/home/CodeExampleSection.tsx";
const targetDocSrc = await readFile(targetDoc, "utf8");
await rm("./codeSamples", { recursive: true, force: true });
[...targetDocSrc.matchAll(/"@\/codeSamples\/(.+?)"/g)].forEach(
async (match) => {
const dir = match[1];
console.log("Rendering", { dir });
const allFiles = Object.fromEntries(
(
await Promise.all(
(
await readdir(path.join("../../", dir))
).map(async (f) =>
(f.endsWith(".ts") && f !== "vite-env.d.ts") || f.endsWith(".tsx")
? [f, await readFile(path.join("../../", dir, f), "utf8")]
: undefined,
),
)
).filter((entry) => entry !== undefined),
);
console.log(allFiles);
const components = (
await Promise.all(
Object.entries(allFiles).map(async ([filename, src]) => {
const otherFilesConcat = Object.entries(allFiles)
.filter(([f, _]) => f !== filename)
.map(([f, src]) => `// @filename: ${f}\n// @errors: 2345\n${src}`)
.join("\n\n");
const forFile =
otherFilesConcat +
"\n\n// @filename: " +
filename +
"\n// @errors: 2345" +
"\n// ---cut---\n" +
src.trim();
const highlighter = await createShikiHighlighter({
theme: "css-variables",
});
const twoslash = runTwoSlash(forFile, "ts", {
disableImplicitReactImport: true,
defaultCompilerOptions: {
allowImportingTsExtensions: true,
noEmit: true,
jsx: "react-jsxdev",
strict: true,
paths: {
"jazz-tools": ["../../../packages/jazz-tools"],
"jazz-react": ["../../../packages/jazz-react"],
"hash-slash": ["../../../packages/hash-slash"],
},
types: ["../../../examples/chat/node_modules/vite/client"],
},
});
const html = renderCodeToHTML(
twoslash.code,
"tsx",
{ twoslash: true },
{
themeName: "css-variables",
},
highlighter,
twoslash,
);
const component = `export function ${
path.basename(filename).slice(0, 1).toUpperCase() +
path.basename(filename).slice(1).replace(".", "_")
}() {\n\treturn <div className="not-prose h-full" dangerouslySetInnerHTML={{__html: \`${html
.replace(/`/g, "\\`")
.replace(/\$/g, "\\$")}\`\n\t}}/>;\n}`;
return component;
}),
)
).join("\n\n");
await mkdir(path.join("./codeSamples/", dir), {
recursive: true,
});
await writeFile(
path.join("./codeSamples/", dir, "index.tsx"),
components,
"utf8",
);
},
);

160
homepage/pnpm-lock.yaml generated
View File

@@ -217,6 +217,9 @@ importers:
next:
specifier: 13.5.4
version: 13.5.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
qrcode:
specifier: ^1.5.4
version: 1.5.4
react:
specifier: ^18
version: 18.3.1
@@ -970,6 +973,10 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
camelcase@5.3.1:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
caniuse-lite@1.0.30001617:
resolution: {integrity: sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==}
@@ -1002,6 +1009,9 @@ packages:
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
clsx@2.0.0:
resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
engines: {node: '>=6'}
@@ -1055,6 +1065,10 @@ packages:
supports-color:
optional: true
decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
decode-named-character-reference@1.0.2:
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
@@ -1076,6 +1090,9 @@ packages:
resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
engines: {node: '>=0.3.1'}
dijkstrajs@1.0.3:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
@@ -1199,6 +1216,10 @@ packages:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
foreground-child@3.1.1:
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
engines: {node: '>=14'}
@@ -1214,6 +1235,10 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
github-slugger@2.0.0:
resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
@@ -1383,6 +1408,10 @@ packages:
resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
engines: {node: '>=6.11.5'}
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
@@ -1777,12 +1806,28 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
p-limit@2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
parse-entities@4.0.1:
resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==}
parseley@0.12.1:
resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==}
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -1815,6 +1860,10 @@ packages:
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
engines: {node: '>= 6'}
pngjs@5.0.0:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
@@ -1874,6 +1923,11 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
qrcode@1.5.4:
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
engines: {node: '>=10.13.0'}
hasBin: true
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@@ -1911,6 +1965,13 @@ packages:
remark-rehype@10.1.0:
resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
require-main-filename@2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
resend@4.0.0:
resolution: {integrity: sha512-rDX0rspl/XcmC2JV2V5obQvRX2arzxXUvNFUDMOv5ObBLR68+7kigCOysb7+dlkb0JE3erhQG0nHrbBt/ZCWIg==}
engines: {node: '>=18'}
@@ -1954,6 +2015,9 @@ packages:
server-only@0.0.1:
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@@ -2228,11 +2292,18 @@ packages:
webpack-cli:
optional: true
which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
hasBin: true
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -2241,11 +2312,22 @@ packages:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
yaml@2.4.2:
resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==}
engines: {node: '>= 14'}
hasBin: true
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
yargs@15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
@@ -2906,6 +2988,8 @@ snapshots:
camelcase-css@2.0.1: {}
camelcase@5.3.1: {}
caniuse-lite@1.0.30001617: {}
ccount@2.0.1: {}
@@ -2938,6 +3022,12 @@ snapshots:
client-only@0.0.1: {}
cliui@6.0.0:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
clsx@2.0.0: {}
clsx@2.1.1: {}
@@ -2975,6 +3065,8 @@ snapshots:
dependencies:
ms: 2.1.2
decamelize@1.2.0: {}
decode-named-character-reference@1.0.2:
dependencies:
character-entities: 2.0.2
@@ -2991,6 +3083,8 @@ snapshots:
diff@5.2.0: {}
dijkstrajs@1.0.3: {}
dlv@1.1.3: {}
dom-serializer@2.0.0:
@@ -3116,6 +3210,11 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
find-up@4.1.0:
dependencies:
locate-path: 5.0.0
path-exists: 4.0.0
foreground-child@3.1.1:
dependencies:
cross-spawn: 7.0.3
@@ -3128,6 +3227,8 @@ snapshots:
function-bind@1.1.2: {}
get-caller-file@2.0.5: {}
github-slugger@2.0.0: {}
glob-parent@5.1.2:
@@ -3298,6 +3399,10 @@ snapshots:
loader-runner@4.3.0: {}
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
@@ -4058,6 +4163,16 @@ snapshots:
object-hash@3.0.0: {}
p-limit@2.3.0:
dependencies:
p-try: 2.2.0
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
p-try@2.2.0: {}
parse-entities@4.0.1:
dependencies:
'@types/unist': 2.0.10
@@ -4074,6 +4189,8 @@ snapshots:
leac: 0.6.0
peberminta: 0.9.0
path-exists@4.0.0: {}
path-key@3.1.1: {}
path-parse@1.0.7: {}
@@ -4099,6 +4216,8 @@ snapshots:
pirates@4.0.6: {}
pngjs@5.0.0: {}
postcss-import@15.1.0(postcss@8.4.38):
dependencies:
postcss: 8.4.38
@@ -4153,6 +4272,12 @@ snapshots:
punycode@2.3.1: {}
qrcode@1.5.4:
dependencies:
dijkstrajs: 1.0.3
pngjs: 5.0.0
yargs: 15.4.1
queue-microtask@1.2.3: {}
randombytes@2.1.0:
@@ -4211,6 +4336,10 @@ snapshots:
mdast-util-to-hast: 12.3.0
unified: 10.1.2
require-directory@2.1.1: {}
require-main-filename@2.0.0: {}
resend@4.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@react-email/render': 0.0.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -4258,6 +4387,8 @@ snapshots:
server-only@0.0.1: {}
set-blocking@2.0.0: {}
shebang-command@2.0.0:
dependencies:
shebang-regex: 3.0.0
@@ -4596,10 +4727,18 @@ snapshots:
- esbuild
- uglify-js
which-module@2.0.1: {}
which@2.0.2:
dependencies:
isexe: 2.0.0
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -4612,6 +4751,27 @@ snapshots:
string-width: 5.1.2
strip-ansi: 7.1.0
y18n@4.0.3: {}
yaml@2.4.2: {}
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1
decamelize: 1.2.0
yargs@15.4.1:
dependencies:
cliui: 6.0.0
decamelize: 1.2.0
find-up: 4.1.0
get-caller-file: 2.0.5
require-directory: 2.1.1
require-main-filename: 2.0.0
set-blocking: 2.0.0
string-width: 4.2.3
which-module: 2.0.1
y18n: 4.0.3
yargs-parser: 18.1.3
zwitch@2.0.4: {}

View File

@@ -12,7 +12,7 @@
"happy-dom": "^15.8.3",
"lefthook": "^1.8.2",
"ts-node": "^10.9.1",
"turbo": "^1.11.2",
"turbo": "^2.3.1",
"typedoc": "^0.25.13",
"vitest": "1.5.3"
},

View File

@@ -1,5 +1,33 @@
# cojson-storage-indexeddb
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
## 0.8.24
### Patch Changes
- e17e959: Fix: IndexedDB not delivering depended-on CoValues
## 0.8.23
### Patch Changes

View File

@@ -1,12 +1,12 @@
{
"name": "cojson-storage-indexeddb",
"version": "0.8.23",
"version": "0.8.29",
"main": "dist/index.js",
"type": "module",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"cojson": "workspace:0.8.23"
"cojson": "workspace:0.8.29"
},
"devDependencies": {
"@vitest/browser": "^0.34.1",

View File

@@ -703,7 +703,7 @@ function getDependedOnCoValues(
coValueRow?.header.ruleset.group,
...new Set(
newContentPieces.flatMap((piece) =>
Object.keys(piece)
Object.keys(piece.new)
.map((sessionID) =>
cojsonInternals.accountOrAgentIDfromSessionID(
sessionID as SessionID,

View File

@@ -1,5 +1,33 @@
# cojson-storage-sqlite
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
## 0.8.25
### Patch Changes
- 63d46c9: Fix: sqlite not delivering depended-on CoValues
## 0.8.23
### Patch Changes

View File

@@ -1,13 +1,13 @@
{
"name": "cojson-storage-sqlite",
"type": "module",
"version": "0.8.23",
"version": "0.8.29",
"main": "dist/index.js",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"better-sqlite3": "^8.5.2",
"cojson": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"typescript": "^5.3.3"
},
"devDependencies": {

View File

@@ -403,7 +403,7 @@ export class SQLiteStorage {
parsedHeader?.ruleset.group,
...new Set(
newContentPieces.flatMap((piece) =>
Object.keys(piece)
Object.keys(piece.new)
.map((sessionID) =>
cojsonInternals.accountOrAgentIDfromSessionID(
sessionID as SessionID,

View File

@@ -1,5 +1,28 @@
# cojson-transport-nodejs-ws
## 0.8.29
### Patch Changes
- dcc9c2e: Clear out the queues when closing a Peer
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
## 0.8.23
### Patch Changes

View File

@@ -1,12 +1,12 @@
{
"name": "cojson-transport-ws",
"type": "module",
"version": "0.8.23",
"version": "0.8.29",
"main": "dist/index.js",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"cojson": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"typescript": "^5.3.3"
},
"scripts": {

View File

@@ -59,6 +59,7 @@ function createOutgoingMessagesManager(
websocket: AnyWebSocket,
batchingByDefault: boolean,
) {
let closed = false;
const outgoingMessages = new BatchedOutgoingMessages((messages) => {
if (websocket.readyState === 1) {
websocket.send(messages);
@@ -68,6 +69,10 @@ function createOutgoingMessagesManager(
let batchingEnabled = batchingByDefault;
async function sendMessage(msg: SyncMessage) {
if (closed) {
return Promise.reject(new Error("WebSocket closed"));
}
if (websocket.readyState !== 1) {
await waitForWebSocketOpen(websocket);
}
@@ -98,6 +103,7 @@ function createOutgoingMessagesManager(
batchingEnabled = enabled;
},
close() {
closed = true;
outgoingMessages.close();
},
};

View File

@@ -153,6 +153,23 @@ describe("createWebSocketPeer", () => {
expect(mockWebSocket.close).toHaveBeenCalled();
});
test("should return a rejection if a message is sent after the peer is closed", async () => {
const { peer } = setup();
peer.outgoing.close();
const message: SyncMessage = {
action: "known",
id: "co_ztest",
header: false,
sessions: {},
};
await expect(peer.outgoing.push(message)).rejects.toThrow(
"WebSocket closed",
);
});
describe("batchingByDefault = true", () => {
test("should batch outgoing messages", async () => {
const { peer, mockWebSocket } = setup();

View File

@@ -1,5 +1,24 @@
# cojson
## 0.8.29
### Patch Changes
- dcc9c2e: Clear out the queues when closing a Peer
- 699553f: Restore offline support and improve loading perfromance when values are cached
## 0.8.28
### Patch Changes
- 605734c: Send empty known state on all states except available
## 0.8.27
### Patch Changes
- 75fdff4: Improve the initial load by telling what's on storage in the first load request
## 0.8.23
### Patch Changes

View File

@@ -19,7 +19,7 @@
},
"type": "module",
"license": "MIT",
"version": "0.8.23",
"version": "0.8.29",
"devDependencies": {
"@types/jest": "^29.5.3",
"typescript": "^5.3.3",

View File

@@ -97,6 +97,10 @@ export class PeerState {
}
pushOutgoingMessage(msg: SyncMessage) {
if (this.closed) {
return Promise.resolve();
}
const promise = this.queue.push(msg);
void this.processQueue();
@@ -114,8 +118,16 @@ export class PeerState {
return this.peer.incoming;
}
private closeQueue() {
let entry: QueueEntry | undefined;
while ((entry = this.queue.pull())) {
entry.reject(new Error("Peer disconnected"));
}
}
gracefulShutdown() {
console.debug("Gracefully closing", this.id);
this.closeQueue();
this.peer.outgoing.close();
this.closed = true;
}

View File

@@ -4,6 +4,7 @@ import { RawCoID } from "./ids.js";
import { PeerID } from "./sync.js";
export const CO_VALUE_LOADING_MAX_RETRIES = 5;
export const CO_VALUE_LOADING_TIMEOUT = 5000;
export class CoValueUnknownState {
type = "unknown" as const;
@@ -264,15 +265,53 @@ async function loadCoValueFromPeers(
peers: PeerState[],
) {
for (const peer of peers) {
await peer.pushOutgoingMessage({
action: "load",
id: coValueEntry.id,
header: false,
sessions: {},
});
if (peer.closed) {
continue;
}
if (coValueEntry.state.type === "available") {
/**
* We don't need to wait for the message to be delivered here.
*
* This way when the coValue becomes available because it's cached we don't wait for the server
* peer to consume the messages queue before moving forward.
*/
peer
.pushOutgoingMessage({
action: "load",
...coValueEntry.state.coValue.knownState(),
})
.catch((err) => {
console.error(`Failed to push load message to peer ${peer.id}`, err);
});
} else {
/**
* We only wait for the load state to be resolved.
*/
peer
.pushOutgoingMessage({
action: "load",
id: coValueEntry.id,
header: false,
sessions: {},
})
.catch((err) => {
console.error(`Failed to push load message to peer ${peer.id}`, err);
});
}
if (coValueEntry.state.type === "loading") {
const timeout = setTimeout(() => {
if (coValueEntry.state.type === "loading") {
console.error("Failed to load coValue from peer", peer.id);
coValueEntry.dispatch({
type: "not-found-in-peer",
peerId: peer.id,
});
}
}, CO_VALUE_LOADING_TIMEOUT);
await coValueEntry.state.waitForPeer(peer.id);
clearTimeout(timeout);
}
}
}

View File

@@ -451,12 +451,17 @@ export class SyncManager {
dependencyEntry.state.type === "available" ||
dependencyEntry.state.type === "loading"
) {
this.local.loadCoValueCore(msg.id, peer.id).catch((e) => {
console.error(
`Error loading coValue ${msg.id} to create loading state, as dependency of ${msg.asDependencyOf}`,
e,
);
});
this.local
.loadCoValueCore(
msg.id,
peer.role === "storage" ? undefined : peer.id,
)
.catch((e) => {
console.error(
`Error loading coValue ${msg.id} to create loading state, as dependency of ${msg.asDependencyOf}`,
e,
);
});
} else {
throw new Error(
"Expected coValue dependency entry to be created, missing subscribe?",

View File

@@ -57,6 +57,36 @@ describe("PeerState", () => {
consoleSpy.mockRestore();
});
test("should empty the queue when closing", async () => {
const { mockPeer, peerState } = setup();
mockPeer.outgoing.push = vi.fn().mockImplementation((message) => {
return new Promise<void>((resolve) => {
setTimeout(resolve, 100);
});
});
const message1 = peerState.pushOutgoingMessage({
action: "content",
id: "co_z1",
new: {},
priority: CO_VALUE_PRIORITY.HIGH,
});
const message2 = peerState.pushOutgoingMessage({
action: "content",
id: "co_z1",
new: {},
priority: CO_VALUE_PRIORITY.HIGH,
});
peerState.gracefulShutdown();
await Promise.allSettled([message1, message2]);
await expect(message1).resolves.toBe(undefined);
await expect(message2).rejects.toThrow("Peer disconnected");
});
test("should schedule outgoing messages based on their priority", async () => {
const { peerState } = setup();

View File

@@ -24,7 +24,7 @@ describe("CoValueState", () => {
});
test("should create available state", async () => {
const mockCoValue = { id: mockCoValueId } as CoValueCore;
const mockCoValue = createMockCoValueCore(mockCoValueId);
const state = CoValueState.Available(mockCoValue);
expect(state.id).toBe(mockCoValueId);
@@ -34,7 +34,7 @@ describe("CoValueState", () => {
});
test("should handle found action", async () => {
const mockCoValue = { id: mockCoValueId } as CoValueCore;
const mockCoValue = createMockCoValueCore(mockCoValueId);
const state = CoValueState.Loading(mockCoValueId, ["peer1", "peer2"]);
const stateValuePromise = state.getCoValue();
@@ -232,7 +232,7 @@ describe("CoValueState", () => {
setTimeout(() => {
state.dispatch({
type: "available",
coValue: { id: mockCoValueId } as CoValueCore,
coValue: createMockCoValueCore(mockCoValueId),
});
}, 100);
}
@@ -285,7 +285,7 @@ describe("CoValueState", () => {
state.dispatch({
type: "available",
coValue: { id: mockCoValueId } as CoValueCore,
coValue: createMockCoValueCore(mockCoValueId),
});
await loadPromise;
@@ -311,7 +311,7 @@ describe("CoValueState", () => {
if (run > 2) {
state.dispatch({
type: "available",
coValue: { id: mockCoValueId } as CoValueCore,
coValue: createMockCoValueCore(mockCoValueId),
});
}
state.dispatch({
@@ -338,6 +338,129 @@ describe("CoValueState", () => {
vi.useRealTimers();
});
test("should start sending the known state to peers when available", async () => {
vi.useFakeTimers();
const mockCoValue = createMockCoValueCore(mockCoValueId);
const peer1 = createMockPeerState(
{
id: "peer1",
role: "storage",
},
async () => {
state.dispatch({
type: "available",
coValue: mockCoValue,
});
},
);
const peer2 = createMockPeerState(
{
id: "peer1",
role: "server",
},
async () => {
state.dispatch({
type: "not-found-in-peer",
peerId: "peer2",
});
},
);
const state = CoValueState.Unknown(mockCoValueId);
const loadPromise = state.loadFromPeers([peer1, peer2]);
for (let i = 0; i < CO_VALUE_LOADING_MAX_RETRIES; i++) {
await vi.runAllTimersAsync();
}
await loadPromise;
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(1);
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(1);
expect(peer2.pushOutgoingMessage).toHaveBeenCalledWith({
action: "load",
...mockCoValue.knownState(),
});
expect(state.state.type).toBe("available");
await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
vi.useRealTimers();
});
test("should skip closed peers", async () => {
vi.useFakeTimers();
const mockCoValue = createMockCoValueCore(mockCoValueId);
const peer1 = createMockPeerState(
{
id: "peer1",
role: "storage",
},
async () => {
return new Promise(() => {});
},
);
const peer2 = createMockPeerState(
{
id: "peer1",
role: "server",
},
async () => {
state.dispatch({
type: "available",
coValue: mockCoValue,
});
},
);
peer1.closed = true;
const state = CoValueState.Unknown(mockCoValueId);
const loadPromise = state.loadFromPeers([peer1, peer2]);
for (let i = 0; i < CO_VALUE_LOADING_MAX_RETRIES; i++) {
await vi.runAllTimersAsync();
}
await loadPromise;
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(0);
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(1);
expect(state.state.type).toBe("available");
await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
vi.useRealTimers();
});
test("should not be stuck in loading state when not getting a response", async () => {
vi.useFakeTimers();
const peer1 = createMockPeerState(
{
id: "peer1",
role: "server",
},
async () => {},
);
const state = CoValueState.Unknown(mockCoValueId);
const loadPromise = state.loadFromPeers([peer1]);
for (let i = 0; i < CO_VALUE_LOADING_MAX_RETRIES * 2; i++) {
await vi.runAllTimersAsync();
}
await loadPromise;
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(5);
expect(state.state.type).toBe("unavailable");
await expect(state.getCoValue()).resolves.toEqual("unavailable");
vi.useRealTimers();
});
});
function createMockPeerState(
@@ -360,3 +483,18 @@ function createMockPeerState(
return peerState;
}
function createMockCoValueCore(mockCoValueId: string) {
// Setting the knownState as part of the prototype to simplify
// the equality checks
const mockCoValue = Object.create({
knownState: vi.fn().mockReturnValue({
id: mockCoValueId,
header: true,
sessions: {},
}),
});
mockCoValue.id = mockCoValueId;
return mockCoValue as unknown as CoValueCore;
}

View File

@@ -1,5 +1,39 @@
# jazz-browser-media-images
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-browser@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-browser@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-browser@0.8.27
- jazz-tools@0.8.27
## 0.8.24
### Patch Changes
- jazz-browser@0.8.24
## 0.8.23
### Patch Changes

View File

@@ -1,14 +1,14 @@
{
"name": "jazz-browser-auth-clerk",
"version": "0.8.23",
"version": "0.8.29",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"cojson": "workspace:0.8.23",
"jazz-browser": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23"
"cojson": "workspace:0.8.29",
"jazz-browser": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29"
},
"scripts": {
"format-and-lint": "biome check .",

View File

@@ -1,5 +1,32 @@
# jazz-browser-media-images
## 0.8.29
### Patch Changes
- jazz-browser@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- jazz-browser@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- jazz-browser@0.8.27
- jazz-tools@0.8.27
## 0.8.24
### Patch Changes
- jazz-browser@0.8.24
## 0.8.23
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser-media-images",
"version": "0.8.23",
"version": "0.8.29",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
@@ -8,8 +8,8 @@
"dependencies": {
"@types/image-blob-reduce": "^4.1.1",
"image-blob-reduce": "^4.1.0",
"jazz-browser": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"jazz-browser": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"pica": "^9.0.1",
"typescript": "^5.3.3"
},

View File

@@ -1,5 +1,43 @@
# jazz-browser
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson-transport-ws@0.8.29
- cojson@0.8.29
- cojson-storage-indexeddb@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- cojson-storage-indexeddb@0.8.28
- cojson-transport-ws@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- cojson-storage-indexeddb@0.8.27
- cojson-transport-ws@0.8.27
- jazz-tools@0.8.27
## 0.8.24
### Patch Changes
- Updated dependencies [e17e959]
- cojson-storage-indexeddb@0.8.24
## 0.8.23
### Patch Changes

View File

@@ -1,16 +1,16 @@
{
"name": "jazz-browser",
"version": "0.8.23",
"version": "0.8.29",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"@scure/bip39": "^1.3.0",
"cojson": "workspace:0.8.23",
"cojson-storage-indexeddb": "workspace:0.8.23",
"cojson-transport-ws": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"cojson-storage-indexeddb": "workspace:0.8.29",
"cojson-transport-ws": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"typescript": "^5.3.3"
},
"scripts": {

View File

@@ -1,4 +1,4 @@
import { LSMStorage, Peer, RawAccountID } from "cojson";
import { LSMStorage, LocalNode, Peer, RawAccountID } from "cojson";
import { IDBStorage } from "cojson-storage-indexeddb";
import {
Account,
@@ -64,12 +64,15 @@ export async function createJazzBrowserContext<Acc extends Account>(
options: BrowserContextOptions<Acc> | BaseBrowserContextOptions,
): Promise<BrowserContext<Acc> | BrowserGuestContext> {
const crypto = options.crypto || (await WasmCrypto.create());
let node: LocalNode | undefined = undefined;
const wsPeer = createWebSocketPeerWithReconnection(
options.peer,
options.reconnectionTimeout,
(peer) => {
node.syncManager.addPeer(peer);
if (node) {
node.syncManager.addPeer(peer);
}
},
);
@@ -106,7 +109,7 @@ export async function createJazzBrowserContext<Acc extends Account>(
peersToLoadFrom,
});
const node =
node =
"account" in context ? context.account._raw.core.node : context.agent.node;
return "account" in context

View File

@@ -1,5 +1,33 @@
# jazz-autosub
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson-transport-ws@0.8.29
- cojson@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- cojson-transport-ws@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- cojson-transport-ws@0.8.27
- jazz-tools@0.8.27
## 0.8.23
### Patch Changes

View File

@@ -5,11 +5,11 @@
"types": "src/index.ts",
"type": "module",
"license": "MIT",
"version": "0.8.23",
"version": "0.8.29",
"dependencies": {
"cojson": "workspace:0.8.23",
"cojson-transport-ws": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23",
"cojson": "workspace:0.8.29",
"cojson-transport-ws": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29",
"ws": "^8.14.2"
},
"devDependencies": {

View File

@@ -1,5 +1,50 @@
# jazz-browser-media-images
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-browser-auth-clerk@0.8.29
- jazz-react@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-browser-auth-clerk@0.8.28
- jazz-react@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-browser-auth-clerk@0.8.27
- jazz-react@0.8.27
- jazz-tools@0.8.27
## 0.8.26
### Patch Changes
- Updated dependencies [59d37df]
- jazz-react@0.8.26
## 0.8.24
### Patch Changes
- jazz-browser-auth-clerk@0.8.24
- jazz-react@0.8.24
## 0.8.23
### Patch Changes

View File

@@ -1,15 +1,15 @@
{
"name": "jazz-react-auth-clerk",
"version": "0.8.23",
"version": "0.8.29",
"type": "module",
"main": "dist/index.js",
"types": "src/index.tsx",
"license": "MIT",
"dependencies": {
"cojson": "workspace:0.8.23",
"jazz-browser-auth-clerk": "workspace:0.8.23",
"jazz-react": "workspace:0.8.23",
"jazz-tools": "workspace:0.8.23"
"cojson": "workspace:0.8.29",
"jazz-browser-auth-clerk": "workspace:0.8.29",
"jazz-react": "workspace:0.8.29",
"jazz-tools": "workspace:0.8.29"
},
"peerDependencies": {
"react": "^18.2.0"

View File

@@ -1,5 +1,23 @@
# jazz-browser-media-images
## 0.8.21
### Patch Changes
- jazz-tools@0.8.29
## 0.8.20
### Patch Changes
- jazz-tools@0.8.28
## 0.8.19
### Patch Changes
- jazz-tools@0.8.27
## 0.8.18
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-native-media-images",
"version": "0.8.18",
"version": "0.8.21",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,33 @@
# jazz-browser
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson-transport-ws@0.8.29
- cojson@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- cojson-transport-ws@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- cojson-transport-ws@0.8.27
- jazz-tools@0.8.27
## 0.8.23
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-native",
"version": "0.8.23",
"version": "0.8.29",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",

View File

@@ -1,5 +1,45 @@
# jazz-react
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
- jazz-browser@0.8.29
- jazz-tools@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
- jazz-browser@0.8.28
- jazz-tools@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
- jazz-browser@0.8.27
- jazz-tools@0.8.27
## 0.8.26
### Patch Changes
- 59d37df: add autologin option to DemoAuth to skip login
## 0.8.24
### Patch Changes
- jazz-browser@0.8.24
## 0.8.23
### Patch Changes

Some files were not shown because too many files have changed in this diff Show More