Compare commits

...

59 Commits

Author SHA1 Message Date
Guido D'Orsi
b04e2be665 feat: increase depth limit to 10 2025-03-25 11:03:23 +01:00
Guido D'Orsi
80b1535cdf Merge remote-tracking branch 'origin/main' into 0-12-0 2025-03-24 18:36:48 +01:00
Guido D'Orsi
dda9672dcb Merge pull request #1680 from garden-co/changeset-release/main
Version Packages
2025-03-24 13:54:19 +01:00
github-actions[bot]
a86cd0e74e Version Packages 2025-03-24 12:45:13 +00:00
Guido D'Orsi
95e84a2ca7 Merge pull request #1720 from garden-co/image-targetWidth
feat: add targetWidth option to ProgressiveImage
2025-03-24 13:42:19 +01:00
Guido D'Orsi
e7c85b7575 feat: add targetWidth option to ProgressiveImage 2025-03-24 13:13:45 +01:00
Guido D'Orsi
8ad57f9d50 Merge pull request #1471 from garden-co/jazz-739-handle-reloading-page-while-image-upload-is-in-progress
jazz-739-handle-reloading-page-while-image-upload-is-in-progress
2025-03-24 12:30:47 +01:00
Benjamin S. Leveritt
4a0f70692f Update healthy-peas-kick.md 2025-03-24 11:29:34 +00:00
Guido D'Orsi
51db96e8d0 chore: align the lockfile with main 2025-03-24 12:20:18 +01:00
Guido D'Orsi
4b0b27bde7 Merge remote-tracking branch 'origin/main' into jazz-739-handle-reloading-page-while-image-upload-is-in-progress 2025-03-24 12:19:50 +01:00
Guido D'Orsi
29a177224d test: add a test for createImage 2025-03-24 12:19:12 +01:00
Guido D'Orsi
63ccdaa3b2 chore: remove vitest file 2025-03-24 11:58:26 +01:00
Guido D'Orsi
8ed144e857 chore: changeset 2025-03-24 11:01:54 +01:00
Guido D'Orsi
c9e2ab69bf feat: mark the package as async and remove the setTimeout 2025-03-24 11:00:03 +01:00
Guido D'Orsi
3d882f0442 fix: update resolve in the new music player action 2025-03-14 15:25:23 +01:00
Guido D'Orsi
f61d568c9d Merge remote-tracking branch 'origin/main' into 0-12-0 2025-03-14 15:21:09 +01:00
Benjamin S. Leveritt
02fe68d207 Adds equality check to sessionID comparison 2025-03-13 14:29:42 +00:00
Benjamin S. Leveritt
0f87cfbbb0 Fixes sort order fallback when madeAt is identical 2025-03-13 13:41:44 +00:00
Guido D'Orsi
cc1eb6da90 Merge pull request #1506 from garden-co/image-upload-ux
Image upload example UX improvement
2025-03-13 08:34:15 +00:00
Benjamin S. Leveritt
f7b91b7ce1 Adds unload notification while uploading 2025-03-13 08:34:15 +00:00
Benjamin S. Leveritt
e2b1247969 Return promise while processing image 2025-03-13 08:34:15 +00:00
Guido D'Orsi
6dd02d289c chore: fix a type error in the tests 2025-03-11 17:22:26 +01:00
Guido D'Orsi
33a4944ba3 Merge remote-tracking branch 'origin/jazz-581-add-docs' into 0-12-0 2025-03-11 17:17:26 +01:00
Guido D'Orsi
e367b6056d Merge remote-tracking branch 'origin/main' into jazz-581-rfc-new-deep-loading-api 2025-03-11 17:14:38 +01:00
Guido D'Orsi
f3f56b9be0 docs: clarifications 2025-03-06 14:42:30 +01:00
Guido D'Orsi
4cae6bad34 Merge 2025-03-06 14:38:01 +01:00
Guido D'Orsi
17f2ef57de docs: bump the upgrade version 2025-03-06 14:37:19 +01:00
Guido D'Orsi
3a4d111a37 Merge remote-tracking branch 'origin/main' into jazz-581-rfc-new-deep-loading-api 2025-03-06 14:33:18 +01:00
Guido D'Orsi
1e18c7f5fc Merge remote-tracking branch 'origin/0-11-0' into jazz-581-rfc-new-deep-loading-api 2025-02-28 14:58:32 +01:00
Guido D'Orsi
8c7a6b27ed docs: refine the examples and align the feature descripted with the implementation 2025-02-26 18:23:02 +01:00
Guido D'Orsi
91f96e1188 Merge branch 'jazz-581-rfc-new-deep-loading-api' into jazz-581-add-docs 2025-02-26 18:12:56 +01:00
Guido D'Orsi
28dac10723 Merge pull request #1517 from garden-co/fix/optional-fields-acl
feat(deepLoading): return undefined when an optional field is not accessible
2025-02-26 14:58:27 +01:00
Guido D'Orsi
9cb11e38dd feat(deepLoading): return undefined when an optional field is not accessible 2025-02-26 12:56:06 +01:00
Guido D'Orsi
f3e4bacb33 Merge remote-tracking branch 'origin/main' into jazz-581-rfc-new-deep-loading-api 2025-02-25 17:46:22 +01:00
Guido D'Orsi
626d43f07b Merge remote-tracking branch 'origin/main' into jazz-581-rfc-new-deep-loading-api 2025-02-21 18:27:14 +01:00
Benjamin S. Leveritt
1f5d073035 Update homepage/homepage/app/(docs)/docs/[framework]/[...slug]/upgrade/0-11-0.mdx
Co-authored-by: Guido D'Orsi <guido@float.com>
2025-02-13 17:34:20 +00:00
Benjamin S. Leveritt
a3b607e799 Update homepage/homepage/app/(docs)/docs/[framework]/[...slug]/upgrade/0-11-0.mdx
Co-authored-by: Guido D'Orsi <guido@float.com>
2025-02-13 17:34:06 +00:00
Benjamin S. Leveritt
8fb93502af Update homepage/homepage/app/(docs)/docs/[framework]/[...slug]/upgrade/0-11-0.mdx
Co-authored-by: Guido D'Orsi <guido@float.com>
2025-02-13 17:33:49 +00:00
Benjamin S. Leveritt
36774122e0 Updates react guide for new resolve API
Signed-off-by: Benjamin S. Leveritt <benjamin@leveritt.co.uk>
2025-02-13 16:08:52 +00:00
Benjamin S. Leveritt
a6923128c1 Adds upgrade guide
Signed-off-by: Benjamin S. Leveritt <benjamin@leveritt.co.uk>
2025-02-13 15:56:11 +00:00
Guido D'Orsi
706ca62feb Merge pull request #1363 from garden-co/unauthorized-deep-loading
fix: check CoValue permissions when loading/subscribing
2025-02-13 09:55:16 +01:00
Guido D'Orsi
01523dcca3 fix: check CoValue permissions when loading/subscribing 2025-02-13 09:19:19 +01:00
Guido D'Orsi
77f039b561 Merge remote-tracking branch 'origin/main' into jazz-581-rfc-new-deep-loading-api 2025-02-13 09:18:47 +01:00
Guido D'Orsi
d661ba77be chore: improve pre-release comment output 2025-02-12 11:32:05 +01:00
Guido D'Orsi
f8fbc59b6f Merge remote-tracking branch 'origin/main' into jazz-581-rfc-new-deep-loading-api 2025-02-11 16:26:12 +01:00
Guido D'Orsi
cce0d22007 fix: update resolve property 2025-02-11 15:15:44 +01:00
Guido D'Orsi
e3ff76e9cb Merge remote-tracking branch 'origin/authv2' into jazz-581-rfc-new-deep-loading-api 2025-02-11 15:12:51 +01:00
Guido D'Orsi
4cbf71bff7 Merge pull request #1338 from garden-co/new-deep-loading-extra-props-fix
fix: disallow extra props in the resolve type
2025-02-11 14:38:43 +01:00
Guido D'Orsi
ceb060243a fix: disallow extra props in the resolve type 2025-02-10 20:04:32 +01:00
Anselm
a70bebb96a Clean up new deep-loading API 2025-01-29 14:39:16 +00:00
Anselm
b3b2507c35 Merge branch 'main' into jazz-581-rfc-new-deep-loading-api 2025-01-27 11:36:08 +00:00
Anselm
6a8fa16b49 Fix form and chat-rn-clerk examples 2024-12-16 15:56:48 +00:00
Anselm
1f08807701 Merge branch 'main' into jazz-581-rfc-new-deep-loading-api 2024-12-16 15:37:39 +00:00
Anselm
ba4a7f6170 Remove temp vite config 2024-12-16 15:35:06 +00:00
Anselm
a2854e3602 Upgrade to minor version change 2024-12-16 11:25:00 +00:00
Anselm
4ea87dc494 Add changeset 2024-12-16 10:55:51 +00:00
Anselm
d8c87c5314 Use $each instead of each 2024-12-16 10:54:25 +00:00
Anselm
46f624a12e Replace 'items' with 'each' 2024-12-13 16:28:40 +00:00
Anselm
86ce770f38 Implement clearer syntax for deep loading 2024-12-13 15:12:42 +00:00
207 changed files with 3173 additions and 1570 deletions

View File

@@ -1,18 +0,0 @@
---
"jazz-tailwind-demo-auth-starter": patch
"file-share-svelte": patch
"jazz-password-manager": patch
"version-history": patch
"passkey-svelte": patch
"chat-rn-clerk": patch
"jazz-example-music-player": patch
"passphrase": patch
"multiauth": patch
"reactions": patch
"passkey": patch
"clerk": patch
"jazz-example-pets": patch
"jazz-example-todo": patch
---
Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.

View File

@@ -0,0 +1,6 @@
---
"jazz-tools": minor
"cojson": minor
---
Check CoValue access permissions when loading

View File

@@ -1,5 +0,0 @@
---
"create-jazz-app": patch
---
add directory param to create-jazz-app

View File

@@ -1,6 +0,0 @@
---
"jazz-inspector": patch
"jazz-inspector-app": patch
---
UI and JSON display improvements

View File

@@ -0,0 +1,5 @@
---
"jazz-tools": minor
---
Implement new API for deep loading

View File

@@ -1,6 +0,0 @@
---
"jazz-inspector-app": patch
"jazz-inspector": patch
---
isolate class name hashing on inspector

View File

@@ -0,0 +1,5 @@
---
"cojson": minor
---
Return the EVERYONE role if the account is not direct a member of the group

View File

@@ -1,5 +1,16 @@
# chat-rn-clerk
## 1.0.87
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react-native@0.11.6
- jazz-tools@0.11.6
- jazz-react-native-auth-clerk@0.11.6
- jazz-react-native-media-images@0.11.6
## 1.0.86
### Patch Changes

View File

@@ -28,7 +28,7 @@ export default function Conversation() {
const { me } = useAccount();
const [chat, setChat] = useState<Chat>();
const [message, setMessage] = useState("");
const loadedChat = useCoState(Chat, chat?.id, [{}]);
const loadedChat = useCoState(Chat, chat?.id, { resolve: { $each: true } });
const navigation = useNavigation();
const [isUploading, setIsUploading] = useState(false);
@@ -71,7 +71,7 @@ export default function Conversation() {
const loadChat = async (chatId: ID<Chat>) => {
try {
const chat = await Chat.load(chatId, me, []);
const chat = await Chat.load(chatId, me);
setChat(chat);
} catch (error) {
console.log("Error loading chat", error);

View File

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

View File

@@ -1,5 +1,13 @@
# chat-rn
## 1.0.83
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-react-native@0.11.6
- jazz-tools@0.11.6
## 1.0.82
### Patch Changes

View File

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

View File

@@ -20,7 +20,7 @@ import { Chat, Message } from "./schema";
export default function ChatScreen({ navigation }: { navigation: any }) {
const { me, logOut } = useAccount();
const [chatId, setChatId] = useState<ID<Chat>>();
const loadedChat = useCoState(Chat, chatId, [{}]);
const loadedChat = useCoState(Chat, chatId, { resolve: { $each: true } });
const [message, setMessage] = useState("");
const profile = useCoState(Profile, me._refs.profile?.id, {});

View File

@@ -1,5 +1,14 @@
# chat-vue
## 0.0.68
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-tools@0.11.6
- jazz-vue@0.11.6
- jazz-browser@0.11.6
## 0.0.67
### Patch Changes

View File

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

View File

@@ -49,7 +49,7 @@ export default defineComponent({
},
},
setup(props) {
const chat = useCoState(Chat, props.chatId, [{}]);
const chat = useCoState(Chat, props.chatId, { resolve: { $each: true } });
const showNLastMessages = ref(30);
const displayedMessages = computed(() => {

View File

@@ -1,5 +1,18 @@
# jazz-example-chat
## 0.0.165
### Patch Changes
- Updated dependencies [e7c85b7]
- Updated dependencies [09f0a98]
- Updated dependencies [11da4d1]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-inspector@0.11.6
- jazz-browser-media-images@0.11.6
## 0.0.164
### Patch Changes

View File

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

View File

@@ -17,8 +17,8 @@ import {
} from "./ui.tsx";
export function ChatScreen(props: { chatID: ID<Chat> }) {
const chat = useCoState(Chat, props.chatID, { resolve: { $each: true } });
const account = useAccount();
const chat = useCoState(Chat, props.chatID, [{}]);
const [showNLastMessages, setShowNLastMessages] = useState(30);
if (!chat)

View File

@@ -1,5 +1,15 @@
# minimal-auth-clerk
## 0.0.64
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-react-auth-clerk@0.11.6
## 0.0.63
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.63",
"version": "0.0.64",
"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.11.5",
"jazz-react-auth-clerk": "workspace:0.11.6",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"

View File

@@ -1,5 +1,14 @@
# file-share-svelte
## 0.0.48
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-tools@0.11.6
- jazz-svelte@0.11.6
## 0.0.47
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# jazz-tailwind-demo-auth-starter
## 0.0.4
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.3
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "filestream",
"private": true,
"version": "0.0.3",
"version": "0.0.4",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,15 @@
# form
## 0.1.6
### Patch Changes
- Updated dependencies [e7c85b7]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-browser-media-images@0.11.6
## 0.1.5
### Patch Changes

View File

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

View File

@@ -12,7 +12,9 @@ import {
} from "./schema.ts";
export function CreateOrder() {
const { me } = useAccount({ root: { draft: {}, orders: [] } });
const { me } = useAccount({
resolve: { root: { draft: true, orders: true } },
});
const router = useIframeHashRouter();
const [errors, setErrors] = useState<string[]>([]);
@@ -60,7 +62,7 @@ function CreateOrderForm({
onSave: (draft: DraftBubbleTeaOrder) => void;
}) {
const draft = useCoState(DraftBubbleTeaOrder, id, {
addOns: [],
resolve: { addOns: true },
});
if (!draft) return;

View File

@@ -2,7 +2,7 @@ import { useAccount } from "jazz-react";
export function DraftIndicator() {
const { me } = useAccount({
root: { draft: {} },
resolve: { root: { draft: true } },
});
if (me?.root.draft?.hasChanges) {

View File

@@ -6,7 +6,7 @@ import { OrderThumbnail } from "./OrderThumbnail.tsx";
import { BubbleTeaOrder } from "./schema.ts";
export function EditOrder(props: { id: ID<BubbleTeaOrder> }) {
const order = useCoState(BubbleTeaOrder, props.id, []);
const order = useCoState(BubbleTeaOrder, props.id);
if (!order) return;

View File

@@ -4,7 +4,7 @@ import { OrderThumbnail } from "./OrderThumbnail.tsx";
export function Orders() {
const { me } = useAccount({
root: { orders: [] },
resolve: { root: { orders: true } },
});
return (

View File

@@ -1,5 +1,15 @@
# image-upload
## 0.0.62
### Patch Changes
- Updated dependencies [e7c85b7]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-browser-media-images@0.11.6
## 0.0.61
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "image-upload",
"private": true,
"version": "0.0.61",
"version": "0.0.62",
"type": "module",
"scripts": {
"dev": "vite",
@@ -24,6 +24,9 @@
"@vitejs/plugin-react": "^4.3.3",
"globals": "^15.11.0",
"typescript": "~5.6.2",
"vite": "^6.0.11"
"vite": "^6.0.11",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.17"
}
}

View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -3,7 +3,7 @@ import ImageUpload from "./ImageUpload.tsx";
function App() {
return (
<>
<main className="container">
<main className="container py-16">
<ImageUpload />
</main>
</>

View File

@@ -1,60 +1,97 @@
import { createImage } from "jazz-browser-media-images";
import { ProgressiveImg, useAccount } from "jazz-react";
import { ImageDefinition } from "jazz-tools";
import { ChangeEvent, useRef } from "react";
function Image({ image }: { image: ImageDefinition }) {
return (
<ProgressiveImg image={image}>
{({ src }) => <img src={src} />}
</ProgressiveImg>
);
}
import { ChangeEvent, useEffect, useRef, useState } from "react";
export default function ImageUpload() {
const { me } = useAccount();
const [imagePreviewUrl, setImagePreviewUrl] = useState<string | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
if (imagePreviewUrl) {
e.preventDefault();
return "Upload in progress. Are you sure you want to leave?";
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
if (imagePreviewUrl) {
URL.revokeObjectURL(imagePreviewUrl);
}
};
}, [imagePreviewUrl]);
const onImageChange = async (event: ChangeEvent<HTMLInputElement>) => {
if (!me?.profile) return;
const file = event.currentTarget.files?.[0];
if (file) {
me.profile.image = await createImage(file, {
owner: me.profile._owner,
});
const objectUrl = URL.createObjectURL(file);
setImagePreviewUrl(objectUrl);
try {
me.profile.image = await createImage(file, {
owner: me.profile._owner,
});
} catch (error) {
console.error("Error uploading image:", error);
} finally {
URL.revokeObjectURL(objectUrl);
setImagePreviewUrl(null);
}
}
};
const deleteImage = () => {
if (!me?.profile) return;
me.profile.image = null;
};
return (
<>
<div>{me?.profile?.image && <Image image={me.profile.image} />}</div>
if (me?.profile?.image) {
return (
<>
<ProgressiveImg image={me.profile.image}>
{({ src }) => <img alt="" src={src} className="w-full h-auto" />}
</ProgressiveImg>
<div>
{me?.profile?.image ? (
<button type="button" onClick={deleteImage}>
Delete image
</button>
) : (
<div>
<label>Upload image</label>
<input
ref={inputRef}
type="file"
accept="image/png, image/jpeg, image/gif"
onChange={onImageChange}
/>
</div>
)}
<button type="button" onClick={deleteImage} className="mt-5">
Delete image
</button>
</>
);
}
if (imagePreviewUrl) {
return (
<div className="relative">
<p className="z-10 absolute font-semibold text-gray-900 inset-0 flex items-center justify-center">
Uploading image...
</p>
<img
src={imagePreviewUrl}
alt="Preview"
className="opacity-50 w-full h-auto"
/>
</div>
</>
);
}
return (
<div className="flex flex-col gap-3">
<label htmlFor="image">Image</label>
<input
id="image"
name="image"
ref={inputRef}
type="file"
accept="image/png, image/jpeg, image/gif, image/bmp"
onChange={onImageChange}
/>
</div>
);
}

View File

@@ -1,82 +1,3 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
--border-color: #2f2e2d;
}
html,
body,
#root {
height: 100%;
}
body {
margin: 0;
}
button {
border-radius: 8px;
border: 0;
padding: 0.6em 1.2em;
font-weight: 500;
background-color: #1a1a1a;
cursor: pointer;
}
@media (prefers-color-scheme: light) {
:root {
--border-color: #e5e5e5;
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
* {
border-color: var(--border-color);
}
header,
main {
padding: 0.5rem 0;
}
header {
border-bottom: 1px solid var(--border-color);
margin-bottom: 2rem;
}
nav {
display: flex;
align-items: center;
justify-content: space-between;
}
.container {
margin-right: auto;
margin-left: auto;
padding: 2rem 0.75rem;
max-width: 800px;
}
label {
display: block;
margin-bottom: 0.25rem;
}
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,18 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
container: {
center: true,
padding: {
DEFAULT: "0.75rem",
sm: "1rem",
},
},
},
},
} as const;
export default config;

View File

@@ -1,5 +1,18 @@
# jazz-example-inspector
## 0.0.115
### Patch Changes
- 09f0a98: UI and JSON display improvements
- 11da4d1: isolate class name hashing on inspector
- Updated dependencies [09f0a98]
- Updated dependencies [11da4d1]
- Updated dependencies [8ed144e]
- jazz-inspector@0.11.6
- cojson@0.11.6
- cojson-transport-ws@0.11.6
## 0.0.114
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector-app",
"private": true,
"version": "0.0.114",
"version": "0.0.115",
"type": "module",
"scripts": {
"dev": "vite",
@@ -13,8 +13,8 @@
"dependencies": {
"jazz-inspector": "workspace:*",
"clsx": "^2.0.0",
"cojson": "workspace:0.11.5",
"cojson-transport-ws": "workspace:0.11.5",
"cojson": "workspace:0.11.6",
"cojson-transport-ws": "workspace:0.11.6",
"hash-slash": "workspace:0.2.2",
"lucide-react": "^0.274.0",
"react": "^18.3.1",

View File

@@ -1,5 +1,15 @@
# multiauth
## 0.0.5
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-react-auth-clerk@0.11.6
## 0.0.4
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multiauth",
"private": true,
"version": "0.0.4",
"version": "0.0.5",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,17 @@
# jazz-example-musicplayer
## 0.0.86
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- Updated dependencies [09f0a98]
- Updated dependencies [11da4d1]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-inspector@0.11.6
## 0.0.85
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.85",
"version": "0.0.86",
"type": "module",
"scripts": {
"dev": "vite",
@@ -22,8 +22,8 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"jazz-inspector": "workspace:*",
"jazz-react": "workspace:0.11.5",
"jazz-tools": "workspace:0.11.5",
"jazz-react": "workspace:0.11.6",
"jazz-tools": "workspace:0.11.6",
"lucide-react": "^0.274.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View File

@@ -24,10 +24,7 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
* access rights to CoValues. We get it from the top-level provider `<WithJazz/>`.
*/
const { me } = useAccount({
root: {
rootPlaylist: {},
playlists: [],
},
resolve: { root: { rootPlaylist: true, playlists: true } },
});
const navigate = useNavigate();
@@ -51,8 +48,9 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
const params = useParams<{ playlistId: ID<Playlist> }>();
const playlistId = params.playlistId ?? me?.root._refs.rootPlaylist.id;
const playlist = useCoState(Playlist, playlistId, {
tracks: [],
resolve: { tracks: true },
});
const isRootPlaylist = !params.playlistId;

View File

@@ -27,9 +27,11 @@ export async function uploadMusicTracks(
isExampleTrack: boolean = false,
) {
const { root } = await MusicaAccount.getMe().ensureLoaded({
root: {
rootPlaylist: {
tracks: [],
resolve: {
root: {
rootPlaylist: {
tracks: true,
},
},
},
});
@@ -65,8 +67,10 @@ export async function uploadMusicTracks(
export async function createNewPlaylist() {
const { root } = await MusicaAccount.getMe().ensureLoaded({
root: {
playlists: [],
resolve: {
root: {
playlists: true,
},
},
});
@@ -149,9 +153,11 @@ export async function updateMusicTrackTitle(track: MusicTrack, title: string) {
export async function updateActivePlaylist(playlist?: Playlist) {
const { root } = await MusicaAccount.getMe().ensureLoaded({
root: {
activePlaylist: {},
rootPlaylist: {},
resolve: {
root: {
activePlaylist: true,
rootPlaylist: true,
},
},
});
@@ -160,7 +166,9 @@ export async function updateActivePlaylist(playlist?: Playlist) {
export async function updateActiveTrack(track: MusicTrack) {
const { root } = await MusicaAccount.getMe().ensureLoaded({
root: {},
resolve: {
root: {},
},
});
root.activeTrack = track;
@@ -170,17 +178,23 @@ export async function onAnonymousAccountDiscarded(
anonymousAccount: MusicaAccount,
) {
const { root: anonymousAccountRoot } = await anonymousAccount.ensureLoaded({
root: {
rootPlaylist: {
tracks: [{}],
resolve: {
root: {
rootPlaylist: {
tracks: {
$each: true,
},
},
},
},
});
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
rootPlaylist: {
tracks: [],
resolve: {
root: {
rootPlaylist: {
tracks: true,
},
},
},
});
@@ -197,8 +211,10 @@ export async function onAnonymousAccountDiscarded(
export async function deletePlaylist(playlistId: string) {
const { root } = await MusicaAccount.getMe().ensureLoaded({
root: {
playlists: [],
resolve: {
root: {
playlists: true,
},
},
});

View File

@@ -9,7 +9,7 @@ import { getNextTrack, getPrevTrack } from "./lib/getters";
export function useMediaPlayer() {
const { me } = useAccount({
root: {},
resolve: { root: true },
});
const playState = usePlayState();

View File

@@ -16,8 +16,10 @@ export function InvitePage() {
const playlist = await Playlist.load(playlistId, {});
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
playlists: [],
resolve: {
root: {
playlists: true,
},
},
});

View File

@@ -22,9 +22,13 @@ export function AuthModal({ open, onOpenChange }: AuthModalProps) {
const [error, setError] = useState<string | null>(null);
const { me } = useAccount({
root: {
rootPlaylist: {
tracks: [{}],
resolve: {
root: {
rootPlaylist: {
tracks: {
$each: true,
},
},
},
},
});

View File

@@ -30,9 +30,7 @@ export function MusicTrackRow({
const track = useCoState(MusicTrack, trackId);
const { me } = useAccount({
root: {
playlists: [{}],
},
resolve: { root: { playlists: { $each: true } } },
});
const playlists = me?.root.playlists ?? [];

View File

@@ -12,9 +12,7 @@ export function PlayerControls({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
const isPlaying = playState.value === "play";
const activePlaylist = useAccount({
root: {
activePlaylist: {},
},
resolve: { root: { activePlaylist: true } },
}).me?.root.activePlaylist;
useMediaEndListener(mediaPlayer.playNextTrack);
@@ -25,7 +23,7 @@ export function PlayerControls({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
});
const activeTrack = useCoState(MusicTrack, mediaPlayer.activeTrackId, {
waveform: {},
resolve: { waveform: true },
});
if (!activeTrack) return null;

View File

@@ -8,9 +8,7 @@ export function SidePanel() {
const { playlistId } = useParams();
const navigate = useNavigate();
const { me } = useAccount({
root: {
playlists: [{}],
},
resolve: { root: { playlists: { $each: true } } },
});
function handleAllTracksClick(evt: React.MouseEvent<HTMLAnchorElement>) {

View File

@@ -8,7 +8,6 @@ export function Waveform(props: { track: MusicTrack; height: number }) {
const waveformData = useCoState(
MusicTrackWaveform,
track._refs.waveform.id,
{},
)?.data;
const duration = track.duration;

View File

@@ -2,9 +2,11 @@ import { MusicaAccount } from "../1_schema";
export async function getNextTrack() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
activePlaylist: {
tracks: [],
resolve: {
root: {
activePlaylist: {
tracks: true,
},
},
},
});
@@ -21,9 +23,11 @@ export async function getNextTrack() {
export async function getPrevTrack() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
activePlaylist: {
tracks: [],
resolve: {
root: {
activePlaylist: {
tracks: true,
},
},
},
});

View File

@@ -13,7 +13,7 @@ export function useUploadExampleData() {
async function uploadOnboardingData() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {},
resolve: { root: true },
});
if (me.root.exampleDataLoaded) return;

View File

@@ -1,5 +1,13 @@
# organization
## 0.0.58
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.57
### Patch Changes

View File

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

View File

@@ -5,11 +5,11 @@ import { Organization } from "./schema.ts";
export function AcceptInvitePage() {
const navigate = useNavigate();
const { me } = useAccount({ root: { organizations: [] } });
const { me } = useAccount({ resolve: { root: { organizations: true } } });
const onAccept = (organizationId: ID<Organization>) => {
if (me?.root?.organizations) {
Organization.load(organizationId, me, []).then((organization) => {
Organization.load(organizationId).then((organization) => {
if (organization) {
// avoid duplicates
const ids = me.root.organizations.map(

View File

@@ -5,7 +5,7 @@ import { Heading } from "./components/Heading.tsx";
export function HomePage() {
const { me } = useAccount({
root: { organizations: [{}] },
resolve: { root: { organizations: true } },
});
if (!me?.root.organizations) return;

View File

@@ -3,7 +3,7 @@ import { UserIcon } from "lucide-react";
export function Layout({ children }: { children: React.ReactNode }) {
const { me, logOut } = useAccount({
root: { draftOrganization: {} },
resolve: { root: { draftOrganization: true } },
});
return (

View File

@@ -13,7 +13,7 @@ export function OrganizationPage() {
.organizationId;
const organization = useCoState(Organization, paramOrganizationId, {
projects: [],
resolve: { projects: true },
});
if (!organization) return <p>Loading organization...</p>;

View File

@@ -8,7 +8,7 @@ import { OrganizationForm } from "./OrganizationForm.tsx";
export function CreateOrganization() {
const { me } = useAccount({
root: { draftOrganization: {}, organizations: [] },
resolve: { root: { draftOrganization: true, organizations: true } },
});
const [errors, setErrors] = useState<string[]>([]);
const navigate = useNavigate();

View File

@@ -7,7 +7,7 @@ import { Organization } from "../schema.ts";
export function OrganizationSelector({ className }: { className?: string }) {
const { me } = useAccount({
root: { organizations: [{}] },
resolve: { root: { organizations: { $each: true } } },
});
const navigate = useNavigate();

View File

@@ -1,5 +1,12 @@
# passkey-svelte
## 0.0.52
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- jazz-svelte@0.11.6
## 0.0.51
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# minimal-auth-passkey
## 0.0.63
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.62
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# passphrase
## 0.0.60
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.59
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passphrase",
"private": true,
"version": "0.0.59",
"version": "0.0.60",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# jazz-password-manager
## 0.0.84
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.83
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.83",
"version": "0.0.84",
"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.11.5",
"jazz-tools": "workspace:0.11.5",
"jazz-react": "workspace:0.11.6",
"jazz-tools": "workspace:0.11.6",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.41.5",

View File

@@ -43,9 +43,11 @@ const VaultPage: React.FC = () => {
(item): item is Exclude<typeof item, null> => !!item,
) || [],
);
const folders = useCoState(FolderList, me.root?._refs.folders?.id, [
{ items: [{}] },
]);
const folders = useCoState(FolderList, me.root?._refs.folders?.id, {
resolve: {
$each: { items: { $each: true } },
},
});
const [selectedFolder, setSelectedFolder] = useState<Folder | undefined>();
const [isNewItemModalOpen, setIsNewItemModalOpen] = useState(false);

View File

@@ -60,11 +60,9 @@ export async function addSharedFolder(
me: PasswordManagerAccount,
) {
const [sharedFolder, account] = await Promise.all([
Folder.load(sharedFolderId, me, {}),
PasswordManagerAccount.load(me.id, me, {
root: {
folders: [],
},
Folder.load(sharedFolderId),
PasswordManagerAccount.load(me.id, {
resolve: { root: { folders: true } },
}),
]);

View File

@@ -1,5 +1,16 @@
# jazz-example-pets
## 0.0.182
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-browser-media-images@0.11.6
## 0.0.181
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.181",
"version": "0.0.182",
"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.11.5",
"jazz-react": "workspace:0.11.5",
"jazz-tools": "workspace:0.11.5",
"jazz-browser-media-images": "workspace:0.11.6",
"jazz-react": "workspace:0.11.6",
"jazz-tools": "workspace:0.11.6",
"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.11.5",
"jazz-run": "workspace:0.11.6",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.17",
"typescript": "~5.6.2",

View File

@@ -1,5 +1,16 @@
# reactions
## 0.0.62
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-browser-media-images@0.11.6
## 0.0.61
### Patch Changes

View File

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

View File

@@ -14,7 +14,7 @@ const reactionEmojiMap: {
};
export function ReactionsScreen(props: { id: ID<Reactions> }) {
const reactions = useCoState(Reactions, props.id, []);
const reactions = useCoState(Reactions, props.id);
if (!reactions) return;

View File

@@ -1,5 +1,14 @@
# todo-vue
## 0.0.66
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-tools@0.11.6
- jazz-vue@0.11.6
- jazz-browser@0.11.6
## 0.0.65
### Patch Changes

View File

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

View File

@@ -4,15 +4,15 @@
<div class="section-header">
<h2>Folders</h2>
<div class="new-folder">
<input
v-model="newFolderName"
placeholder="New folder name"
<input
v-model="newFolderName"
placeholder="New folder name"
class="input"
/>
<button class="btn btn-primary" @click="createFolder">Create</button>
</div>
</div>
<div class="folder-list">
<div
v-for="folder in folders"
@@ -32,9 +32,9 @@
<div class="section-header">
<h2>{{ selectedFolder?.name }}</h2>
<div class="new-todo">
<input
v-model="newTodoTitle"
placeholder="Add a new task"
<input
v-model="newTodoTitle"
placeholder="Add a new task"
class="input"
/>
<button class="btn btn-primary" @click="createTodo">Add</button>
@@ -72,7 +72,9 @@ import { Folder, FolderList, ToDoItem, ToDoList } from "../schema";
const { me } = useAccount();
const computedFoldersId = computed(() => me.value?.root?.folders?.id);
const folders = useCoState(FolderList, computedFoldersId, [{ items: [{}] }]);
const folders = useCoState(FolderList, computedFoldersId, {
resolve: { $each: { items: true } },
});
const selectedFolder = ref<Folder>();
const newFolderName = ref("");

View File

@@ -1,5 +1,14 @@
# jazz-example-todo
## 0.0.181
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.180
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.180",
"version": "0.0.181",
"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.11.5",
"jazz-tools": "workspace:0.11.5",
"jazz-react": "workspace:0.11.6",
"jazz-tools": "workspace:0.11.6",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.3.1",

View File

@@ -121,7 +121,7 @@ export default function App() {
function HomeScreen() {
const { me } = useAccount({
root: { projects: [{}] },
resolve: { root: { projects: { $each: true } } },
});
const navigate = useNavigate();

View File

@@ -1,5 +1,17 @@
# version-history
## 0.0.59
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- Updated dependencies [09f0a98]
- Updated dependencies [11da4d1]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-inspector@0.11.6
## 0.0.58
### Patch Changes

View File

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

View File

@@ -4,7 +4,9 @@ import { ID } from "jazz-tools";
import { IssueComponent } from "./Issue.tsx";
import { Issue, Project } from "./schema.ts";
export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {
const project = useCoState(Project, projectID, { issues: [{}] });
const project = useCoState(Project, projectID, {
resolve: { issues: { $each: true } },
});
if (!project) return;

View File

@@ -331,7 +331,7 @@ This works because CoValues
<CodeGroup>
```ts
const unsub = issue.subscribe([], (updatedIssue) => console.log(updatedIssue));
const unsub = issue.subscribe({ resolve: true }, (updatedIssue) => console.log(updatedIssue));
```
</CodeGroup>
@@ -339,7 +339,7 @@ This works because CoValues
<CodeGroup>
```ts
const unsub = Issue.subscribe(issueID, me, [], (updatedIssue) => {
const unsub = Issue.subscribe(issueID, me, { resolve: true }, (updatedIssue) => {
console.log(updatedIssue);
});
```
@@ -358,7 +358,7 @@ This works because CoValues
function useCoState<V extends CoValue>(Schema: CoValueClass<V>, id?: ID<V>): V | undefined {
const [value, setValue] = useState<V>();
useEffect(() => Schema.subscribe(id, [], setValue), [id]);
useEffect(() => Schema.subscribe(id, { resolve: true }, setValue), [id]);
return value;
}
@@ -454,7 +454,7 @@ function App() { // old
const issue = useCoState(Issue, issueID); // old
// old
const createIssue = () => { // old
const group = Group.create({ owner: me });
const group = Group.create();
group.addMember("everyone", "writer");
// old
const newIssue = Issue.create( // old
@@ -605,6 +605,8 @@ export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {
<button onClick={createAndAddIssue}>Create Issue</button>
</div>
</div>
) : project === null ? (
<div>Project not found or access denied</div>
) : (
<div>Loading project...</div>
);
@@ -635,7 +637,7 @@ import { IssueComponent } from "./Issue.tsx"; // old
import { useCoState } from "jazz-react"; // old
// old
export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {// old
const project = useCoState(Project, projectID, { issues: [{}] });
const project = useCoState(Project, projectID, { resolve: { issues: { $each: true } } });
const createAndAddIssue = () => {// old
project?.issues.push(Issue.create({
@@ -663,7 +665,7 @@ export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {//
```
</CodeGroup>
The loading-depth spec `{ issues: [{}] }` means "in `Project`, load `issues` and load each item in `issues` shallowly". (Since an `Issue` doesn't have any further references, "shallowly" actually means all its properties will be available).
The loading-depth spec `{ resolve: { issues: { $each: true } } }` means "in `Project`, load `issues` and load each item in `issues` deeply". (Since an `Issue` doesn't have any further references, "deeply" actually means all its properties will be available).
- Now, we can get rid of a lot of conditional accesses because we know that once `project` is loaded, `project.issues` and each `Issue` in it will be loaded as well.
- This also results in only one rerender and visual update when everything is loaded, which is faster (especially for long lists) and gives you more control over the loading UX.
@@ -747,7 +749,7 @@ import { createInviteLink } from "jazz-react";
// old
export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {// old
const project = useCoState(Project, projectID, { issues: [{}] }); // old
const project = useCoState(Project, projectID, { resolve: { issues: { $each: true } } }); // old
const { me } = useAccount();

View File

@@ -0,0 +1,110 @@
import { CodeGroup } from '@/components/forMdx'
export const metadata = { title: "Jazz 0.11.0 - Deeply resolved data" };
# Jazz 0.11.0 - Deeply resolved data
<h2 className="not-prose text-sm text-stone-600 dark:text-stone-400 mb-5 pb-2 border-b">
15 March 2025
</h2>
<div>
Jazz 0.11.0 makes it easier and safer to load nested data. You can now specify exactly which nested data you want to load, and Jazz will check permissions and handle missing data gracefully. This helps catch errors earlier during development and makes your code more reliable.
<h3>What's new?</h3>
- New resolve API for a more type-safe deep loading
- Improved permission checks on deep loading
- Easier type safety with the Resolved type
</div>
<h3>New Resolve API</h3>
<div>
We're introducing a new resolve API for deep loading, more friendly to TypeScript, IDE autocompletion and LLMs.
To get started with the new resolve API, replace empty array/object parameters with structured resolve configs:
<CodeGroup>
{/* prettier-ignore */}
```tsx
// Before
const playlist = useCoState(Playlist, id, [{}]);
const { me } = useAccount({ root: { playlists: [] } });
// After
const playlist = useCoState(Playlist, id, {
resolve: { $each: true }
});
const { me } = useAccount({
resolve: { root: { playlists: true } }
});
```
</CodeGroup>
The new API works across all loading methods:
<CodeGroup>
{/* prettier-ignore */}
```ts
// Before
Playlist.load(id, account, {
tracks: [],
});
// After
Playlist.load(id, {
loadAs: account,
resolve: { tracks: true }
});
```
</CodeGroup>
</div>
<h3>Improved permission checks on deep loading</h3>
<div>
Now `useCoState` will return `null` when the current user lacks permissions to load the requested data.
Previously, `useCoState` would return `undefined` if the current user lacked permissions, making it hard to tell if the value is loading or if it's missing.
Now `undefined` means that the value is definitely loading, and `null` means that the value is temporarily missing.
We also have implemented a more granular permission checking, where if an optional coValue cannot be accessed, useCoState will return the data stripped of that coValue.
<CodeGroup>
{/* prettier-ignore */}
```tsx
class ListOfTracks extends CoList.Of(co.optional.ref(Track)) {}
// Before (ambiguous states)
const value = useCoState(ListOfTracks, id, [{}]);
if (value === undefined) return <div>Loading or access denied</div>;
if (value === null) return <div>Not found</div>;
// After
const value = useCoState(ListOfTracks, id, { resolve: { $each: true } });
if (value === undefined) return <div>Loading...</div>;
if (value === null) return <div>Not found or access denied</div>;
// If the current user lacks permissions to load a Track, the ListOfTracks will be returned without that Track.
return tracks.map(track => track && <MusicTrack track={track} />);
```
</CodeGroup>
</div>
<h3>Type Safety Improvements</h3>
<div>
The new `Resolved` type can be used to define what kind of deeply loaded data you expect in your parameters:
<CodeGroup>
{/* prettier-ignore */}
```ts
// Before
type PlaylistResolved = Resolved<Playlist, {
tracks: { $each: true }
}>;
// After
function TrackList({ playlist }: { playlist: PlaylistResolved }) {
// Safe access to resolved tracks
return playlist.tracks.map(track => /* ... */);
}
```
</CodeGroup>
</div>

View File

@@ -68,6 +68,12 @@ export const docNavigationItems = [
{
name: "Upgrade guides",
items: [
{
// upgrade guides
name: "0.12.0 - Deeply Resolved Data",
href: "/docs/upgrade/0-12-0",
done: 100,
},
{
// upgrade guides
name: "0.11.0 - Roles and permissions",

View File

@@ -1,5 +1,13 @@
# cojson-storage-indexeddb
## 0.11.6
### Patch Changes
- Updated dependencies [8ed144e]
- cojson@0.11.6
- cojson-storage@0.11.6
## 0.11.5
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# cojson-storage-sqlite
## 0.11.6
### Patch Changes
- Updated dependencies [8ed144e]
- cojson@0.11.6
- cojson-storage@0.11.6
## 0.11.5
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "cojson-storage-rn-sqlite",
"type": "module",
"version": "0.11.5",
"version": "0.11.6",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",

View File

@@ -1,5 +1,13 @@
# cojson-storage-sqlite
## 0.11.6
### Patch Changes
- Updated dependencies [8ed144e]
- cojson@0.11.6
- cojson-storage@0.11.6
## 0.11.5
### Patch Changes

View File

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

View File

@@ -1,5 +1,12 @@
# cojson-storage
## 0.11.6
### Patch Changes
- Updated dependencies [8ed144e]
- cojson@0.11.6
## 0.11.5
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "cojson-storage",
"version": "0.11.5",
"version": "0.11.6",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",

View File

@@ -1,5 +1,12 @@
# cojson-transport-nodejs-ws
## 0.11.6
### Patch Changes
- Updated dependencies [8ed144e]
- cojson@0.11.6
## 0.11.5
### Patch Changes

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