Compare commits

..

22 Commits

Author SHA1 Message Date
Guido D'Orsi
0cfc32f591 Merge pull request #1198 from garden-co/changeset-release/main
Version Packages
2025-01-14 12:42:19 +01:00
github-actions[bot]
e8b1e07625 Version Packages 2025-01-14 10:20:58 +00:00
pax
f97946bd21 Merge pull request #1199 from garden-co/fix-react-usecontext-reference
Fix React.useContext() reference
2025-01-14 12:19:41 +02:00
pax-k
f7f461db31 chore: changeset 2025-01-14 12:04:47 +02:00
pax-k
653d09c337 fix: explicitly use useContext() instead of React.useContext() 2025-01-14 12:03:53 +02:00
pax-k
3fa5ac30ff chore: cleanup 2025-01-14 11:39:59 +02:00
Guido D'Orsi
4095041da9 Merge pull request #1179 from garden-co/jazz-640-api-make-the-current-active-account-the-default-in
Without me
2025-01-14 10:11:40 +01:00
Guido D'Orsi
c1c2f39cb5 test: fix failing test 2025-01-14 09:33:33 +01:00
Guido D'Orsi
f7f1a0aff0 fix: use groups as defult owner 2025-01-13 20:24:51 +01:00
Guido D'Orsi
3bc82dc382 Update homepage/homepage/app/docs/[framework]/[...slug]/guide/react.mdx
Co-authored-by: Anselm Eickhoff <anselm.eickhoff@gmail.com>
2025-01-13 19:36:14 +01:00
Guido D'Orsi
99bac77ae7 Update homepage/homepage/app/docs/[framework]/[...slug]/guide/react.mdx
Co-authored-by: Anselm Eickhoff <anselm.eickhoff@gmail.com>
2025-01-13 19:36:03 +01:00
Guido D'Orsi
5705ebdcad Update packages/jazz-tools/src/implementation/activeAccountContext.ts
Co-authored-by: Anselm Eickhoff <anselm.eickhoff@gmail.com>
2025-01-13 19:35:54 +01:00
pax
f3fb445c9e Merge pull request #1197 from garden-co/JAZZ-638/set-specific-package-version-on-create-jazz-app
create-jazz-app gets the latest semver package version for jazz-* dependencies from NPM via HTTP
2025-01-13 18:19:08 +02:00
pax-k
c60fe8aae2 chore: cleanup 2025-01-13 18:15:43 +02:00
pax-k
d2a882e531 fix: actually throw an error if getLatestPackageVersions() fails, without falling back to "latest" 2025-01-13 18:11:37 +02:00
pax-k
036fa1f43b chore: changeset 2025-01-13 18:06:41 +02:00
pax-k
839b4af45c fix: fetching latest semver jazz-* package versions from NPM when using create-jazz-app, instead of using "latest" 2025-01-13 18:04:07 +02:00
Guido D'Orsi
c25a1af96e feat: update test and add active account management to testing utils 2025-01-10 17:20:47 +01:00
Guido D'Orsi
70667d06a1 fix: cover FileStream and createImage 2025-01-10 17:02:07 +01:00
Guido D'Orsi
fc934157f6 fix: remove unused import 2025-01-10 16:52:07 +01:00
Guido D'Orsi
0bbded1772 docs: update examples with the new simplified API 2025-01-10 16:50:51 +01:00
Guido D'Orsi
d1d773bc9c feat: make possible to call the load/subscribe/create API without passing me 2025-01-10 16:19:41 +01:00
116 changed files with 1350 additions and 434 deletions

View File

@@ -1,5 +1,15 @@
# chat-rn-clerk
## 1.0.49
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react-native@0.9.8
- jazz-react-native-auth-clerk@0.9.8
- jazz-react-native-media-images@0.9.8
## 1.0.48
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# chat-rn
## 1.0.46
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react-native@0.9.8
## 1.0.45
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# chat-vue
## 0.0.33
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-browser@0.9.8
- jazz-vue@0.9.8
## 0.0.32
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# jazz-example-chat
## 0.0.129
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.128
### Patch Changes

View File

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

View File

@@ -16,9 +16,9 @@ export function App() {
const createChat = () => {
if (!me) return;
const group = Group.create({ owner: me });
const group = Group.create();
group.addMember("everyone", "writer");
const chat = Chat.create([], { owner: group });
const chat = Chat.create([], group);
router.navigate("/#/chat/" + chat.id);
// for https://jazz.tools marketing site demo only

View File

@@ -1,5 +1,5 @@
import { createImage } from "jazz-browser-media-images";
import { useAccount, useCoState } from "jazz-react";
import { useCoState } from "jazz-react";
import { ID } from "jazz-tools";
import { useState } from "react";
import { Chat, Message } from "./schema.ts";
@@ -18,7 +18,6 @@ import {
export function ChatScreen(props: { chatID: ID<Chat> }) {
const chat = useCoState(Chat, props.chatID, [{}]);
const { me } = useAccount();
const [showNLastMessages, setShowNLastMessages] = useState(30);
if (!chat)
@@ -27,8 +26,6 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
);
const sendImage = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!me?.profile) return;
const file = event.currentTarget.files?.[0];
if (!file) return;
@@ -38,13 +35,8 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
return;
}
createImage(file, { owner: chat._owner }).then((image) => {
chat.push(
Message.create(
{ text: file.name, image: image },
{ owner: chat._owner },
),
);
createImage(file).then((image) => {
chat.push(Message.create({ text: file.name, image: image }, chat._owner));
});
};

View File

@@ -1,5 +1,14 @@
# minimal-auth-clerk
## 0.0.28
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-react-auth-clerk@0.9.8
## 0.0.27
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.27",
"version": "0.0.28",
"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.9.4",
"jazz-react-auth-clerk": "workspace:0.9.8",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"

View File

@@ -1,5 +1,13 @@
# file-share-svelte
## 0.0.13
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-svelte@0.9.8
## 0.0.12
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# form
## 0.0.24
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.23
### Patch Changes

View File

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

View File

@@ -30,12 +30,9 @@ export function CreateOrder() {
me.root.orders.push(draft as BubbleTeaOrder);
// reset the draft
me.root.draft = DraftBubbleTeaOrder.create(
{
addOns: ListOfBubbleTeaAddOns.create([], me),
},
me,
);
me.root.draft = DraftBubbleTeaOrder.create({
addOns: ListOfBubbleTeaAddOns.create([]),
});
router.navigate("/");
};

View File

@@ -1,5 +1,14 @@
# image-upload
## 0.0.26
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.25
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# jazz-example-musicplayer
## 0.0.49
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.48
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.48",
"version": "0.0.49",
"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.9.4",
"jazz-tools": "workspace:0.9.1",
"jazz-react": "workspace:0.9.8",
"jazz-tools": "workspace:0.9.8",
"lucide-react": "^0.274.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",

View File

@@ -65,7 +65,7 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
return (
<>
<JazzProvider
storage={["singleTabOPFS", "indexedDB"]}
storage="indexedDB"
auth={auth}
peer={peer}
AccountSchema={MusicaAccount}

View File

@@ -31,19 +31,15 @@ export function HomePage({ mediaPlayer }: { mediaPlayer: MediaPlayer }) {
const { toast } = useToast();
async function handleFileLoad(files: FileList) {
if (!me) return;
/**
* Follow this function definition to see how we update
* values in Jazz and manage files!
*/
await uploadMusicTracks(me, files);
await uploadMusicTracks(files);
}
async function handleCreatePlaylist() {
if (!me) return;
const playlist = await createNewPlaylist(me);
const playlist = await createNewPlaylist();
navigate(`/playlist/${playlist.id}`);
}

View File

@@ -22,14 +22,22 @@ import {
* pattern that best fits your app.
*/
export async function uploadMusicTracks(
account: MusicaAccount,
files: Iterable<File>,
) {
export async function uploadMusicTracks(files: Iterable<File>) {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
rootPlaylist: {
tracks: [],
},
playlists: [],
},
});
if (!me) return;
for (const file of files) {
// The ownership object defines the user that owns the created coValues
// We are creating a group for each CoValue in order to be able to share them via Playlist
const group = Group.create(account);
const group = Group.create();
const data = await getAudioFileData(file);
@@ -50,15 +58,23 @@ export async function uploadMusicTracks(
// The newly created musicTrack can be associated to the
// user track list using a simple push call
account.root?.rootPlaylist?.tracks?.push(musicTrack);
me.root.rootPlaylist.tracks.push(musicTrack);
}
}
export async function createNewPlaylist(account: MusicaAccount) {
export async function createNewPlaylist() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
playlists: [],
},
});
if (!me) throw new Error("Current playlist not resolved");
// Since playlists are meant to be shared we associate them
// to a group which will contain the keys required to get
// access to the "owned" values
const playlistGroup = Group.create(account);
const playlistGroup = Group.create();
const playlist = Playlist.create(
{
@@ -70,7 +86,7 @@ export async function createNewPlaylist(account: MusicaAccount) {
// Again, we associate the new playlist to the
// user by pushing it into the playlists CoList
account.root?.playlists?.push(playlist);
me.root.playlists.push(playlist);
return playlist;
}
@@ -78,10 +94,7 @@ export async function createNewPlaylist(account: MusicaAccount) {
export async function addTrackToPlaylist(
playlist: Playlist,
track: MusicTrack,
account: MusicaAccount | undefined,
) {
if (!account) return;
const alreadyAdded = playlist.tracks?.some(
(t) => t?.id === track.id || t?._refs.sourceTrack?.id === track.id,
);
@@ -108,12 +121,8 @@ export async function addTrackToPlaylist(
*
* Doing this for backwards compatibility for when the Group inheritance wasn't possible
*/
const blob = await FileStream.loadAsBlob(track._refs.file.id, account);
const waveform = await MusicTrackWaveform.load(
track._refs.waveform.id,
account,
{},
);
const blob = await FileStream.loadAsBlob(track._refs.file.id);
const waveform = await MusicTrackWaveform.load(track._refs.waveform.id, {});
if (!blob || !waveform) return;
@@ -142,13 +151,25 @@ export async function updateMusicTrackTitle(track: MusicTrack, title: string) {
track.title = title;
}
export async function updateActivePlaylist(
playlist: Playlist,
me: MusicaAccount,
) {
me.root!.activePlaylist = playlist ?? me.root!.rootPlaylist;
export async function updateActivePlaylist(playlist?: Playlist) {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
activePlaylist: {},
rootPlaylist: {},
},
});
if (!me) return;
me.root.activePlaylist = playlist ?? me.root.rootPlaylist;
}
export async function updateActiveTrack(track: MusicTrack, me: MusicaAccount) {
me.root!.activeTrack = track;
export async function updateActiveTrack(track: MusicTrack) {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {},
});
if (!me) return;
me.root.activeTrack = track;
}

View File

@@ -8,26 +8,26 @@ import { updateActivePlaylist, updateActiveTrack } from "./4_actions";
import { getNextTrack, getPrevTrack } from "./lib/getters";
export function useMediaPlayer() {
const { me } = useAccount();
const { me } = useAccount({
root: {},
});
const playState = usePlayState();
const playMedia = usePlayMedia();
const [loading, setLoading] = useState<ID<MusicTrack> | null>(null);
const activeTrackId = me?.root?._refs.activeTrack?.id;
const activeTrackId = me?.root._refs.activeTrack?.id;
// Reference used to avoid out-of-order track loads
const lastLoadedTrackId = useRef<ID<MusicTrack> | null>(null);
async function loadTrack(track: MusicTrack) {
if (!me.root) return;
lastLoadedTrackId.current = track.id;
setLoading(track.id);
const file = await FileStream.loadAsBlob(track._refs.file.id, me);
const file = await FileStream.loadAsBlob(track._refs.file.id);
if (!file) {
setLoading(null);
@@ -40,7 +40,7 @@ export function useMediaPlayer() {
return;
}
updateActiveTrack(track, me);
updateActiveTrack(track);
await playMedia(file);
@@ -48,20 +48,16 @@ export function useMediaPlayer() {
}
async function playNextTrack() {
if (!me?.root) return;
const track = await getNextTrack(me);
const track = await getNextTrack();
if (track) {
updateActiveTrack(track, me);
updateActiveTrack(track);
await loadTrack(track);
}
}
async function playPrevTrack() {
if (!me?.root) return;
const track = await getPrevTrack(me);
const track = await getPrevTrack();
if (track) {
await loadTrack(track);
@@ -69,14 +65,12 @@ export function useMediaPlayer() {
}
async function setActiveTrack(track: MusicTrack, playlist?: Playlist) {
if (!me?.root) return;
if (activeTrackId === track.id && lastLoadedTrackId.current !== null) {
playState.toggle();
return;
}
updateActivePlaylist(playlist!, me);
updateActivePlaylist(playlist);
await loadTrack(track);

View File

@@ -1,25 +1,25 @@
import { useAcceptInvite, useAccount } from "jazz-react";
import { useAcceptInvite } from "jazz-react";
import { ID } from "jazz-tools";
import { useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { Playlist } from "./1_schema";
import { MusicaAccount, Playlist } from "./1_schema";
export function InvitePage() {
const navigate = useNavigate();
const { me } = useAccount({
root: {
playlists: [],
},
});
useAcceptInvite({
invitedObjectSchema: Playlist,
onAccept: useCallback(
async (playlistId: ID<Playlist>) => {
if (!me) return;
const playlist = await Playlist.load(playlistId, {});
const playlist = await Playlist.load(playlistId, me, {});
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
playlists: [],
},
});
if (!me) return;
if (
playlist &&
@@ -30,7 +30,7 @@ export function InvitePage() {
navigate("/playlist/" + playlistId);
},
[navigate, me],
[navigate],
),
});

View File

@@ -43,7 +43,7 @@ export function MusicTrackRow({
function handleAddToPlaylist(playlist: Playlist) {
if (!track) return;
addTrackToPlaylist(playlist, track, me);
addTrackToPlaylist(playlist, track);
}
return (

View File

@@ -1,10 +1,18 @@
import { MusicaAccount } from "../1_schema";
export async function getNextTrack(account: MusicaAccount) {
if (!account.root?.activePlaylist?.tracks) return;
export async function getNextTrack() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
activePlaylist: {
tracks: [],
},
},
});
const tracks = account.root.activePlaylist.tracks;
const activeTrack = account.root._refs.activeTrack;
if (!me) return;
const tracks = me.root.activePlaylist.tracks;
const activeTrack = me.root._refs.activeTrack;
const currentIndex = tracks.findIndex((item) => item?.id === activeTrack.id);
@@ -13,11 +21,19 @@ export async function getNextTrack(account: MusicaAccount) {
return tracks[nextIndex];
}
export async function getPrevTrack(account: MusicaAccount) {
if (!account.root?.activePlaylist?.tracks) return;
export async function getPrevTrack() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
activePlaylist: {
tracks: [],
},
},
});
const tracks = account.root.activePlaylist.tracks;
const activeTrack = account.root._refs.activeTrack;
if (!me) return;
const tracks = me.root.activePlaylist.tracks;
const activeTrack = me.root._refs.activeTrack;
const currentIndex = tracks.findIndex((item) => item?.id === activeTrack.id);

View File

@@ -1,30 +1,30 @@
import { useAccount } from "jazz-react";
// eslint-disable-next-line react-compiler/react-compiler
/* eslint-disable react-hooks/exhaustive-deps */
import { MusicaAccount } from "@/1_schema";
import { useEffect } from "react";
import { MusicaAccount } from "../1_schema";
import { uploadMusicTracks } from "../4_actions";
export function useUploadExampleData() {
const { me } = useAccount({
useEffect(() => {
uploadOnboardingData();
}, []);
}
async function uploadOnboardingData() {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {},
});
const shouldUploadOnboardingData = me?.root?.exampleDataLoaded === false;
if (!me) throw new Error("Me not resolved");
useEffect(() => {
if (me?.root && shouldUploadOnboardingData) {
me.root.exampleDataLoaded = true;
if (me.root.exampleDataLoaded) return;
uploadOnboardingData(me).then(() => {
me.root.exampleDataLoaded = true;
});
}
}, [shouldUploadOnboardingData]);
}
async function uploadOnboardingData(me: MusicaAccount) {
const trackFile = await (await fetch("/example.mp3")).blob();
return uploadMusicTracks(me, [new File([trackFile], "Example song")]);
me.root.exampleDataLoaded = true;
try {
const trackFile = await (await fetch("/example.mp3")).blob();
await uploadMusicTracks([new File([trackFile], "Example song")]);
} catch (error) {
me.root.exampleDataLoaded = false;
throw error;
}
}

View File

@@ -1,5 +1,14 @@
# jazz-example-onboarding
## 0.0.30
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.29
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# organization
## 0.0.22
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.21
### Patch Changes

View File

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

View File

@@ -1,5 +1,11 @@
# passkey-svelte
## 0.0.17
### Patch Changes
- jazz-svelte@0.9.8
## 0.0.16
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# minimal-auth-passkey
## 0.0.27
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.26
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# jazz-password-manager
## 0.0.48
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.47
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.47",
"version": "0.0.48",
"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.9.4",
"jazz-tools": "workspace:0.9.1",
"jazz-react": "workspace:0.9.8",
"jazz-tools": "workspace:0.9.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.41.5",

View File

@@ -1,5 +1,14 @@
# jazz-example-pets
## 0.0.146
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.145
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.145",
"version": "0.0.146",
"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.9.1",
"jazz-react": "workspace:0.9.4",
"jazz-tools": "workspace:0.9.1",
"jazz-browser-media-images": "workspace:0.9.8",
"jazz-react": "workspace:0.9.8",
"jazz-tools": "workspace:0.9.8",
"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.9.1",
"jazz-run": "workspace:0.9.8",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.15",
"typescript": "~5.6.2",

View File

@@ -1,5 +1,14 @@
# reactions
## 0.0.26
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.25
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# todo-vue
## 0.0.31
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-browser@0.9.8
- jazz-vue@0.9.8
## 0.0.30
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# jazz-example-todo
## 0.0.145
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.144
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.144",
"version": "0.0.145",
"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.9.4",
"jazz-tools": "workspace:0.9.1",
"jazz-react": "workspace:0.9.8",
"jazz-tools": "workspace:0.9.8",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.3.1",

View File

@@ -70,7 +70,6 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
</JazzAndAuth>
</div>
</ThemeProvider>
,
</React.StrictMode>,
);

View File

@@ -1,5 +1,13 @@
# version-history
## 0.0.23
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.22
### Patch Changes

View File

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

View File

@@ -125,7 +125,7 @@ export function CreateOrder() {
const [draft, setDraft] = useState<DraftBubbleTeaOrder>();
useEffect(() => {
setDraft(DraftBubbleTeaOrder.create({}, { owner: me }));
setDraft(DraftBubbleTeaOrder.create({}));
}, [me?.id]);
const onSave = (e: React.FormEvent<HTMLFormElement>) => {
@@ -179,7 +179,7 @@ export function CreateOrder() { // old
const [draft, setDraft] = useState<DraftBubbleTeaOrder>(); // old
useEffect(() => { // old
setDraft(DraftBubbleTeaOrder.create({}, { owner: me })); // old
setDraft(DraftBubbleTeaOrder.create({})); // old
}, [me?.id]); // old
const onSave = (e: React.FormEvent<HTMLFormElement>) => { // old
@@ -229,14 +229,10 @@ export class JazzAccount extends Account {
root = co.ref(AccountRoot);
migrate(this: JazzAccount, creationProps?: { name: string }) {
super.migrate(creationProps);
if (this.root === undefined) {
const draft = DraftBubbleTeaOrder.create({});
if (!this._refs.root) {
const ownership = { owner: this };
const draft = DraftBubbleTeaOrder.create({}, ownership);
this.root = AccountRoot.create({ draft }, ownership);
this.root = AccountRoot.create({ draft });
}
}
}
@@ -303,11 +299,11 @@ export function CreateOrder() {// old
// create a new empty draft
me.root.draft = DraftBubbleTeaOrder.create(
{}, { owner: me },
{},
);
};// old
return <CreateOrderForm id={me?.root?.draft.id} onSave={onSave} />
return <CreateOrderForm id={me.root.draft.id} onSave={onSave} />
} // old
function CreateOrderForm({

View File

@@ -54,11 +54,9 @@ export class JazzAccount extends Account {
root = co.ref(JazzAccountRoot);
async migrate() {
if (!this._refs.root) {
if (this.root === undefined) {
// Using a Group as an owner allows you to give access to other users
const initialOrganizationOwnership = {
owner: Group.create({ owner: this }),
};
const organizationGroup = Group.create();
const organizations = ListOfOrganizations.create(
[
@@ -66,17 +64,15 @@ export class JazzAccount extends Account {
Organization.create(
{
name: "My organization",
projects: ListOfProjects.create([], initialOrganizationOwnership),
projects: ListOfProjects.create([], organizationGroup),
},
initialOrganizationOwnership,
organizationGroup,
),
],
{ owner: this },
);
this.root = JazzAccountRoot.create(
{ organizations },
{ owner: this },
);
}
}
@@ -101,22 +97,27 @@ When the user accepts the invite, add the `Organization` to the user's `organiza
<CodeGroup>
```ts
const onAccept = (organizationId: ID<Organization>) => {
if (me?.root?.organizations) {
Organization.load(organizationId, me, []).then((organization) => {
if (organization) {
// Avoid duplicates
const ids = me.root.organizations.map(
(organization) => organization?.id,
);
const onAccept = async (organizationId: ID<Organization>) => {
const me = await MusicaAccount.getMe().ensureLoaded({
root: {
organizations: [],
},
});
if (ids.includes(organizationId)) return;
if (!me) throw new Error("Failed to load account data");
me.root.organizations.push(organization);
navigate("/organizations/" + organizationId);
}
});
}
const organization = await Organization.load(organizationId, []);
if (!organization) throw new Error("Failed to load organization data");
const ids = me.root.organizations.map(
(organization) => organization?.id,
);
if (ids.includes(organizationId)) return;
me.root.organizations.push(organization);
navigate("/organizations/" + organizationId);
};
useAcceptInvite({

View File

@@ -36,9 +36,9 @@ You can add group members by ID by using `Account.load` and `Group.addMember`.
```tsx
import { Group, Account } from "jazz-tools";
const group = Group.create({ owner: me });
const group = Group.create();
const bob = await Account.load(bobsID, me, []);
const bob = await Account.load(bobsID, []);
group.addMember(bob, "writer");
```
</CodeGroup>
@@ -49,7 +49,7 @@ Note: if the account ID is of type `string`, because it comes from a URL paramet
```tsx
import { Group, Account, ID } from "jazz-tools";
const bob = await Account.load(bobsID as ID<Account>, me, []);
const bob = await Account.load(bobsID as ID<Account>, []);
group.addMember(bob, "writer");
```
</CodeGroup>

View File

@@ -13,7 +13,7 @@ access to "everyone".
<CodeGroup>
```ts
const group = Group.create({ owner: me });
const group = Group.create();
group.addMember("everyone", "writer"); // *highlight*
```
</CodeGroup>

View File

@@ -186,10 +186,8 @@ Now, finally, let's implement creating an issue:
import { useState } from "react"; // old
import { Issue } from "./schema"; // old
import { IssueComponent } from "./components/Issue.tsx"; // old
import { useAccount } from "jazz-react";
// old
function App() {// old
const { me } = useAccount();
const [issue, setIssue] = useState<Issue>(); // old
// old
const createIssue = () => {
@@ -200,7 +198,6 @@ function App() {// old
estimate: 5,
status: "backlog",
},
{ owner: me },
);
setIssue(newIssue);
};
@@ -234,7 +231,7 @@ We'll already notice one interesting thing here:
- We have to create every CoValue with an `owner`!
- this will determine access rights on the CoValue, which we'll learn about in "Groups & Permissions"
- here we set `owner` to the current user `me`, which we get from the Jazz context / `useAccount`
- here the `owner` is set automatically to a group managed by the current user because we have not declared any
**Behind the scenes, Jazz not only creates the Issue in memory but also automatically syncs an encrypted version to the cloud and persists it locally. The Issue also has a globally unique ID.**
@@ -260,11 +257,10 @@ Let's modify `src/App.tsx`:
import { useState } from "react"; // old
import { Issue } from "./schema"; // old
import { IssueComponent } from "./components/Issue.tsx"; // old
import { useAccount, useCoState } from "jazz-react";
import { useCoState } from "jazz-react";
import { ID } from "jazz-tools"
// old
function App() { // old
const { me } = useAccount(); // old
const [issueID, setIssueID] = useState<ID<Issue>>();
// old
const issue = useCoState(Issue, issueID);
@@ -277,7 +273,6 @@ function App() { // old
estimate: 5, // old
status: "backlog", // old
}, // old
{ owner: me }, // old
); // old
setIssueID(newIssue.id);
}; // old
@@ -381,10 +376,9 @@ This works because CoValues
<CodeGroup size="sm">
```ts
function useCoState<V extends CoValue>(Schema: CoValueClass<V>, id?: ID<V>): V | undefined {
const { me } = useAccount();
const [value, setValue] = useState<V>();
useEffect(() => Schema.subscribe(id, me, [], setValue), [id]);
useEffect(() => Schema.subscribe(id, [], setValue), [id]);
return value;
}
@@ -409,11 +403,10 @@ So let's store the ID in the browser's URL and make sure our useState is in sync
import { useState } from "react"; // old
import { Issue } from "./schema"; // old
import { IssueComponent } from "./components/Issue.tsx"; // old
import { useAccount, useCoState } from "jazz-react"; // old
import { useCoState } from "jazz-react"; // old
import { ID } from "jazz-tools" // old
// old
function App() { // old
const { me } = useAccount(); // old
const [issueID, setIssueID] = useState<ID<Issue> | undefined>(
(window.location.search?.replace("?issue=", "") || undefined) as ID<Issue> | undefined,
);
@@ -428,7 +421,6 @@ function App() { // old
estimate: 5, // old
status: "backlog", // old
}, // old
{ owner: me }, // old
); // old
setIssueID(newIssue.id); // old
window.history.pushState({}, "", `?issue=${newIssue.id}`);
@@ -470,7 +462,7 @@ All we have to do is create a new group to own each new issue and add "everyone"
import { useState } from "react"; // old
import { Issue } from "./schema"; // old
import { IssueComponent } from "./components/Issue.tsx"; // old
import { useAccount, useCoState } from "jazz-react"; // old
import { useCoState } from "jazz-react"; // old
import { ID, Group } from "jazz-tools"
// old
function App() { // old
@@ -564,11 +556,9 @@ First, we'll change `App.tsx` to create and render `Project`s instead of `Issue`
import { useState } from "react"; // old
import { Project, ListOfIssues } from "./schema";
import { ProjectComponent } from "./components/Project.tsx";
import { useAccount } from "jazz-react";
import { ID, Group } from "jazz-tools"
// old
function App() { // old
const { me } = useAccount(); // old
const [projectID, setProjectID] = useState<ID<Project> | undefined>(
(window.location.search?.replace("?project=", "") || undefined) as ID<Project> | undefined
);
@@ -576,7 +566,7 @@ function App() { // old
const issue = useCoState(Issue, issueID); // *bin*
// old
const createProject = () => {
const group = Group.create({ owner: me });
const group = Group.create();
group.addMember("everyone", "writer");
const newProject = Project.create(
@@ -584,7 +574,7 @@ function App() { // old
name: "New Project",
issues: ListOfIssues.create([], { owner: group })
},
{ owner: group },
group,
);
setProjectID(newProject.id);
window.history.pushState({}, "", `?project=${newProject.id}`);
@@ -622,7 +612,7 @@ export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {
description: "",
estimate: 0,
status: "backlog",
}, { owner: project._owner }));
}, project._owner));
};
return project ? (
@@ -673,7 +663,7 @@ export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {//
description: "",// old
estimate: 0,// old
status: "backlog",// old
}, { owner: project._owner }));// old
}, project._owner));// old
};// old
// old
return project ? (// old
@@ -731,17 +721,15 @@ Turns out, we're already mostly there! First, let's remove making the Project pu
import { useState } from "react"; // old
import { Project, ListOfIssues } from "./schema"; // old
import { ProjectComponent } from "./components/Project.tsx"; // old
import { useAccount } from "jazz-react"; // old
import { ID, Group } from "jazz-tools" // old
// old
function App() { // old
const { me } = useAccount(); // old
const [projectID, setProjectID] = useState<ID<Project> | undefined>( // old
(window.location.search?.replace("?project=", "") || undefined) as ID<Project> | undefined, // old
); // old
// old
const createProject = () => { // old
const group = Group.create({ owner: me }); // old
const group = Group.create(); // old
group.addMember("everyone", "writer"); // *bin*
// old
const newProject = Project.create( // old
@@ -749,7 +737,7 @@ function App() { // old
name: "New Project", // old
issues: ListOfIssues.create([], { owner: group }) // old
}, // old
{ owner: group }, // old
group, // old
); // old
setProjectID(newProject.id); // old
window.history.pushState({}, "", `?project=${newProject.id}`); // old
@@ -792,7 +780,7 @@ export function ProjectComponent({ projectID }: { projectID: ID<Project> }) {//
description: "",// old
estimate: 0,// old
status: "backlog",// old
}, { owner: project._owner }));// old
}, project._owner));// old
};// old
// old
return project ? (// old

View File

@@ -186,19 +186,40 @@ Lastly, ensure that the `"main"` field in your `package.json` points to `index.j
```
</CodeGroup>
## Using Jazz
## Setting up the provider
### `createJazzRNApp()`
Create a file `jazz.tsx` with the following contents:
Wrap your app components with the `JazzProvider:
<CodeGroup>
```tsx
import { createJazzRNApp } from "jazz-react-native";
```tsx
import { JazzProvider, useDemoAuth, DemoAuthBasicUI } from "jazz-react-native";
import { MyAppAccount } from "./schema";
export const Jazz = createJazzRNApp();
export const { useAccount, useCoState, useAcceptInvite } = Jazz;
```
export function JazzAndAuth({ children }: { children: React.ReactNode }) {
const [auth, state] = useDemoAuth();
return (
<>
<JazzProvider
auth={auth}
peer="wss://cloud.jazz.tools/?key=you@example.com"
AccountSchema={MyAppAccount}
>
{children}
</JazzProvider>
<DemoAuthBasicUI appName="My App" state={state} />
</>
);
}
// Register the Account schema so `useAccount` returns our custom `MyAppAccount`
declare module "jazz-react-native" {
interface Register {
Account: MyAppAccount;
}
}
```
</CodeGroup>
You can optionally pass a custom `kvStore` and `AccountSchema` to `createJazzRNApp()`, otherwise, it defaults to `ExpoSecureStoreAdapter` and `Account`.

View File

@@ -148,18 +148,16 @@ 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({
if (this.root === undefined) {
this.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));
myChats: ListOfChats.create([], Group.create()),
myContacts: ListOfAccounts.create([], Group.create())
});
}
}
}
@@ -182,17 +180,15 @@ 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
if (this.root === undefined) { // old
this.root = MyAppRoot.create({ // old
myChats: ListOfChats.create([], Group.create()), // old
myContacts: ListOfAccounts.create([], Group.create()) // old
}); // old
} // old
// We need to load the root field to check for the myContacts field
const result = await me.ensureLoaded({
const result = await this.ensureLoaded({
root: {},
});
@@ -203,7 +199,7 @@ export class MyAppAccount extends Account {
// 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));
root.myBookmarks = ListOfBookmarks.create([], Group.create());
}
}
}

View File

@@ -52,9 +52,9 @@ import { TodoProject, ListOfTasks } from "./schema";
const project: TodoProject = TodoProject.create(
{
title: "New Project",
tasks: ListOfTasks.create([], { owner: me }),
tasks: ListOfTasks.create([], Group.create()),
},
{ owner: me }
Group.create()
);
```
</CodeGroup>

View File

@@ -1,5 +1,11 @@
# create-jazz-app
## 0.1.6
### Patch Changes
- 036fa1f: Fix fetching latest semver jazz-\* package versions from NPM when using create-jazz-app, instead of using "latest"
## 0.1.5
### Patch Changes

View File

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

View File

@@ -21,6 +21,50 @@ type ScaffoldOptions = {
packageManager: "npm" | "yarn" | "pnpm" | "bun" | "deno";
};
async function getLatestPackageVersions(
dependencies: Record<string, string>,
): Promise<Record<string, string>> {
const versionsSpinner = ora({
text: chalk.blue("Fetching package versions..."),
spinner: "dots",
}).start();
const versions: Record<string, string> = {};
const failures: string[] = [];
await Promise.all(
Object.keys(dependencies).map(async (pkg) => {
if (
typeof dependencies[pkg] === "string" &&
dependencies[pkg].includes("workspace:")
) {
try {
const response = await fetch(
`https://registry.npmjs.org/${pkg}/latest`,
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
versions[pkg] = `^${data.version}`; // Using caret for minor version updates
} catch (error) {
failures.push(pkg);
}
}
}),
);
if (failures.length > 0) {
versionsSpinner.fail(
chalk.red(
`Failed to fetch versions for packages: ${failures.join(", ")}. Please check your internet connection and try again.`,
),
);
throw new Error("Failed to fetch package versions");
}
versionsSpinner.succeed(chalk.green("Package versions fetched successfully"));
return versions;
}
async function scaffoldProject({
starter,
projectName,
@@ -72,9 +116,13 @@ async function scaffoldProject({
// Replace workspace: dependencies with latest
if (packageJson.dependencies) {
const latestVersions = await getLatestPackageVersions(
packageJson.dependencies,
);
Object.entries(packageJson.dependencies).forEach(([pkg, version]) => {
if (typeof version === "string" && version.includes("workspace:")) {
packageJson.dependencies[pkg] = "latest";
packageJson.dependencies[pkg] = latestVersions[pkg];
}
});
}

View File

@@ -1,5 +1,13 @@
# jazz-browser-media-images
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-browser@0.9.8
## 0.9.1
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# jazz-browser-media-images
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-browser@0.9.8
## 0.9.1
### Patch Changes

View File

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

View File

@@ -7,11 +7,13 @@ const pica = new Pica();
/** @category Image creation */
export async function createImage(
imageBlobOrFile: Blob | File,
options: {
owner: Group | Account;
options?: {
owner?: Group | Account;
maxSize?: 256 | 1024 | 2048;
},
): Promise<ImageDefinition> {
const owner = options?.owner;
let originalWidth!: number;
let originalHeight!: number;
const Reducer = new ImageBlobReduce({ pica });
@@ -36,7 +38,7 @@ export async function createImage(
originalSize: [originalWidth, originalHeight],
placeholderDataURL,
},
{ owner: options.owner },
owner,
);
setTimeout(async () => {
const max256 = await Reducer.toBlob(imageBlobOrFile, { max: 256 });
@@ -51,16 +53,15 @@ export async function createImage(
? 256
: Math.round(256 * (originalHeight / originalWidth));
const binaryStream = await FileStream.createFromBlob(max256, {
owner: options.owner,
});
const binaryStream = await FileStream.createFromBlob(max256, owner);
console.log(`${width}x${height}`);
imageDefinition[`${width}x${height}`] = binaryStream;
}
await new Promise((resolve) => setTimeout(resolve, 0));
if (options.maxSize === 256) return;
if (options?.maxSize === 256) return;
const max1024 = await Reducer.toBlob(imageBlobOrFile, { max: 1024 });
@@ -74,16 +75,14 @@ export async function createImage(
? 1024
: Math.round(1024 * (originalHeight / originalWidth));
const binaryStream = await FileStream.createFromBlob(max1024, {
owner: options.owner,
});
const binaryStream = await FileStream.createFromBlob(max1024, owner);
imageDefinition[`${width}x${height}`] = binaryStream;
}
await new Promise((resolve) => setTimeout(resolve, 0));
if (options.maxSize === 1024) return;
if (options?.maxSize === 1024) return;
const max2048 = await Reducer.toBlob(imageBlobOrFile, { max: 2048 });
@@ -97,20 +96,18 @@ export async function createImage(
? 2048
: Math.round(2048 * (originalHeight / originalWidth));
const binaryStream = await FileStream.createFromBlob(max2048, {
owner: options.owner,
});
const binaryStream = await FileStream.createFromBlob(max2048, owner);
imageDefinition[`${width}x${height}`] = binaryStream;
}
await new Promise((resolve) => setTimeout(resolve, 0));
if (options.maxSize === 2048) return;
if (options?.maxSize === 2048) return;
const originalBinaryStream = await FileStream.createFromBlob(
imageBlobOrFile,
{ owner: options.owner },
owner,
);
imageDefinition[`${originalWidth}x${originalHeight}`] =

View File

@@ -0,0 +1,59 @@
// @vitest-environment happy-dom
import { createJazzTestAccount, setActiveAccount } from "jazz-tools/testing";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createImage } from "../index.js";
beforeEach(async () => {
const account = await createJazzTestAccount();
setActiveAccount(account);
});
vi.mock("pica", () => {
return {
default: vi.fn().mockImplementation(() => ({
resize: vi.fn().mockResolvedValue({}),
})),
};
});
const originalWidth = 400;
const originalHeight = 300;
// Mock ImageBlobReduce
vi.mock("image-blob-reduce", () => {
return {
default: vi.fn().mockImplementation(() => ({
toCanvas: vi.fn().mockImplementation(async () => ({
toDataURL: () => "data:image/png;base64,mockedBase64Data",
})),
toBlob: vi.fn().mockImplementation(async (blob, { max }) => {
// Return a new blob with mock dimensions based on max size
return new Blob(["reduced-image-data"], { type: "image/jpeg" });
}),
after: vi.fn().mockImplementation((event, callback) => {
// Simulate the _blob_to_image callback with mock dimensions
callback({
image: { width: originalWidth, height: originalHeight },
orientation: 1,
});
}),
})),
};
});
describe("createImage", () => {
it("should create an image definition with correct dimensions", async () => {
// Create a test blob that simulates a 400x300 image
const blob = new Blob(["fake-image-data"], { type: "image/jpeg" });
Object.defineProperty(blob, "size", { value: 1024 * 50 }); // 50KB
const imageDefinition = await createImage(blob);
expect(imageDefinition.originalSize).toEqual([
originalWidth,
originalHeight,
]);
expect(imageDefinition.placeholderDataURL).toBeDefined();
});
});

View File

@@ -1,5 +1,12 @@
# jazz-browser
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
## 0.9.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser",
"version": "0.9.1",
"version": "0.9.8",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
@@ -10,7 +10,7 @@
"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",
"jazz-tools": "workspace:0.9.8",
"typescript": "~5.6.2"
},
"scripts": {

View File

@@ -55,12 +55,13 @@ export class BrowserDemoAuth implements AuthMethod {
*/
async start() {
// 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["demo-auth-logged-in-secret"]) {
if (!localStorage[localStorageKey]) {
localStorage[localStorageKey] =
localStorage["demo-auth-logged-in-secret"];
}
delete localStorage["demo-auth-logged-in-secret"];
}
if (localStorage[localStorageKey]) {
const localStorageData = JSON.parse(

View File

@@ -1,5 +1,12 @@
# jazz-autosub
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
## 0.9.7
### Patch Changes

View File

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

View File

@@ -1,5 +1,14 @@
# jazz-browser-media-images
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-auth-clerk@0.9.8
## 0.9.4
### Patch Changes

View File

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

View File

@@ -1,5 +1,13 @@
# jazz-react-core
## 0.8.49
### Patch Changes
- f7f461d: Explicitly use useContext() instead of React.useContext()
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
## 0.8.48
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-core",
"version": "0.8.48",
"version": "0.8.49",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useRef } from "react";
import React, { useCallback, useContext, useRef } from "react";
import {
Account,
@@ -14,7 +14,7 @@ import {
import { JazzContext, JazzContextType } from "./provider.js";
export function useJazzContext<Acc extends Account>() {
const value = React.useContext(JazzContext) as JazzContextType<Acc>;
const value = useContext(JazzContext) as JazzContextType<Acc>;
if (!value) {
throw new Error(

View File

@@ -21,4 +21,5 @@ export {
createJazzTestAccount,
createJazzTestGuest,
linkAccounts,
setActiveAccount,
} from "jazz-tools/testing";

View File

@@ -12,14 +12,13 @@ describe("useCoState", () => {
value = co.string;
}
const account = await createJazzTestAccount();
const account = await createJazzTestAccount({
isCurrentActiveAccount: true,
});
const map = TestMap.create(
{
value: "123",
},
{ owner: account },
);
const map = TestMap.create({
value: "123",
});
const { result } = renderHook(() => useCoState(TestMap, map.id, {}), {
account,
@@ -33,14 +32,13 @@ describe("useCoState", () => {
value = co.string;
}
const account = await createJazzTestAccount();
const account = await createJazzTestAccount({
isCurrentActiveAccount: true,
});
const map = TestMap.create(
{
value: "123",
},
{ owner: account },
);
const map = TestMap.create({
value: "123",
});
const { result } = renderHook(() => useCoState(TestMap, map.id, {}), {
account,
@@ -65,20 +63,16 @@ describe("useCoState", () => {
nested = co.ref(TestNestedMap);
}
const account = await createJazzTestAccount();
const account = await createJazzTestAccount({
isCurrentActiveAccount: true,
});
const map = TestMap.create(
{
value: "123",
nested: TestNestedMap.create(
{
value: "456",
},
{ owner: account },
),
},
{ owner: account },
);
const map = TestMap.create({
value: "123",
nested: TestNestedMap.create({
value: "456",
}),
});
const { result } = renderHook(
() =>
@@ -104,20 +98,16 @@ describe("useCoState", () => {
nested = co.ref(TestNestedMap);
}
const account = await createJazzTestAccount();
const account = await createJazzTestAccount({
isCurrentActiveAccount: true,
});
const map = TestMap.create(
{
value: "123",
nested: TestNestedMap.create(
{
value: "456",
},
{ owner: account },
),
},
{ owner: account },
);
const map = TestMap.create({
value: "123",
nested: TestNestedMap.create({
value: "456",
}),
});
const { result } = renderHook(() => useCoState(TestMap, map.id, {}), {
account,

View File

@@ -1,5 +1,13 @@
# jazz-react-native-auth-clerk
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react-native@0.9.8
## 0.9.6
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-native-auth-clerk",
"version": "0.9.6",
"version": "0.9.8",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,12 @@
# jazz-browser-media-images
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
## 0.9.1
### Patch Changes

View File

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

View File

@@ -93,9 +93,9 @@ async function getImageDimensions(
export async function createImage(
base64ImageDataURI: string,
options: {
owner: Group | Account;
owner?: Group | Account;
maxSize?: 256 | 1024 | 2048;
},
} = {},
): Promise<ImageDefinition> {
try {
const { contentType } = base64DataURIToParts(base64ImageDataURI);
@@ -139,7 +139,7 @@ export async function createImage(
originalSize: [originalWidth, originalHeight],
placeholderDataURL,
},
{ owner: options.owner },
options.owner,
);
const addImageStream = async (

View File

@@ -1,5 +1,14 @@
# jazz-browser
## 0.9.8
### Patch Changes
- Updated dependencies [f7f461d]
- Updated dependencies [d1d773b]
- jazz-react-core@0.8.49
- jazz-tools@0.9.8
## 0.9.6
### Patch Changes

View File

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

View File

@@ -1,5 +1,15 @@
# jazz-react
## 0.9.8
### Patch Changes
- Updated dependencies [f7f461d]
- Updated dependencies [d1d773b]
- jazz-react-core@0.8.49
- jazz-tools@0.9.8
- jazz-browser@0.9.8
## 0.9.4
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react",
"version": "0.9.4",
"version": "0.9.8",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
@@ -18,8 +18,8 @@
"dependencies": {
"@scure/bip39": "^1.3.0",
"cojson": "workspace:0.9.0",
"jazz-browser": "workspace:0.9.1",
"jazz-tools": "workspace:0.9.1",
"jazz-browser": "workspace:0.9.8",
"jazz-tools": "workspace:0.9.8",
"jazz-react-core": "workspace:*"
},
"devDependencies": {

View File

@@ -1,5 +1,12 @@
# jazz-run
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
## 0.9.1
### Patch Changes

View File

@@ -3,7 +3,7 @@
"bin": "./dist/index.js",
"type": "module",
"license": "MIT",
"version": "0.9.1",
"version": "0.9.8",
"exports": {
"./startSyncServer": {
"import": "./dist/startSyncServer.js",
@@ -32,7 +32,7 @@
"cojson-storage-sqlite": "workspace:0.9.0",
"cojson-transport-ws": "workspace:0.9.0",
"effect": "^3.6.5",
"jazz-tools": "workspace:0.9.1",
"jazz-tools": "workspace:0.9.8",
"ws": "^8.14.2"
},
"devDependencies": {

View File

@@ -1,5 +1,13 @@
# jazz-svelte
## 0.9.8
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-browser@0.9.8
## 0.9.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-svelte",
"version": "0.9.1",
"version": "0.9.8",
"scripts": {
"dev": "vite dev",
"build": "vite build && npm run package",

View File

@@ -28,5 +28,6 @@ export function createJazzTestContext<Acc extends Account>({ account }: {
export {
createJazzTestAccount,
createJazzTestGuest,
linkAccounts
linkAccounts,
setActiveAccount,
} from "jazz-tools/testing";

View File

@@ -1,5 +1,11 @@
# jazz-tools
## 0.9.8
### Patch Changes
- d1d773b: Make possible to call the load/subscribe/create API without passing me
## 0.9.1
### Patch Changes

View File

@@ -23,7 +23,7 @@
},
"type": "module",
"license": "MIT",
"version": "0.9.1",
"version": "0.9.8",
"dependencies": {
"cojson": "workspace:*"
},

View File

@@ -12,6 +12,7 @@ import {
SessionID,
cojsonInternals,
} from "cojson";
import { activeAccountContext } from "../implementation/activeAccountContext.js";
import {
AnonymousJazzAgent,
type CoValue,
@@ -29,7 +30,8 @@ import {
ensureCoValueLoaded,
inspect,
loadCoValue,
subscribeToCoValue,
loadCoValueWithoutMe,
subscribeToCoValueWithoutMe,
subscribeToExistingCoValue,
subscriptionsScopes,
} from "../internal.js";
@@ -192,6 +194,10 @@ export class Account extends CoValueBase implements CoValue {
return this.fromNode(node) as A;
}
static getMe<A extends Account>(this: CoValueClass<A> & typeof Account) {
return activeAccountContext.get() as A;
}
static async createAs<A extends Account>(
this: CoValueClass<A> & typeof Account,
as: Account,
@@ -266,24 +272,56 @@ export class Account extends CoValueBase implements CoValue {
}
/** @category Subscription & Loading */
static load<A extends Account, Depth>(
this: CoValueClass<A>,
id: ID<A>,
depth: Depth & DepthsIn<A>,
): Promise<DeeplyLoaded<A, Depth> | undefined>;
static load<A extends Account, Depth>(
this: CoValueClass<A>,
id: ID<A>,
as: Account,
depth: Depth & DepthsIn<A>,
): Promise<DeeplyLoaded<A, Depth> | undefined>;
static load<A extends Account, Depth>(
this: CoValueClass<A>,
id: ID<A>,
asOrDepth: Account | (Depth & DepthsIn<A>),
depth?: Depth & DepthsIn<A>,
): Promise<DeeplyLoaded<A, Depth> | undefined> {
return loadCoValue(this, id, as, depth);
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
}
/** @category Subscription & Loading */
static subscribe<A extends Account, Depth>(
this: CoValueClass<A>,
id: ID<A>,
depth: Depth & DepthsIn<A>,
listener: (value: DeeplyLoaded<A, Depth>) => void,
): () => void;
static subscribe<A extends Account, Depth>(
this: CoValueClass<A>,
id: ID<A>,
as: Account,
depth: Depth & DepthsIn<A>,
listener: (value: DeeplyLoaded<A, Depth>) => void,
): () => void;
static subscribe<A extends Account, Depth>(
this: CoValueClass<A>,
id: ID<A>,
asOrDepth: Account | (Depth & DepthsIn<A>),
depthOrListener:
| (Depth & DepthsIn<A>)
| ((value: DeeplyLoaded<A, Depth>) => void),
listener?: (value: DeeplyLoaded<A, Depth>) => void,
): () => void {
return subscribeToCoValue<A, Depth>(this, id, as, depth, listener);
return subscribeToCoValueWithoutMe<A, Depth>(
this,
id,
asOrDepth,
depthOrListener,
listener!,
);
}
/** @category Subscription & Loading */

View File

@@ -10,6 +10,7 @@ import type {
SessionID,
} from "cojson";
import { MAX_RECOMMENDED_TX_SIZE, cojsonInternals } from "cojson";
import { activeAccountContext } from "../implementation/activeAccountContext.js";
import type {
AnonymousJazzAgent,
CoValue,
@@ -30,10 +31,12 @@ import {
co,
ensureCoValueLoaded,
inspect,
isAccountInstance,
isRefEncoded,
loadCoValue,
loadCoValueWithoutMe,
parseCoValueCreateOptions,
subscribeToCoValue,
subscribeToCoValueWithoutMe,
subscribeToExistingCoValue,
} from "../internal.js";
import { type Account } from "./account.js";
@@ -205,7 +208,7 @@ export class CoFeed<Item = any> extends CoValueBase implements CoValue {
static create<S extends CoFeed>(
this: CoValueClass<S>,
init: S extends CoFeed<infer Item> ? UnCo<Item>[] : never,
options: { owner: Account | Group } | Account | Group,
options?: { owner: Account | Group } | Account | Group,
) {
const { owner } = parseCoValueCreateOptions(options);
const instance = new this({ init, owner });
@@ -323,27 +326,59 @@ export class CoFeed<Item = any> extends CoValueBase implements CoValue {
* Load a `CoFeed`
* @category Subscription & Loading
*/
static load<S extends CoFeed, Depth>(
this: CoValueClass<S>,
id: ID<S>,
depth: Depth & DepthsIn<S>,
): Promise<DeeplyLoaded<S, Depth> | undefined>;
static load<S extends CoFeed, Depth>(
this: CoValueClass<S>,
id: ID<S>,
as: Account,
depth: Depth & DepthsIn<S>,
): Promise<DeeplyLoaded<S, Depth> | undefined>;
static load<S extends CoFeed, Depth>(
this: CoValueClass<S>,
id: ID<S>,
asOrDepth: Account | (Depth & DepthsIn<S>),
depth?: Depth & DepthsIn<S>,
): Promise<DeeplyLoaded<S, Depth> | undefined> {
return loadCoValue(this, id, as, depth);
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
}
/**
* Subscribe to a `CoFeed`, when you have an ID but don't have a `CoFeed` instance yet
* @category Subscription & Loading
*/
static subscribe<S extends CoFeed, Depth>(
this: CoValueClass<S>,
id: ID<S>,
depth: Depth & DepthsIn<S>,
listener: (value: DeeplyLoaded<S, Depth>) => void,
): () => void;
static subscribe<S extends CoFeed, Depth>(
this: CoValueClass<S>,
id: ID<S>,
as: Account,
depth: Depth & DepthsIn<S>,
listener: (value: DeeplyLoaded<S, Depth>) => void,
): () => void;
static subscribe<S extends CoFeed, Depth>(
this: CoValueClass<S>,
id: ID<S>,
asOrDepth: Account | (Depth & DepthsIn<S>),
depthOrListener:
| (Depth & DepthsIn<S>)
| ((value: DeeplyLoaded<S, Depth>) => void),
listener?: (value: DeeplyLoaded<S, Depth>) => void,
): () => void {
return subscribeToCoValue<S, Depth>(this, id, as, depth, listener);
return subscribeToCoValueWithoutMe<S, Depth>(
this,
id,
asOrDepth,
depthOrListener,
listener,
);
}
/**
@@ -675,7 +710,7 @@ export class FileStream extends CoValueBase implements CoValue {
static create<S extends FileStream>(
this: CoValueClass<S>,
options: { owner: Account | Group } | Account | Group,
options?: { owner?: Account | Group } | Account | Group,
) {
return new this(parseCoValueCreateOptions(options));
}
@@ -722,13 +757,37 @@ export class FileStream extends CoValueBase implements CoValue {
*
* @category Content
*/
static async loadAsBlob(
id: ID<FileStream>,
options?: {
allowUnfinished?: boolean;
},
): Promise<Blob | undefined>;
static async loadAsBlob(
id: ID<FileStream>,
as: Account,
options?: {
allowUnfinished?: boolean;
},
): Promise<Blob | undefined>;
static async loadAsBlob(
id: ID<FileStream>,
asOrOptions?:
| Account
| {
allowUnfinished?: boolean;
},
optionsOrUndefined?: {
allowUnfinished?: boolean;
},
): Promise<Blob | undefined> {
const as = isAccountInstance(asOrOptions)
? asOrOptions
: activeAccountContext.get();
const options = isAccountInstance(asOrOptions)
? optionsOrUndefined
: asOrOptions;
let stream = await this.load(id, as, []);
/**
@@ -764,16 +823,17 @@ export class FileStream extends CoValueBase implements CoValue {
*/
static async createFromBlob(
blob: Blob | File,
options:
options?:
| {
owner: Group | Account;
owner?: Group | Account;
onProgress?: (progress: number) => void;
}
| Account
| Group,
): Promise<FileStream> {
const stream = this.create(options);
const onProgress = "onProgress" in options ? options.onProgress : undefined;
const onProgress =
options && "onProgress" in options ? options.onProgress : undefined;
const start = Date.now();
@@ -840,27 +900,59 @@ export class FileStream extends CoValueBase implements CoValue {
* Load a `FileStream`
* @category Subscription & Loading
*/
static load<B extends FileStream, Depth>(
this: CoValueClass<B>,
id: ID<B>,
static load<C extends FileStream, Depth>(
this: CoValueClass<C>,
id: ID<C>,
depth: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined>;
static load<C extends FileStream, Depth>(
this: CoValueClass<C>,
id: ID<C>,
as: Account,
depth: Depth & DepthsIn<B>,
): Promise<DeeplyLoaded<B, Depth> | undefined> {
return loadCoValue(this, id, as, depth);
depth: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined>;
static load<C extends FileStream, Depth>(
this: CoValueClass<C>,
id: ID<C>,
asOrDepth: Account | (Depth & DepthsIn<C>),
depth?: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined> {
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
}
/**
* Subscribe to a `FileStream`, when you have an ID but don't have a `FileStream` instance yet
* @category Subscription & Loading
*/
static subscribe<B extends FileStream, Depth>(
this: CoValueClass<B>,
id: ID<B>,
static subscribe<C extends FileStream, Depth>(
this: CoValueClass<C>,
id: ID<C>,
depth: Depth & DepthsIn<C>,
listener: (value: DeeplyLoaded<C, Depth>) => void,
): () => void;
static subscribe<C extends FileStream, Depth>(
this: CoValueClass<C>,
id: ID<C>,
as: Account,
depth: Depth & DepthsIn<B>,
listener: (value: DeeplyLoaded<B, Depth>) => void,
depth: Depth & DepthsIn<C>,
listener: (value: DeeplyLoaded<C, Depth>) => void,
): () => void;
static subscribe<C extends FileStream, Depth>(
this: CoValueClass<C>,
id: ID<C>,
asOrDepth: Account | (Depth & DepthsIn<C>),
depthOrListener:
| (Depth & DepthsIn<C>)
| ((value: DeeplyLoaded<C, Depth>) => void),
listener?: (value: DeeplyLoaded<C, Depth>) => void,
): () => void {
return subscribeToCoValue<B, Depth>(this, id, as, depth, listener);
return subscribeToCoValueWithoutMe<C, Depth>(
this,
id,
asOrDepth,
depthOrListener,
listener,
);
}
ensureLoaded<B extends FileStream, Depth>(

View File

@@ -21,10 +21,10 @@ import {
ensureCoValueLoaded,
inspect,
isRefEncoded,
loadCoValue,
loadCoValueWithoutMe,
makeRefs,
parseCoValueCreateOptions,
subscribeToCoValue,
subscribeToCoValueWithoutMe,
subscribeToExistingCoValue,
subscriptionsScopes,
} from "../internal.js";
@@ -221,7 +221,7 @@ export class CoList<Item = any> extends Array<Item> implements CoValue {
static create<L extends CoList>(
this: CoValueClass<L>,
items: UnCo<L[number]>[],
options: { owner: Account | Group } | Account | Group,
options?: { owner: Account | Group } | Account | Group,
) {
const { owner } = parseCoValueCreateOptions(options);
const instance = new this({ init: items, owner });
@@ -360,13 +360,24 @@ export class CoList<Item = any> extends Array<Item> implements CoValue {
*
* @category Subscription & Loading
*/
static load<L extends CoList, Depth>(
this: CoValueClass<L>,
id: ID<L>,
static load<C extends CoList, Depth>(
this: CoValueClass<C>,
id: ID<C>,
depth: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined>;
static load<C extends CoList, Depth>(
this: CoValueClass<C>,
id: ID<C>,
as: Account,
depth: Depth & DepthsIn<L>,
): Promise<DeeplyLoaded<L, Depth> | undefined> {
return loadCoValue(this, id, as, depth);
depth: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined>;
static load<C extends CoList, Depth>(
this: CoValueClass<C>,
id: ID<C>,
asOrDepth: Account | (Depth & DepthsIn<C>),
depth?: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined> {
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
}
/**
@@ -397,14 +408,35 @@ export class CoList<Item = any> extends Array<Item> implements CoValue {
*
* @category Subscription & Loading
*/
static subscribe<L extends CoList, Depth>(
this: CoValueClass<L>,
id: ID<L>,
static subscribe<C extends CoList, Depth>(
this: CoValueClass<C>,
id: ID<C>,
depth: Depth & DepthsIn<C>,
listener: (value: DeeplyLoaded<C, Depth>) => void,
): () => void;
static subscribe<C extends CoList, Depth>(
this: CoValueClass<C>,
id: ID<C>,
as: Account,
depth: Depth & DepthsIn<L>,
listener: (value: DeeplyLoaded<L, Depth>) => void,
depth: Depth & DepthsIn<C>,
listener: (value: DeeplyLoaded<C, Depth>) => void,
): () => void;
static subscribe<C extends CoList, Depth>(
this: CoValueClass<C>,
id: ID<C>,
asOrDepth: Account | (Depth & DepthsIn<C>),
depthOrListener:
| (Depth & DepthsIn<C>)
| ((value: DeeplyLoaded<C, Depth>) => void),
listener?: (value: DeeplyLoaded<C, Depth>) => void,
): () => void {
return subscribeToCoValue<L, Depth>(this, id, as, depth, listener);
return subscribeToCoValueWithoutMe<C, Depth>(
this,
id,
asOrDepth,
depthOrListener,
listener,
);
}
/**

View File

@@ -7,6 +7,7 @@ import {
type RawCoMap,
cojsonInternals,
} from "cojson";
import { activeAccountContext } from "../implementation/activeAccountContext.js";
import type {
AnonymousJazzAgent,
CoValue,
@@ -28,10 +29,10 @@ import {
ensureCoValueLoaded,
inspect,
isRefEncoded,
loadCoValue,
loadCoValueWithoutMe,
makeRefs,
parseCoValueCreateOptions,
subscribeToCoValue,
subscribeToCoValueWithoutMe,
subscribeToExistingCoValue,
subscriptionsScopes,
} from "../internal.js";
@@ -274,7 +275,7 @@ export class CoMap extends CoValueBase implements CoValue {
static create<M extends CoMap>(
this: CoValueClass<M>,
init: Simplify<CoMapInit<M>>,
options:
options?:
| {
owner: Account | Group;
unique?: CoValueUniqueness["uniqueness"];
@@ -432,13 +433,24 @@ export class CoMap extends CoValueBase implements CoValue {
*
* @category Subscription & Loading
*/
static load<M extends CoMap, Depth>(
this: CoValueClass<M>,
id: ID<M>,
static load<C extends CoMap, Depth>(
this: CoValueClass<C>,
id: ID<C>,
depth: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined>;
static load<C extends CoMap, Depth>(
this: CoValueClass<C>,
id: ID<C>,
as: Account,
depth: Depth & DepthsIn<M>,
): Promise<DeeplyLoaded<M, Depth> | undefined> {
return loadCoValue(this, id, as, depth);
depth: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined>;
static load<C extends CoMap, Depth>(
this: CoValueClass<C>,
id: ID<C>,
asOrDepth: Account | (Depth & DepthsIn<C>),
depth?: Depth & DepthsIn<C>,
): Promise<DeeplyLoaded<C, Depth> | undefined> {
return loadCoValueWithoutMe(this, id, asOrDepth, depth);
}
/**
@@ -469,22 +481,45 @@ export class CoMap extends CoValueBase implements CoValue {
*
* @category Subscription & Loading
*/
static subscribe<M extends CoMap, Depth>(
this: CoValueClass<M>,
id: ID<M>,
static subscribe<C extends CoMap, Depth>(
this: CoValueClass<C>,
id: ID<C>,
depth: Depth & DepthsIn<C>,
listener: (value: DeeplyLoaded<C, Depth>) => void,
): () => void;
static subscribe<C extends CoMap, Depth>(
this: CoValueClass<C>,
id: ID<C>,
as: Account,
depth: Depth & DepthsIn<M>,
listener: (value: DeeplyLoaded<M, Depth>) => void,
depth: Depth & DepthsIn<C>,
listener: (value: DeeplyLoaded<C, Depth>) => void,
): () => void;
static subscribe<C extends CoMap, Depth>(
this: CoValueClass<C>,
id: ID<C>,
asOrDepth: Account | (Depth & DepthsIn<C>),
depthOrListener:
| (Depth & DepthsIn<C>)
| ((value: DeeplyLoaded<C, Depth>) => void),
listener?: (value: DeeplyLoaded<C, Depth>) => void,
): () => void {
return subscribeToCoValue<M, Depth>(this, id, as, depth, listener);
return subscribeToCoValueWithoutMe<C, Depth>(
this,
id,
asOrDepth,
depthOrListener,
listener,
);
}
static findUnique<M extends CoMap>(
this: CoValueClass<M>,
unique: CoValueUniqueness["uniqueness"],
ownerID: ID<Account> | ID<Group>,
as: Account | Group | AnonymousJazzAgent,
as?: Account | Group | AnonymousJazzAgent,
) {
as ||= activeAccountContext.get();
const header = {
type: "comap" as const,
ruleset: {

View File

@@ -4,9 +4,11 @@ import {
type RawCoPlainText,
stringifyOpID,
} from "cojson";
import { activeAccountContext } from "../implementation/activeAccountContext.js";
import type { CoValue, CoValueClass, ID } from "../internal.js";
import {
inspect,
isAccountInstance,
loadCoValue,
subscribeToCoValue,
subscribeToExistingCoValue,
@@ -132,9 +134,9 @@ export class CoPlainText extends String implements CoValue {
static load<T extends CoPlainText>(
this: CoValueClass<T>,
id: ID<T>,
as: Account,
as?: Account,
): Promise<T | undefined> {
return loadCoValue(this, id, as, []);
return loadCoValue(this, id, as ?? activeAccountContext.get(), []);
}
// /**
@@ -179,13 +181,34 @@ export class CoPlainText extends String implements CoValue {
*
* @category Subscription & Loading
*/
static subscribe<T extends CoPlainText>(
this: CoValueClass<T>,
id: ID<T>,
listener: (value: T) => void,
): () => void;
static subscribe<T extends CoPlainText>(
this: CoValueClass<T>,
id: ID<T>,
as: Account,
listener: (value: T) => void,
): () => void;
static subscribe<T extends CoPlainText>(
this: CoValueClass<T>,
id: ID<T>,
asOrListener: Account | ((value: T) => void),
listener?: (value: T) => void,
): () => void {
return subscribeToCoValue(this, id, as, [], listener);
if (isAccountInstance(asOrListener)) {
return subscribeToCoValue(this, id, asOrListener, [], listener!);
}
return subscribeToCoValue(
this,
id,
activeAccountContext.get(),
[],
listener!,
);
}
// /**

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