Compare commits

...

82 Commits

Author SHA1 Message Date
Guido D'Orsi
83513b624e Merge pull request #1187 from garden-co/changeset-release/main
Version Packages
2025-01-12 12:41:54 +01:00
github-actions[bot]
6042250940 Version Packages 2025-01-12 09:54:11 +00:00
Guido D'Orsi
f78c234780 fix(rn): add unstable_enablePackageExports to the metro config 2025-01-12 10:53:03 +01:00
Guido D'Orsi
21efae9276 Merge pull request #1185 from garden-co/changeset-release/main
Version Packages
2025-01-11 16:35:54 +01:00
github-actions[bot]
1e58606ae7 Version Packages 2025-01-11 14:44:01 +00:00
Guido D'Orsi
4a11682316 Merge pull request #1186 from tobiaslins/fix-priority-rn-sqlite
[React Native] Change priority of sqlite to `100`
2025-01-11 15:42:46 +01:00
Tobias Lins
3e92680b08 Update README.md 2025-01-11 15:12:37 +01:00
Tobias Lins
2be47d688b Change priority of sqlite to 100 2025-01-11 15:11:37 +01:00
Guido D'Orsi
2ddccdbca5 Update dull-walls-crash.md 2025-01-11 14:00:02 +01:00
Guido D'Orsi
ab05897cd6 Merge pull request #1183 from tobiaslins/improve-expo-secure-storage
[react native] don't require faceid for every KV operation
2025-01-11 13:56:16 +01:00
Tobias Lins
7cd691f5f0 Create dull-walls-crash.md 2025-01-11 13:48:08 +01:00
Tobias Lins
24a13af657 Improve initialization when using custom kv storage 2025-01-11 13:41:12 +01:00
Tobias Lins
b13530e84b don't require faceid for every get/set 2025-01-11 11:09:56 +01:00
Guido D'Orsi
3911b72f87 docs: fix version number on the rn upgrade docs 2025-01-11 00:23:32 +01:00
Guido D'Orsi
ec278cfcd8 Merge pull request #1182 from garden-co/changeset-release/main
Version Packages
2025-01-11 00:22:19 +01:00
github-actions[bot]
912730378e Version Packages 2025-01-10 21:59:07 +00:00
Guido D'Orsi
ac35f19f01 Merge pull request #1130 from tobiaslins/rn-storage-sqlite
feat: sqlite react native storage
2025-01-10 22:58:03 +01:00
Guido D'Orsi
31fd994d83 Merge pull request #1180 from garden-co/jazz-636-add-test-for-react-starter-app
Fix and test react starter app
2025-01-10 16:53:42 +01:00
Trisha Lim
a6eea34c74 Run starter test 2025-01-10 15:35:16 +00:00
Trisha Lim
3605b746a9 Highlight new lines on upgrade guide 2025-01-10 15:32:02 +00:00
Trisha Lim
4b29a9aaa6 Test react starter app 2025-01-10 15:30:15 +00:00
Trisha Lim
e60a9f4a74 Fix react starter app 2025-01-10 15:26:56 +00:00
Guido D'Orsi
55e8a269c0 fix: fix homepage type error 2025-01-10 12:45:42 +01:00
Guido D'Orsi
0db0aadd45 fix: fix homepage type error 2025-01-10 12:38:12 +01:00
Guido D'Orsi
83f3873e03 feat: make the persistence disabled by default 2025-01-10 12:26:14 +01:00
Guido D'Orsi
80fd3e9697 chore: changeset 2025-01-10 12:16:04 +01:00
Guido D'Orsi
bae8268b29 feat: add upgrade docs and option to disable storage 2025-01-10 12:14:16 +01:00
Guido D'Orsi
3e9b7e829c Merge pull request #1175 from garden-co/jazz-639-fix-passkey-svelte
Fix imports for passkey-svelte
2025-01-09 15:51:05 +01:00
Benjamin S. Leveritt
530720f2b9 Fix imports 2025-01-09 14:47:23 +00:00
Benjamin S. Leveritt
a5d6d364db Merge pull request #877 from garden-co/benjamin-jazz-534
Bring CoPlainText up to current
2025-01-09 13:05:56 +00:00
Benjamin S. Leveritt
cb7e580942 Simplify Segmenter comment
Co-authored-by: Guido D'Orsi <guido@float.com>
2025-01-09 12:02:51 +00:00
Benjamin S. Leveritt
8653fc7eb1 Improve thrown error for envs missing Segmenter 2025-01-09 12:02:51 +00:00
Benjamin S. Leveritt
d077702250 Move segmenter into constructor
Chore: Fix formatting
2025-01-09 12:02:51 +00:00
Benjamin S. Leveritt
472b15d940 Move segmenter into class 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
f71176b362 Chore: Fix formatting 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
aa5f988776 Fix imports 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
328311e781 Moves Document into component 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
f2875de83d Add comments 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
2108f918b4 Chore: Format source 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
32441bdcd6 Fix export types 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
b80b9c08db Fix exports for rich-text example 2025-01-09 10:58:19 +00:00
Benjamin S. Leveritt
4f09c94098 Fix libs for coPlainText 2025-01-09 10:58:15 +00:00
pax
5e47f2fb52 Merge pull request #1168 from garden-co/changeset-release/main
Version Packages
2025-01-09 12:22:38 +02:00
github-actions[bot]
47f2f62b4f Version Packages 2025-01-09 10:19:41 +00:00
pax
61642b2536 Merge pull request #1170 from garden-co/feat/anonymous-auth
feat: add Onboarding auth to handle users onboarding without an auth screen
2025-01-09 12:18:12 +02:00
pax-k
20d12c5aa1 chore: formatting 2025-01-09 12:16:56 +02:00
pax-k
dd9ac6e4f8 fix: migrate DemoAuth old localStorage key to new one 2025-01-09 12:16:23 +02:00
Guido D'Orsi
1b7196938f feat: add Onboarding auth to handle users onboarding without an auth screen 2025-01-09 11:11:06 +01:00
pax-k
5d9818914c chore: changeset 2025-01-09 12:08:40 +02:00
pax-k
f33ec81f19 fix: DemoAuth localStorage key name 2025-01-09 12:01:08 +02:00
Guido D'Orsi
a9dbcc29d0 fix: migrate starter to jazz 0.9 2025-01-09 09:35:08 +01:00
Anselm Eickhoff
f30f92d1b6 Merge pull request #1167 from garden-co/fix/set-fixed-version-starter-app
Set fixed version for packages in starter apps (temporary fix)
2025-01-08 22:52:37 +00:00
Trisha Lim
33d250d0e1 Add changeset 2025-01-08 22:27:33 +00:00
Trisha Lim
f025ffa7b1 Set fixed version for packages in starter apps 2025-01-08 22:20:00 +00:00
Guido D'Orsi
6467bb89b3 docs: fix ensureLoaded migrate example 2025-01-08 21:58:00 +01:00
Trisha Lim
7fc9195068 Fix face id icon 2025-01-08 18:30:28 +00:00
Guido D'Orsi
2e7e276abf Merge pull request #1158 from garden-co/homepage-doc-improvements
Homepage doc improvements
2025-01-08 19:17:31 +01:00
Guido D'Orsi
cc249d3e8b docs: update the migration docs and comment the TODO 2025-01-08 19:17:21 +01:00
Guido D'Orsi
2db8b35cf7 feat: simplify storage setup and update docs 2025-01-08 18:12:22 +01:00
Anselm
f098002da5 Add todos 2025-01-08 17:03:19 +00:00
Anselm
0b47d279c0 Accounts and migrations docs sketch 2025-01-08 17:03:03 +00:00
Guido D'Orsi
a3234f3912 Merge remote-tracking branch 'origin/main' into pr-rn-storage-sqlite 2025-01-08 16:38:35 +01:00
Guido D'Orsi
2a6f2bbb4b Merge pull request #1144 from garden-co/changeset-release/main
Version Packages
2025-01-08 14:28:34 +01:00
github-actions[bot]
fcdad5d80d Version Packages 2025-01-08 12:05:19 +00:00
Guido D'Orsi
dfa15c1e0f Merge pull request #1128 from garden-co/next
Jazz 0.9.0 - Top level imports for hooks and simplified app setup
2025-01-08 13:04:05 +01:00
Guido D'Orsi
bead3462e7 Merge pull request #1151 from garden-co/react-0.9.0-migration-docs
feat(svelte): syncronously resolve local values in useCoState
2025-01-08 12:57:00 +01:00
Guido D'Orsi
468de3d3af Merge pull request #1150 from garden-co/react-0.9.0-migration-docs
docs: migration docs for rn, vue and svelte
2025-01-08 12:49:15 +01:00
Tobias Lins
7ebc77c95f Update chat.tsx 2025-01-08 09:54:55 +01:00
Tobias Lins
de20b17989 Update App.tsx 2025-01-08 09:53:37 +01:00
Tobias Lins
cae4b244e8 Update polyfills.js 2025-01-08 09:52:53 +01:00
Tobias Lins
eed5aec08d Cleanup 2025-01-08 09:51:29 +01:00
Tobias Lins
90fa0e0588 Merge remote-tracking branch 'upstream/main' into rn-storage-sqlite 2025-01-08 09:26:44 +01:00
Anselm Eickhoff
f4fc60707f More progress 2025-01-07 07:51:07 +00:00
Anselm Eickhoff
8527c3fef9 More plaintext progress 2025-01-07 07:50:26 +00:00
Anselm Eickhoff
c279174465 Rich text progress 2025-01-07 07:50:26 +00:00
Anselm
49fa18825b Progress on text 2025-01-07 07:50:26 +00:00
Anselm
32d7dca15b More implementation 2025-01-07 07:50:25 +00:00
Anselm
8ba2d47e48 Implement RawCoPlainText 2025-01-07 07:40:30 +00:00
Tobias Lins
c4d5cad2d4 Fixes 2025-01-05 10:53:59 +01:00
Tobias Lins
718543cf83 fix tx support 2025-01-04 16:52:05 +01:00
Tobias Lins
ca8f21358e Move to other library 2025-01-04 12:42:22 +01:00
Tobias Lins
d09584fa88 WIP sqlite react native storage 2025-01-04 11:24:13 +01:00
151 changed files with 4055 additions and 307 deletions

View File

@@ -1,5 +0,0 @@
---
"cojson": patch
---
Add a crypto entry to optionally import the crypto modules

View File

@@ -1,7 +0,0 @@
---
"jazz-svelte": minor
---
Change the way the JazzProvider is created and make the API available as top-level imports.
This is a breaking change.

View File

@@ -1,7 +0,0 @@
---
"jazz-vue": minor
---
Change the way the JazzProvider is created and make the composables available as top-level imports.
This is a breaking change.

View File

@@ -1,7 +0,0 @@
---
"jazz-react": minor
---
Change the way the JazzProvider is created and make the hooks available as top-level imports.
This is a breaking change.

View File

@@ -1,7 +0,0 @@
---
"jazz-react-native": patch
---
Fix username key hashing in DemoAuth
Improve error handling when loading an existing account fails
Fix the double context creation in Reacc development mode

View File

@@ -1,5 +0,0 @@
---
"jazz-tools": patch
---
Optimize the subscribe to resolve the CoValues stored in memory synchronously

View File

@@ -1,5 +0,0 @@
---
"cojson": patch
---
Add the assign method to RawCoMap to create bulk transactions and optimize RawCoMap init

View File

@@ -1,5 +0,0 @@
---
"jazz-react-native": minor
---
Change the way the JazzProvider is created and make the hooks available as top-level imports.

View File

@@ -13,7 +13,7 @@ jobs:
continue-on-error: true
strategy:
matrix:
project: ["tests/e2e", "examples/chat", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/pets", "examples/onboarding"]
project: ["tests/e2e", "examples/chat", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/pets", "examples/onboarding", "starters/react-demo-auth-tailwind"]
steps:
- uses: actions/checkout@v3

View File

@@ -1,5 +1,43 @@
# chat-rn-clerk
## 1.0.45
### Patch Changes
- Updated dependencies [7cd691f]
- jazz-react-native@0.9.3
- jazz-react-native-auth-clerk@0.9.3
## 1.0.44
### Patch Changes
- Updated dependencies [80fd3e9]
- jazz-react-native@0.9.2
- jazz-react-native-auth-clerk@0.9.2
## 1.0.43
### Patch Changes
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
- jazz-react-native@0.9.1
- jazz-react-native-auth-clerk@0.9.1
- jazz-react-native-media-images@0.9.1
## 1.0.42
### Patch Changes
- Updated dependencies [1da4d55]
- Updated dependencies [8eda792]
- Updated dependencies [1e5e3a1]
- jazz-react-native@0.9.0
- jazz-tools@0.9.0
- jazz-react-native-auth-clerk@0.9.0
- jazz-react-native-media-images@0.9.0
## 1.0.41
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-clerk",
"main": "index.js",
"version": "1.0.41",
"version": "1.0.45",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",
@@ -20,6 +20,7 @@
"@bam.tech/react-native-image-resizer": "^3.0.11",
"@clerk/clerk-expo": "^2.2.21",
"@expo/vector-icons": "^14.0.2",
"@op-engineering/op-sqlite": "^11.2.12",
"@react-native-community/netinfo": "^11.4.1",
"@react-navigation/native": "^7.0.13",
"@react-navigation/native-stack": "^7.1.14",

View File

@@ -50,6 +50,7 @@ export function JazzAndAuth({ children }: PropsWithChildren) {
{auth && clerk.user ? (
<JazzProvider
auth={auth}
storage="sqlite"
peer="wss://cloud.jazz.tools/?key=chat-rn-clerk-example-jazz@garden.co"
>
{children}

View File

@@ -1,5 +1,37 @@
# chat-rn
## 1.0.42
### Patch Changes
- Updated dependencies [7cd691f]
- jazz-react-native@0.9.3
## 1.0.41
### Patch Changes
- Updated dependencies [80fd3e9]
- jazz-react-native@0.9.2
## 1.0.40
### Patch Changes
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
- jazz-react-native@0.9.1
## 1.0.39
### Patch Changes
- Updated dependencies [1da4d55]
- Updated dependencies [8eda792]
- Updated dependencies [1e5e3a1]
- jazz-react-native@0.9.0
- jazz-tools@0.9.0
## 1.0.38
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.38",
"version": "1.0.42",
"main": "index.js",
"scripts": {
"build": "expo export -p ios",
@@ -13,6 +13,7 @@
},
"dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@op-engineering/op-sqlite": "^11.2.12",
"@react-native-community/netinfo": "^11.4.1",
"@react-navigation/native": "^7.0.13",
"@react-navigation/native-stack": "^7.1.14",

View File

@@ -33,7 +33,6 @@ function App() {
"ChatScreen" | "HandleInviteScreen"
>("ChatScreen");
const navigationRef = useNavigationContainerRef();
useEffect(() => {
Linking.getInitialURL().then((url) => {
if (url) {
@@ -52,6 +51,7 @@ function App() {
<StrictMode>
<JazzProvider
auth={auth}
storage="sqlite"
peer="wss://cloud.jazz.tools/?key=chat-rn-example-jazz@garden.co"
>
<NavigationContainer linking={linking} ref={navigationRef}>

View File

@@ -1,5 +1,25 @@
# chat-vue
## 0.0.32
### Patch Changes
- Updated dependencies [1b71969]
- Updated dependencies [5d98189]
- jazz-browser@0.9.1
- jazz-tools@0.9.1
- jazz-vue@0.9.1
## 0.0.31
### Patch Changes
- Updated dependencies [9dd8d95]
- Updated dependencies [8eda792]
- jazz-vue@0.9.0
- jazz-tools@0.9.0
- jazz-browser@0.9.0
## 0.0.30
### Patch Changes

View File

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

View File

@@ -1,5 +1,24 @@
# jazz-example-chat
## 0.0.127
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.126
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.125
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.125",
"version": "0.0.127",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,24 @@
# minimal-auth-clerk
## 0.0.26
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-react-auth-clerk@0.9.1
## 0.0.25
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-react-auth-clerk@0.9.0
## 0.0.24
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.24",
"version": "0.0.26",
"type": "module",
"scripts": {
"dev": "vite",
@@ -13,7 +13,7 @@
"dependencies": {
"@clerk/clerk-react": "^5.4.1",
"jazz-react": "workspace:*",
"jazz-react-auth-clerk": "workspace:0.8.51",
"jazz-react-auth-clerk": "workspace:0.9.1",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"

View File

@@ -1,5 +1,22 @@
# file-share-svelte
## 0.0.12
### Patch Changes
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
- jazz-svelte@0.9.1
## 0.0.11
### Patch Changes
- Updated dependencies [9dd8d95]
- Updated dependencies [8eda792]
- jazz-svelte@0.9.0
- jazz-tools@0.9.0
## 0.0.10
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "file-share-svelte",
"version": "0.0.10",
"version": "0.0.12",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,24 @@
# form
## 0.0.22
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.21
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.20
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "form",
"private": true,
"version": "0.0.20",
"version": "0.0.22",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,24 @@
# image-upload
## 0.0.24
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.23
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.22
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "image-upload",
"private": true,
"version": "0.0.22",
"version": "0.0.24",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# jazz-example-inspector
## 0.0.93
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
- cojson-transport-ws@0.9.0
## 0.0.92
### Patch Changes

View File

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

View File

@@ -1,5 +1,22 @@
# jazz-example-musicplayer
## 0.0.47
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.46
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.45
### Patch Changes

View File

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

View File

@@ -1,5 +1,24 @@
# jazz-example-onboarding
## 0.0.28
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.27
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.26
### Patch Changes

View File

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

View File

@@ -1,5 +1,22 @@
# organization
## 0.0.20
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.19
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.18
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "organization",
"private": true,
"version": "0.0.18",
"version": "0.0.20",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,18 @@
# passkey-svelte
## 0.0.16
### Patch Changes
- jazz-svelte@0.9.1
## 0.0.15
### Patch Changes
- Updated dependencies [9dd8d95]
- jazz-svelte@0.9.0
## 0.0.14
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "passkey-svelte",
"version": "0.0.14",
"version": "0.0.16",
"type": "module",
"private": true,
"scripts": {

View File

@@ -1,3 +0,0 @@
import { createJazzApp } from 'jazz-svelte';
export const { useAccount, useCoState, Provider } = createJazzApp();

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { usePasskeyAuth, PasskeyAuthBasicUI } from 'jazz-svelte';
import { Provider } from '$lib/jazz';
import { JazzProvider, PasskeyAuthBasicUI, usePasskeyAuth } from 'jazz-svelte';
let { children } = $props();
@@ -15,12 +14,12 @@
<PasskeyAuthBasicUI state={auth.state} />
{#if auth.current}
<Provider
<JazzProvider
auth={auth.current}
peer="wss://cloud.jazz.tools/?key=minimal-svelte-auth-passkey@garden.co"
>
{@render children?.()}
</Provider>
</JazzProvider>
{/if}
</div>

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { useAccount } from '$lib/jazz';
import { useAccount } from 'jazz-svelte';
const account = useAccount({
root: {}

View File

@@ -1,5 +1,22 @@
# minimal-auth-passkey
## 0.0.25
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.24
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.23
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passkey",
"private": true,
"version": "0.0.23",
"version": "0.0.25",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,22 @@
# jazz-password-manager
## 0.0.46
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.45
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.44
### Patch Changes

View File

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

View File

@@ -1,5 +1,24 @@
# jazz-example-pets
## 0.0.144
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.143
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.142
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.142",
"version": "0.0.144",
"type": "module",
"scripts": {
"dev": "vite",
@@ -19,9 +19,9 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.8.51",
"jazz-react": "workspace:0.8.51",
"jazz-tools": "workspace:0.8.51",
"jazz-browser-media-images": "workspace:0.9.1",
"jazz-react": "workspace:0.9.1",
"jazz-tools": "workspace:0.9.1",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.3.1",
@@ -41,7 +41,7 @@
"@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.20",
"is-ci": "^3.0.1",
"jazz-run": "workspace:0.8.51",
"jazz-run": "workspace:0.9.1",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.15",
"typescript": "~5.6.2",

View File

@@ -1,5 +1,24 @@
# reactions
## 0.0.24
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.23
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.22
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "reactions",
"private": true,
"version": "0.0.22",
"version": "0.0.24",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,25 @@
# todo-vue
## 0.0.30
### Patch Changes
- Updated dependencies [1b71969]
- Updated dependencies [5d98189]
- jazz-browser@0.9.1
- jazz-tools@0.9.1
- jazz-vue@0.9.1
## 0.0.29
### Patch Changes
- Updated dependencies [9dd8d95]
- Updated dependencies [8eda792]
- jazz-vue@0.9.0
- jazz-tools@0.9.0
- jazz-browser@0.9.0
## 0.0.28
### Patch Changes

View File

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

View File

@@ -1,5 +1,22 @@
# jazz-example-todo
## 0.0.143
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.142
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.141
### Patch Changes

View File

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

View File

@@ -1,5 +1,22 @@
# version-history
## 0.0.21
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.20
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.19
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "version-history",
"private": true,
"version": "0.0.19",
"version": "0.0.21",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -130,7 +130,7 @@ export function Icon({
aria-hidden="true"
size={sizes[size]}
strokeWidth={strokeWidths[size]}
strokeLinecap="butt"
strokeLinecap="round"
className={className}
{...svgProps}
/>

View File

@@ -36,9 +36,7 @@ Tested with:
```bash
npx expo install expo-linking expo-secure-store expo-file-system @react-native-community/netinfo @bam.tech/react-native-image-resizer @azure/core-asynciterator-polyfill
npm i -S react-native-polyfill-globals react-native-url-polyfill web-streams-polyfill@3.2.1 base-64 text-encoding react-native-fetch-api react-native-get-random-values buffer
npm i -D @babel/plugin-transform-class-static-block
npm i -S react-native-polyfill-globals react-native-url-polyfill web-streams-polyfill@3.2.1 base-64 text-encoding react-native-fetch-api react-native-get-random-values buffer @op-engineering/op-sqlite
npm i -S jazz-tools jazz-react-native jazz-react-native-media-images

View File

@@ -0,0 +1,218 @@
export const metadata = { title: "Accounts & Migrations" };
import { CodeGroup, ComingSoon, ContentByFramework } from "@/components/forMdx";
# Accounts & Migrations
## CoValues as a graph of data rooted in accounts
Compared to traditional relational databases with tables and foreign keys,
Jazz is more like a graph database, or GraphQL APIs &mdash;
where CoValues can arbitrarily refer to each other and you can resolve references without having to do a join.
(See [Subscribing & deep loading](/docs/using-covalues/subscription-and-loading)).
To find all data related to a user, the account acts as a root node from where you can resolve all the data they have access to.
These root references are modeled explicitly in your schema, distinguishing between data that is typically public
(like a user's profile) and data that is private (like their messages).
### `Account.root` - private data a user cares about
Every Jazz app that wants to refer to per-user data needs to define a custom root `CoMap` schema and declare it in a custom `Account` schema as the `root` field:
<CodeGroup>
{/* prettier-ignore */}
```ts
import { Account, CoMap } from "jazz-tools";
export class MyAppAccount extends Account {
root = co.ref(MyAppRoot);
}
export class MyAppRoot extends CoMap {
myChats = co.ref(ListOfChats);
myContacts = co.ref(ListOfAccounts);
}
```
</CodeGroup>
### `Account.profile` - public data associated with a user
The built-in `Account` schema class comes with a default `profile` field, which is a CoMap (in a Group with `"everyone": "reader"` - so publicly readable permissions)
that is set up for you based on the username the `AuthMethod` provides on account creation.
Their pre-defined schemas roughly look like this:
<CodeGroup>
{/* prettier-ignore */}
```ts
// ...somehwere in jazz-tools itself...
export class Account extends Group {
profile = co.ref(Profile);
}
export class Profile extends CoMap {
name = co.string;
}
```
</CodeGroup>
If you want to keep the default `Profile` schema, but customise your account's private `root`, all you have to do is define a new `root` field in your account schema:
(You don't have to explicitly re-define the `profile` field, but it makes it more readable that the Account contains both `profile` and `root`)
<CodeGroup>
{/* prettier-ignore */}
```ts
import { Account, Profile } from "jazz-tools";
export class MyAppAccount extends Account {
profile = co.ref(Profile);
root = co.ref(MyAppRoot);
}
```
</CodeGroup>
If you want to extend the `profile` to contain additional fields (such as an avatar `ImageDefinition`), you can declare your own profile schema class that extends `Profile`:
<CodeGroup>
{/* prettier-ignore */}
```ts
import { Account, Profile, ImageDefinition } from "jazz-tools";
export class MyAppAccount extends Account {
profile = co.ref(MyAppProfile);
root = co.ref(MyAppRoot);// old
}
export class MyAppRoot extends CoMap {// old
myChats = co.ref(ListOfChats);// old
myContacts = co.ref(ListOfAccounts);// old
}// old
export class MyAppProfile extends Profile {
name = co.string; // compatible with default Profile schema
avatar = co.optional.ref(ImageDefinition);
}
```
</CodeGroup>
## Resolving CoValues starting at `profile` or `root`
<ContentByFramework framework="react">
To use per-user data in your app, you typically use `useAccount` somewhere in a high-level component, specifying which references to resolve using a depth-spec (see [Subscribing & deep loading](/docs/using-covalues/subscription-and-loading)).
<CodeGroup>
{/* prettier-ignore */}
```tsx
import { useAccount } from "jazz-react";
function DashboardPageComponent() {
const { me } = useAccount({ profile: {}, root: { myChats: {}, myContacts: {}}});
return <div>
<h1>Dashboard</h1>
{me ? <div>
<p>Logged in as {me.profile.name}</p>
<h2>My chats</h2>
{me.root.myChats.map((chat) => <ChatPreview key={chat.id} chat={chat} />)}
<h2>My contacts</h2>
{me.root.myContacts.map((contact) => <ContactPreview key={contact.id} contact={contact} />)}
</div> : "Loading..."}
</div>
}
```
</CodeGroup>
</ContentByFramework>
## Populating and evolving `root` and `profile` schemas with migrations
As you develop your app, you'll likely want to
- initialise data in a user's `root` and `profile`
- add more data to your `root` and `profile` schemas
You can achieve both by overriding the static `migrate()` method on your `Account` schema class.
### When migrations run
Migrations are run after account creation and every time a user logs in.
Jazz waits for the migration to finish before passing the account to your app's context.
### Initialising user data after account creation
<CodeGroup>
{/* prettier-ignore */}
```ts
export class MyAppAccount extends Account {
root = co.ref(MyAppRoot);
async migrate() {
const me = this;
// we specifically need to check for undefined,
// because the root might simply be not loaded (`null`) yet
if (me.root === undefined) {
me.root = MyAppRoot.create({
// Using a group to set the owner is always a good idea.
// This way if in the future we want to share
// this coValue we can do so easily.
myChats: ListOfChats.create([], Group.create(me)),
myContacts: ListOfAccounts.create([], Group.create(me))
}, Group.create(me));
}
}
}
```
</CodeGroup>
### Adding/changing fields to `root` and `profile`
To add new fields to your `root` or `profile` schemas, amend their corresponding schema classes with new fields,
and then implement a migration that will populate the new fields for existing users (by using initial data, or by using existing data from old fields).
To do deeply nested migrations, you might need to use the asynchronous `ensureLoaded()` method before determining whether the field already exists, or is simply not loaded yet.
Now let's say we want to add a `myBookmarks` field to the `root` schema:
<CodeGroup>
{/* prettier-ignore */}
```ts
export class MyAppAccount extends Account {
root = co.ref(MyAppRoot);// old
async migrate() { // old
const me = this; // old
if (me.root === undefined) { // old
me.root = MyAppRoot.create({ // old
myChats: ListOfChats.create([], Group.create(me)), // old
myContacts: ListOfAccounts.create([], Group.create(me)) // old
}, Group.create(me)); // old
} // old
// We need to load the root field to check for the myContacts field
const result = await me.ensureLoaded({
root: {},
});
if (!result) throw new Error("Root missing!"); // this should never happen
const { root } = result;
// we specifically need to check for undefined,
// because myBookmarks might simply be not loaded (`null`) yet
if (root.myBookmarks === undefined) {
root.myBookmarks = ListOfBookmarks.create([], Group.create(me));
}
}
}
```
</CodeGroup>
{/*
TODO: Add best practice: only ever add fields
Note: explain and reassure that there will be more guardrails in the future
https://github.com/garden-co/jazz/issues/1160
*/}

View File

@@ -21,7 +21,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<div>
The `JazzProvider` is now imported from `jazz-react` instead of `createJazzReactApp`.
While `createJazzReactApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
While `createJazzReactApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
we found that this approach made the Jazz setup awkward and confusing for some users.
So we decided to remove `createJazzReactApp` step and to provide the types through namespace declarations:
@@ -46,29 +46,29 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<JazzProvider
auth={passkeyAuth} // old
peer="wss://cloud.jazz.tools/?key=you@example.com" // old
AccountSchema={MyAppAccount} {/* The custom Account schema is passed here */}
AccountSchema={MyAppAccount} {/* The custom Account schema is passed here */} // *add*
>
{children} // old
</JazzProvider>
<PasskeyAuthBasicUI state={passKeyState} /> // old
</> // old
);
);
}
// Register the Account schema so `useAccount` returns our custom `MyAppAccount`
declare module "jazz-react" {
interface Register {
Account: MyAppAccount;
}
}
declare module "jazz-react" { // *add*
interface Register { // *add*
Account: MyAppAccount; // *add*
} // *add*
} // *add*
```
</CodeGroup>
<h3>Top level imports for hooks</h3>
<div>
All Jazz hooks are now available as top-level imports from the `jazz-react` package.
All Jazz hooks are now available as top-level imports from the `jazz-react` package.
This change improves IDE intellisense support and simplifies imports:
</div>
@@ -86,7 +86,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<>
Hello {me.profile?.name}
</>
);
);
}
```
</CodeGroup>
@@ -105,7 +105,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
```tsx
import { createJazzTestAccount, JazzTestProvider } from "jazz-react/testing";
import { renderHook } from "@testing-library/react"; // old
import { usePlaylist } from "./usePlaylist"; // old
import { usePlaylist } from "./usePlaylist"; // old
import { Playlist, MusicAccount } from "./schema"; // old
test("should load the playlist", async () => {
@@ -146,7 +146,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<div>
The `JazzProvider` is now imported from `jazz-react-native` instead of `createJazzRNApp`.
While `createJazzRNApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
While `createJazzRNApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
we found that this approach made the Jazz setup awkward and confusing for some users.
So we decided to remove `createJazzRNApp` step and to provide the types through namespace declarations:
@@ -177,7 +177,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
</JazzProvider>
<DemoAuthBasicUI appName="My App" state={state} /> // old
</> // old
);
);
}
// Register the Account schema so `useAccount` returns our custom `MyAppAccount`
@@ -192,8 +192,8 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<h3>Top level imports for hooks</h3>
<div>
All Jazz hooks are now available as top-level imports from the `jazz-react-native` package.
All Jazz hooks are now available as top-level imports from the `jazz-react-native` package.
This change improves IDE intellisense support and simplifies imports:
</div>
@@ -211,7 +211,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<>
Hello {me.profile?.name}
</>
);
);
}
```
</CodeGroup>
@@ -271,7 +271,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<div>
The `JazzProvider` is now imported from `jazz-svelte` instead of `createJazzApp`.
While `createJazzApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
While `createJazzApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
we found that this approach made the Jazz setup awkward and confusing for some users.
So we decided to remove `createJazzApp` step and to provide the types through namespace declarations:
@@ -302,7 +302,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
let AccountSchema = MyAccount;
</script>
<JazzProvider {auth} {peer} {AccountSchema}>
<JazzProvider {auth} {peer} {AccountSchema}>
<App />
</JazzProvider>
```
@@ -311,8 +311,8 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<h3>Top level imports for hooks</h3>
<div>
All Jazz hooks are now available as top-level imports from the `jazz-svelte` package.
All Jazz hooks are now available as top-level imports from the `jazz-svelte` package.
This change improves IDE intellisense support and simplifies imports:
</div>
@@ -387,7 +387,7 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<div>
The `JazzProvider` is now imported from `jazz-vue` instead of `createJazzVueApp`.
While `createJazzReactApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
While `createJazzReactApp` was originally designed to setup strong typing for custom Account schemas in `useAccount`,
we found that this approach made the Jazz setup awkward and confusing for some users.
So we decided to remove `createJazzReactApp` step and to provide the types through namespace declarations:
@@ -409,7 +409,7 @@ export const { useAccount, useCoState } = Jazz; // *bin*
const { JazzProvider } = Jazz; // *bin*
const RootComponent = defineComponent({ // old
name: "RootComponent", // old
name: "RootComponent", // old
setup() { // old
const { authMethod, state } = useDemoAuth(); // old
return () => [ // old
@@ -449,8 +449,8 @@ app.mount("#app"); // old
<h3>Top level imports for hooks</h3>
<div>
All Jazz hooks are now available as top-level imports from the `jazz-vue` package.
All Jazz hooks are now available as top-level imports from the `jazz-vue` package.
This change improves IDE intellisense support and simplifies imports:
</div>

View File

@@ -0,0 +1,49 @@
import { ContentByFramework, CodeGroup } from '@/components/forMdx'
export const metadata = { title: "Enable local persistence" };
# Enable local persistence
<h2 className="not-prose text-sm text-stone-600 dark:text-stone-400 mb-5 pb-2 border-b">
10 January 2025
</h2>
<ContentByFramework framework="react-native">
<div>
Version 0.9.2 introduces local persistence for React Native apps using SQLite.
If you are upgrading from a version before 0.9.2, you need to enable local persistence by following the steps below.
Local persistence will become the default in 0.10.0.
</div>
<h3>Add the required dependencies</h3>
<div>
As SQLite package we now use `@op-engineering/op-sqlite`.
To get local persistence working, you need to add `@op-engineering/op-sqlite` as a direct dependency to your project and run `npx pod-install`.
</div>
<h3>Update your JazzProvider to enable local persistence</h3>
<div>
Local persistence is now disabled by default.
To enable it, you need to pass the `storage` option to the `JazzProvider` component:
</div>
<CodeGroup>
```tsx
<JazzProvider
auth={auto}
storage="sqlite"
peer="wss://cloud.jazz.tools/?key=you@example.com"
AccountSchema={MyAppAccount}
>
<App />
</JazzProvider>
```
</CodeGroup>
</ContentByFramework>

View File

@@ -12,19 +12,21 @@ export function DocNav({ className }: { className?: string }) {
const items = docNavigationItems.map((headerItem) => {
return {
...headerItem,
items: headerItem.items.map((item) => {
if (!item.href?.startsWith("/docs")) return item;
items: headerItem.items
.filter((item) => !item.framework || item.framework === framework)
.map((item) => {
if (!item.href?.startsWith("/docs")) return item;
let done =
typeof item.done === "number" ? item.done : item.done[framework];
let href = item.href.replace("/docs", `/docs/${framework}`);
let done =
typeof item.done === "number" ? item.done : item.done[framework];
let href = item.href.replace("/docs", `/docs/${framework}`);
return {
...item,
href,
done,
};
}),
return {
...item,
href,
done,
};
}),
};
});

View File

@@ -1,5 +1,6 @@
import { ThemeToggle } from "@/components/ThemeToggle";
import { socials } from "@/lib/socials";
import { useFramework } from "@/lib/use-framework";
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
import { Nav } from "gcmp-design-system/src/app/components/organisms/Nav";
import { DocNav } from "./docs/nav";

View File

@@ -50,6 +50,13 @@ export const docNavigationItems = [
href: "/docs/project-setup/server-side",
done: 80,
},
{
// upgrade guides
name: "Enable local persistence",
href: "/docs/upgrade/react-native-local-persistence",
done: 100,
framework: "react-native",
},
{
// upgrade guides
name: "Upgrade to Jazz 0.9.0",
@@ -69,7 +76,7 @@ export const docNavigationItems = [
{
name: "Accounts & migrations",
href: "/docs/schemas/accounts-and-migrations",
done: 0,
done: 20,
},
],
},

View File

@@ -1,5 +1,14 @@
# cojson-storage-indexeddb
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
- cojson-storage@0.9.0
## 0.8.50
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "cojson-storage-indexeddb",
"version": "0.8.50",
"version": "0.9.0",
"main": "dist/index.js",
"type": "module",
"types": "src/index.ts",

View File

@@ -0,0 +1,171 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
# Logs
logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Runtime data
pids
_.pid
_.seed
\*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
\*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
\*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
\*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.\*
.DS_Store

View File

@@ -0,0 +1,2 @@
coverage
node_modules

View File

@@ -0,0 +1,595 @@
# cojson-storage-sqlite
## 0.8.51
### Patch Changes
- 2be47d6: Fix priority of rn sqlite
## 0.8.50
### Patch Changes
- Updated dependencies [43378ef]
- cojson@0.8.50
- cojson-storage@0.8.50
## 0.8.49
### Patch Changes
- Updated dependencies [25dfd90]
- cojson@0.8.49
- cojson-storage@0.8.49
## 0.8.48
### Patch Changes
- Updated dependencies [10ea733]
- cojson@0.8.48
- cojson-storage@0.8.48
## 0.8.45
### Patch Changes
- Updated dependencies [6f0bd7f]
- Updated dependencies [fca6a0b]
- Updated dependencies [88d7d9a]
- cojson@0.8.45
- cojson-storage@0.8.45
## 0.8.44
### Patch Changes
- Updated dependencies [5d20c81]
- cojson@0.8.44
- cojson-storage@0.8.44
## 0.8.41
### Patch Changes
- Updated dependencies [3252502]
- Updated dependencies [6370348]
- Updated dependencies [ac216b9]
- cojson@0.8.41
- cojson-storage@0.8.41
## 0.8.40
### Patch Changes
- Updated dependencies [e905c84]
- cojson-storage@0.8.40
## 0.8.39
### Patch Changes
- ecc7c96: Bump better-sqlite3 dependency, which drops support for Node v21
- Updated dependencies [249eecb]
- Updated dependencies [3121551]
- cojson@0.8.39
- cojson-storage@0.8.39
## 0.8.38
### Patch Changes
- da13eca: Improve work scheduling under pressure
- Updated dependencies [b00ee91]
- Updated dependencies [f488c09]
- cojson@0.8.38
- cojson-storage@0.8.38
## 0.8.37
### Patch Changes
- Updated dependencies [3d9f12e]
- cojson@0.8.37
- cojson-storage@0.8.37
## 0.8.36
### Patch Changes
- 1afbd2c: Refactor the SQLite and IndexedDB storage packages to extract common synchronization functionality into newly created cojson-storage package.
- Updated dependencies [441fe27]
- Updated dependencies [1afbd2c]
- cojson@0.8.36
- cojson-storage@0.8.36
## 0.8.35
### Patch Changes
- 8b87117: Implement Group Inheritance
- Updated dependencies [3f15a23]
- Updated dependencies [46f2ab8]
- Updated dependencies [8b87117]
- Updated dependencies [a6b6ccf]
- cojson@0.8.35
## 0.8.34
### Patch Changes
- Updated dependencies [e4f110f]
- cojson@0.8.34
## 0.8.32
### Patch Changes
- Updated dependencies [df42b2b]
- cojson@0.8.32
## 0.8.31
### Patch Changes
- Updated dependencies [e511d6d]
- cojson@0.8.31
## 0.8.30
### Patch Changes
- Updated dependencies [0a2fae3]
- Updated dependencies [99cda2f]
- cojson@0.8.30
## 0.8.29
### Patch Changes
- Updated dependencies [dcc9c2e]
- Updated dependencies [699553f]
- cojson@0.8.29
## 0.8.28
### Patch Changes
- Updated dependencies [605734c]
- cojson@0.8.28
## 0.8.27
### Patch Changes
- Updated dependencies [75fdff4]
- cojson@0.8.27
## 0.8.25
### Patch Changes
- 63d46c9: Fix: sqlite not delivering depended-on CoValues
## 0.8.23
### Patch Changes
- Updated dependencies [6f745be]
- Updated dependencies [124bf67]
- cojson@0.8.23
## 0.8.21
### Patch Changes
- Updated dependencies [0f30eea]
- cojson@0.8.21
## 0.8.19
### Patch Changes
- Updated dependencies [9c2aadb]
- cojson@0.8.19
## 0.8.18
### Patch Changes
- Updated dependencies [d4319d8]
- cojson@0.8.18
## 0.8.17
### Patch Changes
- Updated dependencies [d433cf4]
- cojson@0.8.17
## 0.8.16
### Patch Changes
- Updated dependencies [b934fab]
- cojson@0.8.16
## 0.8.12
### Patch Changes
- 6ed75eb: Introduce "storage" peer role
- Updated dependencies [6ed75eb]
- cojson@0.8.12
## 0.8.11
### Patch Changes
- Updated dependencies [1ed4ab5]
- cojson@0.8.11
## 0.8.5
### Patch Changes
- Updated dependencies [c3f4e6b]
- Updated dependencies [d9152ed]
- cojson@0.8.5
## 0.8.3
### Patch Changes
- Updated dependencies
- cojson@0.8.3
## 0.8.0
### Patch Changes
- Updated dependencies [6a147c2]
- Updated dependencies [ad40b88]
- cojson@0.8.0
## 0.7.35
### Patch Changes
- f350e90: Added a priority system for the sync messages
- Updated dependencies [35bbcd9]
- Updated dependencies [f350e90]
- cojson@0.7.35
## 0.7.34
### Patch Changes
- Updated dependencies [5d91f9f]
- Updated dependencies [5094e6d]
- Updated dependencies [b09589b]
- Updated dependencies [2c3a40c]
- Updated dependencies [4e16575]
- Updated dependencies [ea882ab]
- cojson@0.7.34
## 0.7.34-neverthrow.8
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.8
## 0.7.34-neverthrow.7
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.7
## 0.7.34-neverthrow.4
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.4
## 0.7.34-neverthrow.3
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.3
## 0.7.34-neverthrow.1
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.1
## 0.7.34-neverthrow.0
### Patch Changes
- Updated dependencies
- cojson@0.7.34-neverthrow.0
## 0.7.33
### Patch Changes
- 3bf5127: Allow crashing whole node on peer errors
- Updated dependencies [b297c93]
- Updated dependencies [3bf5127]
- Updated dependencies [a8b74ff]
- Updated dependencies [db53161]
- cojson@0.7.33
## 0.7.33-hotfixes.6
### Patch Changes
- Get rid of simulated errors
## 0.7.33-hotfixes.5
### Patch Changes
- Make simulated errors even more likely
- Updated dependencies
- cojson@0.7.33-hotfixes.5
## 0.7.33-hotfixes.4
### Patch Changes
- Updated dependencies
- cojson@0.7.33-hotfixes.4
## 0.7.33-hotfixes.3
### Patch Changes
- Allow crashing whole node on peer errors
- Updated dependencies
- cojson@0.7.33-hotfixes.3
## 0.7.33-hotfixes.0
### Patch Changes
- Updated dependencies
- cojson@0.7.33-hotfixes.0
## 0.7.31
### Patch Changes
- Updated dependencies
- cojson@0.7.31
## 0.7.29
### Patch Changes
- Updated dependencies
- cojson@0.7.29
## 0.7.28
### Patch Changes
- Updated dependencies
- cojson@0.7.28
## 0.7.26
### Patch Changes
- Remove Effect from jazz/cojson internals
- Updated dependencies
- cojson@0.7.26
## 0.7.23
### Patch Changes
- Updated dependencies
- cojson@0.7.23
## 0.7.18
### Patch Changes
- Updated dependencies
- cojson@0.7.18
## 0.7.17
### Patch Changes
- Updated dependencies
- cojson@0.7.17
## 0.7.14
### Patch Changes
- Updated dependencies
- cojson@0.7.14
## 0.7.11
### Patch Changes
- Updated dependencies
- cojson@0.7.11
## 0.7.10
### Patch Changes
- Updated dependencies
- cojson@0.7.10
## 0.7.9
### Patch Changes
- Updated dependencies
- cojson@0.7.9
## 0.7.0
### Patch Changes
- c4151fc: Support stricter TS lint rules
- 21771c4: Reintroduce changes from main
- 69ac514: Use effect schema much less
- f0f6f1b: Clean up API more & re-add jazz-nodejs
- Updated dependencies [1a35307]
- Updated dependencies [96c494f]
- Updated dependencies [19f52b7]
- Updated dependencies [d8fe2b1]
- Updated dependencies [1200aae]
- Updated dependencies [52675c9]
- Updated dependencies [1a35307]
- Updated dependencies [e299c3e]
- Updated dependencies [bf0f8ec]
- Updated dependencies [c4151fc]
- Updated dependencies [8636319]
- Updated dependencies [952982e]
- Updated dependencies [21771c4]
- Updated dependencies [69ac514]
- Updated dependencies [f0f6f1b]
- Updated dependencies [1a44f87]
- Updated dependencies [63374cc]
- cojson@0.7.0
## 0.7.0-alpha.42
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.42
## 0.7.0-alpha.39
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.39
## 0.7.0-alpha.38
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.38
## 0.7.0-alpha.37
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.37
## 0.7.0-alpha.36
### Patch Changes
- Updated dependencies [1a35307]
- Updated dependencies [1a35307]
- cojson@0.7.0-alpha.36
## 0.7.0-alpha.35
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.35
## 0.7.0-alpha.29
### Patch Changes
- Reintroduce changes from main
- Updated dependencies
- cojson@0.7.0-alpha.29
## 0.7.0-alpha.28
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.28
## 0.7.0-alpha.27
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.27
## 0.7.0-alpha.24
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.24
## 0.7.0-alpha.11
### Patch Changes
- Support stricter TS lint rules
- Updated dependencies
- cojson@0.7.0-alpha.11
## 0.7.0-alpha.10
### Patch Changes
- Clean up API more & re-add jazz-nodejs
- Updated dependencies
- cojson@0.7.0-alpha.10
## 0.5.3-alpha.1
### Patch Changes
- Use effect schema much less
- Updated dependencies
- cojson@0.7.0-alpha.1
## 0.5.3-alpha.0
### Patch Changes
- Updated dependencies
- cojson@0.7.0-alpha.0
## 0.5.2
### Patch Changes
- Updated dependencies
- cojson@0.6.0
## 0.5.1
### Patch Changes
- Make typedefs for better-sqlite3 a normal dependency
## 0.5.0
### Minor Changes
- Adding a lot of performance improvements to cojson, add a stresstest for the twit example and make that run smoother in a lot of ways.
### Patch Changes
- Updated dependencies
- cojson@0.5.0

View File

@@ -0,0 +1,19 @@
Copyright 2024, Garden Computing, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,3 @@
# CoJSON Storage SQLite for React Native
This implements persistence for CoJSON / Jazz (see [jazz.tools](https://jazz.tools)) using SQLite.

View File

@@ -0,0 +1,23 @@
{
"name": "cojson-storage-rn-sqlite",
"type": "module",
"version": "0.8.51",
"main": "dist/index.js",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"cojson": "workspace:*",
"cojson-storage": "workspace:*"
},
"devDependencies": {
"@op-engineering/op-sqlite": "^11.2.12",
"typescript": "~5.6.2"
},
"scripts": {
"dev": "tsc --watch --sourceMap --outDir dist",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write",
"build": "rm -rf ./dist && tsc --sourceMap --outDir dist",
"prepublishOnly": "npm run build"
}
}

View File

@@ -0,0 +1,159 @@
import { type DB as DatabaseT } from "@op-engineering/op-sqlite";
import { CojsonInternalTypes, type OutgoingSyncQueue, RawCoID } from "cojson";
import type {
DBClientInterface,
SessionRow,
SignatureAfterRow,
StoredCoValueRow,
StoredSessionRow,
TransactionRow,
} from "cojson-storage";
import { Transaction } from "cojson/src/coValueCore.js";
import { Signature } from "cojson/src/crypto/crypto.js";
export class SQLiteClient implements DBClientInterface {
private readonly db: DatabaseT;
constructor(db: DatabaseT, _: OutgoingSyncQueue) {
this.db = db;
}
async getCoValue(coValueId: RawCoID): Promise<StoredCoValueRow | undefined> {
const { rows } = await this.db.execute(
"SELECT * FROM coValues WHERE id = ?",
[coValueId],
);
if (!rows || rows.length === 0) return;
const coValueRow = rows[0] as any & { rowID: number };
try {
const parsedHeader =
coValueRow?.header &&
(JSON.parse(coValueRow.header) as CojsonInternalTypes.CoValueHeader);
return {
...coValueRow,
header: parsedHeader,
};
} catch (e) {
console.warn(coValueId, "Invalid JSON in header", e, coValueRow?.header);
return;
}
}
async getCoValueSessions(coValueRowId: number): Promise<StoredSessionRow[]> {
const { rows } = await this.db.execute(
"SELECT * FROM sessions WHERE coValue = ?",
[coValueRowId],
);
return rows as StoredSessionRow[];
}
async getNewTransactionInSession(
sessionRowId: number,
firstNewTxIdx: number,
): Promise<TransactionRow[]> {
const { rows } = await this.db.execute(
"SELECT * FROM transactions WHERE ses = ? AND idx >= ?",
[sessionRowId, firstNewTxIdx],
);
if (!rows || rows.length === 0) return [];
try {
return rows.map((row: any) => ({
...row,
tx: JSON.parse(row.tx) as Transaction,
}));
} catch (e) {
console.warn("Invalid JSON in transaction", e);
return [];
}
}
getSignatures(
sessionRowId: number,
firstNewTxIdx: number,
): Promise<SignatureAfterRow[]> | SignatureAfterRow[] {
const { rows } = this.db.executeSync(
"SELECT * FROM signatureAfter WHERE ses = ? AND idx >= ?",
[sessionRowId, firstNewTxIdx],
);
return rows as SignatureAfterRow[];
}
async addCoValue(
msg: CojsonInternalTypes.NewContentMessage,
): Promise<number> {
const { insertId } = await this.db.execute(
"INSERT INTO coValues (id, header) VALUES (?, ?)",
[msg.id, JSON.stringify(msg.header)],
);
return insertId ?? 0;
}
async addSessionUpdate({
sessionUpdate,
}: {
sessionUpdate: SessionRow;
}): Promise<number> {
const { rows } = await this.db.execute(
`INSERT INTO sessions (coValue, sessionID, lastIdx, lastSignature, bytesSinceLastSignature)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT(coValue, sessionID)
DO UPDATE SET lastIdx=excluded.lastIdx,
lastSignature=excluded.lastSignature,
bytesSinceLastSignature=excluded.bytesSinceLastSignature
RETURNING rowID`,
[
sessionUpdate.coValue,
sessionUpdate.sessionID,
sessionUpdate.lastIdx,
sessionUpdate.lastSignature,
sessionUpdate.bytesSinceLastSignature!,
],
);
return rows[0]?.rowID as number;
}
async addTransaction(
sessionRowID: number,
nextIdx: number,
newTransaction: Transaction,
): Promise<void> {
await this.db.execute(
"INSERT INTO transactions (ses, idx, tx) VALUES (?, ?, ?)",
[sessionRowID, nextIdx, JSON.stringify(newTransaction)],
);
}
async addSignatureAfter({
sessionRowID,
idx,
signature,
}: {
sessionRowID: number;
idx: number;
signature: Signature;
}): Promise<void> {
await this.db.execute(
"INSERT INTO signatureAfter (ses, idx, signature) VALUES (?, ?, ?)",
[sessionRowID, idx, signature],
);
}
async unitOfWork(
operationsCallback: () => Promise<unknown>[],
): Promise<void> {
try {
await this.db.transaction(async () => {
await Promise.all(operationsCallback());
});
} catch (e) {
console.error("Transaction failed:", e);
throw e;
}
}
}

View File

@@ -0,0 +1,4 @@
export {
SQLiteReactNative,
SQLiteReactNative as SQLiteStorage,
} from "./sqlite-react-native.js";

View File

@@ -0,0 +1,165 @@
import { type DB, open } from "@op-engineering/op-sqlite";
import {
type IncomingSyncStream,
type OutgoingSyncQueue,
type Peer,
cojsonInternals,
} from "cojson";
import { SyncManager } from "cojson-storage";
import { SQLiteClient } from "./client.js";
export class SQLiteReactNative {
private readonly syncManager: SyncManager;
private readonly dbClient: SQLiteClient;
constructor(
db: DB,
fromLocalNode: IncomingSyncStream,
toLocalNode: OutgoingSyncQueue,
) {
this.dbClient = new SQLiteClient(db, toLocalNode);
this.syncManager = new SyncManager(this.dbClient, toLocalNode);
const processMessages = async () => {
let lastTimer = performance.now();
for await (const msg of fromLocalNode) {
try {
if (msg === "Disconnected" || msg === "PingTimeout") {
throw new Error("Unexpected Disconnected message");
}
await this.syncManager.handleSyncMessage(msg);
// Since better-sqlite3 is synchronous there may be the case
// where a bulk of messages are processed using only microtasks
// which may block other peers from sending messages.
// To avoid this we schedule a timer to downgrade the priority of the storage peer work
if (performance.now() - lastTimer > 500) {
lastTimer = performance.now();
await new Promise((resolve) => setTimeout(resolve, 0));
}
} catch (e) {
console.error(
new Error(
`Error reading from localNode, handling msg\n\n${JSON.stringify(
msg,
(k, v) =>
k === "changes" || k === "encryptedChanges"
? `${v.slice(0, 20)}...`
: v,
)}`,
{ cause: e },
),
);
console.error(e);
}
}
};
processMessages().catch((e) =>
console.error("Error in processMessages in sqlite", e),
);
}
static async asPeer({
filename,
trace,
localNodeName = "local",
}: {
filename: string;
trace?: boolean;
localNodeName?: string;
}): Promise<Peer> {
const [localNodeAsPeer, storageAsPeer] = cojsonInternals.connectedPeers(
localNodeName,
"storage",
{ peer1role: "client", peer2role: "storage", trace, crashOnClose: true },
);
await SQLiteReactNative.open(
filename,
localNodeAsPeer.incoming,
localNodeAsPeer.outgoing,
);
return { ...storageAsPeer, priority: 100 };
}
static async open(
filename: string,
fromLocalNode: IncomingSyncStream,
toLocalNode: OutgoingSyncQueue,
) {
const db = open({
name: filename,
});
await db.execute("PRAGMA journal_mode = WAL;"); // or OFF
const oldVersion =
Number((await db.execute("PRAGMA user_version")).rows[0]?.user_version) ??
0;
if (oldVersion === 0) {
await db.execute(
`CREATE TABLE IF NOT EXISTS transactions (
ses INTEGER,
idx INTEGER,
tx TEXT NOT NULL,
PRIMARY KEY (ses, idx)
) WITHOUT ROWID;`,
);
await db.execute(
`CREATE TABLE IF NOT EXISTS sessions (
rowID INTEGER PRIMARY KEY,
coValue INTEGER NOT NULL,
sessionID TEXT NOT NULL,
lastIdx INTEGER,
lastSignature TEXT,
UNIQUE (sessionID, coValue)
);`,
);
await db.execute(
`CREATE INDEX IF NOT EXISTS sessionsByCoValue ON sessions (coValue);`,
);
await db.execute(
`CREATE TABLE IF NOT EXISTS coValues (
rowID INTEGER PRIMARY KEY,
id TEXT NOT NULL UNIQUE,
header TEXT NOT NULL UNIQUE
);`,
);
await db.execute(
`CREATE INDEX IF NOT EXISTS coValuesByID ON coValues (id);`,
);
await db.execute("PRAGMA user_version = 1");
}
if (oldVersion <= 2) {
await db.execute(
`CREATE TABLE IF NOT EXISTS signatureAfter (
ses INTEGER,
idx INTEGER,
signature TEXT NOT NULL,
PRIMARY KEY (ses, idx)
) WITHOUT ROWID;`,
);
await db.execute(
`ALTER TABLE sessions ADD COLUMN bytesSinceLastSignature INTEGER;`,
);
await db.execute("PRAGMA user_version = 3");
}
return new SQLiteReactNative(db, fromLocalNode, toLocalNode);
}
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "esnext",
"target": "ES2020",
"moduleResolution": "bundler",
"moduleDetection": "force",
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true
},
"include": ["./src/**/*"]
}

View File

@@ -1,5 +1,14 @@
# cojson-storage-sqlite
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
- cojson-storage@0.9.0
## 0.8.50
### Patch Changes

View File

@@ -1,13 +1,13 @@
{
"name": "cojson-storage-sqlite",
"type": "module",
"version": "0.8.50",
"version": "0.9.0",
"main": "dist/index.js",
"types": "src/index.ts",
"license": "MIT",
"dependencies": {
"better-sqlite3": "^11.7.0",
"cojson": "workspace:0.8.50",
"cojson": "workspace:0.9.0",
"cojson-storage": "workspace:*"
},
"devDependencies": {

View File

@@ -1,5 +1,13 @@
# cojson-storage
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
## 0.8.50
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "cojson-storage",
"version": "0.8.50",
"version": "0.9.0",
"main": "dist/index.js",
"type": "module",
"types": "src/index.ts",

View File

@@ -1,5 +1,13 @@
# cojson-transport-nodejs-ws
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
## 0.8.50
### Patch Changes

View File

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

View File

@@ -1,5 +1,12 @@
# cojson
## 0.9.0
### Patch Changes
- 8eda792: Add a crypto entry to optionally import the crypto modules
- 1ef3226: Add the assign method to RawCoMap to create bulk transactions and optimize RawCoMap init
## 0.8.50
### Patch Changes

View File

@@ -24,7 +24,7 @@
},
"type": "module",
"license": "MIT",
"version": "0.8.50",
"version": "0.9.0",
"devDependencies": {
"@opentelemetry/sdk-metrics": "^1.29.0",
"@types/jest": "^29.5.3",

View File

@@ -2,6 +2,7 @@ import { CoValueCore } from "./coValueCore.js";
import { RawProfile as Profile, RawAccount } from "./coValues/account.js";
import { RawCoList } from "./coValues/coList.js";
import { RawCoMap } from "./coValues/coMap.js";
import { RawCoPlainText } from "./coValues/coPlainText.js";
import { RawBinaryCoStream, RawCoStream } from "./coValues/coStream.js";
import { RawGroup } from "./coValues/group.js";
import { RawCoID } from "./ids.js";
@@ -66,3 +67,11 @@ export function expectStream(content: RawCoValue): RawCoStream {
return content as RawCoStream;
}
export function expectPlainText(content: RawCoValue): RawCoPlainText {
if (content.type !== "coplaintext") {
throw new Error("Expected plaintext");
}
return content as RawCoPlainText;
}

View File

@@ -7,9 +7,9 @@ import { isCoValue } from "../typeUtils/isCoValue.js";
import { RawAccountID } from "./account.js";
import { RawGroup } from "./group.js";
type OpID = TransactionID & { changeIdx: number };
export type OpID = TransactionID & { changeIdx: number };
type InsertionOpPayload<T extends JsonValue> =
export type InsertionOpPayload<T extends JsonValue> =
| {
op: "pre";
value: T;
@@ -21,7 +21,7 @@ type InsertionOpPayload<T extends JsonValue> =
after: OpID | "start";
};
type DeletionOpPayload = {
export type DeletionOpPayload = {
op: "del";
insertion: OpID;
};
@@ -49,7 +49,7 @@ export class RawCoListView<
/** @category 6. Meta */
id: CoID<this>;
/** @category 6. Meta */
type = "colist" as const;
type: "colist" | "coplaintext" = "colist" as const;
/** @category 6. Meta */
core: CoValueCore;
/** @internal */
@@ -457,13 +457,7 @@ export class RawCoList<
this.core.makeTransaction(changes, privacy);
const listAfter = new RawCoList(this.core) as this;
this.afterStart = listAfter.afterStart;
this.beforeEnd = listAfter.beforeEnd;
this.insertions = listAfter.insertions;
this.deletionsByInsertion = listAfter.deletionsByInsertion;
this._cachedEntries = undefined;
this.rebuildFromCore();
}
/**
@@ -510,13 +504,7 @@ export class RawCoList<
privacy,
);
const listAfter = new RawCoList(this.core) as this;
this.afterStart = listAfter.afterStart;
this.beforeEnd = listAfter.beforeEnd;
this.insertions = listAfter.insertions;
this.deletionsByInsertion = listAfter.deletionsByInsertion;
this._cachedEntries = undefined;
this.rebuildFromCore();
}
/** Deletes the item at index `at`.
@@ -543,13 +531,7 @@ export class RawCoList<
privacy,
);
const listAfter = new RawCoList(this.core) as this;
this.afterStart = listAfter.afterStart;
this.beforeEnd = listAfter.beforeEnd;
this.insertions = listAfter.insertions;
this.deletionsByInsertion = listAfter.deletionsByInsertion;
this._cachedEntries = undefined;
this.rebuildFromCore();
}
replace(
@@ -577,6 +559,11 @@ export class RawCoList<
],
privacy,
);
this.rebuildFromCore();
}
/** @internal */
rebuildFromCore() {
const listAfter = new RawCoList(this.core) as this;
this.afterStart = listAfter.afterStart;

View File

@@ -0,0 +1,145 @@
import { CoValueCore } from "../coValueCore.js";
import { JsonObject } from "../jsonValue.js";
import {
DeletionOpPayload,
InsertionOpPayload,
OpID,
RawCoList,
} from "./coList.js";
export type StringifiedOpID = string & { __stringifiedOpID: true };
export function stringifyOpID(opID: OpID): StringifiedOpID {
return `${opID.sessionID}:${opID.txIndex}:${opID.changeIdx}` as StringifiedOpID;
}
type PlaintextIdxMapping = {
opIDbeforeIdx: OpID[];
opIDafterIdx: OpID[];
idxAfterOpID: { [opID: StringifiedOpID]: number };
idxBeforeOpID: { [opID: StringifiedOpID]: number };
};
export class RawCoPlainText<
Meta extends JsonObject | null = JsonObject | null,
> extends RawCoList<string, Meta> {
/** @category 6. Meta */
type = "coplaintext" as const;
private _segmenter: Intl.Segmenter;
_cachedMapping: WeakMap<
NonNullable<typeof this._cachedEntries>,
PlaintextIdxMapping
>;
constructor(core: CoValueCore) {
super(core);
this._cachedMapping = new WeakMap();
if (!Intl.Segmenter) {
throw new Error(
"Intl.Segmenter is not supported. Use a polyfill to get coPlainText support in Jazz. (eg. https://formatjs.github.io/docs/polyfills/intl-segmenter/)",
);
}
this._segmenter = new Intl.Segmenter("en", {
granularity: "grapheme",
});
}
get mapping() {
const entries = this.entries();
let mapping = this._cachedMapping.get(entries);
if (mapping) {
return mapping;
}
mapping = {
opIDbeforeIdx: [],
opIDafterIdx: [],
idxAfterOpID: {},
idxBeforeOpID: {},
};
let idxBefore = 0;
for (const entry of entries) {
const idxAfter = idxBefore + entry.value.length;
mapping.opIDafterIdx[idxBefore] = entry.opID;
mapping.opIDbeforeIdx[idxAfter] = entry.opID;
mapping.idxAfterOpID[stringifyOpID(entry.opID)] = idxAfter;
mapping.idxBeforeOpID[stringifyOpID(entry.opID)] = idxBefore;
idxBefore = idxAfter;
}
this._cachedMapping.set(entries, mapping);
return mapping;
}
toString() {
return this.entries()
.map((entry) => entry.value)
.join("");
}
insertAfter(
idx: number,
text: string,
privacy: "private" | "trusting" = "private",
) {
const ops: InsertionOpPayload<string>[] = [];
let prevOpId: OpID | "start" | undefined = this.mapping.opIDbeforeIdx[idx];
if (!prevOpId) {
if (idx === 0) {
prevOpId = "start";
} else {
throw new Error("Invalid idx");
}
}
const nextTxId = this.core.nextTransactionID();
let changeIdx = 0;
for (const grapheme of this._segmenter.segment(text)) {
ops.push({
op: "app",
value: grapheme.segment,
after: prevOpId,
});
prevOpId = {
sessionID: nextTxId.sessionID,
txIndex: nextTxId.txIndex,
changeIdx,
};
changeIdx++;
}
this.core.makeTransaction(ops, privacy);
this.rebuildFromCore();
}
deleteRange(
{ from, to }: { from: number; to: number },
privacy: "private" | "trusting" = "private",
) {
const ops: DeletionOpPayload[] = [];
for (let idx = from; idx < to; ) {
const insertion = this.mapping.opIDafterIdx[idx];
if (!insertion) {
throw new Error("Invalid idx to delete " + idx);
}
ops.push({
op: "del",
insertion,
});
console.log("deleting idx", idx);
let nextIdx = idx + 1;
while (!this.mapping.opIDbeforeIdx[nextIdx] && nextIdx < to) {
nextIdx++;
}
idx = nextIdx;
}
this.core.makeTransaction(ops, privacy);
this.rebuildFromCore();
}
}

View File

@@ -22,6 +22,7 @@ import {
} from "./account.js";
import { RawCoList } from "./coList.js";
import { RawCoMap } from "./coMap.js";
import { RawCoPlainText } from "./coPlainText.js";
import { RawBinaryCoStream, RawCoStream } from "./coStream.js";
export const EVERYONE = "everyone" as const;
@@ -699,6 +700,36 @@ export class RawGroup<
return list;
}
/**
* Creates a new `CoList` within this group, with the specified specialized
* `CoList` type `L` and optional static metadata.
*
* @category 3. Value creation
*/
createPlainText<T extends RawCoPlainText>(
init?: string,
meta?: T["headerMeta"],
initPrivacy: "trusting" | "private" = "private",
): T {
const text = this.core.node
.createCoValue({
type: "coplaintext",
ruleset: {
type: "ownedByGroup",
group: this.id,
},
meta: meta || null,
...this.core.crypto.createdNowUnique(),
})
.getCurrentContent() as T;
if (init) {
text.insertAfter(0, init, initPrivacy);
}
return text;
}
/** @category 3. Value creation */
createStream<C extends RawCoStream>(
meta?: C["headerMeta"],

View File

@@ -2,8 +2,8 @@ import type { CoValueCore } from "./coValueCore.js";
import { RawAccount, RawControlledAccount } from "./coValues/account.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";
import { RawCoPlainText } from "./coValues/coPlainText.js";
import { RawBinaryCoStream, RawCoStream } from "./coValues/coStream.js";
import { RawGroup } from "./coValues/group.js";
export function coreToCoValue(
@@ -27,6 +27,8 @@ export function coreToCoValue(
} else {
return new RawCoMap(core);
}
} else if (core.header.type === "coplaintext") {
return new RawCoPlainText(core);
} else if (core.header.type === "colist") {
return new RawCoList(core);
} else if (core.header.type === "costream") {

View File

@@ -6,14 +6,16 @@ import {
MAX_RECOMMENDED_TX_SIZE,
idforHeader,
} from "./coValueCore.js";
import { ControlledAgent, RawControlledAccount } from "./coValues/account.js";
import {
ControlledAgent,
RawAccount,
RawControlledAccount,
RawProfile,
accountHeaderForInitialAgentSecret,
} from "./coValues/account.js";
import { RawCoList } from "./coValues/coList.js";
import { OpID, RawCoList } from "./coValues/coList.js";
import { RawCoMap } from "./coValues/coMap.js";
import { RawCoPlainText, stringifyOpID } from "./coValues/coPlainText.js";
import {
CoStreamItem,
RawBinaryCoStream,
@@ -137,6 +139,8 @@ export {
isRawCoID,
LSMStorage,
emptyKnownState,
RawCoPlainText,
stringifyOpID,
};
export type {
@@ -151,6 +155,7 @@ export type {
CoValueUniqueness,
Stringified,
CoStreamItem,
OpID,
};
// eslint-disable-next-line @typescript-eslint/no-namespace

View File

@@ -0,0 +1,87 @@
import { afterEach, expect, test, vi } from "vitest";
import { expectPlainText } from "../coValue.js";
import { WasmCrypto } from "../crypto/WasmCrypto.js";
import { LocalNode } from "../localNode.js";
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
const Crypto = await WasmCrypto.create();
afterEach(() => void vi.unstubAllGlobals());
test("should throw on creation if Intl.Segmenter is not available", () => {
vi.stubGlobal("Intl", {
Segmenter: undefined,
});
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const group = node.createGroup();
expect(() => group.createPlainText()).toThrow(
"Intl.Segmenter is not supported. Use a polyfill to get coPlainText support in Jazz. (eg. https://formatjs.github.io/docs/polyfills/intl-segmenter/)",
);
});
test("Empty CoPlainText works", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const coValue = node.createCoValue({
type: "coplaintext",
ruleset: { type: "unsafeAllowAll" },
meta: null,
...Crypto.createdNowUnique(),
});
const content = expectPlainText(coValue.getCurrentContent());
expect(content.type).toEqual("coplaintext");
expect(content.toString()).toEqual("");
});
test("Can insert into empty CoPlainText", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const coValue = node.createCoValue({
type: "coplaintext",
ruleset: { type: "unsafeAllowAll" },
meta: null,
...Crypto.createdNowUnique(),
});
const content = expectPlainText(coValue.getCurrentContent());
expect(content.type).toEqual("coplaintext");
content.insertAfter(0, "a", "trusting");
expect(content.toString()).toEqual("a");
});
test("Can insert and delete in CoPlainText", () => {
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
const coValue = node.createCoValue({
type: "coplaintext",
ruleset: { type: "unsafeAllowAll" },
meta: null,
...Crypto.createdNowUnique(),
});
const content = expectPlainText(coValue.getCurrentContent());
expect(content.type).toEqual("coplaintext");
content.insertAfter(0, "hello", "trusting");
expect(content.toString()).toEqual("hello");
content.insertAfter(5, " world", "trusting");
expect(content.toString()).toEqual("hello world");
console.log("first delete");
content.deleteRange({ from: 3, to: 8 }, "trusting");
expect(content.toString()).toEqual("helrld");
content.insertAfter(2, "😍", "trusting");
expect(content.toString()).toEqual("he😍lrld");
console.log("second delete");
content.deleteRange({ from: 2, to: 4 }, "trusting");
expect(content.toString()).toEqual("helrld");
});

View File

@@ -1,5 +1,11 @@
# create-jazz-app
## 0.1.5
### Patch Changes
- f78c234: Fix metro config for the RN starter
## 0.1.4
### Patch Changes

View File

@@ -5,7 +5,7 @@
"types": "src/index.ts",
"type": "module",
"license": "MIT",
"version": "0.1.4",
"version": "0.1.5",
"bin": {
"create-jazz-app": "./dist/index.js"
},

View File

@@ -124,6 +124,8 @@ const { withNativeWind } = require("nativewind/metro");
const config = getDefaultConfig(__dirname);
config.resolver.unstable_enablePackageExports = true;
module.exports = withNativeWind(config, { input: "./src/global.css" });
`;
fs.writeFileSync(metroConfigPath, metroConfig);

View File

@@ -1,5 +1,25 @@
# jazz-browser-media-images
## 0.9.1
### Patch Changes
- Updated dependencies [1b71969]
- Updated dependencies [5d98189]
- jazz-browser@0.9.1
- jazz-tools@0.9.1
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
- jazz-tools@0.9.0
- jazz-browser@0.9.0
## 0.8.51
### Patch Changes

View File

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

View File

@@ -1,5 +1,22 @@
# jazz-browser-media-images
## 0.9.1
### Patch Changes
- Updated dependencies [1b71969]
- Updated dependencies [5d98189]
- jazz-browser@0.9.1
- jazz-tools@0.9.1
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- jazz-tools@0.9.0
- jazz-browser@0.9.0
## 0.8.51
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser-media-images",
"version": "0.8.51",
"version": "0.9.1",
"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.51",
"jazz-tools": "workspace:0.8.51",
"jazz-browser": "workspace:0.9.1",
"jazz-tools": "workspace:0.9.1",
"pica": "^9.0.1",
"typescript": "~5.6.2"
},

View File

@@ -1,5 +1,26 @@
# jazz-browser
## 0.9.1
### Patch Changes
- 1b71969: Add Onboarding auth to handle users onboarding without an auth screen
- 5d98189: Fixed DemoAuth localStorage key name
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
## 0.9.0
### Patch Changes
- Updated dependencies [8eda792]
- Updated dependencies [8eda792]
- Updated dependencies [1ef3226]
- cojson@0.9.0
- jazz-tools@0.9.0
- cojson-storage-indexeddb@0.9.0
- cojson-transport-ws@0.9.0
## 0.8.51
### Patch Changes

View File

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

View File

@@ -6,7 +6,7 @@ type StorageData = {
accountSecret: AgentSecret;
};
const localStorageKey = "demo-auth-logged-in-secret";
const localStorageKey = "jazz-logged-in-secret";
/**
* `BrowserDemoAuth` provides a `JazzAuth` object for demo authentication.
@@ -54,7 +54,15 @@ export class BrowserDemoAuth implements AuthMethod {
* @returns A `JazzAuth` object
*/
async start() {
if (localStorage["demo-auth-logged-in-secret"]) {
// migrate old localStorage key to new one
if (
localStorage["demo-auth-logged-in-secret"] &&
!localStorage[localStorageKey]
)
localStorage[localStorageKey] =
localStorage["demo-auth-logged-in-secret"];
if (localStorage[localStorageKey]) {
const localStorageData = JSON.parse(
localStorage[localStorageKey],
) as StorageData;
@@ -91,7 +99,7 @@ export class BrowserDemoAuth implements AuthMethod {
accountSecret: credentials.secret,
} satisfies StorageData);
localStorage["demo-auth-logged-in-secret"] = storageData;
localStorage[localStorageKey] = storageData;
localStorage["demo-auth-existing-users-" + username] =
storageData;
@@ -119,8 +127,7 @@ export class BrowserDemoAuth implements AuthMethod {
localStorage["demo-auth-existing-users-" + existingUser],
) as StorageData;
localStorage["demo-auth-logged-in-secret"] =
JSON.stringify(storageData);
localStorage[localStorageKey] = JSON.stringify(storageData);
resolve({
type: "existing",

View File

@@ -0,0 +1,91 @@
import { AgentSecret } from "cojson";
import { Account, AuthMethod, AuthResult, ID } from "jazz-tools";
type StorageData = {
accountID: ID<Account>;
accountSecret: AgentSecret;
};
const STORAGE_KEY = "jazz-logged-in-secret";
/**
* `BrowserOnboardingAuth` provides a `JazzAuth` object for demo authentication.
*
* Demo authentication is useful for quickly testing your app, as it allows you to create new accounts and log in as existing ones. The authentication persists across page reloads, with the credentials stored in `localStorage`.
*
* ```
* import { BrowserOnboardingAuth } from "jazz-browser";
*
* const auth = new BrowserOnboardingAuth(driver);
* ```
*
* @category Auth Providers
*/
export class BrowserOnboardingAuth implements AuthMethod {
constructor(
public defaultUserName: string,
public driver: BrowserOnboardingAuth.Driver,
) {}
/**
* @returns A `JazzAuth` object
*/
async start() {
const existingUser = localStorage[STORAGE_KEY];
if (existingUser) {
const existingUserData = JSON.parse(existingUser) as StorageData;
const accountID = existingUserData.accountID as ID<Account>;
const secret = existingUserData.accountSecret;
return {
type: "existing",
credentials: { accountID, secret },
onSuccess: () => {
this.driver.onSignedIn({ logOut });
},
onError: (error: string | Error) => {
this.driver.onError(error);
},
logOut,
} satisfies AuthResult;
} else {
return {
type: "new",
creationProps: { name: this.defaultUserName, anonymous: true },
saveCredentials: async (credentials: {
accountID: ID<Account>;
secret: AgentSecret;
}) => {
const storageData = JSON.stringify({
accountID: credentials.accountID,
accountSecret: credentials.secret,
} satisfies StorageData);
localStorage[STORAGE_KEY] = storageData;
},
onSuccess: () => {
this.driver.onSignedIn({ logOut });
},
onError: (error: string | Error) => {
this.driver.onError(error);
},
logOut,
} satisfies AuthResult;
}
}
}
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace BrowserOnboardingAuth {
export interface Driver {
onSignedIn: (next: { logOut: () => void }) => void;
onError: (error: string | Error) => void;
}
}
function logOut() {
delete localStorage[STORAGE_KEY];
}

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