Compare commits
20 Commits
jazz-react
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be492a8184 | ||
|
|
90149ac411 | ||
|
|
7bae6e43b7 | ||
|
|
32c2435cb1 | ||
|
|
64feacd2c1 | ||
|
|
62bbe9a09b | ||
|
|
4dd80a65da | ||
|
|
52dd1d37ab | ||
|
|
b75df6fa5c | ||
|
|
b7639cffd3 | ||
|
|
21575f2e79 | ||
|
|
35587aaacc | ||
|
|
2398dedbae | ||
|
|
d545a3b8d6 | ||
|
|
dce673ff7a | ||
|
|
d18f6bf371 | ||
|
|
32b05b69a3 | ||
|
|
c1a5c3cad7 | ||
|
|
e82cf3dd71 | ||
|
|
c715587a54 |
@@ -1,5 +1,11 @@
|
||||
# @jazz-e2e/binarycostream
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@jazz-e2e/binarycostream",
|
||||
"private": true,
|
||||
"version": "0.0.87",
|
||||
"version": "0.0.88",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -17,7 +17,7 @@
|
||||
"cojson": "workspace:0.8.5",
|
||||
"hash-slash": "workspace:0.2.1",
|
||||
"is-ci": "^3.0.1",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @jazz-e2e/covalues
|
||||
|
||||
## 0.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@jazz-e2e/covalues",
|
||||
"private": true,
|
||||
"version": "0.0.86",
|
||||
"version": "0.0.87",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-example-book-shelf
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser-media-images@0.8.7
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-example-book-shelf",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -11,8 +11,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-browser-media-images": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-browser-media-images": "workspace:0.8.7",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"next": "14.2.5",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
- jazz-react-auth-clerk@0.8.7
|
||||
|
||||
## 0.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat-clerk",
|
||||
"private": true,
|
||||
"version": "0.0.86",
|
||||
"version": "0.0.87",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -23,8 +23,8 @@
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.8.5",
|
||||
"hash-slash": "workspace:0.2.1",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-react-auth-clerk": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-rn-clerk
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b7639cf: feat(react-native): replaced react-native-mmkv with expo-secure-store and initialize it by default as kvStore in createJazzRNApp() (BREAKING)
|
||||
- Updated dependencies [b7639cf]
|
||||
- jazz-react-native@0.8.8
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [32b05b6]
|
||||
- jazz-react-native-media-images@0.8.6
|
||||
- jazz-react-native@0.8.7
|
||||
- jazz-react-auth-clerk@0.8.7
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,45 +1,46 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "jazz-chat-rn-clerk",
|
||||
"scheme": "jazz-chat-rn-clerk",
|
||||
"slug": "jazz-chat-rn-clerk",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/images/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.jazz.chatrnclerk"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "com.jazz.chatrnclerk"
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
"expo-build-properties",
|
||||
{
|
||||
"ios": {
|
||||
"newArchEnabled": true
|
||||
},
|
||||
"android": {
|
||||
"newArchEnabled": true
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"extra": {
|
||||
"eas": {
|
||||
"projectId": "ca3d46e5-a10a-47ec-9d77-3b841e1c62d4"
|
||||
}
|
||||
"expo": {
|
||||
"name": "jazz-chat-rn-clerk",
|
||||
"scheme": "jazz-chat-rn-clerk",
|
||||
"slug": "jazz-chat-rn-clerk",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/images/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.jazz.chatrnclerk"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "com.jazz.chatrnclerk"
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
"expo-build-properties",
|
||||
{
|
||||
"ios": {
|
||||
"newArchEnabled": true
|
||||
},
|
||||
"android": {
|
||||
"newArchEnabled": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"expo-secure-store"
|
||||
],
|
||||
"extra": {
|
||||
"eas": {
|
||||
"projectId": "ca3d46e5-a10a-47ec-9d77-3b841e1c62d4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.3",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { createJazzRNApp } from "jazz-react-native";
|
||||
import { MMKVStorage } from "./mmkv-storage";
|
||||
|
||||
const nativeStorage = new MMKVStorage();
|
||||
|
||||
export const Jazz = createJazzRNApp({ nativeStorage });
|
||||
export const Jazz = createJazzRNApp();
|
||||
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { MMKV } from "react-native-mmkv";
|
||||
import type { NativeStorage } from "jazz-react-native";
|
||||
|
||||
const storage = new MMKV();
|
||||
|
||||
export class MMKVStorage implements NativeStorage {
|
||||
get(key: string): Promise<string | undefined> {
|
||||
return Promise.resolve(storage.getString(key));
|
||||
}
|
||||
|
||||
set(key: string, value: string): Promise<void> {
|
||||
storage.set(key, value);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
delete(key: string): Promise<void> {
|
||||
storage.delete(key);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
clearAll(): Promise<void> {
|
||||
storage.clearAll();
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_ZXZpZGVudC1kYW5lLTg5LmNsZXJrLmFjY291bnRzLmRldiQ
|
||||
@@ -1,5 +1,20 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b7639cf: feat(react-native): replaced react-native-mmkv with expo-secure-store and initialize it by default as kvStore in createJazzRNApp() (BREAKING)
|
||||
- Updated dependencies [b7639cf]
|
||||
- jazz-react-native@0.8.8
|
||||
|
||||
## 1.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [32b05b6]
|
||||
- jazz-react-native@0.8.7
|
||||
|
||||
## 1.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,46 +1,47 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "jazz-chat-rn",
|
||||
"scheme": "jazz-chat-rn",
|
||||
"slug": "jazz-chat-rn",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.jazz.chatrn"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "com.jazz.chatrn"
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
"expo-build-properties",
|
||||
{
|
||||
"ios": {
|
||||
"newArchEnabled": true
|
||||
},
|
||||
"android": {
|
||||
"newArchEnabled": true
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"extra": {
|
||||
"eas": {
|
||||
"projectId": "e0e61872-1906-4c84-b9d8-9be77355cad0"
|
||||
}
|
||||
},
|
||||
"owner": "paxx"
|
||||
}
|
||||
"expo": {
|
||||
"name": "jazz-chat-rn",
|
||||
"scheme": "jazz-chat-rn",
|
||||
"slug": "jazz-chat-rn",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"ios": {
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.jazz.chatrn"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"package": "com.jazz.chatrn"
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
"expo-build-properties",
|
||||
{
|
||||
"ios": {
|
||||
"newArchEnabled": true
|
||||
},
|
||||
"android": {
|
||||
"newArchEnabled": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"expo-secure-store"
|
||||
],
|
||||
"extra": {
|
||||
"eas": {
|
||||
"projectId": "e0e61872-1906-4c84-b9d8-9be77355cad0"
|
||||
}
|
||||
},
|
||||
"owner": "paxx"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.5",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
@@ -23,6 +23,7 @@
|
||||
"expo-crypto": "~13.0.2",
|
||||
"expo-dev-client": "~4.0.28",
|
||||
"expo-linking": "~6.3.1",
|
||||
"expo-secure-store": "~13.0.2",
|
||||
"expo-status-bar": "~1.12.1",
|
||||
"expo-web-browser": "~13.0.3",
|
||||
"jazz-react-native": "workspace:*",
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { createJazzRNApp } from "jazz-react-native";
|
||||
import { MMKVStorage } from "./mmkv-storage";
|
||||
|
||||
const nativeStorage = new MMKVStorage();
|
||||
|
||||
export const Jazz = createJazzRNApp({ nativeStorage });
|
||||
export const Jazz = createJazzRNApp();
|
||||
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { MMKV } from "react-native-mmkv";
|
||||
import type { NativeStorage } from "jazz-react-native";
|
||||
|
||||
const storage = new MMKV();
|
||||
|
||||
export class MMKVStorage implements NativeStorage {
|
||||
get(key: string): Promise<string | undefined> {
|
||||
return Promise.resolve(storage.getString(key));
|
||||
}
|
||||
|
||||
set(key: string, value: string): Promise<void> {
|
||||
storage.set(key, value);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
delete(key: string): Promise<void> {
|
||||
storage.delete(key);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
clearAll(): Promise<void> {
|
||||
storage.clearAll();
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.88",
|
||||
"version": "0.0.89",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -24,7 +24,7 @@
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.8.5",
|
||||
"hash-slash": "workspace:0.2.1",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.65
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e82cf3d]
|
||||
- cojson-transport-ws@0.8.7
|
||||
|
||||
## 0.0.64
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector",
|
||||
"private": true,
|
||||
"version": "0.0.64",
|
||||
"version": "0.0.65",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -16,7 +16,7 @@
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:0.8.5",
|
||||
"cojson-transport-ws": "workspace:0.8.6",
|
||||
"cojson-transport-ws": "workspace:0.8.7",
|
||||
"hash-slash": "workspace:0.2.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
||||
@@ -9,11 +9,12 @@ module.exports = {
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
plugins: ['react-refresh', "eslint-plugin-react-compiler"],
|
||||
rules: {
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
"react-compiler/react-compiler": "error"
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.9",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"lucide-react": "^0.274.0",
|
||||
"react": "^18.2.0",
|
||||
@@ -38,6 +38,7 @@
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint": "^8.46.0",
|
||||
"eslint-plugin-react-compiler": "0.0.0-experimental-fa06e2c-20241014",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.3",
|
||||
"postcss": "^8.4.27",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { usePlayState } from "./lib/audio/usePlayState";
|
||||
import { SidePanel } from "./components/SidePanel";
|
||||
import { FileUploadButton } from "./components/FileUploadButton";
|
||||
import { Button } from "./components/ui/button";
|
||||
import { createNewPlaylist, uploadMusicTracks } from "./4_actions";
|
||||
import { createNewPlaylist, updatePlaylistTitle, uploadMusicTracks } from "./4_actions";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { ID } from "jazz-tools";
|
||||
import { Playlist } from "./1_schema";
|
||||
@@ -62,7 +62,7 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
|
||||
) => {
|
||||
if (!playlist) return;
|
||||
|
||||
playlist.title = evt.target.value;
|
||||
updatePlaylistTitle(playlist, evt.target.value);
|
||||
};
|
||||
|
||||
const handlePlaylistShareClick = async () => {
|
||||
|
||||
@@ -128,3 +128,19 @@ export async function addTrackToPlaylist(
|
||||
|
||||
playlist.tracks?.push(trackClone);
|
||||
}
|
||||
|
||||
export async function updatePlaylistTitle(playlist: Playlist, title: string) {
|
||||
playlist.title = title;
|
||||
}
|
||||
|
||||
export async function updateMusicTrackTitle(track: MusicTrack, title: string) {
|
||||
track.title = title;
|
||||
}
|
||||
|
||||
export async function updateActivePlaylist(playlist: Playlist, me: MusicaAccount) {
|
||||
me.root!.activePlaylist = playlist ?? me.root!.rootPlaylist;
|
||||
}
|
||||
|
||||
export async function updateActiveTrack(track: MusicTrack, me: MusicaAccount) {
|
||||
me.root!.activeTrack = track;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { MusicTrack, Playlist } from "@/1_schema";
|
||||
import { useRef, useState } from "react";
|
||||
import { getNextTrack, getPrevTrack } from "./lib/getters";
|
||||
import { BinaryCoStream, ID } from "jazz-tools";
|
||||
import { updateActivePlaylist, updateActiveTrack } from "./4_actions";
|
||||
|
||||
export function useMediaPlayer() {
|
||||
const { me } = useAccount();
|
||||
@@ -39,7 +40,7 @@ export function useMediaPlayer() {
|
||||
return;
|
||||
}
|
||||
|
||||
me.root.activeTrack = track;
|
||||
updateActiveTrack(track, me);
|
||||
|
||||
await playMedia(file);
|
||||
|
||||
@@ -52,7 +53,7 @@ export function useMediaPlayer() {
|
||||
const track = await getNextTrack(me);
|
||||
|
||||
if (track) {
|
||||
me.root.activeTrack = track;
|
||||
updateActiveTrack(track, me);
|
||||
await loadTrack(track);
|
||||
}
|
||||
}
|
||||
@@ -78,7 +79,7 @@ export function useMediaPlayer() {
|
||||
return;
|
||||
}
|
||||
|
||||
me.root.activePlaylist = playlist ?? me.root.rootPlaylist;
|
||||
updateActivePlaylist(playlist!, me);
|
||||
|
||||
await loadTrack(track);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { MoreHorizontal } from "lucide-react";
|
||||
import { ChangeEvent } from "react";
|
||||
import { Button } from "./ui/button";
|
||||
import { useAccount, useCoState } from "@/2_main";
|
||||
import { addTrackToPlaylist } from "@/4_actions";
|
||||
import { addTrackToPlaylist, updateMusicTrackTitle } from "@/4_actions";
|
||||
import { ID } from "jazz-tools";
|
||||
|
||||
export function MusicTrackRow({
|
||||
@@ -30,7 +30,8 @@ export function MusicTrackRow({
|
||||
|
||||
function handleTrackTitleChange(evt: ChangeEvent<HTMLInputElement>) {
|
||||
if (!track) return;
|
||||
track.title = evt.target.value;
|
||||
|
||||
updateMusicTrackTitle(track, evt.target.value);
|
||||
}
|
||||
|
||||
const { me } = useAccount({
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -11,7 +11,7 @@
|
||||
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
|
||||
},
|
||||
"dependencies": {
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
||||
@@ -5,9 +5,13 @@ import Table from "./components/table";
|
||||
import NewItemModal from "./components/new-item-modal";
|
||||
import InviteModal from "./components/invite-modal";
|
||||
|
||||
import { saveItem, deleteItem, createFolder, updateItem } from "./4_actions";
|
||||
import { saveItem, deleteItem, createFolder, updateItem, addSharedFolder } from "./4_actions";
|
||||
import { Alert, AlertDescription } from "./components/alert";
|
||||
import { Folder, FolderList, PasswordItem } from "./1_schema";
|
||||
import {
|
||||
Folder,
|
||||
FolderList,
|
||||
PasswordItem,
|
||||
} from "./1_schema";
|
||||
import { useAccount, useCoState } from "./2_main";
|
||||
import { CoMapInit, Group, ID } from "jazz-tools";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
@@ -17,20 +21,19 @@ const VaultPage: React.FC = () => {
|
||||
const { me, logOut } = useAccount();
|
||||
const sharedFolderId = useParams<{ sharedFolderId: ID<Folder> }>()
|
||||
.sharedFolderId;
|
||||
const sharedFolder = useCoState(Folder, sharedFolderId);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (!sharedFolderId || !sharedFolder || !me.root?.folders) return;
|
||||
const existsIndex = me.root?.folders.findIndex(
|
||||
(f) => f?.id === sharedFolder.id
|
||||
);
|
||||
if (existsIndex > -1) {
|
||||
me.root?.folders?.splice(existsIndex, 1);
|
||||
}
|
||||
me.root?.folders?.push(sharedFolder);
|
||||
navigate("/vault");
|
||||
}, [sharedFolder, me.root?.folders, sharedFolderId, navigate]);
|
||||
if (!sharedFolderId) return;
|
||||
|
||||
addSharedFolder(sharedFolderId, me).then(() => {
|
||||
navigate("/vault");
|
||||
});
|
||||
|
||||
// We want to trigger this only on mount
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const items = me.root?.folders?.flatMap(
|
||||
(folder) =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Group } from "jazz-tools";
|
||||
import { Group, ID } from "jazz-tools";
|
||||
import {
|
||||
Folder,
|
||||
PasswordItem,
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import { CoMapInit } from "jazz-tools";
|
||||
import { createInviteLink } from "jazz-react";
|
||||
import { PasswordItemFormValues } from "./types";
|
||||
import { waitForCoValue } from "./lib/waitForCoValue";
|
||||
|
||||
export const saveItem = (item: CoMapInit<PasswordItem>): PasswordItem => {
|
||||
const passwordItem = PasswordItem.create(item, {
|
||||
@@ -54,3 +55,24 @@ export const shareFolder = (
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export async function addSharedFolder(
|
||||
sharedFolderId: ID<Folder>,
|
||||
me: PasswordManagerAccount) {
|
||||
const [sharedFolder, account] = await Promise.all([
|
||||
await waitForCoValue(Folder, sharedFolderId, me, Boolean, {}),
|
||||
await waitForCoValue(PasswordManagerAccount, me.id, me, Boolean, {
|
||||
root: {
|
||||
folders: [],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!account.root?.folders) return;
|
||||
|
||||
const found = account.root.folders.some((f) => f?.id === sharedFolder.id);
|
||||
|
||||
if (!found) {
|
||||
account.root.folders.push(sharedFolder);
|
||||
}
|
||||
}
|
||||
|
||||
39
examples/password-manager/src/lib/waitForCoValue.ts
Normal file
39
examples/password-manager/src/lib/waitForCoValue.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
Account,
|
||||
CoValue,
|
||||
CoValueClass,
|
||||
DepthsIn,
|
||||
ID,
|
||||
subscribeToCoValue,
|
||||
} from "jazz-tools";
|
||||
|
||||
export function waitForCoValue<T extends CoValue>(
|
||||
coMap: CoValueClass<T>,
|
||||
valueId: ID<T>,
|
||||
account: Account,
|
||||
predicate: (value: T) => boolean,
|
||||
depth: DepthsIn<T>
|
||||
) {
|
||||
return new Promise<T>((resolve) => {
|
||||
function subscribe() {
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
coMap,
|
||||
valueId,
|
||||
account,
|
||||
depth,
|
||||
(value) => {
|
||||
if (predicate(value)) {
|
||||
resolve(value);
|
||||
unsubscribe();
|
||||
}
|
||||
},
|
||||
() => {
|
||||
unsubscribe();
|
||||
setTimeout(subscribe, 100);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
subscribe();
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.106
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser-media-images@0.8.7
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.105",
|
||||
"version": "0.0.106",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -23,8 +23,8 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-browser-media-images": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-browser-media-images": "workspace:0.8.7",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
@@ -50,7 +50,7 @@
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.3",
|
||||
"is-ci": "^3.0.1",
|
||||
"jazz-run": "workspace:0.8.6",
|
||||
"jazz-run": "workspace:0.8.7",
|
||||
"postcss": "^8.4.27",
|
||||
"tailwindcss": "3.3.2",
|
||||
"typescript": "^5.3.3",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.104",
|
||||
"version": "0.0.105",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -20,7 +20,7 @@
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"lucide-react": "^0.274.0",
|
||||
"qrcode": "^1.5.3",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# cojson-transport-nodejs-ws
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e82cf3d: Enable WebSocket batching on client peers
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cojson-transport-ws",
|
||||
"type": "module",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -25,7 +25,7 @@ export function createWebSocketPeer({
|
||||
websocket,
|
||||
role,
|
||||
expectPings = true,
|
||||
batchingByDefault = false, // Keeping this false until we release batching upgrade to the mesh
|
||||
batchingByDefault = true,
|
||||
}: CreateWebSocketPeerOpts): Peer {
|
||||
const incoming = new cojsonInternals.Channel<
|
||||
SyncMessage | DisconnectedError | PingTimeoutError
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser-auth-clerk",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.5",
|
||||
"jazz-browser": "workspace:0.8.6",
|
||||
"jazz-browser": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser-media-images",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -8,7 +8,7 @@
|
||||
"dependencies": {
|
||||
"@types/image-blob-reduce": "^4.1.1",
|
||||
"image-blob-reduce": "^4.1.0",
|
||||
"jazz-browser": "workspace:0.8.6",
|
||||
"jazz-browser": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"pica": "^9.0.1",
|
||||
"typescript": "^5.3.3"
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e82cf3d]
|
||||
- cojson-transport-ws@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -9,7 +9,7 @@
|
||||
"@scure/bip39": "^1.3.0",
|
||||
"cojson": "workspace:0.8.5",
|
||||
"cojson-storage-indexeddb": "workspace:0.8.5",
|
||||
"cojson-transport-ws": "workspace:0.8.6",
|
||||
"cojson-transport-ws": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-autosub
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e82cf3d]
|
||||
- cojson-transport-ws@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
"types": "src/index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.5",
|
||||
"cojson-transport-ws": "workspace:0.8.6",
|
||||
"cojson-transport-ws": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser-auth-clerk@0.8.7
|
||||
- jazz-react@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react-auth-clerk",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.tsx",
|
||||
@@ -11,8 +11,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.8.5",
|
||||
"jazz-browser-auth-clerk": "workspace:0.8.6",
|
||||
"jazz-react": "workspace:0.8.6",
|
||||
"jazz-browser-auth-clerk": "workspace:0.8.7",
|
||||
"jazz-react": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 32b05b6: weaker peer dependencies
|
||||
|
||||
## 0.8.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react-native-media-images",
|
||||
"version": "0.8.5",
|
||||
"version": "0.8.6",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -15,9 +15,9 @@
|
||||
"react-native": "~0.74.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@bam.tech/react-native-image-resizer": "^3.0.10",
|
||||
"expo-file-system": "^17.0.1",
|
||||
"react-native": "~0.74.5"
|
||||
"@bam.tech/react-native-image-resizer": "*",
|
||||
"expo-file-system": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.8.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b7639cf: feat(react-native): replaced react-native-mmkv with expo-secure-store and initialize it by default as kvStore in createJazzRNApp() (BREAKING)
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 32b05b6: weaker peer dependencies
|
||||
- Updated dependencies [e82cf3d]
|
||||
- cojson-transport-ws@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react-native",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.8",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -22,16 +22,16 @@
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/netinfo": "^11.4.1",
|
||||
"expo-linking": "~6.3.1",
|
||||
"react-native": "0.74.2",
|
||||
"react-native-mmkv": "3.0.1"
|
||||
"@react-native-community/netinfo": "*",
|
||||
"expo-linking": "*",
|
||||
"expo-secure-store": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/netinfo": "^11.3.1",
|
||||
"expo-linking": "~6.3.1",
|
||||
"react-native": "~0.74.5",
|
||||
"react-native-mmkv": "3.0.1"
|
||||
"expo-secure-store": "~13.0.2",
|
||||
"react-native": "~0.74.5"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AgentSecret } from "cojson";
|
||||
import { Account, AuthMethod, AuthResult, ID } from "jazz-tools";
|
||||
import NativeStorageContext, { NativeStorage } from "../native-storage.js";
|
||||
import { KvStore, KvStoreContext } from "../storage/kv-store-context.js";
|
||||
|
||||
type StorageData = {
|
||||
accountID: ID<Account>;
|
||||
@@ -26,7 +26,7 @@ const localStorageKey = "demo-auth-logged-in-secret";
|
||||
export class RNDemoAuth implements AuthMethod {
|
||||
private constructor(
|
||||
private driver: RNDemoAuth.Driver,
|
||||
private storage: NativeStorage,
|
||||
private kvStore: KvStore,
|
||||
) {}
|
||||
|
||||
public static async init(
|
||||
@@ -38,40 +38,40 @@ export class RNDemoAuth implements AuthMethod {
|
||||
};
|
||||
},
|
||||
) {
|
||||
const storage = NativeStorageContext.getInstance().getStorage();
|
||||
const kvStore = KvStoreContext.getInstance().getStorage();
|
||||
for (const [name, credentials] of Object.entries(seedAccounts || {})) {
|
||||
const storageData = JSON.stringify(
|
||||
credentials satisfies StorageData,
|
||||
);
|
||||
if (
|
||||
!(
|
||||
(await storage.get("demo-auth-existing-users"))?.split(
|
||||
(await kvStore.get("demo-auth-existing-users"))?.split(
|
||||
",",
|
||||
) as string[] | undefined
|
||||
)?.includes(name)
|
||||
) {
|
||||
const existingUsers = await storage.get(
|
||||
const existingUsers = await kvStore.get(
|
||||
"demo-auth-existing-users",
|
||||
);
|
||||
if (existingUsers) {
|
||||
await storage.set(
|
||||
await kvStore.set(
|
||||
"demo-auth-existing-users",
|
||||
existingUsers + "," + name,
|
||||
);
|
||||
} else {
|
||||
await storage.set("demo-auth-existing-users", name);
|
||||
await kvStore.set("demo-auth-existing-users", name);
|
||||
}
|
||||
}
|
||||
await storage.set("demo-auth-existing-users-" + name, storageData);
|
||||
await kvStore.set("demo-auth-existing-users-" + name, storageData);
|
||||
}
|
||||
return new RNDemoAuth(driver, storage);
|
||||
return new RNDemoAuth(driver, kvStore);
|
||||
}
|
||||
|
||||
async start() {
|
||||
try {
|
||||
if (await this.storage.get(localStorageKey)) {
|
||||
if (await this.kvStore.get(localStorageKey)) {
|
||||
const localStorageData = JSON.parse(
|
||||
(await this.storage.get(localStorageKey)) ?? "{}",
|
||||
(await this.kvStore.get(localStorageKey)) ?? "{}",
|
||||
) as StorageData;
|
||||
|
||||
const accountID = localStorageData.accountID as ID<Account>;
|
||||
@@ -87,7 +87,7 @@ export class RNDemoAuth implements AuthMethod {
|
||||
this.driver.onError(error);
|
||||
},
|
||||
logOut: async () => {
|
||||
void (await this.storage.delete(localStorageKey));
|
||||
void (await this.kvStore.delete(localStorageKey));
|
||||
},
|
||||
} satisfies AuthResult;
|
||||
} else {
|
||||
@@ -109,7 +109,7 @@ export class RNDemoAuth implements AuthMethod {
|
||||
|
||||
// Retrieve the list of existing users
|
||||
const existingUsers =
|
||||
await this.storage.get(
|
||||
await this.kvStore.get(
|
||||
"demo-auth-existing-users",
|
||||
);
|
||||
const existingUsernames = existingUsers
|
||||
@@ -129,11 +129,11 @@ export class RNDemoAuth implements AuthMethod {
|
||||
}
|
||||
|
||||
// Save credentials using the unique username
|
||||
await this.storage.set(
|
||||
await this.kvStore.set(
|
||||
localStorageKey,
|
||||
storageData,
|
||||
);
|
||||
await this.storage.set(
|
||||
await this.kvStore.set(
|
||||
"demo-auth-existing-users-" +
|
||||
uniqueUsername,
|
||||
storageData,
|
||||
@@ -143,7 +143,7 @@ export class RNDemoAuth implements AuthMethod {
|
||||
const updatedUsers = existingUsers
|
||||
? `${existingUsers},${uniqueUsername}`
|
||||
: uniqueUsername;
|
||||
await this.storage.set(
|
||||
await this.kvStore.set(
|
||||
"demo-auth-existing-users",
|
||||
updatedUsers,
|
||||
);
|
||||
@@ -157,7 +157,7 @@ export class RNDemoAuth implements AuthMethod {
|
||||
this.driver.onError(error);
|
||||
},
|
||||
logOut: async () => {
|
||||
void (await this.storage.delete(
|
||||
void (await this.kvStore.delete(
|
||||
localStorageKey,
|
||||
));
|
||||
},
|
||||
@@ -166,7 +166,7 @@ export class RNDemoAuth implements AuthMethod {
|
||||
getExistingUsers: async () => {
|
||||
return (
|
||||
(
|
||||
await this.storage.get(
|
||||
await this.kvStore.get(
|
||||
"demo-auth-existing-users",
|
||||
)
|
||||
)?.split(",") ?? []
|
||||
@@ -174,12 +174,12 @@ export class RNDemoAuth implements AuthMethod {
|
||||
},
|
||||
logInAs: async (existingUser) => {
|
||||
const storageData = JSON.parse(
|
||||
(await this.storage.get(
|
||||
(await this.kvStore.get(
|
||||
"demo-auth-existing-users-" + existingUser,
|
||||
)) ?? "{}",
|
||||
) as StorageData;
|
||||
|
||||
await this.storage.set(
|
||||
await this.kvStore.set(
|
||||
localStorageKey,
|
||||
JSON.stringify(storageData),
|
||||
);
|
||||
@@ -197,7 +197,7 @@ export class RNDemoAuth implements AuthMethod {
|
||||
this.driver.onError(error);
|
||||
},
|
||||
logOut: async () => {
|
||||
void (await this.storage.delete(
|
||||
void (await this.kvStore.delete(
|
||||
localStorageKey,
|
||||
));
|
||||
},
|
||||
@@ -214,6 +214,6 @@ export class RNDemoAuth implements AuthMethod {
|
||||
}
|
||||
|
||||
async function logOut() {
|
||||
const storage = NativeStorageContext.getInstance().getStorage();
|
||||
void (await storage.delete(localStorageKey));
|
||||
const kvStore = KvStoreContext.getInstance().getStorage();
|
||||
void (await kvStore.delete(localStorageKey));
|
||||
}
|
||||
|
||||
@@ -18,13 +18,12 @@ import {
|
||||
import { PureJSCrypto } from "jazz-tools/native";
|
||||
import { RawAccountID } from "cojson";
|
||||
import { createWebSocketPeer } from "cojson-transport-ws";
|
||||
import { MMKV } from "react-native-mmkv";
|
||||
import NetInfo from "@react-native-community/netinfo";
|
||||
import * as Linking from "expo-linking";
|
||||
|
||||
export { RNDemoAuth } from "./auth/DemoAuthMethod.js";
|
||||
|
||||
import { NativeStorageContext } from "./native-storage.js";
|
||||
import { KvStoreContext } from "./storage/kv-store-context.js";
|
||||
|
||||
/** @category Context Creation */
|
||||
export type BrowserContext<Acc extends Account> = {
|
||||
@@ -182,12 +181,12 @@ export async function provideLockSession(
|
||||
) {
|
||||
const sessionDone = () => {};
|
||||
|
||||
const storage = NativeStorageContext.getInstance().getStorage();
|
||||
const kvStore = KvStoreContext.getInstance().getStorage();
|
||||
|
||||
const sessionID =
|
||||
((await storage.get(accountID)) as SessionID) ||
|
||||
((await kvStore.get(accountID)) as SessionID) ||
|
||||
crypto.newRandomSessionID(accountID as RawAccountID | AgentID);
|
||||
await storage.set(accountID, sessionID);
|
||||
await kvStore.set(accountID, sessionID);
|
||||
|
||||
return Promise.resolve({
|
||||
sessionID,
|
||||
@@ -272,4 +271,4 @@ export function parseInviteLink<C extends CoValue>(
|
||||
|
||||
export * from "./provider.js";
|
||||
export * from "./auth/auth.js";
|
||||
export * from "./native-storage.js";
|
||||
export * from "./storage/kv-store-context.js";
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
export interface NativeStorage {
|
||||
get(key: string): Promise<string | undefined>;
|
||||
set(key: string, value: string): Promise<void>;
|
||||
delete(key: string): Promise<void>;
|
||||
clearAll(): Promise<void>;
|
||||
}
|
||||
|
||||
export class NativeStorageContext {
|
||||
private static instance: NativeStorageContext;
|
||||
private storageInstance: NativeStorage | null = null;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): NativeStorageContext {
|
||||
if (!NativeStorageContext.instance) {
|
||||
NativeStorageContext.instance = new NativeStorageContext();
|
||||
}
|
||||
return NativeStorageContext.instance;
|
||||
}
|
||||
|
||||
public initialize(db: NativeStorage): void {
|
||||
if (!this.storageInstance) {
|
||||
this.storageInstance = db;
|
||||
}
|
||||
}
|
||||
|
||||
public getStorage(): NativeStorage {
|
||||
if (!this.storageInstance) {
|
||||
throw new Error("Storage instance is not initialized.");
|
||||
}
|
||||
return this.storageInstance;
|
||||
}
|
||||
}
|
||||
|
||||
export default NativeStorageContext;
|
||||
@@ -16,25 +16,26 @@ import {
|
||||
BrowserContext,
|
||||
BrowserGuestContext,
|
||||
createJazzRNContext,
|
||||
NativeStorageContext,
|
||||
NativeStorage,
|
||||
KvStoreContext,
|
||||
parseInviteLink,
|
||||
} from "./index.js";
|
||||
import { Linking } from "react-native";
|
||||
import { ExpoSecureStoreAdapter } from "./storage/expo-secure-store-adapter.js";
|
||||
|
||||
/** @category Context & Hooks */
|
||||
export function createJazzRNApp<Acc extends Account>({
|
||||
nativeStorage,
|
||||
kvStore = new ExpoSecureStoreAdapter(),
|
||||
AccountSchema = Account as unknown as AccountClass<Acc>,
|
||||
}: {
|
||||
nativeStorage: NativeStorage;
|
||||
AccountSchema?: AccountClass<Acc>;
|
||||
}): JazzReactApp<Acc> {
|
||||
} = {}): JazzReactApp<Acc> {
|
||||
const JazzContext = React.createContext<
|
||||
BrowserContext<Acc> | BrowserGuestContext | undefined
|
||||
>(undefined);
|
||||
|
||||
NativeStorageContext.getInstance().initialize(nativeStorage);
|
||||
if (!kvStore) {
|
||||
throw new Error("kvStore is required");
|
||||
}
|
||||
|
||||
KvStoreContext.getInstance().initialize(kvStore);
|
||||
|
||||
function Provider({
|
||||
children,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import * as SecureStore from "expo-secure-store";
|
||||
import type { KvStore } from "./kv-store-context.js";
|
||||
|
||||
export class ExpoSecureStoreAdapter implements KvStore {
|
||||
get(key: string): Promise<string | null> {
|
||||
return SecureStore.getItemAsync(key, {
|
||||
requireAuthentication: SecureStore.canUseBiometricAuthentication(),
|
||||
keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK,
|
||||
});
|
||||
}
|
||||
|
||||
async set(key: string, value: string): Promise<void> {
|
||||
return SecureStore.setItemAsync(key, value, {
|
||||
requireAuthentication: SecureStore.canUseBiometricAuthentication(),
|
||||
keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK,
|
||||
});
|
||||
}
|
||||
|
||||
async delete(key: string): Promise<void> {
|
||||
return SecureStore.deleteItemAsync(key, {
|
||||
requireAuthentication: SecureStore.canUseBiometricAuthentication(),
|
||||
keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK,
|
||||
});
|
||||
}
|
||||
|
||||
async clearAll(): Promise<void> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
}
|
||||
35
packages/jazz-react-native/src/storage/kv-store-context.ts
Normal file
35
packages/jazz-react-native/src/storage/kv-store-context.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export interface KvStore {
|
||||
get(key: string): Promise<string | null>;
|
||||
set(key: string, value: string): Promise<void>;
|
||||
delete(key: string): Promise<void>;
|
||||
clearAll(): Promise<void>;
|
||||
}
|
||||
|
||||
export class KvStoreContext {
|
||||
private static instance: KvStoreContext;
|
||||
private storageInstance: KvStore | null = null;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): KvStoreContext {
|
||||
if (!KvStoreContext.instance) {
|
||||
KvStoreContext.instance = new KvStoreContext();
|
||||
}
|
||||
return KvStoreContext.instance;
|
||||
}
|
||||
|
||||
public initialize(store: KvStore): void {
|
||||
if (!this.storageInstance) {
|
||||
this.storageInstance = store;
|
||||
}
|
||||
}
|
||||
|
||||
public getStorage(): KvStore {
|
||||
if (!this.storageInstance) {
|
||||
throw new Error("Storage instance is not initialized.");
|
||||
}
|
||||
return this.storageInstance;
|
||||
}
|
||||
}
|
||||
|
||||
export default KvStoreContext;
|
||||
@@ -1,5 +1,11 @@
|
||||
# jazz-react
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -8,7 +8,7 @@
|
||||
"dependencies": {
|
||||
"@scure/bip39": "^1.3.0",
|
||||
"cojson": "workspace:0.8.5",
|
||||
"jazz-browser": "workspace:0.8.6",
|
||||
"jazz-browser": "workspace:0.8.7",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
DeeplyLoaded,
|
||||
DepthsIn,
|
||||
ID,
|
||||
subscribeToCoValue,
|
||||
createCoValueObservable,
|
||||
} from "jazz-tools";
|
||||
|
||||
/** @category Context & Hooks */
|
||||
@@ -152,30 +152,38 @@ export function createJazzReactApp<Acc extends Account>({
|
||||
id: ID<V> | undefined,
|
||||
depth: D & DepthsIn<V> = [] as D & DepthsIn<V>,
|
||||
): DeeplyLoaded<V, D> | undefined {
|
||||
const [state, setState] = useState<{
|
||||
value: DeeplyLoaded<V, D> | undefined;
|
||||
}>({ value: undefined });
|
||||
const context = React.useContext(JazzContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useCoState must be used within a JazzProvider");
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) return;
|
||||
const [observable] = React.useState(() => createCoValueObservable());
|
||||
|
||||
return subscribeToCoValue(
|
||||
Schema,
|
||||
id,
|
||||
"me" in context ? context.me : context.guest,
|
||||
depth,
|
||||
(value) => {
|
||||
setState({ value });
|
||||
const value = React.useSyncExternalStore<
|
||||
DeeplyLoaded<V, D> | undefined
|
||||
>(
|
||||
React.useCallback(
|
||||
(callback) => {
|
||||
if (!id) return () => {};
|
||||
|
||||
const agent = "me" in context ? context.me : context.guest;
|
||||
|
||||
return observable.subscribe(
|
||||
Schema,
|
||||
id,
|
||||
agent,
|
||||
depth,
|
||||
callback,
|
||||
);
|
||||
},
|
||||
);
|
||||
}, [Schema, id, context]);
|
||||
[Schema, id, context],
|
||||
),
|
||||
() => observable.getCurrentValue(),
|
||||
() => observable.getCurrentValue(),
|
||||
);
|
||||
|
||||
return state.value;
|
||||
return value;
|
||||
}
|
||||
|
||||
function useAcceptInvite<V extends CoValue>({
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# jazz-run
|
||||
|
||||
## 0.8.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e82cf3d]
|
||||
- cojson-transport-ws@0.8.7
|
||||
|
||||
## 0.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"bin": "./dist/index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.8.6",
|
||||
"version": "0.8.7",
|
||||
"scripts": {
|
||||
"lint": "eslint . --ext ts,tsx",
|
||||
"format": "prettier --write './src/**/*.{ts,tsx}'",
|
||||
@@ -19,7 +19,7 @@
|
||||
"@effect/typeclass": "^0.25.5",
|
||||
"cojson": "workspace:0.8.5",
|
||||
"cojson-storage-sqlite": "workspace:0.8.5",
|
||||
"cojson-transport-ws": "workspace:0.8.6",
|
||||
"cojson-transport-ws": "workspace:0.8.7",
|
||||
"effect": "^3.6.5",
|
||||
"jazz-tools": "workspace:0.8.5",
|
||||
"ws": "^8.14.2"
|
||||
|
||||
@@ -213,6 +213,40 @@ export function subscribeToCoValue<V extends CoValue, Depth>(
|
||||
};
|
||||
}
|
||||
|
||||
export function createCoValueObservable<V extends CoValue, Depth>() {
|
||||
let currentValue: DeeplyLoaded<V, Depth> | undefined = undefined;
|
||||
|
||||
function subscribe(
|
||||
cls: CoValueClass<V>,
|
||||
id: ID<V>,
|
||||
as: Account | AnonymousJazzAgent,
|
||||
depth: Depth & DepthsIn<V>,
|
||||
listener: () => void,
|
||||
onUnavailable?: () => void,
|
||||
) {
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
cls,
|
||||
id,
|
||||
as,
|
||||
depth,
|
||||
(value) => {
|
||||
currentValue = value;
|
||||
listener();
|
||||
},
|
||||
onUnavailable,
|
||||
);
|
||||
|
||||
return unsubscribe
|
||||
}
|
||||
|
||||
const observable = {
|
||||
getCurrentValue: () => currentValue,
|
||||
subscribe,
|
||||
};
|
||||
|
||||
return observable;
|
||||
}
|
||||
|
||||
export function subscribeToExistingCoValue<V extends CoValue, Depth>(
|
||||
existing: V,
|
||||
depth: Depth & DepthsIn<V>,
|
||||
|
||||
@@ -21,7 +21,7 @@ export { ImageDefinition } from "./internal.js";
|
||||
export { CoValueBase, type CoValueClass } from "./internal.js";
|
||||
export type { DepthsIn, DeeplyLoaded } from "./internal.js";
|
||||
|
||||
export { loadCoValue, subscribeToCoValue } from "./internal.js";
|
||||
export { loadCoValue, subscribeToCoValue, createCoValueObservable } from "./internal.js";
|
||||
|
||||
export {
|
||||
type AuthMethod,
|
||||
|
||||
@@ -26,10 +26,10 @@ export class SubscriptionScope<Root extends CoValue> {
|
||||
>();
|
||||
rootEntry: {
|
||||
state: "loaded";
|
||||
value: Root;
|
||||
value: RawCoValue;
|
||||
rawUnsub: () => void;
|
||||
};
|
||||
onUpdate: (newRoot: Root) => void;
|
||||
scheduleUpdate: () => void;
|
||||
scheduledUpdate: boolean = false;
|
||||
cachedValues: { [id: ID<CoValue>]: CoValue } = {};
|
||||
parents: { [id: ID<CoValue>]: Set<ID<CoValue>> } = {};
|
||||
@@ -41,7 +41,7 @@ export class SubscriptionScope<Root extends CoValue> {
|
||||
) {
|
||||
this.rootEntry = {
|
||||
state: "loaded" as const,
|
||||
value: root,
|
||||
value: root._raw,
|
||||
rawUnsub: () => {}, // placeholder
|
||||
};
|
||||
this.entries.set(root.id, this.rootEntry);
|
||||
@@ -49,22 +49,21 @@ export class SubscriptionScope<Root extends CoValue> {
|
||||
subscriptionsScopes.set(root, this);
|
||||
|
||||
this.subscriber = root._loadedAs;
|
||||
this.onUpdate = onUpdate;
|
||||
this.scheduleUpdate = () => {
|
||||
const value = rootSchema.fromRaw(this.rootEntry.value) as Root;
|
||||
subscriptionsScopes.set(value, this);
|
||||
onUpdate(value);
|
||||
};
|
||||
|
||||
this.rootEntry.rawUnsub = root._raw.core.subscribe(
|
||||
(rawUpdate: RawCoValue | undefined) => {
|
||||
if (!rawUpdate) return;
|
||||
this.rootEntry.value = rootSchema.fromRaw(rawUpdate) as Root;
|
||||
// console.log("root update", this.rootEntry.value.toJSON());
|
||||
subscriptionsScopes.set(this.rootEntry.value, this);
|
||||
this.rootEntry.value = rawUpdate;
|
||||
this.scheduleUpdate();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
scheduleUpdate() {
|
||||
this.onUpdate(this.rootEntry.value);
|
||||
}
|
||||
|
||||
onRefAccessedOrSet(
|
||||
fromId: ID<CoValue>,
|
||||
accessedOrSetId: ID<CoValue> | undefined,
|
||||
|
||||
348
packages/jazz-tools/src/tests/subscribe.test.ts
Normal file
348
packages/jazz-tools/src/tests/subscribe.test.ts
Normal file
@@ -0,0 +1,348 @@
|
||||
const Crypto = await WasmCrypto.create();
|
||||
import { expect, describe, it, vi, onTestFinished } from "vitest";
|
||||
import { connectedPeers } from "cojson/src/streamUtils.js";
|
||||
import {
|
||||
Account,
|
||||
CoList,
|
||||
CoMap,
|
||||
CoStream,
|
||||
WasmCrypto,
|
||||
co,
|
||||
isControlledAccount,
|
||||
createJazzContext,
|
||||
fixedCredentialsAuth,
|
||||
} from "../index.web.js";
|
||||
import {
|
||||
BinaryCoStream,
|
||||
Group,
|
||||
randomSessionProvider,
|
||||
subscribeToCoValue,
|
||||
} from "../internal.js";
|
||||
|
||||
class ChatRoom extends CoMap {
|
||||
messages = co.ref(MessagesList);
|
||||
name = co.string;
|
||||
}
|
||||
|
||||
class Message extends CoMap {
|
||||
text = co.string;
|
||||
reactions = co.ref(ReactionsStream);
|
||||
attachment = co.optional.ref(BinaryCoStream);
|
||||
}
|
||||
|
||||
class MessagesList extends CoList.Of(co.ref(Message)) {}
|
||||
class ReactionsStream extends CoStream.Of(co.string) {}
|
||||
|
||||
async function setupAccount() {
|
||||
const me = await Account.create({
|
||||
creationProps: { name: "Hermes Puggington" },
|
||||
crypto: Crypto,
|
||||
});
|
||||
|
||||
const [initialAsPeer, secondPeer] = connectedPeers("initial", "second", {
|
||||
peer1role: "server",
|
||||
peer2role: "client",
|
||||
});
|
||||
|
||||
if (!isControlledAccount(me)) {
|
||||
throw "me is not a controlled account";
|
||||
}
|
||||
me._raw.core.node.syncManager.addPeer(secondPeer);
|
||||
const { account: meOnSecondPeer } = await createJazzContext({
|
||||
auth: fixedCredentialsAuth({
|
||||
accountID: me.id,
|
||||
secret: me._raw.agentSecret,
|
||||
}),
|
||||
sessionProvider: randomSessionProvider,
|
||||
peersToLoadFrom: [initialAsPeer],
|
||||
crypto: Crypto,
|
||||
});
|
||||
|
||||
return { me, meOnSecondPeer };
|
||||
}
|
||||
|
||||
function createChatRoom(me: Account | Group, name: string) {
|
||||
return ChatRoom.create(
|
||||
{ messages: MessagesList.create([], { owner: me }), name },
|
||||
{ owner: me },
|
||||
);
|
||||
}
|
||||
|
||||
function createMessage(me: Account | Group, text: string) {
|
||||
return Message.create(
|
||||
{ text, reactions: ReactionsStream.create([], { owner: me }) },
|
||||
{ owner: me },
|
||||
);
|
||||
}
|
||||
|
||||
describe("subscribeToCoValue", () => {
|
||||
it("subscribes to a CoMap", async () => {
|
||||
const { me, meOnSecondPeer } = await setupAccount();
|
||||
|
||||
const chatRoom = createChatRoom(me, "General");
|
||||
const updateFn = vi.fn();
|
||||
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
ChatRoom,
|
||||
chatRoom.id,
|
||||
meOnSecondPeer,
|
||||
{},
|
||||
updateFn,
|
||||
);
|
||||
|
||||
onTestFinished(unsubscribe);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(updateFn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: chatRoom.id,
|
||||
messages: null,
|
||||
name: "General",
|
||||
}),
|
||||
);
|
||||
|
||||
updateFn.mockClear();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(updateFn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: chatRoom.id,
|
||||
name: "General",
|
||||
messages: expect.any(Array),
|
||||
}),
|
||||
);
|
||||
|
||||
updateFn.mockClear();
|
||||
chatRoom.name = "Lounge";
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(updateFn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: chatRoom.id,
|
||||
name: "Lounge",
|
||||
messages: expect.any(Array),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("shouldn't fire updates until the declared load depth isn't reached", async () => {
|
||||
const { me, meOnSecondPeer } = await setupAccount();
|
||||
|
||||
const chatRoom = createChatRoom(me, "General");
|
||||
const updateFn = vi.fn();
|
||||
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
ChatRoom,
|
||||
chatRoom.id,
|
||||
meOnSecondPeer,
|
||||
{
|
||||
messages: [],
|
||||
},
|
||||
updateFn,
|
||||
);
|
||||
|
||||
onTestFinished(unsubscribe);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(updateFn).toHaveBeenCalledTimes(1);
|
||||
expect(updateFn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: chatRoom.id,
|
||||
name: "General",
|
||||
messages: expect.any(Array),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("should fire updates when a ref entity is updates", async () => {
|
||||
const { me, meOnSecondPeer } = await setupAccount();
|
||||
|
||||
const chatRoom = createChatRoom(me, "General");
|
||||
const message = createMessage(me, "Hello Luigi, are you ready to save the princess?");
|
||||
chatRoom.messages?.push(message);
|
||||
|
||||
const updateFn = vi.fn()
|
||||
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
ChatRoom,
|
||||
chatRoom.id,
|
||||
meOnSecondPeer,
|
||||
{
|
||||
messages: [{
|
||||
}],
|
||||
},
|
||||
updateFn,
|
||||
);
|
||||
|
||||
onTestFinished(unsubscribe);
|
||||
|
||||
await waitFor(() => {
|
||||
const lastValue = updateFn.mock.lastCall[0];
|
||||
|
||||
expect(lastValue?.messages?.[0]?.text).toBe(message.text);
|
||||
});
|
||||
|
||||
message.text = "Nevermind, she was gone to the supermarket";
|
||||
updateFn.mockClear();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const lastValue = updateFn.mock.lastCall[0];
|
||||
expect(lastValue?.messages?.[0]?.text).toBe("Nevermind, she was gone to the supermarket");
|
||||
});
|
||||
|
||||
it("should handle the updates as immutable changes", async () => {
|
||||
const { me, meOnSecondPeer } = await setupAccount();
|
||||
|
||||
const chatRoom = createChatRoom(me, "General");
|
||||
const message = createMessage(me, "Hello Luigi, are you ready to save the princess?");
|
||||
const message2 = createMessage(me, "Let's go!");
|
||||
chatRoom.messages?.push(message);
|
||||
chatRoom.messages?.push(message2);
|
||||
|
||||
const updateFn = vi.fn()
|
||||
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
ChatRoom,
|
||||
chatRoom.id,
|
||||
meOnSecondPeer,
|
||||
{
|
||||
messages: [{
|
||||
reactions: [],
|
||||
}],
|
||||
},
|
||||
updateFn,
|
||||
);
|
||||
|
||||
onTestFinished(unsubscribe);
|
||||
|
||||
await waitFor(() => {
|
||||
const lastValue = updateFn.mock.lastCall[0];
|
||||
|
||||
expect(lastValue?.messages?.[0]?.text).toBe(message.text);
|
||||
});
|
||||
|
||||
const initialValue = updateFn.mock.lastCall[0];
|
||||
const initialMessagesList = initialValue?.messages;
|
||||
const initialMessage1 = initialValue?.messages[0];
|
||||
const initialMessage2 = initialValue?.messages[1];
|
||||
const initialMessageReactions = initialValue?.messages[0].reactions;
|
||||
|
||||
message.reactions?.push("👍");
|
||||
|
||||
updateFn.mockClear();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const lastValue = updateFn.mock.lastCall[0];
|
||||
expect(lastValue).not.toBe(initialValue);
|
||||
expect(lastValue.messages).not.toBe(initialMessagesList);
|
||||
expect(lastValue.messages[0]).not.toBe(initialMessage1);
|
||||
expect(lastValue.messages[0].reactions).not.toBe(initialMessageReactions);
|
||||
|
||||
// This shouldn't change
|
||||
expect(lastValue.messages[1]).toBe(initialMessage2);
|
||||
|
||||
// TODO: The initial should point at that snapshot in time
|
||||
// expect(lastValue.messages).not.toBe(initialValue.messages);
|
||||
// expect(lastValue.messages[0]).not.toBe(initialValue.messages[0]);
|
||||
// expect(lastValue.messages[1]).toBe(initialValue.messages[1]);
|
||||
// expect(lastValue.messages[0].reactions).not.toBe(initialValue.messages[0].reactions);
|
||||
});
|
||||
|
||||
it("should keep the same identity on the ref entities when a property is updated", async () => {
|
||||
const { me, meOnSecondPeer } = await setupAccount();
|
||||
|
||||
const chatRoom = createChatRoom(me, "General");
|
||||
const message = createMessage(me, "Hello Luigi, are you ready to save the princess?");
|
||||
const message2 = createMessage(me, "Let's go!");
|
||||
chatRoom.messages?.push(message);
|
||||
chatRoom.messages?.push(message2);
|
||||
|
||||
const updateFn = vi.fn()
|
||||
|
||||
const unsubscribe = subscribeToCoValue(
|
||||
ChatRoom,
|
||||
chatRoom.id,
|
||||
meOnSecondPeer,
|
||||
{
|
||||
messages: [{
|
||||
reactions: [],
|
||||
}],
|
||||
},
|
||||
updateFn,
|
||||
);
|
||||
|
||||
onTestFinished(unsubscribe);
|
||||
|
||||
await waitFor(() => {
|
||||
const lastValue = updateFn.mock.lastCall[0];
|
||||
|
||||
expect(lastValue?.messages?.[0]?.text).toBe(message.text);
|
||||
expect(lastValue?.messages?.[1]?.text).toBe(message2.text);
|
||||
});
|
||||
|
||||
const initialValue = updateFn.mock.lastCall[0];
|
||||
chatRoom.name = "Me and Luigi";
|
||||
|
||||
updateFn.mockClear();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const lastValue = updateFn.mock.lastCall[0];
|
||||
expect(lastValue).not.toBe(initialValue);
|
||||
expect(lastValue.name).toBe("Me and Luigi");
|
||||
expect(initialValue.name).toBe("General");
|
||||
|
||||
expect(lastValue.messages).toBe(initialValue.messages);
|
||||
expect(lastValue.messages[0]).toBe(initialValue.messages[0]);
|
||||
expect(lastValue.messages[1]).toBe(initialValue.messages[1]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function waitFor(callback: () => boolean | void) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const checkPassed = () => {
|
||||
try {
|
||||
return { ok: callback(), error: null };
|
||||
} catch (error) {
|
||||
return { ok: false, error };
|
||||
}
|
||||
};
|
||||
|
||||
let retries = 0;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
const { ok, error } = checkPassed();
|
||||
|
||||
if (ok !== false) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
|
||||
if (++retries > 10) {
|
||||
clearInterval(interval);
|
||||
reject(error);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
125
pnpm-lock.yaml
generated
125
pnpm-lock.yaml
generated
@@ -49,7 +49,7 @@ importers:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -144,10 +144,10 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
jazz-browser-media-images:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-browser-media-images
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -223,7 +223,7 @@ importers:
|
||||
specifier: workspace:0.2.1
|
||||
version: link:../../packages/hash-slash
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -335,10 +335,10 @@ importers:
|
||||
specifier: workspace:0.2.1
|
||||
version: link:../../packages/hash-slash
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-react-auth-clerk:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react-auth-clerk
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -458,6 +458,9 @@ importers:
|
||||
expo-linking:
|
||||
specifier: ~6.3.1
|
||||
version: 6.3.1(expo@51.0.37(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2)))
|
||||
expo-secure-store:
|
||||
specifier: ~13.0.2
|
||||
version: 13.0.2(expo@51.0.37(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2)))
|
||||
expo-status-bar:
|
||||
specifier: ~1.12.1
|
||||
version: 1.12.1
|
||||
@@ -722,7 +725,7 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../../packages/cojson
|
||||
cojson-transport-ws:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/cojson-transport-ws
|
||||
hash-slash:
|
||||
specifier: workspace:0.2.1
|
||||
@@ -819,7 +822,7 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -867,6 +870,9 @@ importers:
|
||||
eslint:
|
||||
specifier: ^8.46.0
|
||||
version: 8.56.0
|
||||
eslint-plugin-react-compiler:
|
||||
specifier: 0.0.0-experimental-fa06e2c-20241014
|
||||
version: 0.0.0-experimental-fa06e2c-20241014(eslint@8.56.0)
|
||||
eslint-plugin-react-hooks:
|
||||
specifier: ^4.6.0
|
||||
version: 4.6.0(eslint@8.56.0)
|
||||
@@ -889,7 +895,7 @@ importers:
|
||||
examples/password-manager:
|
||||
dependencies:
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -968,10 +974,10 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
jazz-browser-media-images:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-browser-media-images
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1044,7 +1050,7 @@ importers:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
jazz-run:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-run
|
||||
postcss:
|
||||
specifier: ^8.4.27
|
||||
@@ -1082,7 +1088,7 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../../packages/jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1291,7 +1297,7 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../cojson-storage-indexeddb
|
||||
cojson-transport-ws:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../cojson-transport-ws
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1306,7 +1312,7 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../cojson
|
||||
jazz-browser:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../jazz-browser
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1325,7 +1331,7 @@ importers:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
jazz-browser:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../jazz-browser
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1347,7 +1353,7 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../cojson
|
||||
cojson-transport-ws:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../cojson-transport-ws
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1372,7 +1378,7 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../cojson
|
||||
jazz-browser:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../jazz-browser
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1397,10 +1403,10 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../cojson
|
||||
jazz-browser-auth-clerk:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../jazz-browser-auth-clerk
|
||||
jazz-react:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../jazz-react
|
||||
jazz-tools:
|
||||
specifier: workspace:0.8.5
|
||||
@@ -1440,12 +1446,12 @@ importers:
|
||||
expo-linking:
|
||||
specifier: ~6.3.1
|
||||
version: 6.3.1(expo@51.0.37(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2)))
|
||||
expo-secure-store:
|
||||
specifier: ~13.0.2
|
||||
version: 13.0.2(expo@51.0.37(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2)))
|
||||
react-native:
|
||||
specifier: ~0.74.5
|
||||
version: 0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1)
|
||||
react-native-mmkv:
|
||||
specifier: 3.0.1
|
||||
version: 3.0.1(react-native@0.74.5(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1)
|
||||
|
||||
packages/jazz-react-native-media-images:
|
||||
dependencies:
|
||||
@@ -1493,7 +1499,7 @@ importers:
|
||||
specifier: workspace:0.8.5
|
||||
version: link:../cojson-storage-sqlite
|
||||
cojson-transport-ws:
|
||||
specifier: workspace:0.8.5
|
||||
specifier: workspace:0.8.7
|
||||
version: link:../cojson-transport-ws
|
||||
effect:
|
||||
specifier: ^3.6.5
|
||||
@@ -1774,6 +1780,13 @@ packages:
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
||||
'@babel/plugin-proposal-private-methods@7.18.6':
|
||||
resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.0.0-0
|
||||
|
||||
'@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2':
|
||||
resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -3291,7 +3304,7 @@ packages:
|
||||
'@radix-ui/react-compose-refs@1.1.0':
|
||||
resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react': ^18.2.32
|
||||
react: 18.3.1
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
@@ -3375,8 +3388,8 @@ packages:
|
||||
'@radix-ui/react-focus-scope@1.1.0':
|
||||
resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
'@types/react': ^18.2.32
|
||||
'@types/react-dom': ^18.2.14
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1
|
||||
peerDependenciesMeta:
|
||||
@@ -3388,7 +3401,7 @@ packages:
|
||||
'@radix-ui/react-id@1.1.0':
|
||||
resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react': ^18.2.32
|
||||
react: 18.3.1
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
@@ -3410,8 +3423,8 @@ packages:
|
||||
'@radix-ui/react-popper@1.2.0':
|
||||
resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
'@types/react': ^18.2.32
|
||||
'@types/react-dom': ^18.2.14
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1
|
||||
peerDependenciesMeta:
|
||||
@@ -3488,8 +3501,8 @@ packages:
|
||||
'@radix-ui/react-primitive@2.0.0':
|
||||
resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
'@types/react': ^18.2.32
|
||||
'@types/react-dom': ^18.2.14
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1
|
||||
peerDependenciesMeta:
|
||||
@@ -5884,6 +5897,12 @@ packages:
|
||||
eslint-config-prettier:
|
||||
optional: true
|
||||
|
||||
eslint-plugin-react-compiler@0.0.0-experimental-fa06e2c-20241014:
|
||||
resolution: {integrity: sha512-tHntZz8Kx/6RgCLn7aDGfBQizqTUUfHEDaBcrvJi1GhKzgDxmAbdn85Y6z8eGSh4s0gufNWyO9WRCYLf0hP0ow==}
|
||||
engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0}
|
||||
peerDependencies:
|
||||
eslint: '>=7'
|
||||
|
||||
eslint-plugin-react-hooks@4.6.0:
|
||||
resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -6596,12 +6615,18 @@ packages:
|
||||
hermes-estree@0.19.1:
|
||||
resolution: {integrity: sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g==}
|
||||
|
||||
hermes-estree@0.20.1:
|
||||
resolution: {integrity: sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==}
|
||||
|
||||
hermes-estree@0.23.1:
|
||||
resolution: {integrity: sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==}
|
||||
|
||||
hermes-parser@0.19.1:
|
||||
resolution: {integrity: sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A==}
|
||||
|
||||
hermes-parser@0.20.1:
|
||||
resolution: {integrity: sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==}
|
||||
|
||||
hermes-parser@0.23.1:
|
||||
resolution: {integrity: sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==}
|
||||
|
||||
@@ -10331,6 +10356,12 @@ packages:
|
||||
peerDependencies:
|
||||
zod: ^3.18.0
|
||||
|
||||
zod-validation-error@3.4.0:
|
||||
resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
zod: ^3.18.0
|
||||
|
||||
zod@3.23.8:
|
||||
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
||||
|
||||
@@ -10653,6 +10684,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.25.2)':
|
||||
dependencies:
|
||||
'@babel/core': 7.25.2
|
||||
'@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
|
||||
'@babel/helper-plugin-utils': 7.24.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.2)':
|
||||
dependencies:
|
||||
'@babel/core': 7.25.2
|
||||
@@ -15891,6 +15930,18 @@ snapshots:
|
||||
'@types/eslint': 9.6.0
|
||||
eslint-config-prettier: 9.1.0(eslint@8.57.1)
|
||||
|
||||
eslint-plugin-react-compiler@0.0.0-experimental-fa06e2c-20241014(eslint@8.56.0):
|
||||
dependencies:
|
||||
'@babel/core': 7.25.2
|
||||
'@babel/parser': 7.25.6
|
||||
'@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.25.2)
|
||||
eslint: 8.56.0
|
||||
hermes-parser: 0.20.1
|
||||
zod: 3.23.8
|
||||
zod-validation-error: 3.4.0(zod@3.23.8)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-react-hooks@4.6.0(eslint@8.56.0):
|
||||
dependencies:
|
||||
eslint: 8.56.0
|
||||
@@ -16807,12 +16858,18 @@ snapshots:
|
||||
|
||||
hermes-estree@0.19.1: {}
|
||||
|
||||
hermes-estree@0.20.1: {}
|
||||
|
||||
hermes-estree@0.23.1: {}
|
||||
|
||||
hermes-parser@0.19.1:
|
||||
dependencies:
|
||||
hermes-estree: 0.19.1
|
||||
|
||||
hermes-parser@0.20.1:
|
||||
dependencies:
|
||||
hermes-estree: 0.20.1
|
||||
|
||||
hermes-parser@0.23.1:
|
||||
dependencies:
|
||||
hermes-estree: 0.23.1
|
||||
@@ -21015,4 +21072,8 @@ snapshots:
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
|
||||
zod-validation-error@3.4.0(zod@3.23.8):
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
|
||||
zod@3.23.8: {}
|
||||
|
||||
Reference in New Issue
Block a user