Compare commits

..

38 Commits

Author SHA1 Message Date
Anselm
e85ab79026 Manually trigger hashchange event for now 2024-10-08 12:06:57 +01:00
Anselm
5f3680e749 Manually trigger hashchange for now 2024-10-08 12:06:27 +01:00
Anselm
03c0d81ca1 Stop chat example from creating history entries 2024-10-08 12:00:44 +01:00
Anselm
428ec8c170 Limit number of messages and scroll to bottom 2024-10-08 11:31:50 +01:00
Anselm Eickhoff
4cc442babc Merge pull request #500 from gardencmp/trishalim-jazz-365
Set 2048 character limit per message to chat app
2024-10-08 12:13:29 +02:00
Anselm Eickhoff
1f9b94c0c7 Apply suggestions from code review
Let's clamp to 10 lines
2024-10-08 11:11:27 +01:00
Trisha Lim
4c9d2b5a41 Limit chat messages to display 20 lines max 2024-10-08 11:08:11 +01:00
Trisha Lim
183e384819 Center align loading text in chat app 2024-10-08 11:08:11 +01:00
Trisha Lim
7295abeac5 Fix: can't find input box in mobile til scrolling down 2024-10-08 11:08:11 +01:00
Trisha Lim
77f1351000 Set 2048 character limit per message to chat app 2024-10-08 11:00:15 +01:00
Anselm Eickhoff
ba3e09a2a0 Merge pull request #501 from gardencmp/fix/chat-crash
fix(localNode): do not crash the app when we fail to resolve the account agent
2024-10-08 11:59:38 +02:00
Guido D'Orsi
21890eb99d fix(localNode): do not crash the app when we fail to resolve the account agent 2024-10-08 11:55:15 +02:00
Guido D'Orsi
489de02696 chore: update lockfile 2024-10-08 11:54:38 +02:00
Anselm
a8d33d14c8 Release 2024-10-07 15:20:11 +01:00
Anselm Eickhoff
fd21db18fc Merge pull request #471 from gardencmp/JAZZ-314/react-native-proof-of-concept
React Native Support
2024-10-07 16:08:33 +02:00
pax-k
738940a634 fix: sherif lint - pin dependencies versions 2024-10-07 16:35:11 +03:00
pax-k
a0d3dcafdc chore: lint issues 2024-10-07 16:22:05 +03:00
pax-k
9bae5569de chore: pnpm lock 2024-10-07 16:18:44 +03:00
pax-k
6f6fcf25e7 Merge branch 'main' into JAZZ-314/react-native-proof-of-concept 2024-10-07 16:17:27 +03:00
pax-k
430cf732a6 fix: temporary skipErrorChecking for jazz-react in genDocs 2024-10-07 16:15:43 +03:00
pax-k
9851227258 chore: use the same typescript version across packages 2024-10-07 16:00:16 +03:00
pax-k
3c302cb675 fix(react-native): handle duplicate usernames by appending incremental suffix 2024-10-07 15:47:25 +03:00
pax-k
0fb11b4f98 fix(react-native): native chat UI 2024-10-07 15:46:28 +03:00
pax-k
cee3750f2e fix(react-native): polyfils 2024-10-07 15:46:00 +03:00
pax-k
140c5fc928 fix(react-native): polyfils 2024-10-07 15:45:42 +03:00
pax
fd331a5692 Merge pull request #488 from tobiaslins/improve-chat-ui-rn
First iteration of improved chat ui
2024-10-07 12:21:51 +03:00
Tobias Lins
7c12a16ad4 First iteration of chat ui 2024-10-06 21:18:16 +02:00
pax-k
358dec2e09 feat(react-native): chat demo to handle invite links (wip) 2024-10-03 22:46:23 +03:00
pax-k
b76b9aa267 feat(react-native): added support for handling invite deep links 2024-10-03 22:45:49 +03:00
pax-k
9cb111373b fix(react-native): added native kv storage support 2024-10-02 17:46:13 +03:00
pax-k
e07fb36c26 fix(react-native): implement network connectivity logic 2024-10-02 14:58:29 +03:00
Anselm Eickhoff
79bb915b43 Merge pull request #473 from gardencmp/trishalim-jazz-321
Remove empty space in code example tab
2024-10-02 09:38:40 +01:00
Trisha Lim
9926c485e7 Remove empty space in code example tab 2024-10-01 21:03:08 +01:00
pax-k
d77fb9db0c chore(react-native): cleanup 2024-10-01 20:10:09 +03:00
pax-k
595b1c71b4 feat(rn-poc): implementing react-native support 2024-10-01 19:30:13 +03:00
Anselm
d87c081055 Fix lockfile 2024-10-01 10:40:25 +01:00
pax-k
958f534a16 Merge branch 'main' into JAZZ-314/react-native-proof-of-concept 2024-09-30 16:56:02 +03:00
pax-k
15356960e9 chore: react-native scaffolding (wip) 2024-09-23 12:52:48 +03:00
142 changed files with 10863 additions and 689 deletions

View File

@@ -12,6 +12,7 @@
"jazz-browser-auth-clerk",
"jazz-react-auth-clerk",
"jazz-react",
"jazz-react-native",
"jazz-nodejs",
"jazz-run",
"cojson-transport-ws",

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
node-linker=hoisted

9
.prettierrc.js Normal file
View File

@@ -0,0 +1,9 @@
/** @type {import("prettier").Config} */
const config = {
trailingComma: "all",
tabWidth: 4,
semi: true,
singleQuote: false,
};
export default config;

View File

@@ -1,17 +1,26 @@
# @jazz-e2e/binarycostream
## 0.0.84
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- jazz-react@0.8.3
- jazz-tools@0.8.3
## 0.0.83
### Patch Changes
- Updated dependencies [a075f90]
- jazz-tools@0.8.2
- jazz-react@0.8.2
- Updated dependencies [a075f90]
- jazz-tools@0.8.2
- jazz-react@0.8.2
## 0.0.82
### Patch Changes
- Updated dependencies
- jazz-tools@0.8.1
- jazz-react@0.8.1
- Updated dependencies
- jazz-tools@0.8.1
- jazz-react@0.8.1

View File

@@ -1,7 +1,7 @@
{
"name": "@jazz-e2e/binarycostream",
"private": true,
"version": "0.0.83",
"version": "0.0.84",
"type": "module",
"scripts": {
"dev": "vite",
@@ -14,11 +14,11 @@
"*.{js,jsx,mdx,json}": "prettier --write"
},
"dependencies": {
"cojson": "workspace:0.8.0",
"cojson": "workspace:0.8.3",
"hash-slash": "workspace:0.2.0",
"is-ci": "^3.0.1",
"jazz-react": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-react": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},

View File

@@ -1,9 +1,18 @@
# @jazz-e2e/covalues
## 0.0.83
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- jazz-react@0.8.3
- jazz-tools@0.8.3
## 0.0.82
### Patch Changes
- Updated dependencies [a075f90]
- jazz-tools@0.8.2
- jazz-react@0.8.2
- Updated dependencies [a075f90]
- jazz-tools@0.8.2
- jazz-react@0.8.2

View File

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

View File

@@ -1,5 +1,15 @@
# jazz-example-chat
## 0.0.83
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- jazz-react@0.8.3
- jazz-react-auth-clerk@0.8.3
- jazz-tools@0.8.3
## 0.0.82
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat-clerk",
"private": true,
"version": "0.0.82",
"version": "0.0.83",
"type": "module",
"scripts": {
"dev": "vite",
@@ -21,11 +21,11 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.0",
"cojson": "workspace:0.8.3",
"hash-slash": "workspace:0.2.0",
"jazz-react": "workspace:0.8.2",
"jazz-react-auth-clerk": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-react": "workspace:0.8.3",
"jazz-react-auth-clerk": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
@@ -49,7 +49,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}

View File

@@ -13,7 +13,8 @@ export function App() {
const group = Group.create({ owner: me });
group.addMember("everyone", "writer");
const chat = Chat.create([], { owner: group });
location.hash = "/chat/" + chat.id;
history.replaceState({}, "", "/#/chat/" + chat.id);
window.dispatchEvent(new HashChangeEvent("hashchange"));
};
return (

38
examples/chat-rn/.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
# dependencies
node_modules/
# Expo
.expo/
dist/
web-build/
# Native
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
# Metro
.metro-health-check*
# debug
npm-debug.*
yarn-debug.*
yarn-error.*
# macOS
.DS_Store
*.pem
# local env files
.env*.local
# typescript
*.tsbuildinfo
ios
android

View File

@@ -0,0 +1,9 @@
# chat-rn
## 1.0.1
### Patch Changes
- Updated dependencies
- jazz-react-native@0.8.3
- jazz-tools@0.8.3

46
examples/chat-rn/app.json Normal file
View File

@@ -0,0 +1,46 @@
{
"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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -0,0 +1,10 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
"nativewind/babel",
"@babel/plugin-transform-class-static-block",
],
};
};

27
examples/chat-rn/eas.json Normal file
View File

@@ -0,0 +1,27 @@
{
"cli": {
"version": ">= 12.5.1",
"appVersionSource": "remote"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"ios-simulator": {
"extends": "development",
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
},
"submit": {
"production": {}
}
}

View File

@@ -0,0 +1,5 @@
import "./polyfills";
import { registerRootComponent } from "expo";
import App from "./src/App";
registerRootComponent(App);

View File

@@ -0,0 +1,29 @@
// Learn more https://docs.expo.dev/guides/monorepos
const { getDefaultConfig } = require("expo/metro-config");
const { FileStore } = require("metro-cache");
const path = require("path");
const projectRoot = __dirname;
const workspaceRoot = path.resolve(projectRoot, "../..");
const config = getDefaultConfig(projectRoot);
// Since we are using pnpm, we have to setup the monorepo manually for Metro
// #1 - Watch all files in the monorepo
config.watchFolders = [workspaceRoot];
// #2 - Try resolving with project modules first, then workspace modules
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, "node_modules"),
path.resolve(workspaceRoot, "node_modules"),
];
config.resolver.sourceExts = ["js", "json", "ts", "tsx"];
config.resolver.unstable_enablePackageExports = true;
// Use turborepo to restore the cache when possible
config.cacheStores = [
new FileStore({
root: path.join(projectRoot, "node_modules", ".cache", "metro"),
}),
];
module.exports = config;

1
examples/chat-rn/nativewind-env.d.ts vendored Normal file
View File

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

View File

@@ -0,0 +1,49 @@
{
"name": "chat-rn",
"version": "1.0.1",
"main": "index.js",
"scripts": {
"start": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web"
},
"dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@react-native-community/netinfo": "^11.3.1",
"@react-navigation/native": "^6.1.18",
"@react-navigation/native-stack": "^6.11.0",
"base-64": "^1.0.0",
"clsx": "^2.0.0",
"expo": "~51.0.36",
"expo-build-properties": "~0.12.5",
"expo-clipboard": "~6.0.3",
"expo-constants": "~16.0.2",
"expo-crypto": "~13.0.2",
"expo-dev-client": "~4.0.27",
"expo-linking": "~6.3.1",
"expo-status-bar": "~1.12.1",
"jazz-react-native": "workspace:*",
"jazz-tools": "workspace:*",
"nativewind": "^2.0.11",
"react": "^18.2.0",
"react-native": "~0.74.5",
"react-native-fetch-api": "^3.0.0",
"react-native-get-random-values": "^1.11.0",
"react-native-mmkv": "3.0.1",
"react-native-polyfill-globals": "^3.1.0",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-url-polyfill": "^2.0.0",
"text-encoding": "^0.7.0",
"web-streams-polyfill": "^3.2.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/plugin-transform-class-static-block": "^7.24.7",
"@types/react": "^18.2.19",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3"
},
"private": true
}

View File

@@ -0,0 +1,6 @@
import "react-native-polyfill-globals/auto";
import "@azure/core-asynciterator-polyfill";
import { ReadableStream } from "web-streams-polyfill/ponyfill/es6";
import { polyfillGlobal } from "react-native/Libraries/Utilities/PolyfillFunctions";
polyfillGlobal("ReadableStream", () => ReadableStream);

View File

@@ -0,0 +1,78 @@
import React, { StrictMode, useEffect, useState } from "react";
import {
NavigationContainer,
useNavigationContainerRef,
} from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import * as Linking from "expo-linking";
import HandleInviteScreen from "./invite";
import { useDemoAuth, DemoAuthBasicUI } from "jazz-react-native";
import ChatScreen from "./chat";
import { Jazz } from "./jazz";
const Stack = createNativeStackNavigator();
const prefix = Linking.createURL("/");
const linking = {
prefixes: [prefix],
config: {
screens: {
HandleInviteScreen: {
path: "router/invite/:valueHint?/:valueID/:inviteSecret",
},
},
},
};
function App() {
const [auth, state] = useDemoAuth();
const [initialRoute, setInitialRoute] = useState<
"ChatScreen" | "HandleInviteScreen"
>("ChatScreen");
const navigationRef = useNavigationContainerRef();
useEffect(() => {
Linking.getInitialURL().then((url) => {
if (url) {
if (url && url.includes("invite")) {
setInitialRoute("HandleInviteScreen");
}
}
});
}, []);
if (!auth) {
return null;
}
return (
<StrictMode>
<Jazz.Provider
auth={auth}
peer="wss://mesh.jazz.tools/?key=chat-rn-example-jazz@gcmp.io"
storage={undefined}
>
<NavigationContainer linking={linking} ref={navigationRef}>
<Stack.Navigator initialRouteName={initialRoute}>
<Stack.Screen
options={{ title: "Jazz Chat" }}
name="ChatScreen"
component={ChatScreen}
/>
<Stack.Screen
name="HandleInviteScreen"
component={HandleInviteScreen}
/>
</Stack.Navigator>
</NavigationContainer>
</Jazz.Provider>
{state.state !== "signedIn" ? (
<DemoAuthBasicUI appName="Jazz Chat" state={state} />
) : null}
</StrictMode>
);
}
export default App;

View File

@@ -0,0 +1,208 @@
import { useEffect, useState } from "react";
import React, {
Button,
FlatList,
KeyboardAvoidingView,
SafeAreaView,
Text,
TextInput,
TouchableOpacity,
View,
Alert,
} from "react-native";
import { Group, ID } from "jazz-tools";
import clsx from "clsx";
import * as Clipboard from "expo-clipboard";
import { Chat, Message } from "./schema";
import { useAccount, useCoState } from "./jazz";
export default function ChatScreen({ navigation }: { navigation: any }) {
const { me, logOut } = useAccount();
const [chat, setChat] = useState<Chat>();
const [message, setMessage] = useState("");
const loadedChat = useCoState(Chat, chat?.id, [{}]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
navigation.setOptions({
headerRight: () => <Button onPress={logOut} title="Logout" />,
headerLeft: () =>
chat ? (
<Button
onPress={() => {
if (chat?.id) {
Clipboard.setStringAsync(
`https://chat.jazz.tools/#/chat/${chat.id}`,
);
Alert.alert(
"Copied to clipboard",
`Chat ID: ${chat.id}`,
);
}
}}
title="Share"
/>
) : null,
});
}, [navigation, chat]);
const createChat = () => {
const group = Group.create({ owner: me });
group.addMember("everyone", "writer");
const chat = Chat.create([], { owner: group });
setChat(chat);
};
const loadChat = async (chatId: ID<Chat>) => {
try {
const chat = await Chat.load(chatId, me, []);
setChat(chat);
} catch (error) {
console.log("Error loading chat", error);
Alert.alert("Error", `Error loading chat: ${error}`);
}
};
const joinChat = () => {
Alert.prompt(
"Join Chat",
"Enter the Chat ID (example: co_zBGEHYvRfGuT2YSBraY3njGjnde)",
[
{
text: "Cancel",
style: "cancel",
},
{
text: "Join",
onPress: (chatId) => {
if (chatId) {
loadChat(chatId as ID<Chat>);
} else {
Alert.alert("Error", "Chat ID cannot be empty.");
}
},
},
],
"plain-text",
);
};
const sendMessage = () => {
if (!chat) return;
if (message.trim()) {
chat.push(
Message.create({ text: message }, { owner: chat._owner }),
);
setMessage("");
}
};
const renderMessageItem = ({ item }: { item: Message }) => {
const isMe = item._edits.text.by?.isMe;
return (
<View
className={clsx(
`rounded-lg p-1 px-1.5 max-w-[80%] `,
isMe
? `bg-gray-200 self-end text-right`
: `bg-gray-300 self-start `,
)}
>
{!isMe ? (
<Text
className={clsx(
`text-xs text-gray-500`,
isMe ? "text-right" : "text-left",
)}
>
{item._edits.text.by?.profile?.name}
</Text>
) : null}
<View
className={clsx(
"flex relative items-end justify-between",
isMe ? "flex-row" : "flex-row",
)}
>
<Text className={clsx(`text-black text-md max-w-[85%]`)}>
{item.text}
</Text>
<Text
className={clsx(
"text-[10px] text-gray-500 text-right ml-2",
!isMe ? "mt-2" : "mt-1",
)}
>
{item._edits.text.madeAt.getHours()}:
{item._edits.text.madeAt.getMinutes()}
</Text>
</View>
</View>
);
};
return (
<View className="flex flex-col h-full">
{!chat ? (
<View className="flex flex-col h-full items-center justify-center">
<TouchableOpacity
onPress={createChat}
className="bg-blue-500 p-4 rounded-md"
>
<Text className="text-white font-semibold">
Start new chat
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={joinChat}
className="bg-green-500 p-4 rounded-md mt-4"
>
<Text className="text-white font-semibold">
Join chat
</Text>
</TouchableOpacity>
</View>
) : (
<>
<FlatList
contentContainerStyle={{
flexGrow: 1,
flex: 1,
gap: 6,
padding: 8,
}}
className="flex"
data={loadedChat}
keyExtractor={(item) => item.id}
renderItem={renderMessageItem}
/>
<KeyboardAvoidingView
keyboardVerticalOffset={110}
behavior="padding"
className="p-3 bg-white border-t border-gray-300"
>
<SafeAreaView className="flex flex-row items-center gap-2">
<TextInput
className="rounded-full h-8 py-0 px-2 border border-gray-200 block flex-1"
value={message}
onChangeText={setMessage}
placeholder="Type a message..."
textAlignVertical="center"
onSubmitEditing={sendMessage}
/>
<TouchableOpacity
onPress={sendMessage}
className="bg-gray-300 text-white rounded-full h-8 w-8 items-center justify-center"
>
<Text></Text>
</TouchableOpacity>
</SafeAreaView>
</KeyboardAvoidingView>
</>
)}
</View>
);
}

View File

@@ -0,0 +1,24 @@
import React, { Text } from "react-native";
import { useAcceptInvite } from "./jazz";
import { Chat } from "./schema";
type ChatScreenParams = {
valueHint?: string;
valueID?: string;
inviteSecret?: string;
};
export default function HandleInviteScreen({
navigation,
}: {
navigation: any;
}) {
useAcceptInvite({
invitedObjectSchema: Chat,
onAccept: async (chatId) => {
navigation.navigate("ChatScreen", { chatId });
},
});
return <Text>Accepting invite...</Text>;
}

View File

@@ -0,0 +1,8 @@
import { createJazzRNApp } from "jazz-react-native";
import { MMKVStorage } from "./mmkv-storage";
import { Account } from "jazz-tools";
const nativeStorage = new MMKVStorage();
export const Jazz = createJazzRNApp({ nativeStorage });
export const { useAccount, useCoState, useAcceptInvite } = Jazz;

View File

@@ -0,0 +1,25 @@
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();
}
}

View File

@@ -0,0 +1,7 @@
import { CoMap, CoList, co } from "jazz-tools";
export class Message extends CoMap {
text = co.string;
}
export class Chat extends CoList.Of(co.ref(Message)) {}

View File

@@ -0,0 +1,12 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -0,0 +1,10 @@
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"moduleResolution": "bundler"
},
"exclude": [
"src/tests"
]
}

View File

@@ -1,5 +1,14 @@
# jazz-example-chat
## 0.0.85
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- jazz-react@0.8.3
- jazz-tools@0.8.3
## 0.0.84
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.84",
"version": "0.0.85",
"type": "module",
"scripts": {
"dev": "vite",
@@ -20,10 +20,10 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.0",
"cojson": "workspace:0.8.3",
"hash-slash": "workspace:0.2.0",
"jazz-react": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-react": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
@@ -47,7 +47,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}

View File

@@ -13,7 +13,8 @@ export function App() {
const group = Group.create({ owner: me });
group.addMember("everyone", "writer");
const chat = Chat.create([], { owner: group });
location.hash = "/chat/" + chat.id;
history.replaceState({}, "", "/#/chat/" + chat.id);
window.dispatchEvent(new HashChangeEvent("hashchange"));
};
return (

View File

@@ -9,18 +9,31 @@ import {
ChatInput,
EmptyChatMessage,
} from "./ui.tsx";
import { useState } from "react";
export function ChatScreen(props: { chatID: ID<Chat> }) {
const chat = useCoState(Chat, props.chatID, [{}]);
const [showNLastMessages, setShowNLastMessages] = useState(30);
return chat ? (
<>
<ChatBody>
{chat.length > 0 ? (
chat.map(msg => <ChatBubble msg={msg} key={msg.id} />)
chat
.slice(-showNLastMessages)
.reverse() // this plus flex-col-reverse on ChatBody gives us scroll-to-bottom behavior
.map(msg => <ChatBubble msg={msg} key={msg.id} />)
) : (
<EmptyChatMessage />
)}
{chat.length > showNLastMessages && (
<button
className="px-4 py-1 block mx-auto my-2 border rounded"
onClick={() => setShowNLastMessages(showNLastMessages + 10)}
>
Show more
</button>
)}
</ChatBody>
<ChatInput
onSubmit={text => {
@@ -29,7 +42,7 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
/>
</>
) : (
<div>Loading...</div>
<div className="flex-1 flex justify-center items-center">Loading...</div>
);
}

View File

@@ -1,6 +1,6 @@
export function AppContainer(props: { children: React.ReactNode }) {
return (
<div className="flex flex-col justify-between w-screen h-screen bg-stone-50 dark:bg-black dark:text-white">
<div className="flex flex-col justify-between w-screen h-screen bg-stone-50 pb-12 sm:pb-0 dark:bg-black dark:text-white">
{props.children}
</div>
);
@@ -16,7 +16,7 @@ export function TopBar(props: { children: React.ReactNode }) {
export function ChatBody(props: { children: React.ReactNode }) {
return (
<div className="flex-1 overflow-y-auto">
<div className="flex-1 overflow-y-auto flex flex-col-reverse">
{props.children}
</div>
);
@@ -36,7 +36,7 @@ export function BubbleContainer(props: {
export function BubbleBody(props: { children: React.ReactNode }) {
return (
<div className="rounded-2xl text-sm bg-white dark:bg-stone-700 dark:text-white py-1 px-3 shadow-sm">
<div className="rounded-2xl text-sm line-clamp-10 text-ellipsis bg-white dark:bg-stone-700 dark:text-white py-1 px-3 shadow-sm">
{props.children}
</div>
);
@@ -56,6 +56,7 @@ export function ChatInput(props: { onSubmit: (text: string) => void }) {
<input
className="rounded-full py-2 px-4 text-sm 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 }) => {
if (key !== "Enter" || !input.value) return;
props.onSubmit(input.value);

View File

@@ -69,6 +69,9 @@ module.exports = {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
lineClamp: {
10: '10',
},
},
},
plugins: [require("tailwindcss-animate")],

View File

@@ -1,243 +1,251 @@
# jazz-example-inspector
## 0.0.60
## 0.0.61
### Patch Changes
- Updated dependencies [6a147c2]
- Updated dependencies [ad40b88]
- cojson@0.8.0
- cojson-transport-ws@0.8.0
- Updated dependencies
- cojson@0.8.3
- cojson-transport-ws@0.8.3
## 0.0.60
### Patch Changes
- 63daf6a: fix(inspector): subscribe to latent covalues instead of loading them immediately
- Updated dependencies [35bbcd9]
- Updated dependencies [f350e90]
- cojson@0.7.35
- cojson-transport-ws@0.7.35
- Updated dependencies [6a147c2]
- Updated dependencies [ad40b88]
- cojson@0.8.0
- cojson-transport-ws@0.8.0
## 0.0.60
### Patch Changes
- 63daf6a: fix(inspector): subscribe to latent covalues instead of loading them immediately
- Updated dependencies [35bbcd9]
- Updated dependencies [f350e90]
- cojson@0.7.35
- cojson-transport-ws@0.7.35
## 0.0.59
### Patch Changes
- Updated dependencies [5d91f9f]
- Updated dependencies [5094e6d]
- Updated dependencies [b09589b]
- Updated dependencies [2c3a40c]
- Updated dependencies [406ab9b]
- Updated dependencies [4e16575]
- Updated dependencies [ea882ab]
- cojson@0.7.34
- cojson-transport-ws@0.7.34
- Updated dependencies [5d91f9f]
- Updated dependencies [5094e6d]
- Updated dependencies [b09589b]
- Updated dependencies [2c3a40c]
- Updated dependencies [406ab9b]
- Updated dependencies [4e16575]
- Updated dependencies [ea882ab]
- cojson@0.7.34
- cojson-transport-ws@0.7.34
## 0.0.59-neverthrow.6
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.8
- cojson-transport-ws@0.7.34-neverthrow.8
- Updated dependencies
- cojson@0.7.34-neverthrow.8
- cojson-transport-ws@0.7.34-neverthrow.8
## 0.0.59-neverthrow.5
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.7
- cojson-transport-ws@0.7.34-neverthrow.7
- Updated dependencies
- cojson@0.7.34-neverthrow.7
- cojson-transport-ws@0.7.34-neverthrow.7
## 0.0.59-neverthrow.4
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.4
- cojson-transport-ws@0.7.34-neverthrow.4
- Updated dependencies
- cojson@0.7.34-neverthrow.4
- cojson-transport-ws@0.7.34-neverthrow.4
## 0.0.59-neverthrow.3
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.3
- cojson-transport-ws@0.7.34-neverthrow.3
- Updated dependencies
- cojson@0.7.34-neverthrow.3
- cojson-transport-ws@0.7.34-neverthrow.3
## 0.0.59-neverthrow.2
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.34-neverthrow.2
- Updated dependencies
- cojson-transport-ws@0.7.34-neverthrow.2
## 0.0.59-neverthrow.1
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.1
- cojson-transport-ws@0.7.34-neverthrow.1
- Updated dependencies
- cojson@0.7.34-neverthrow.1
- cojson-transport-ws@0.7.34-neverthrow.1
## 0.0.59-neverthrow.0
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.0
- cojson-transport-ws@0.7.34-neverthrow.0
- Updated dependencies
- cojson@0.7.34-neverthrow.0
- cojson-transport-ws@0.7.34-neverthrow.0
## 0.0.58
### Patch Changes
- Updated dependencies [fdde8db]
- Updated dependencies [b297c93]
- Updated dependencies [07fe2b9]
- Updated dependencies [3bf5127]
- Updated dependencies [a8b74ff]
- Updated dependencies [db53161]
- cojson-transport-ws@0.7.33
- cojson@0.7.33
- Updated dependencies [fdde8db]
- Updated dependencies [b297c93]
- Updated dependencies [07fe2b9]
- Updated dependencies [3bf5127]
- Updated dependencies [a8b74ff]
- Updated dependencies [db53161]
- cojson-transport-ws@0.7.33
- cojson@0.7.33
## 0.0.58-hotfixes.5
### Patch Changes
- Updated dependencies
- cojson@0.7.33-hotfixes.5
- cojson-transport-ws@0.7.33-hotfixes.5
- Updated dependencies
- cojson@0.7.33-hotfixes.5
- cojson-transport-ws@0.7.33-hotfixes.5
## 0.0.58-hotfixes.4
### Patch Changes
- Updated dependencies
- cojson@0.7.33-hotfixes.4
- cojson-transport-ws@0.7.33-hotfixes.4
- Updated dependencies
- cojson@0.7.33-hotfixes.4
- cojson-transport-ws@0.7.33-hotfixes.4
## 0.0.58-hotfixes.3
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.33-hotfixes.3
- cojson@0.7.33-hotfixes.3
- Updated dependencies
- cojson-transport-ws@0.7.33-hotfixes.3
- cojson@0.7.33-hotfixes.3
## 0.0.58-hotfixes.2
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.33-hotfixes.2
- Updated dependencies
- cojson-transport-ws@0.7.33-hotfixes.2
## 0.0.58-hotfixes.1
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.33-hotfixes.1
- Updated dependencies
- cojson-transport-ws@0.7.33-hotfixes.1
## 0.0.58-hotfixes.0
### Patch Changes
- Updated dependencies
- cojson@0.7.33-hotfixes.0
- cojson-transport-ws@0.7.33-hotfixes.0
- Updated dependencies
- cojson@0.7.33-hotfixes.0
- cojson-transport-ws@0.7.33-hotfixes.0
## 0.0.57
### Patch Changes
- Updated dependencies
- Updated dependencies
- cojson-transport-ws@0.7.31
- cojson@0.7.31
- Updated dependencies
- Updated dependencies
- cojson-transport-ws@0.7.31
- cojson@0.7.31
## 0.0.56
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.30
- Updated dependencies
- cojson-transport-ws@0.7.30
## 0.0.55
### Patch Changes
- Updated dependencies
- cojson@0.7.29
- cojson-transport-ws@0.7.29
- Updated dependencies
- cojson@0.7.29
- cojson-transport-ws@0.7.29
## 0.0.54
### Patch Changes
- Updated dependencies
- cojson@0.7.28
- cojson-transport-ws@0.7.28
- Updated dependencies
- cojson@0.7.28
- cojson-transport-ws@0.7.28
## 0.0.53
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.27
- Updated dependencies
- cojson-transport-ws@0.7.27
## 0.0.52
### Patch Changes
- Updated dependencies
- cojson@0.7.26
- cojson-transport-ws@0.7.26
- Updated dependencies
- cojson@0.7.26
- cojson-transport-ws@0.7.26
## 0.0.51
### Patch Changes
- Updated dependencies
- cojson@0.7.23
- cojson-transport-ws@0.7.23
- Updated dependencies
- cojson@0.7.23
- cojson-transport-ws@0.7.23
## 0.0.50
### Patch Changes
- Updated dependencies
- cojson-transport-ws@0.7.22
- Updated dependencies
- cojson-transport-ws@0.7.22
## 0.0.49
### Patch Changes
- Updated dependencies
- cojson@0.7.18
- cojson-transport-ws@0.7.18
- Updated dependencies
- cojson@0.7.18
- cojson-transport-ws@0.7.18
## 0.0.48
### Patch Changes
- Updated dependencies
- cojson@0.7.17
- cojson-transport-ws@0.7.17
- Updated dependencies
- cojson@0.7.17
- cojson-transport-ws@0.7.17
## 0.0.47
### Patch Changes
- Updated dependencies
- cojson@0.6.7
- jazz-react@0.5.5
- jazz-react-auth-local@0.4.18
- Updated dependencies
- cojson@0.6.7
- jazz-react@0.5.5
- jazz-react-auth-local@0.4.18
## 0.0.46
### Patch Changes
- Updated dependencies
- jazz-react@0.5.0
- jazz-react-auth-local@0.4.16
- Updated dependencies
- jazz-react@0.5.0
- jazz-react-auth-local@0.4.16

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector",
"private": true,
"version": "0.0.60",
"version": "0.0.61",
"type": "module",
"scripts": {
"dev": "vite",
@@ -15,8 +15,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.0",
"cojson-transport-ws": "workspace:0.8.0",
"cojson": "workspace:0.8.3",
"cojson-transport-ws": "workspace:0.8.3",
"hash-slash": "workspace:0.2.0",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
@@ -41,7 +41,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}

View File

@@ -5,16 +5,16 @@ import {
RawCoStream,
RawCoValue,
} from "cojson";
import { JsonObject, JsonValue } from "cojson/src/jsonValue";
import { JsonObject, JsonValue } from "cojson/src/jsonValue.ts";
import { PageInfo } from "./types";
import { base64URLtoBytes } from "cojson/src/base64url";
import { base64URLtoBytes } from "cojson/src/base64url.ts";
import { useEffect, useState } from "react";
import { ArrowDownToLine } from "lucide-react";
import {
BinaryStreamItem,
BinaryStreamStart,
CoStreamItem,
} from "cojson/src/coValues/coStream";
} from "cojson/src/coValues/coStream.ts";
import { AccountOrGroupPreview } from "./value-renderer";
// typeguard for BinaryStreamStart

View File

@@ -1,5 +1,5 @@
import { CoID, LocalNode, RawCoValue } from "cojson";
import { JsonObject } from "cojson/src/jsonValue";
import { JsonObject } from "cojson/src/jsonValue.ts";
import { CoMapPreview, ValueRenderer } from "./value-renderer";
import clsx from "clsx";
import { PageInfo, isCoId } from "./types";

View File

@@ -1,5 +1,5 @@
import { CoID, LocalNode, RawCoValue } from "cojson";
import { JsonObject } from "cojson/src/jsonValue";
import { JsonObject } from "cojson/src/jsonValue.ts";
import { PageInfo } from "./types";
import { useMemo, useState } from "react";
import { ValueRenderer } from "./value-renderer";

View File

@@ -1,5 +1,12 @@
# jazz-example-musicplayer
## 0.0.6
### Patch Changes
- jazz-react@0.8.3
- jazz-tools@0.8.3
## 0.0.5
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.5",
"version": "0.0.6",
"type": "module",
"scripts": {
"dev": "vite",
@@ -17,8 +17,8 @@
"dependencies": {
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-react": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-react": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "^6.16.0",
@@ -37,7 +37,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-refresh/only-export-components */
import React from "react";
import ReactDOM from "react-dom/client";
import { createHashRouter, RouterProvider } from "react-router-dom";
@@ -25,8 +26,9 @@ import { useUploadExampleData } from "./lib/useUploadExampleData";
*
* `<Jazz.Provider/>` also runs our account migration
*/
const Jazz = createJazzReactApp({
AccountSchema: MusicaAccount
AccountSchema: MusicaAccount,
});
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
@@ -101,7 +103,10 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
return (
<>
<Jazz.Provider auth={auth} peer="wss://mesh.jazz.tools/?key=music-player-example-jazz@gcmp.io">
<Jazz.Provider
auth={auth}
peer="wss://mesh.jazz.tools/?key=music-player-example-jazz@gcmp.io"
>
{children}
</Jazz.Provider>
<DemoAuthBasicUI appName="Jazz Music Player" state={state} />

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect } from "react";
import { useAccount } from "../2_main";
import { uploadMusicTracks } from "@/3_actions";
@@ -5,7 +6,7 @@ import { MusicaAccount } from "@/1_schema";
export function useUploadExampleData() {
const { me } = useAccount({
root: {}
root: {},
});
const shouldUploadOnboardingData = me?.root?.exampleDataLoaded === false;
@@ -18,11 +19,11 @@ export function useUploadExampleData() {
me.root.exampleDataLoaded = true;
});
}
}, [shouldUploadOnboardingData])
}, [shouldUploadOnboardingData]);
}
async function uploadOnboardingData(me: MusicaAccount) {
const trackFile = await (await fetch("/example.mp3")).blob();
return uploadMusicTracks(me, [new File([trackFile], "Example song")]);
}
}

View File

@@ -1,50 +1,57 @@
# jazz-password-manager
## 0.0.5
### Patch Changes
- jazz-react@0.8.3
- jazz-tools@0.8.3
## 0.0.4
### Patch Changes
- Updated dependencies [a075f90]
- jazz-tools@0.8.2
- jazz-react@0.8.2
- Updated dependencies [a075f90]
- jazz-tools@0.8.2
- jazz-react@0.8.2
## 0.0.3
### Patch Changes
- Updated dependencies
- jazz-tools@0.8.1
- jazz-react@0.8.1
- Updated dependencies
- jazz-tools@0.8.1
- jazz-react@0.8.1
## 0.0.2
### Patch Changes
- Updated dependencies [ad40b88]
- Updated dependencies [23369dc]
- Updated dependencies [c2b62a0]
- Updated dependencies [1a979b6]
- Updated dependencies [bcec3be]
- Updated dependencies [6ce2051]
- jazz-tools@0.8.0
- jazz-react@0.8.0
- Updated dependencies [ad40b88]
- Updated dependencies [23369dc]
- Updated dependencies [c2b62a0]
- Updated dependencies [1a979b6]
- Updated dependencies [bcec3be]
- Updated dependencies [6ce2051]
- jazz-tools@0.8.0
- jazz-react@0.8.0
## 0.0.2-guest-auth.0
### Patch Changes
- Updated dependencies
- jazz-react@0.7.35-guest-auth.6
- jazz-tools@0.7.35-guest-auth.6
- Updated dependencies
- jazz-react@0.7.35-guest-auth.6
- jazz-tools@0.7.35-guest-auth.6
## 0.0.1
### Patch Changes
- Updated dependencies [49a8b54]
- Updated dependencies [6f80282]
- Updated dependencies [35bbcd9]
- Updated dependencies [cac2ec9]
- Updated dependencies [f350e90]
- jazz-tools@0.7.35
- jazz-react@0.7.35
- Updated dependencies [49a8b54]
- Updated dependencies [6f80282]
- Updated dependencies [35bbcd9]
- Updated dependencies [cac2ec9]
- Updated dependencies [f350e90]
- jazz-tools@0.7.35
- jazz-react@0.7.35

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.4",
"version": "0.0.5",
"type": "module",
"scripts": {
"dev": "vite",
@@ -11,8 +11,8 @@
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
},
"dependencies": {
"jazz-react": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-react": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.41.5",
@@ -30,7 +30,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}

View File

@@ -1,5 +1,13 @@
# jazz-example-pets
## 0.0.103
### Patch Changes
- jazz-react@0.8.3
- jazz-tools@0.8.3
- jazz-browser-media-images@0.8.3
## 0.0.102
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.102",
"version": "0.0.103",
"type": "module",
"scripts": {
"dev": "vite",
@@ -22,9 +22,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.2",
"jazz-react": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-browser-media-images": "workspace:0.8.3",
"jazz-react": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
@@ -50,7 +50,7 @@
"eslint-plugin-react-refresh": "^0.4.3",
"is-ci": "^3.0.1",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"vite-plugin-top-level-await": "^1.4.4"

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { ChangeEvent, useCallback, useState } from "react";
import { useNavigate } from "react-router";
import { createImage } from "jazz-browser-media-images";

View File

@@ -1,5 +1,12 @@
# jazz-example-todo
## 0.0.102
### Patch Changes
- jazz-react@0.8.3
- jazz-tools@0.8.3
## 0.0.101
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.101",
"version": "0.0.102",
"type": "module",
"scripts": {
"dev": "vite",
@@ -20,8 +20,8 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-react": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2",
"jazz-react": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
@@ -45,7 +45,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.27",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}

View File

@@ -1,34 +1,34 @@
{
"name": "gcmp-design-system",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@evilmartians/harmony": "^1.0.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.436.0",
"next": "14.2.7",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^1.14.0",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@csstools/postcss-oklab-function": "^3.0.6",
"@tailwindcss/typography": "^0.5.10",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.7",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
"name": "gcmp-design-system",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@evilmartians/harmony": "^1.0.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.436.0",
"next": "14.2.7",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^1.14.0",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@csstools/postcss-oklab-function": "^3.0.6",
"@tailwindcss/typography": "^0.5.10",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.7",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5.3.3"
}
}

View File

@@ -1,5 +1,6 @@
pre.shiki {
overflow: hidden;
height: 100%;
}
pre.shiki:hover .dim {
opacity: 1;
@@ -78,7 +79,7 @@ pre.twoslash data-lsp:hover::before {
}
pre .code-container {
@apply overflow-auto p-2 pl-0 bg-white dark:bg-stone-925 rounded-b-xl text-xs dark:border-stone-900;
@apply overflow-auto p-2 pl-0 bg-white dark:bg-stone-925 rounded-b-xl text-xs h-full dark:border-stone-900;
}
/* The try button */
pre .code-container > a {

View File

@@ -1,8 +1,18 @@
import { Application } from "typedoc";
for (const { packageName, entryPoint } of [
{ packageName: "jazz-tools" },
{ packageName: "jazz-react", entryPoint: "index.tsx" },
for (const { packageName, entryPoint, tsconfig, typedocOptions } of [
{
packageName: "jazz-tools",
entryPoint: "index.web.ts",
tsconfig: "tsconfig.web.json",
},
{
packageName: "jazz-react",
entryPoint: "index.tsx",
typedocOptions: {
skipErrorChecking: true, // TODO: remove this. Temporary workaround
},
},
{ packageName: "jazz-browser" },
{ packageName: "jazz-browser-media-images" },
{ packageName: "jazz-nodejs" },
@@ -11,7 +21,7 @@ for (const { packageName, entryPoint } of [
entryPoints: [
`../../packages/${packageName}/src/${entryPoint || "index.ts"}`,
],
tsconfig: `../../packages/${packageName}/tsconfig.json`,
tsconfig: `../../packages/${packageName}/${tsconfig || "tsconfig.json"}`,
sort: ["required-first"],
groupOrder: ["Functions", "Classes", "TypeAliases", "Namespaces"],
categoryOrder: [
@@ -39,11 +49,12 @@ for (const { packageName, entryPoint } of [
categorizeByGroup: false,
pretty: false,
preserveWatchOutput: true,
...typedocOptions,
});
if (process.argv.includes("--build")) {
const project = await app.convert();
await app.generateJson(project, "typedoc/" + packageName + ".json");
console.log(packageName + " done.");
console.log(packageName + " done.");
} else {
app.convertAndWatch(async (project) => {
await app.generateJson(project, "typedoc/" + packageName + ".json");

View File

@@ -50,6 +50,6 @@
"prettier": "^3.2.5",
"tailwindcss": "^3",
"typedoc": "^0.25.13",
"typescript": "^5"
"typescript": "^5.3.3"
}
}

View File

@@ -93,7 +93,7 @@ await rm("./codeSamples", { recursive: true, force: true });
const component = `export function ${
path.basename(filename).slice(0, 1).toUpperCase() +
path.basename(filename).slice(1).replace(".", "_")
}() {\n\treturn <div className="not-prose" dangerouslySetInnerHTML={{__html: \`${html
}() {\n\treturn <div className="not-prose h-full" dangerouslySetInnerHTML={{__html: \`${html
.replace(/`/g, "\\`")
.replace(/\$/g, "\\$")}\`\n\t}}/>;\n}`;

View File

@@ -29,8 +29,18 @@
"changeset-version": "changeset version",
"monorepo-linting": "npx sherif@1.0.0",
"monorepo-linting:fix": "npx sherif@1.0.0 --fix",
"release": "pnpm changeset publish && git push --follow-tags"
"release": "pnpm changeset publish && git push --follow-tags",
"clean": "rm -rf ./packages/*/dist && rm -rf ./packages/*/node_modules && rm -rf ./examples/*/node_modules && rm -rf ./examples/*/dist"
},
"lint-staged": {},
"version": "0.0.0"
"version": "0.0.0",
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@babel/*",
"expo-modules-*",
"typescript"
]
}
}
}

View File

@@ -1,5 +1,12 @@
# cojson-storage-indexeddb
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
## 0.8.0
### Patch Changes

View File

@@ -1,12 +1,12 @@
{
"name": "cojson-storage-indexeddb",
"version": "0.8.0",
"version": "0.8.3",
"main": "dist/index.js",
"type": "module",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"cojson": "workspace:0.8.0",
"cojson": "workspace:0.8.3",
"typescript": "^5.3.3"
},
"devDependencies": {

View File

@@ -92,7 +92,12 @@ export class IDBStorage {
const [localNodeAsPeer, storageAsPeer] = cojsonInternals.connectedPeers(
localNodeName,
"storage",
{ peer1role: "client", peer2role: "server", trace, crashOnClose: true },
{
peer1role: "client",
peer2role: "server",
trace,
crashOnClose: true,
},
);
await IDBStorage.open(
@@ -309,7 +314,9 @@ export class IDBStorage {
? undefined
: coValueRow?.header,
new: {},
priority: cojsonInternals.getPriorityFromHeader(coValueRow?.header),
priority: cojsonInternals.getPriorityFromHeader(
coValueRow?.header,
),
},
];

View File

@@ -1,5 +1,12 @@
# cojson-storage-sqlite
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
## 0.8.0
### Patch Changes

View File

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

View File

@@ -1,5 +1,12 @@
# cojson-transport-nodejs-ws
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
## 0.8.0
### Patch Changes

View File

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

View File

@@ -6,7 +6,7 @@ import {
} from "../index.js";
import { AnyWebSocket, PingMsg } from "../types.js";
import { SyncMessage } from "cojson";
import { Channel } from "cojson/src/streamUtils";
import { Channel } from "cojson/src/streamUtils.ts";
const g: typeof globalThis & {
jazzPings?: {

View File

@@ -1,5 +1,11 @@
# cojson
## 0.8.3
### Patch Changes
- Experimental support for React Native
## 0.8.0
### Patch Changes

View File

@@ -1,11 +1,25 @@
{
"name": "cojson",
"module": "dist/index.js",
"main": "dist/index.js",
"types": "src/index.ts",
"module": "dist/web/index.web.js",
"main": "dist/web/index.web.js",
"types": "src/index.web.ts",
"react-native": "dist/native/index.native.js",
"exports": {
".": {
"react-native": "./dist/native/index.native.js",
"default": "./dist/web/index.web.js",
"types": "./src/index.web.ts"
},
"./native": {
"react-native": "./dist/native/index.native.js",
"default": "./dist/native/index.native.js",
"types": "./src/index.native.ts"
},
"./src/*": "./src/*"
},
"type": "module",
"license": "MIT",
"version": "0.8.0",
"version": "0.8.3",
"devDependencies": {
"@types/jest": "^29.5.3",
"@typescript-eslint/eslint-plugin": "^6.2.1",
@@ -28,12 +42,15 @@
"queueueue": "^4.1.2"
},
"scripts": {
"dev": "tsc --watch --sourceMap --outDir dist",
"dev": "tsc --watch --sourceMap --outDir dist/web -p tsconfig.web.json",
"dev:native": "tsc --watch --sourceMap --outDir dist/native -p tsconfig.native.json",
"test": "vitest --run --root ../../ --project cojson",
"test:watch": "vitest --watch --root ../../ --project cojson",
"lint": "eslint . --ext ts,tsx",
"format": "prettier --write './src/**/*.{ts,tsx}'",
"build": "npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist",
"build:web": "tsc --sourceMap --outDir dist/web -p tsconfig.web.json",
"build:native": "tsc --sourceMap --outDir dist/native -p tsconfig.native.json",
"build": "npm run lint && rm -rf ./dist && pnpm run build:native && pnpm run build:web",
"prepublishOnly": "npm run build"
},
"lint-staged": {

View File

@@ -5,7 +5,7 @@ import { RawBinaryCoStream, RawCoStream } from "./coValues/coStream.js";
import { RawCoList } from "./coValues/coList.js";
import { CoValueCore } from "./coValueCore.js";
import { RawGroup } from "./coValues/group.js";
import { RawAccount, Profile } from "./index.js";
import { RawAccount, RawProfile as Profile } from "./coValues/account.js";
export type CoID<T extends RawCoValue> = RawCoID & {
readonly __type: T;

View File

@@ -43,7 +43,10 @@ export type CoValueHeader = {
meta: JsonObject | null;
} & CoValueUniqueness;
export type CoValueUniqueness = {uniqueness: JsonValue, createdAt?: `2${string}` | null}
export type CoValueUniqueness = {
uniqueness: JsonValue;
createdAt?: `2${string}` | null;
};
export function idforHeader(
header: CoValueHeader,

View File

@@ -1,4 +1,8 @@
import { CoValueCore, CoValueHeader, CoValueUniqueness } from "../coValueCore.js";
import {
CoValueCore,
CoValueHeader,
CoValueUniqueness,
} from "../coValueCore.js";
import { CoID, RawCoValue } from "../coValue.js";
import {
AgentSecret,
@@ -11,9 +15,9 @@ import {
import { AgentID } from "../ids.js";
import { RawCoMap } from "./coMap.js";
import { RawGroup, InviteSecret } from "./group.js";
import { LocalNode } from "../index.js";
import { JsonObject } from "../jsonValue.js";
import { err, ok, Result } from "neverthrow";
import { LocalNode } from "../localNode.js";
export function accountHeaderForInitialAgentSecret(
agentSecret: AgentSecret,
@@ -92,7 +96,9 @@ export class RawControlledAccount<Meta extends AccountMeta = AccountMeta>
* Creates a new group (with the current account as the group's first admin).
* @category 1. High-level
*/
createGroup(uniqueness: CoValueUniqueness = this.core.crypto.createdNowUnique()) {
createGroup(
uniqueness: CoValueUniqueness = this.core.crypto.createdNowUnique(),
) {
return this.core.node.createGroup(uniqueness);
}

View File

@@ -36,6 +36,11 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
return blake3.create({});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cloneBlake3State(state: any): Blake3State {
return state.clone();
}
blake3HashOnce(data: Uint8Array) {
return blake3(data);
}

View File

@@ -64,6 +64,10 @@ export class WasmCrypto extends CryptoProvider<Uint8Array> {
return this.blake3Instance.init().save();
}
cloneBlake3State(state: Uint8Array): Uint8Array {
return this.blake3Instance.load(state).save();
}
blake3HashOnce(data: Uint8Array) {
return this.blake3Instance.init().update(data).digest("binary");
}

View File

@@ -2,7 +2,8 @@ import { JsonValue } from "../jsonValue.js";
import { base58 } from "@scure/base";
import { AgentID, RawCoID, TransactionID } from "../ids.js";
import { Stringified, parseJSON, stableStringify } from "../jsonStringify.js";
import { RawAccountID, SessionID } from "../index.js";
import { RawAccountID } from "../coValues/account.js";
import { SessionID } from "../ids.js";
export type SignerSecret = `signerSecret_z${string}`;
export type SignerID = `signer_z${string}`;
@@ -103,6 +104,7 @@ export abstract class CryptoProvider<Blake3State = any> {
}
abstract emptyBlake3State(): Blake3State;
abstract cloneBlake3State(state: Blake3State): Blake3State;
abstract blake3HashOnce(data: Uint8Array): Uint8Array;
abstract blake3HashOnceWithContext(
data: Uint8Array,
@@ -323,7 +325,10 @@ export class StreamingHash {
}
clone(): StreamingHash {
return new StreamingHash(this.crypto, new Uint8Array(this.state));
return new StreamingHash(
this.crypto,
this.crypto.cloneBlake3State(this.state),
);
}
}

View File

@@ -1,3 +1,5 @@
import { PureJSCrypto } from "./crypto/PureJSCrypto.js";
import {
CoValueCore,
type CoValueUniqueness,
@@ -16,8 +18,6 @@ import {
StreamingHash,
CryptoProvider,
} from "./crypto/crypto.js";
import { WasmCrypto } from "./crypto/WasmCrypto.js";
import { PureJSCrypto } from "./crypto/PureJSCrypto.js";
import { connectedPeers, Channel } from "./streamUtils.js";
import { ControlledAgent, RawControlledAccount } from "./coValues/account.js";
import type { Role } from "./permissions.js";
@@ -115,11 +115,10 @@ export {
AgentSecret,
InviteSecret,
CryptoProvider,
WasmCrypto,
PureJSCrypto,
SyncMessage,
isRawCoID,
LSMStorage,
PureJSCrypto,
};
export type {
@@ -131,7 +130,7 @@ export type {
OutgoingSyncQueue,
DisconnectedError,
PingTimeoutError,
CoValueUniqueness
CoValueUniqueness,
};
// eslint-disable-next-line @typescript-eslint/no-namespace

View File

@@ -0,0 +1,152 @@
import { WasmCrypto } from "./crypto/WasmCrypto.js";
import {
CoValueCore,
type CoValueUniqueness,
MAX_RECOMMENDED_TX_SIZE,
idforHeader,
} from "./coValueCore.js";
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
import { LocalNode } from "./localNode.js";
import { type RawCoValue } from "./coValue.js";
import { RawCoMap } from "./coValues/coMap.js";
import { RawCoList } from "./coValues/coList.js";
import { RawCoStream, RawBinaryCoStream } from "./coValues/coStream.js";
import {
secretSeedLength,
shortHashLength,
StreamingHash,
CryptoProvider,
} from "./crypto/crypto.js";
import { connectedPeers, Channel } from "./streamUtils.js";
import { ControlledAgent, RawControlledAccount } from "./coValues/account.js";
import type { Role } from "./permissions.js";
import { rawCoIDtoBytes, rawCoIDfromBytes, isRawCoID } from "./ids.js";
import { RawGroup, EVERYONE } from "./coValues/group.js";
import type { Everyone } from "./coValues/group.js";
import { base64URLtoBytes, bytesToBase64url } from "./base64url.js";
import { parseJSON } from "./jsonStringify.js";
import {
RawAccount,
RawProfile,
accountHeaderForInitialAgentSecret,
} from "./coValues/account.js";
import { expectGroup } from "./typeUtils/expectGroup.js";
import { isAccountID } from "./typeUtils/isAccountID.js";
import type { SessionID, AgentID } from "./ids.js";
import type { CoID, AnyRawCoValue } from "./coValue.js";
import type {
BinaryStreamInfo,
BinaryCoStreamMeta,
} from "./coValues/coStream.js";
import type { JsonValue } from "./jsonValue.js";
import type {
SyncMessage,
Peer,
IncomingSyncStream,
OutgoingSyncQueue,
} from "./sync.js";
import { DisconnectedError, PingTimeoutError } from "./sync.js";
import type { AgentSecret } from "./crypto/crypto.js";
import type {
RawAccountID,
AccountMeta,
RawAccountMigration,
} from "./coValues/account.js";
import type { InviteSecret } from "./coValues/group.js";
import type * as Media from "./media.js";
type Value = JsonValue | AnyRawCoValue;
import { LSMStorage, BlockFilename, WalFilename } from "./storage/index.js";
import { FileSystem } from "./storage/FileSystem.js";
import { getPriorityFromHeader } from "./priority.js";
/** @hidden */
export const cojsonInternals = {
connectedPeers,
rawCoIDtoBytes,
rawCoIDfromBytes,
secretSeedLength,
shortHashLength,
expectGroup,
base64URLtoBytes,
bytesToBase64url,
parseJSON,
accountOrAgentIDfromSessionID,
isAccountID,
accountHeaderForInitialAgentSecret,
idforHeader,
StreamingHash,
Channel,
getPriorityFromHeader,
};
export {
LocalNode,
RawGroup,
Role,
EVERYONE,
Everyone,
RawCoMap,
RawCoList,
RawCoStream,
RawBinaryCoStream,
RawCoValue,
CoID,
AnyRawCoValue,
RawAccount,
RawAccountID,
AccountMeta,
RawAccountMigration,
RawProfile as Profile,
SessionID,
Media,
CoValueCore,
ControlledAgent,
RawControlledAccount,
MAX_RECOMMENDED_TX_SIZE,
JsonValue,
Peer,
BinaryStreamInfo,
BinaryCoStreamMeta,
AgentID,
AgentSecret,
InviteSecret,
CryptoProvider,
SyncMessage,
isRawCoID,
LSMStorage,
WasmCrypto,
};
export type {
Value,
FileSystem,
BlockFilename,
WalFilename,
IncomingSyncStream,
OutgoingSyncQueue,
DisconnectedError,
PingTimeoutError,
CoValueUniqueness,
};
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace CojsonInternalTypes {
export type CoValueKnownState = import("./sync.js").CoValueKnownState;
export type DoneMessage = import("./sync.js").DoneMessage;
export type KnownStateMessage = import("./sync.js").KnownStateMessage;
export type LoadMessage = import("./sync.js").LoadMessage;
export type NewContentMessage = import("./sync.js").NewContentMessage;
export type CoValueHeader = import("./coValueCore.js").CoValueHeader;
export type Transaction = import("./coValueCore.js").Transaction;
export type TransactionID = import("./ids.js").TransactionID;
export type Signature = import("./crypto/crypto.js").Signature;
export type RawCoID = import("./ids.js").RawCoID;
export type ProfileShape = import("./coValues/account.js").ProfileShape;
export type SealerSecret = import("./crypto/crypto.js").SealerSecret;
export type SignerSecret = import("./crypto/crypto.js").SignerSecret;
export type JsonObject = import("./jsonValue.js").JsonObject;
}

View File

@@ -21,10 +21,11 @@ import {
ControlledAgent,
RawAccountID,
RawProfile,
RawProfile as Profile,
RawAccountMigration,
InvalidAccountAgentIDError,
} from "./coValues/account.js";
import { Profile, RawCoValue } from "./index.js";
import { RawCoValue } from "./coValue.js";
import { expectGroup } from "./typeUtils/expectGroup.js";
import { err, ok, okAsync, Result, ResultAsync } from "neverthrow";
@@ -180,66 +181,71 @@ export class LocalNode {
crypto: CryptoProvider;
migration?: RawAccountMigration<Meta>;
}): Promise<LocalNode> {
const loadingNode = new LocalNode(
new ControlledAgent(accountSecret, crypto),
crypto.newRandomSessionID(accountID),
crypto,
);
for (const peer of peersToLoadFrom) {
loadingNode.syncManager.addPeer(peer);
}
const accountPromise = loadingNode.load(accountID);
const account = await accountPromise;
if (account === "unavailable") {
throw new Error("Account unavailable from all peers");
}
const controlledAccount = new RawControlledAccount(
account.core,
accountSecret,
);
// since this is all synchronous, we can just swap out nodes for the SyncManager
const node = loadingNode.testWithDifferentAccount(
controlledAccount,
sessionID || crypto.newRandomSessionID(accountID),
);
node.syncManager = loadingNode.syncManager;
node.syncManager.local = node;
controlledAccount.core.node = node;
node.coValues[accountID] = {
state: "loaded",
coValue: controlledAccount.core,
};
controlledAccount.core._cachedContent = undefined;
const profileID = account.get("profile");
if (!profileID) {
throw new Error("Account has no profile");
}
const profile = await node.load(profileID);
if (profile === "unavailable") {
throw new Error("Profile unavailable from all peers");
}
if (migration) {
await migration(
controlledAccount as RawControlledAccount<Meta>,
node,
try {
const loadingNode = new LocalNode(
new ControlledAgent(accountSecret, crypto),
crypto.newRandomSessionID(accountID),
crypto,
);
node.account = new RawControlledAccount(
controlledAccount.core,
controlledAccount.agentSecret,
);
}
return node;
for (const peer of peersToLoadFrom) {
loadingNode.syncManager.addPeer(peer);
}
const accountPromise = loadingNode.load(accountID);
const account = await accountPromise;
if (account === "unavailable") {
throw new Error("Account unavailable from all peers");
}
const controlledAccount = new RawControlledAccount(
account.core,
accountSecret,
);
// since this is all synchronous, we can just swap out nodes for the SyncManager
const node = loadingNode.testWithDifferentAccount(
controlledAccount,
sessionID || crypto.newRandomSessionID(accountID),
);
node.syncManager = loadingNode.syncManager;
node.syncManager.local = node;
controlledAccount.core.node = node;
node.coValues[accountID] = {
state: "loaded",
coValue: controlledAccount.core,
};
controlledAccount.core._cachedContent = undefined;
const profileID = account.get("profile");
if (!profileID) {
throw new Error("Account has no profile");
}
const profile = await node.load(profileID);
if (profile === "unavailable") {
throw new Error("Profile unavailable from all peers");
}
if (migration) {
await migration(
controlledAccount as RawControlledAccount<Meta>,
node,
);
node.account = new RawControlledAccount(
controlledAccount.core,
controlledAccount.agentSecret,
);
}
return node;
} catch (e) {
console.error("Error withLoadedAccount", e);
throw e;
}
}
/** @internal */
@@ -540,8 +546,19 @@ export class LocalNode {
return ok(id);
}
const coValue = this.expectCoValueLoaded(id, expectation);
let coValue: CoValueCore;
try {
coValue = this.expectCoValueLoaded(id, expectation);
} catch (e) {
return err({
type: "ErrorLoadingCoValueCore",
expectation,
id,
error: e,
} satisfies LoadCoValueCoreError);
}
if (
coValue.header.type !== "comap" ||
coValue.header.ruleset.type !== "group" ||
@@ -606,12 +623,14 @@ export class LocalNode {
/**
* @deprecated use Account.createGroup() instead
*/
createGroup(uniqueness: CoValueUniqueness = this.crypto.createdNowUnique()): RawGroup {
createGroup(
uniqueness: CoValueUniqueness = this.crypto.createdNowUnique(),
): RawGroup {
const groupCoValue = this.createCoValue({
type: "comap",
ruleset: { type: "group", initialAdmin: this.account.id },
meta: null,
...uniqueness
...uniqueness,
});
const group = expectGroup(groupCoValue.getCurrentContent());

View File

@@ -1,5 +1,5 @@
import { RawCoID, SessionID } from "../ids.js";
import { MAX_RECOMMENDED_TX_SIZE } from "../index.js";
import { MAX_RECOMMENDED_TX_SIZE } from "../coValueCore.js";
import { getPriorityFromHeader } from "../priority.js";
import { CoValueKnownState, NewContentMessage } from "../sync.js";
import { CoValueChunk } from "./index.js";

View File

@@ -8,7 +8,7 @@ import {
OutgoingSyncQueue,
Peer,
} from "../sync.js";
import { CoID, RawCoValue } from "../index.js";
import { CoID, RawCoValue } from "../coValue.js";
import { connectedPeers } from "../streamUtils.js";
import {
chunkToKnownState,

View File

@@ -1,8 +1,8 @@
import { expect, test } from "vitest";
import { expectList } from "../coValue.js";
import { WasmCrypto } from "../index.js";
import { LocalNode } from "../localNode.js";
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
const Crypto = await WasmCrypto.create();

View File

@@ -1,9 +1,9 @@
import { expect, test } from "vitest";
import { expectMap } from "../coValue.js";
import { WasmCrypto } from "../index.js";
import { LocalNode } from "../localNode.js";
import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
const Crypto = await WasmCrypto.create();

View File

@@ -1,9 +1,10 @@
import { expect, test, describe } from "vitest";
import { expectStream } from "../coValue.js";
import { RawBinaryCoStream } from "../coValues/coStream.js";
import { MAX_RECOMMENDED_TX_SIZE, WasmCrypto } from "../index.js";
import { MAX_RECOMMENDED_TX_SIZE } from "../coValueCore.js";
import { LocalNode } from "../localNode.js";
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
const Crypto = await WasmCrypto.create();

View File

@@ -1,8 +1,8 @@
import { KeySecret } from "../crypto/crypto.js";
import { KeySecret, StreamingHash } from "../crypto/crypto.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
import { PureJSCrypto } from "../crypto/PureJSCrypto.js";
import { describe, test, expect } from "vitest";
import { SessionID } from "../index.js";
import { SessionID } from "../ids.js";
describe.each([
{ impl: await WasmCrypto.create(), name: "Wasm" },
@@ -180,4 +180,26 @@ describe.each([
),
).toThrow();
});
test("StreamingHash clone", () => {
const originalHash = new StreamingHash(impl);
originalHash.update({ foo: "bar" });
const clonedHash = originalHash.clone();
// Update the original hash
originalHash.update({ baz: "qux" });
// Update the cloned hash differently
clonedHash.update({ quux: "corge" });
// The digests should be different
expect(originalHash.digest()).not.toEqual(clonedHash.digest());
// The cloned hash should match a new hash with the same updates
const newHash = new StreamingHash(impl);
newHash.update({ foo: "bar" });
newHash.update({ quux: "corge" });
expect(clonedHash.digest()).toEqual(newHash.digest());
});
});

View File

@@ -1,13 +1,11 @@
import { expect, test } from "vitest";
import {
LocalNode,
RawCoMap,
RawCoList,
RawCoStream,
RawBinaryCoStream,
WasmCrypto,
} from "../index.js";
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
import { LocalNode } from "../localNode.js";
import { RawCoList } from "../coValues/coList.js";
import { RawCoMap } from "../coValues/coMap.js";
import { RawCoStream } from "../coValues/coStream.js";
import { RawBinaryCoStream } from "../coValues/coStream.js";
const Crypto = await WasmCrypto.create();

View File

@@ -6,8 +6,9 @@ import {
groupWithTwoAdmins,
groupWithTwoAdminsHighLevel,
} from "./testUtils.js";
import { ControlledAgent, WasmCrypto } from "../index.js";
import { expectGroup } from "../typeUtils/expectGroup.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
import { ControlledAgent } from "../coValues/account.js";
const Crypto = await WasmCrypto.create();
@@ -113,7 +114,10 @@ test("Admins an add writers to a group, who can't add admins, writers, or reader
const groupAsWriter = expectGroup(
groupCore
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
.testWithDifferentAccount(
writer,
Crypto.newRandomSessionID(writer.id),
)
.getCurrentContent(),
);
@@ -141,7 +145,10 @@ test("Admins an add writers to a group, who can't add admins, writers, or reader
const groupAsWriter = expectGroup(
group.core
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
.testWithDifferentAccount(
writer,
Crypto.newRandomSessionID(writer.id),
)
.getCurrentContent(),
);
@@ -173,7 +180,10 @@ test("Admins can add readers to a group, who can't add admins, writers, or reade
const groupAsReader = expectGroup(
groupCore
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
.testWithDifferentAccount(
reader,
Crypto.newRandomSessionID(reader.id),
)
.getCurrentContent(),
);
@@ -202,7 +212,10 @@ test("Admins can add readers to a group, who can't add admins, writers, or reade
const groupAsReader = expectGroup(
group.core
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
.testWithDifferentAccount(
reader,
Crypto.newRandomSessionID(reader.id),
)
.getCurrentContent(),
);
@@ -288,7 +301,10 @@ test("Writers can write to an object that is owned by their group (high level)",
const childObjectAsWriter = expectMap(
childObject.core
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
.testWithDifferentAccount(
writer,
Crypto.newRandomSessionID(writer.id),
)
.getCurrentContent(),
);
@@ -336,7 +352,10 @@ test("Readers can not write to an object that is owned by their group (high leve
const childObjectAsReader = expectMap(
childObject.core
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
.testWithDifferentAccount(
reader,
Crypto.newRandomSessionID(reader.id),
)
.getCurrentContent(),
);
@@ -465,7 +484,10 @@ test("Admins can set group read key and then writers can use it to create and re
const childObjectAsWriter = expectMap(
childObject.core
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
.testWithDifferentAccount(
writer,
Crypto.newRandomSessionID(writer.id),
)
.getCurrentContent(),
);
@@ -551,7 +573,10 @@ test("Admins can set group read key and then use it to create private transactio
const childContentAsReader = expectMap(
childObject.core
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
.testWithDifferentAccount(
reader,
Crypto.newRandomSessionID(reader.id),
)
.getCurrentContent(),
);
@@ -665,7 +690,10 @@ test("Admins can set group read key and then use it to create private transactio
const childContentAsReader1 = expectMap(
childObject.core
.testWithDifferentAccount(reader1, Crypto.newRandomSessionID(reader1.id))
.testWithDifferentAccount(
reader1,
Crypto.newRandomSessionID(reader1.id),
)
.getCurrentContent(),
);
@@ -675,7 +703,10 @@ test("Admins can set group read key and then use it to create private transactio
const childContentAsReader2 = expectMap(
childObject.core
.testWithDifferentAccount(reader2, Crypto.newRandomSessionID(reader2.id))
.testWithDifferentAccount(
reader2,
Crypto.newRandomSessionID(reader2.id),
)
.getCurrentContent(),
);
@@ -882,7 +913,10 @@ test("Admins can set group read key, make a private transaction in an owned obje
const childContentAsReader = expectMap(
childObject.core
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
.testWithDifferentAccount(
reader,
Crypto.newRandomSessionID(reader.id),
)
.getCurrentContent(),
);
@@ -1071,7 +1105,10 @@ test("Admins can set group read rey, make a private transaction in an owned obje
const childContentAsReader2 = expectMap(
childObject.core
.testWithDifferentAccount(reader2, Crypto.newRandomSessionID(reader2.id))
.testWithDifferentAccount(
reader2,
Crypto.newRandomSessionID(reader2.id),
)
.getCurrentContent(),
);
@@ -1082,7 +1119,10 @@ test("Admins can set group read rey, make a private transaction in an owned obje
expect(
expectMap(
childObject.core
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
.testWithDifferentAccount(
reader,
Crypto.newRandomSessionID(reader.id),
)
.getCurrentContent(),
).get("foo3"),
).toBeUndefined();
@@ -1609,7 +1649,9 @@ test("Can give read permission to 'everyone'", () => {
childObject
.testWithDifferentAccount(
newAccount,
Crypto.newRandomSessionID(newAccount.currentAgentID()._unsafeUnwrap()),
Crypto.newRandomSessionID(
newAccount.currentAgentID()._unsafeUnwrap(),
),
)
.getCurrentContent(),
);
@@ -1638,7 +1680,9 @@ test("Can give read permissions to 'everyone' (high-level)", async () => {
childObject.core
.testWithDifferentAccount(
new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto),
Crypto.newRandomSessionID(newAccount.currentAgentID()._unsafeUnwrap()),
Crypto.newRandomSessionID(
newAccount.currentAgentID()._unsafeUnwrap(),
),
)
.getCurrentContent(),
);
@@ -1679,7 +1723,9 @@ test("Can give write permission to 'everyone'", async () => {
childObject
.testWithDifferentAccount(
newAccount,
Crypto.newRandomSessionID(newAccount.currentAgentID()._unsafeUnwrap()),
Crypto.newRandomSessionID(
newAccount.currentAgentID()._unsafeUnwrap(),
),
)
.getCurrentContent(),
);
@@ -1714,7 +1760,9 @@ test("Can give write permissions to 'everyone' (high-level)", async () => {
childObject.core
.testWithDifferentAccount(
newAccount,
Crypto.newRandomSessionID(newAccount.currentAgentID()._unsafeUnwrap()),
Crypto.newRandomSessionID(
newAccount.currentAgentID()._unsafeUnwrap(),
),
)
.getCurrentContent(),
);

View File

@@ -1,8 +1,8 @@
import { expect, test, describe } from "vitest";
import { WasmCrypto } from "../index.js";
import { LocalNode } from "../localNode.js";
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
import { getPriorityFromHeader, CO_VALUE_PRIORITY } from "../priority.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
const Crypto = await WasmCrypto.create();
@@ -10,11 +10,16 @@ describe("getPriorityFromHeader", () => {
test("returns MEDIUM priority for boolean or undefined headers", () => {
expect(getPriorityFromHeader(true)).toEqual(CO_VALUE_PRIORITY.MEDIUM);
expect(getPriorityFromHeader(false)).toEqual(CO_VALUE_PRIORITY.MEDIUM);
expect(getPriorityFromHeader(undefined)).toEqual(CO_VALUE_PRIORITY.MEDIUM);
expect(getPriorityFromHeader(undefined)).toEqual(
CO_VALUE_PRIORITY.MEDIUM,
);
});
test("returns MEDIUM priority for costream type", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const node = new LocalNode(
...randomAnonymousAccountAndSessionID(),
Crypto,
);
const costream = node.createCoValue({
type: "costream",
ruleset: { type: "unsafeAllowAll" },
@@ -22,11 +27,16 @@ describe("getPriorityFromHeader", () => {
...Crypto.createdNowUnique(),
});
expect(getPriorityFromHeader(costream.header)).toEqual(CO_VALUE_PRIORITY.MEDIUM);
expect(getPriorityFromHeader(costream.header)).toEqual(
CO_VALUE_PRIORITY.MEDIUM,
);
});
test("returns LOW priority for binary costream type", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const node = new LocalNode(
...randomAnonymousAccountAndSessionID(),
Crypto,
);
const costream = node.createCoValue({
type: "costream",
ruleset: { type: "unsafeAllowAll" },
@@ -34,27 +44,42 @@ describe("getPriorityFromHeader", () => {
...Crypto.createdNowUnique(),
});
expect(getPriorityFromHeader(costream.header)).toEqual(CO_VALUE_PRIORITY.LOW);
expect(getPriorityFromHeader(costream.header)).toEqual(
CO_VALUE_PRIORITY.LOW,
);
});
test("returns HIGH priority for account type", async () => {
const node =new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const node = new LocalNode(
...randomAnonymousAccountAndSessionID(),
Crypto,
);
const account = node.createAccount(node.crypto.newRandomAgentSecret());
expect(getPriorityFromHeader(account.core.header)).toEqual(CO_VALUE_PRIORITY.HIGH);
expect(getPriorityFromHeader(account.core.header)).toEqual(
CO_VALUE_PRIORITY.HIGH,
);
});
test("returns HIGH priority for group type", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const node = new LocalNode(
...randomAnonymousAccountAndSessionID(),
Crypto,
);
const group = node.createGroup();
expect(getPriorityFromHeader(group.core.header)).toEqual(CO_VALUE_PRIORITY.HIGH);
expect(getPriorityFromHeader(group.core.header)).toEqual(
CO_VALUE_PRIORITY.HIGH,
);
});
test("returns MEDIUM priority for other types", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const node = new LocalNode(
...randomAnonymousAccountAndSessionID(),
Crypto,
);
const comap = node.createCoValue({
type: "comap",
ruleset: { type: "unsafeAllowAll" },
@@ -69,7 +94,11 @@ describe("getPriorityFromHeader", () => {
...Crypto.createdNowUnique(),
});
expect(getPriorityFromHeader(comap.header)).toEqual(CO_VALUE_PRIORITY.MEDIUM);
expect(getPriorityFromHeader(colist.header)).toEqual(CO_VALUE_PRIORITY.MEDIUM);
expect(getPriorityFromHeader(comap.header)).toEqual(
CO_VALUE_PRIORITY.MEDIUM,
);
expect(getPriorityFromHeader(colist.header)).toEqual(
CO_VALUE_PRIORITY.MEDIUM,
);
});
});
});

View File

@@ -1,6 +1,8 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"lib": [
"ESNext"
],
"module": "esnext",
"target": "ES2020",
"moduleResolution": "bundler",
@@ -9,7 +11,6 @@
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true
"esModuleInterop": true,
},
"include": ["./src/**/*"],
}
}

View File

@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"include": [
"./src/**/*.ts"
],
"exclude": [
"./node_modules",
"./src/tests",
"./src/crypto/WasmCrypto.ts",
"./src/index.web.ts"
],
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"include": [
"./src/**/*.ts"
],
"exclude": [
"./node_modules",
"./src/tests",
"./src/index.native.ts"
]
}

View File

@@ -1,5 +1,14 @@
# jazz-browser-media-images
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- jazz-browser@0.8.3
- jazz-tools@0.8.3
## 0.8.2
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser-auth-clerk",
"version": "0.8.2",
"version": "0.8.3",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
@@ -10,9 +10,9 @@
"*.{js,jsx,mdx,json}": "prettier --write"
},
"dependencies": {
"cojson": "workspace:0.8.0",
"jazz-browser": "workspace:0.8.2",
"jazz-tools": "workspace:0.8.2"
"cojson": "workspace:0.8.3",
"jazz-browser": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3"
},
"scripts": {
"lint": "eslint . --ext ts,tsx",

View File

@@ -1,5 +1,12 @@
# jazz-browser-media-images
## 0.8.3
### Patch Changes
- jazz-browser@0.8.3
- jazz-tools@0.8.3
## 0.8.2
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser-media-images",
"version": "0.8.2",
"version": "0.8.3",
"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.2",
"jazz-tools": "workspace:0.8.2",
"jazz-browser": "workspace:0.8.3",
"jazz-tools": "workspace:0.8.3",
"pica": "^9.0.1",
"typescript": "^5.3.3"
},

View File

@@ -1,5 +1,15 @@
# jazz-browser
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- cojson-storage-indexeddb@0.8.3
- cojson-transport-ws@0.8.3
- jazz-tools@0.8.3
## 0.8.2
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# jazz-autosub
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
- cojson-transport-ws@0.8.3
- jazz-tools@0.8.3
## 0.8.2
### Patch Changes

View File

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

View File

@@ -5,7 +5,7 @@ import {
AccountClass,
fixedCredentialsAuth,
randomSessionProvider,
} from "jazz-tools/src/internal";
} from "jazz-tools/src/internal.js";
import { WebSocket } from "ws";
/** @category Context Creation */

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