Compare commits
56 Commits
jazz-react
...
jazz-inspe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d41feafebe | ||
|
|
05e3e30451 | ||
|
|
637ae13131 | ||
|
|
4a601a6441 | ||
|
|
15b422f711 | ||
|
|
2e42825971 | ||
|
|
089cdb2031 | ||
|
|
fa3cf6d0c1 | ||
|
|
d823700a7c | ||
|
|
ed472e834a | ||
|
|
365b0ea3a9 | ||
|
|
43c831167f | ||
|
|
cac0f1ad2b | ||
|
|
f66b7c1a5a | ||
|
|
1b57cfc3f6 | ||
|
|
a805e27b0a | ||
|
|
9d6d9fe7a5 | ||
|
|
409758afd0 | ||
|
|
e0bc532345 | ||
|
|
87e02c0516 | ||
|
|
405f9be7b9 | ||
|
|
c82bf737bf | ||
|
|
91cbb2f9d4 | ||
|
|
cfbba59c6d | ||
|
|
b1209e2e09 | ||
|
|
20b3d88135 | ||
|
|
d9ad1f4de5 | ||
|
|
c90153e0c9 | ||
|
|
a4241c0f4b | ||
|
|
e1ff7a65a8 | ||
|
|
011af55446 | ||
|
|
e9dbcf53c8 | ||
|
|
3da21b95ec | ||
|
|
a6d0dd07a1 | ||
|
|
ac474c4afb | ||
|
|
afe8e1f3b2 | ||
|
|
b12b3808fa | ||
|
|
08ec8fe709 | ||
|
|
f70cae6bf6 | ||
|
|
59fe373863 | ||
|
|
be58b4c1d8 | ||
|
|
96c520ae4d | ||
|
|
a9553b4945 | ||
|
|
fa516522e3 | ||
|
|
59e4b5da54 | ||
|
|
2fa3f94b4a | ||
|
|
a2f8461e26 | ||
|
|
cabaf079be | ||
|
|
d8de4a7ada | ||
|
|
e510a544b7 | ||
|
|
b2ee30630d | ||
|
|
ab0d4f364a | ||
|
|
6d9c6ae698 | ||
|
|
914af3deae | ||
|
|
4ad8e9ae78 | ||
|
|
1e0b496555 |
@@ -1,5 +1,67 @@
|
||||
# betterauth
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-betterauth-server-plugin@0.14.8
|
||||
- jazz-inspector@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
- jazz-react-auth-betterauth@0.14.8
|
||||
- jazz-betterauth-client-plugin@0.14.8
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-betterauth-server-plugin@0.14.7
|
||||
- jazz-inspector@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
- jazz-react-auth-betterauth@0.14.7
|
||||
- jazz-betterauth-client-plugin@0.14.7
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-betterauth-server-plugin@0.14.6
|
||||
- jazz-inspector@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
- jazz-react-auth-betterauth@0.14.6
|
||||
- jazz-betterauth-client-plugin@0.14.6
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-betterauth-server-plugin@0.14.5
|
||||
- jazz-inspector@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
- jazz-react-auth-betterauth@0.14.5
|
||||
- jazz-betterauth-client-plugin@0.14.5
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-betterauth-server-plugin@0.14.4
|
||||
- jazz-inspector@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
- jazz-react-auth-betterauth@0.14.4
|
||||
- jazz-betterauth-client-plugin@0.14.4
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "betterauth",
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.12",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# chat-rn-expo-clerk
|
||||
|
||||
## 1.0.131
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-expo@0.14.8
|
||||
- jazz-react-native-media-images@0.14.8
|
||||
|
||||
## 1.0.130
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-expo@0.14.7
|
||||
- jazz-react-native-media-images@0.14.7
|
||||
|
||||
## 1.0.129
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-expo@0.14.6
|
||||
- jazz-react-native-media-images@0.14.6
|
||||
|
||||
## 1.0.128
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-expo@0.14.5
|
||||
- jazz-react-native-media-images@0.14.5
|
||||
|
||||
## 1.0.127
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-expo@0.14.4
|
||||
- jazz-react-native-media-images@0.14.4
|
||||
|
||||
## 1.0.126
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-expo-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.126",
|
||||
"version": "1.0.131",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# chat-rn-expo
|
||||
|
||||
## 1.0.118
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-expo@0.14.8
|
||||
|
||||
## 1.0.117
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-expo@0.14.7
|
||||
|
||||
## 1.0.116
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-expo@0.14.6
|
||||
|
||||
## 1.0.115
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-expo@0.14.5
|
||||
|
||||
## 1.0.114
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-expo@0.14.4
|
||||
|
||||
## 1.0.113
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn-expo",
|
||||
"version": "1.0.113",
|
||||
"version": "1.0.118",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "tsc --noEmit && expo export -p ios",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.126
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react-native@0.14.8
|
||||
|
||||
## 1.0.125
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react-native@0.14.7
|
||||
|
||||
## 1.0.124
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react-native@0.14.6
|
||||
|
||||
## 1.0.123
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react-native@0.14.5
|
||||
|
||||
## 1.0.122
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react-native@0.14.4
|
||||
|
||||
## 1.0.121
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.121",
|
||||
"version": "1.0.126",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# chat-vue
|
||||
|
||||
## 0.0.109
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-browser@0.14.8
|
||||
- jazz-vue@0.14.8
|
||||
|
||||
## 0.0.108
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-browser@0.14.7
|
||||
- jazz-vue@0.14.7
|
||||
|
||||
## 0.0.107
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-browser@0.14.6
|
||||
- jazz-vue@0.14.6
|
||||
|
||||
## 0.0.106
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-browser@0.14.5
|
||||
- jazz-vue@0.14.5
|
||||
|
||||
## 0.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
- jazz-vue@0.14.4
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.104",
|
||||
"version": "0.0.109",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.207
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-inspector@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.206
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-inspector@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.205
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-inspector@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.204
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-inspector@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.203
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-inspector@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.202
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.202",
|
||||
"version": "0.0.207",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createImage, useAccount, useCoState } from "jazz-react";
|
||||
import { Account, Loaded, co } from "jazz-tools";
|
||||
import { Account, co } from "jazz-tools";
|
||||
import { useState } from "react";
|
||||
import { Chat, Message } from "./schema.ts";
|
||||
import {
|
||||
@@ -91,7 +91,7 @@ export function ChatScreen(props: { chatID: string }) {
|
||||
|
||||
function ChatBubble(props: {
|
||||
me: Account;
|
||||
msg: Loaded<typeof Message, { text: true }>;
|
||||
msg: co.loaded<typeof Message, { text: true }>;
|
||||
}) {
|
||||
if (!props.me.canRead(props.msg) || !props.msg.text?.toString()) {
|
||||
return (
|
||||
|
||||
@@ -4,5 +4,7 @@ export const Message = co.map({
|
||||
text: co.plainText(),
|
||||
image: z.optional(co.image()),
|
||||
});
|
||||
export type Message = co.loaded<typeof Message>;
|
||||
|
||||
export const Chat = co.list(Message);
|
||||
export type Chat = co.loaded<typeof Chat>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import clsx from "clsx";
|
||||
import { ProgressiveImg } from "jazz-react";
|
||||
import { CoPlainText, ImageDefinition, Loaded } from "jazz-tools";
|
||||
import { CoPlainText, ImageDefinition } from "jazz-tools";
|
||||
import { ImageIcon } from "lucide-react";
|
||||
import { useId, useRef } from "react";
|
||||
|
||||
@@ -81,7 +81,7 @@ export function BubbleText(props: {
|
||||
);
|
||||
}
|
||||
|
||||
export function BubbleImage(props: { image: Loaded<typeof ImageDefinition> }) {
|
||||
export function BubbleImage(props: { image: ImageDefinition }) {
|
||||
return (
|
||||
<ProgressiveImg image={props.image}>
|
||||
{({ src }) => (
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// This is NOT needed to make the chat work
|
||||
|
||||
import { Chat } from "@/schema.ts";
|
||||
import { Loaded } from "jazz-tools";
|
||||
export function onChatLoad(chat: Loaded<typeof Chat>) {
|
||||
|
||||
export function onChatLoad(chat: Chat) {
|
||||
if (window.parent) {
|
||||
chat.waitForSync().then(() => {
|
||||
window.parent.postMessage(
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 0.0.106
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
- jazz-react-auth-clerk@0.14.8
|
||||
|
||||
## 0.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
- jazz-react-auth-clerk@0.14.7
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
- jazz-react-auth-clerk@0.14.6
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
- jazz-react-auth-clerk@0.14.5
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
- jazz-react-auth-clerk@0.14.4
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.101",
|
||||
"version": "0.0.106",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,59 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 0.0.91
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-inspector-element@0.14.8
|
||||
- jazz-svelte@0.14.8
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-inspector-element@0.14.7
|
||||
- jazz-svelte@0.14.7
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-inspector-element@0.14.6
|
||||
- jazz-svelte@0.14.6
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-inspector-element@0.14.5
|
||||
- jazz-svelte@0.14.5
|
||||
|
||||
## 0.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-inspector-element@0.14.4
|
||||
- jazz-svelte@0.14.4
|
||||
|
||||
## 0.0.86
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b2ee306]
|
||||
- jazz-svelte@0.14.3
|
||||
|
||||
## 0.0.85
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.85",
|
||||
"version": "0.0.91",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"build": "pnpm run check && vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { slide } from 'svelte/transition';
|
||||
import { SharedFile } from '$lib/schema';
|
||||
import { FileStream } from 'jazz-tools';
|
||||
import { type SharedFile } from '$lib/schema';
|
||||
import { FileStream, type Loaded } from 'jazz-tools';
|
||||
import { File, FileDown, Trash2, Link2 } from 'lucide-svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { downloadFileBlob, formatFileSize } from '$lib/utils';
|
||||
@@ -11,9 +11,9 @@
|
||||
loading = false,
|
||||
onDelete
|
||||
}: {
|
||||
file: SharedFile;
|
||||
file: Loaded<SharedFile>;
|
||||
loading?: boolean;
|
||||
onDelete: (file: SharedFile) => void;
|
||||
onDelete: (file: Loaded<SharedFile>) => void;
|
||||
} = $props();
|
||||
|
||||
const isAdmin = $derived(file._owner?.myRole() === 'admin');
|
||||
@@ -55,7 +55,7 @@
|
||||
class="flex items-center justify-between rounded-lg border border-gray-200 bg-white p-4"
|
||||
transition:slide={{ duration: 200 }}
|
||||
>
|
||||
<div class="flex items-center space-x-4 flex-grow">
|
||||
<div class="flex flex-grow items-center space-x-4">
|
||||
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600">
|
||||
<File class="h-6 w-6" />
|
||||
</div>
|
||||
@@ -64,7 +64,12 @@
|
||||
<label class="sr-only" for={`file-name-${file.id}`}>File name</label>
|
||||
<!-- Jazz values are reactive, but they are not recognized as reactive by Svelte -->
|
||||
<!-- svelte-ignore binding_property_non_reactive -->
|
||||
<input class="font-medium text-gray-900 w-full py-1" type="text" bind:value={file.name} id={`file-name-${file.id}`} />
|
||||
<input
|
||||
class="w-full py-1 font-medium text-gray-900"
|
||||
type="text"
|
||||
bind:value={file.name}
|
||||
id={`file-name-${file.id}`}
|
||||
/>
|
||||
{:else}
|
||||
<h3 class="font-medium text-gray-900">{file.name}</h3>
|
||||
{/if}
|
||||
|
||||
@@ -1,46 +1,31 @@
|
||||
import { Account, CoList, CoMap, FileStream, Profile, coField, Group } from 'jazz-tools';
|
||||
import { Group, co, z } from 'jazz-tools';
|
||||
|
||||
export class SharedFile extends CoMap {
|
||||
name = coField.string;
|
||||
file = coField.ref(FileStream);
|
||||
createdAt = coField.Date;
|
||||
uploadedAt = coField.Date;
|
||||
size = coField.number;
|
||||
}
|
||||
export const SharedFile = co.map({
|
||||
name: z.string(),
|
||||
file: co.fileStream(),
|
||||
createdAt: z.date(),
|
||||
uploadedAt: z.date(),
|
||||
size: z.number(),
|
||||
});
|
||||
|
||||
export class FileShareProfile extends Profile {
|
||||
name = coField.string;
|
||||
}
|
||||
export type SharedFile = typeof SharedFile;
|
||||
|
||||
export class ListOfSharedFiles extends CoList.Of(coField.ref(SharedFile)) {}
|
||||
export const FileShareAccountRoot = co.map({
|
||||
type: z.literal('file-share-account'),
|
||||
sharedFiles: co.list(SharedFile),
|
||||
})
|
||||
|
||||
export class FileShareAccountRoot extends CoMap {
|
||||
type = coField.literal('file-share-account');
|
||||
sharedFiles = coField.ref(ListOfSharedFiles);
|
||||
}
|
||||
export const FileShareAccount = co.account({
|
||||
profile: co.profile(),
|
||||
root: FileShareAccountRoot,
|
||||
}).withMigration((account) => {
|
||||
if (account.root === undefined) {
|
||||
const publicGroup = Group.create({ owner: account });
|
||||
publicGroup.addMember('everyone', 'reader');
|
||||
|
||||
export class FileShareAccount extends Account {
|
||||
profile = coField.ref(FileShareProfile);
|
||||
root = coField.ref(FileShareAccountRoot);
|
||||
|
||||
/** The account migration is run on account creation and on every log-in.
|
||||
* You can use it to set up the account root and any other initial CoValues you need.
|
||||
*/
|
||||
async migrate() {
|
||||
await this._refs.root?.load();
|
||||
|
||||
// Initialize root if it doesn't exist
|
||||
if (this.root === undefined || this.root?.type !== 'file-share-account') {
|
||||
// Create a group that will own all shared files
|
||||
const publicGroup = Group.create({ owner: this });
|
||||
publicGroup.addMember('everyone', 'reader');
|
||||
|
||||
this.root = FileShareAccountRoot.create(
|
||||
{
|
||||
type: 'file-share-account',
|
||||
sharedFiles: ListOfSharedFiles.create([], { owner: publicGroup }),
|
||||
},
|
||||
);
|
||||
}
|
||||
account.root = FileShareAccountRoot.create({
|
||||
type: 'file-share-account',
|
||||
sharedFiles: co.list(SharedFile).create([], publicGroup),
|
||||
}, publicGroup);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts" module>
|
||||
declare module 'jazz-svelte' {
|
||||
interface Register {
|
||||
Account: FileShareAccount;
|
||||
Account: typeof FileShareAccount;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { AccountCoState } from 'jazz-svelte';
|
||||
import { SharedFile } from '$lib/schema';
|
||||
import { FileStream } from 'jazz-tools';
|
||||
import { SharedFile, FileShareAccount } from '$lib/schema';
|
||||
import { FileStream, type Loaded } from 'jazz-tools';
|
||||
import FileItem from '$lib/components/FileItem.svelte';
|
||||
import { CloudUpload } from 'lucide-svelte';
|
||||
|
||||
const me = new AccountCoState({
|
||||
const me = new AccountCoState(FileShareAccount, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
root: {
|
||||
sharedFiles: {
|
||||
$each: true
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$inspect(me);
|
||||
|
||||
const sharedFiles = $derived(me.current?.root.sharedFiles);
|
||||
|
||||
let fileInput: HTMLInputElement;
|
||||
@@ -53,7 +55,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFile(file: SharedFile) {
|
||||
async function deleteFile(file: Loaded<typeof SharedFile>) {
|
||||
if (!sharedFiles) return;
|
||||
|
||||
const index = sharedFiles.indexOf(file);
|
||||
@@ -107,10 +109,7 @@
|
||||
{#if sharedFiles.length}
|
||||
{#each sharedFiles as file}
|
||||
{#if file}
|
||||
<FileItem
|
||||
{file}
|
||||
onDelete={deleteFile}
|
||||
/>
|
||||
<FileItem {file} onDelete={deleteFile} />
|
||||
{/if}
|
||||
{/each}
|
||||
{:else}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { CoState } from 'jazz-svelte';
|
||||
import { CoState } from 'jazz-svelte';
|
||||
import { SharedFile } from '$lib/schema';
|
||||
import { File, FileDown, Link2 } from 'lucide-svelte';
|
||||
import type { ID } from 'jazz-tools';
|
||||
import { FileStream } from 'jazz-tools';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { downloadFileBlob } from '$lib/utils';
|
||||
|
||||
const fileId = $page.params.fileId;
|
||||
|
||||
const file = $derived(new CoState(SharedFile, fileId as ID<SharedFile>));
|
||||
const file = $derived(new CoState(SharedFile, fileId));
|
||||
const isAdmin = $derived(file.current?._owner?.myRole() === 'admin');
|
||||
|
||||
const fileStreamId = $derived(file.current?._refs.file?.id);
|
||||
const fileStreamId = $derived(file.current?._refs?.file?.id);
|
||||
|
||||
async function downloadFile() {
|
||||
if (!fileStreamId || !file.current) {
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# jazz-tailwind-demo-auth-starter
|
||||
|
||||
## 0.0.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-inspector@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-inspector@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-inspector@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-inspector@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-inspector@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filestream",
|
||||
"private": true,
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.46",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { FileStream, co } from "jazz-tools";
|
||||
import { co } from "jazz-tools";
|
||||
import { useRef, useState } from "react";
|
||||
import { JazzAccount } from "./schema";
|
||||
|
||||
@@ -125,7 +125,7 @@ export function FileWidget() {
|
||||
|
||||
try {
|
||||
setIsUploading(true);
|
||||
me.profile.file = await FileStream.createFromBlob(file, {
|
||||
me.profile.file = await co.fileStream().createFromBlob(file, {
|
||||
onProgress: (p) => setProgress(Math.round(p * 100)),
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# form
|
||||
|
||||
## 0.1.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.1.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.1.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.1.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.1.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.1.42",
|
||||
"version": "0.1.47",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.98",
|
||||
"version": "0.0.103",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.156
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.8
|
||||
|
||||
## 0.0.155
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.7
|
||||
|
||||
## 0.0.154
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.6
|
||||
|
||||
## 0.0.153
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.5
|
||||
|
||||
## 0.0.152
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.4
|
||||
|
||||
## 0.0.151
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector-app",
|
||||
"private": true,
|
||||
"version": "0.0.151",
|
||||
"version": "0.0.156",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { WORKER_ID } from "@/constants";
|
||||
import { JoinGameRequest, WaitingRoom } from "@/schema";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { Group, InboxSender, type Loaded } from "jazz-tools";
|
||||
import { Group, InboxSender } from "jazz-tools";
|
||||
import { ClipboardCopyIcon, Loader2Icon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
@@ -29,10 +29,7 @@ export const Route = createFileRoute(
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
if (!waitingRoom?.account1?.isMe) {
|
||||
const sender = await InboxSender.load<
|
||||
Loaded<typeof JoinGameRequest>,
|
||||
Loaded<typeof WaitingRoom>
|
||||
>(
|
||||
const sender = await InboxSender.load<JoinGameRequest, WaitingRoom>(
|
||||
WORKER_ID,
|
||||
me,
|
||||
// { account1: {}, account2: {}, me, game: {} },
|
||||
|
||||
@@ -4,6 +4,7 @@ export const Player = co.map({
|
||||
account: co.account(),
|
||||
playSelection: z.optional(z.literal(["rock", "paper", "scissors"])),
|
||||
});
|
||||
export type Player = co.loaded<typeof Player>;
|
||||
|
||||
export const Game = co.map({
|
||||
player1: Player,
|
||||
@@ -12,12 +13,14 @@ export const Game = co.map({
|
||||
player1Score: z.number(),
|
||||
player2Score: z.number(),
|
||||
});
|
||||
export type Game = co.loaded<typeof Game>;
|
||||
|
||||
export const WaitingRoom = co.map({
|
||||
account1: co.account(),
|
||||
account2: z.optional(co.account()),
|
||||
game: z.optional(Game),
|
||||
});
|
||||
export type WaitingRoom = co.loaded<typeof WaitingRoom>;
|
||||
|
||||
export const PlayIntent = co.map({
|
||||
type: z.literal("play"),
|
||||
@@ -25,24 +28,29 @@ export const PlayIntent = co.map({
|
||||
player: z.literal(["player1", "player2"]),
|
||||
playSelection: z.literal(["rock", "paper", "scissors"]),
|
||||
});
|
||||
export type PlayIntent = co.loaded<typeof PlayIntent>;
|
||||
|
||||
export const NewGameIntent = co.map({
|
||||
type: z.literal("newGame"),
|
||||
gameId: z.string(),
|
||||
});
|
||||
export type NewGameIntent = co.loaded<typeof NewGameIntent>;
|
||||
|
||||
export const CreateGameRequest = co.map({
|
||||
type: z.literal("createGame"),
|
||||
});
|
||||
export type CreateGameRequest = co.loaded<typeof CreateGameRequest>;
|
||||
|
||||
export const JoinGameRequest = co.map({
|
||||
type: z.literal("joinGame"),
|
||||
waitingRoom: WaitingRoom,
|
||||
});
|
||||
export type JoinGameRequest = co.loaded<typeof JoinGameRequest>;
|
||||
|
||||
export const InboxMessage = z.discriminatedUnion([
|
||||
export const InboxMessage = z.discriminatedUnion("type", [
|
||||
PlayIntent,
|
||||
NewGameIntent,
|
||||
CreateGameRequest,
|
||||
JoinGameRequest,
|
||||
]);
|
||||
export type InboxMessage = co.loaded<typeof InboxMessage>;
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
WaitingRoom,
|
||||
} from "@/schema";
|
||||
import { startWorker } from "jazz-nodejs";
|
||||
import { Account, Group, type Loaded, co } from "jazz-tools";
|
||||
import { Account, Group, co } from "jazz-tools";
|
||||
import { determineWinner } from "./lib/utils";
|
||||
|
||||
if (!process.env.VITE_JAZZ_WORKER_ACCOUNT || !process.env.JAZZ_WORKER_SECRET) {
|
||||
@@ -124,10 +124,7 @@ function createPlayer({ account }: CreatePlayerParams) {
|
||||
return player;
|
||||
}
|
||||
|
||||
async function handleNewGameIntent(
|
||||
_: string,
|
||||
message: Loaded<typeof NewGameIntent>,
|
||||
) {
|
||||
async function handleNewGameIntent(_: string, message: NewGameIntent) {
|
||||
const gameId = message.gameId;
|
||||
|
||||
const game = await Game.load(gameId, {
|
||||
@@ -152,7 +149,7 @@ async function handleNewGameIntent(
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePlayIntent(_: string, message: Loaded<typeof PlayIntent>) {
|
||||
async function handlePlayIntent(_: string, message: PlayIntent) {
|
||||
// determine current player, update game with outcome
|
||||
const gameId = message.gameId;
|
||||
if (!gameId) {
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# multi-cursors
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multi-cursors",
|
||||
"private": true,
|
||||
"version": "0.0.94",
|
||||
"version": "0.0.99",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -16,7 +16,8 @@
|
||||
"jazz-react": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
"react-dom": "^18.3.1",
|
||||
"zod": "3.25.0-beta.20250518T002810"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { z } from "jazz-tools";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export const Vec2 = z.object({
|
||||
x: z.number(),
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# multiauth
|
||||
|
||||
## 0.0.47
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
- jazz-react-auth-clerk@0.14.8
|
||||
|
||||
## 0.0.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
- jazz-react-auth-clerk@0.14.7
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
- jazz-react-auth-clerk@0.14.6
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
- jazz-react-auth-clerk@0.14.5
|
||||
|
||||
## 0.0.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
- jazz-react-auth-clerk@0.14.4
|
||||
|
||||
## 0.0.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multiauth",
|
||||
"private": true,
|
||||
"version": "0.0.42",
|
||||
"version": "0.0.47",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.128
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-inspector@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.127
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-inspector@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.126
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-inspector@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.125
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-inspector@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.124
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-inspector@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.123
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.123",
|
||||
"version": "0.0.128",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -13,6 +13,7 @@ import { co, z } from "jazz-tools";
|
||||
export const MusicTrackWaveform = co.map({
|
||||
data: z.array(z.number()),
|
||||
});
|
||||
export type MusicTrackWaveform = co.loaded<typeof MusicTrackWaveform>;
|
||||
|
||||
export const MusicTrack = co.map({
|
||||
/**
|
||||
@@ -44,12 +45,13 @@ export const MusicTrack = co.map({
|
||||
return z.optional(MusicTrack);
|
||||
},
|
||||
});
|
||||
export type MusicTrack = co.loaded<typeof MusicTrack>;
|
||||
|
||||
export const Playlist = co.map({
|
||||
title: z.string(),
|
||||
tracks: co.list(MusicTrack), // CoList is the collaborative version of Array
|
||||
});
|
||||
|
||||
export type Playlist = co.loaded<typeof Playlist>;
|
||||
/** The account root is an app-specific per-user private `CoMap`
|
||||
* where you can store top-level objects for that user */
|
||||
export const MusicaAccountRoot = co.map({
|
||||
@@ -69,7 +71,7 @@ export const MusicaAccountRoot = co.map({
|
||||
|
||||
exampleDataLoaded: z.optional(z.boolean()),
|
||||
});
|
||||
|
||||
export type MusicaAccountRoot = co.loaded<typeof MusicaAccountRoot>;
|
||||
export const MusicaAccount = co
|
||||
.account({
|
||||
/** the default user profile with a name */
|
||||
@@ -97,5 +99,6 @@ export const MusicaAccount = co
|
||||
});
|
||||
}
|
||||
});
|
||||
export type MusicaAccount = co.loaded<typeof MusicaAccount>;
|
||||
|
||||
/** Walkthrough: Continue with ./2_main.tsx */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getAudioFileData } from "@/lib/audio/getAudioFileData";
|
||||
import { FileStream, Group, Loaded, co } from "jazz-tools";
|
||||
import { FileStream, Group, co } from "jazz-tools";
|
||||
import {
|
||||
MusicTrack,
|
||||
MusicTrackWaveform,
|
||||
@@ -94,8 +94,8 @@ export async function createNewPlaylist() {
|
||||
}
|
||||
|
||||
export async function addTrackToPlaylist(
|
||||
playlist: Loaded<typeof Playlist>,
|
||||
track: Loaded<typeof MusicTrack>,
|
||||
playlist: Playlist,
|
||||
track: MusicTrack,
|
||||
) {
|
||||
const alreadyAdded = playlist.tracks?.some(
|
||||
(t) => t?.id === track.id || t?._refs.sourceTrack?.id === track.id,
|
||||
@@ -118,8 +118,8 @@ export async function addTrackToPlaylist(
|
||||
}
|
||||
|
||||
export async function removeTrackFromPlaylist(
|
||||
playlist: Loaded<typeof Playlist>,
|
||||
track: Loaded<typeof MusicTrack>,
|
||||
playlist: Playlist,
|
||||
track: MusicTrack,
|
||||
) {
|
||||
const notAdded = !playlist.tracks?.some(
|
||||
(t) => t?.id === track.id || t?._refs.sourceTrack?.id === track.id,
|
||||
@@ -142,21 +142,15 @@ export async function removeTrackFromPlaylist(
|
||||
}
|
||||
}
|
||||
|
||||
export async function updatePlaylistTitle(
|
||||
playlist: Loaded<typeof Playlist>,
|
||||
title: string,
|
||||
) {
|
||||
export async function updatePlaylistTitle(playlist: Playlist, title: string) {
|
||||
playlist.title = title;
|
||||
}
|
||||
|
||||
export async function updateMusicTrackTitle(
|
||||
track: Loaded<typeof MusicTrack>,
|
||||
title: string,
|
||||
) {
|
||||
export async function updateMusicTrackTitle(track: MusicTrack, title: string) {
|
||||
track.title = title;
|
||||
}
|
||||
|
||||
export async function updateActivePlaylist(playlist?: Loaded<typeof Playlist>) {
|
||||
export async function updateActivePlaylist(playlist?: Playlist) {
|
||||
const { root } = await MusicaAccount.getMe().ensureLoaded({
|
||||
resolve: {
|
||||
root: {
|
||||
@@ -169,7 +163,7 @@ export async function updateActivePlaylist(playlist?: Loaded<typeof Playlist>) {
|
||||
root.activePlaylist = playlist ?? root.rootPlaylist;
|
||||
}
|
||||
|
||||
export async function updateActiveTrack(track: Loaded<typeof MusicTrack>) {
|
||||
export async function updateActiveTrack(track: MusicTrack) {
|
||||
const { root } = await MusicaAccount.getMe().ensureLoaded({
|
||||
resolve: {
|
||||
root: {},
|
||||
@@ -180,7 +174,7 @@ export async function updateActiveTrack(track: Loaded<typeof MusicTrack>) {
|
||||
}
|
||||
|
||||
export async function onAnonymousAccountDiscarded(
|
||||
anonymousAccount: Loaded<typeof MusicaAccount>,
|
||||
anonymousAccount: MusicaAccount,
|
||||
) {
|
||||
const { root: anonymousAccountRoot } = await anonymousAccount.ensureLoaded({
|
||||
resolve: {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { MusicTrack, MusicaAccount, Playlist } from "@/1_schema";
|
||||
import { usePlayMedia } from "@/lib/audio/usePlayMedia";
|
||||
import { usePlayState } from "@/lib/audio/usePlayState";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { FileStream, Loaded } from "jazz-tools";
|
||||
import { FileStream } from "jazz-tools";
|
||||
import { useRef, useState } from "react";
|
||||
import { updateActivePlaylist, updateActiveTrack } from "./4_actions";
|
||||
import { getNextTrack, getPrevTrack } from "./lib/getters";
|
||||
@@ -22,7 +22,7 @@ export function useMediaPlayer() {
|
||||
// Reference used to avoid out-of-order track loads
|
||||
const lastLoadedTrackId = useRef<string | null>(null);
|
||||
|
||||
async function loadTrack(track: Loaded<typeof MusicTrack>) {
|
||||
async function loadTrack(track: MusicTrack) {
|
||||
lastLoadedTrackId.current = track.id;
|
||||
|
||||
setLoading(track.id);
|
||||
@@ -64,10 +64,7 @@ export function useMediaPlayer() {
|
||||
}
|
||||
}
|
||||
|
||||
async function setActiveTrack(
|
||||
track: Loaded<typeof MusicTrack>,
|
||||
playlist?: Loaded<typeof Playlist>,
|
||||
) {
|
||||
async function setActiveTrack(track: MusicTrack, playlist?: Playlist) {
|
||||
if (activeTrackId === track.id && lastLoadedTrackId.current !== null) {
|
||||
playState.toggle();
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# organization
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.94",
|
||||
"version": "0.0.99",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,54 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-svelte@0.14.8
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-svelte@0.14.7
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-svelte@0.14.6
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-svelte@0.14.5
|
||||
|
||||
## 0.0.91
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-svelte@0.14.4
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [b2ee306]
|
||||
- jazz-svelte@0.14.3
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,6 +5,7 @@ This example app demonstrates how to implement passkey authentication in a Svelt
|
||||
## Features
|
||||
|
||||
This example showcases how to:
|
||||
|
||||
- Set up passkey authentication in a Svelte application
|
||||
- Handle user registration with passkeys
|
||||
- Manage authentication state
|
||||
@@ -13,23 +14,26 @@ This example showcases how to:
|
||||
## Getting started
|
||||
|
||||
You can either
|
||||
|
||||
1. Clone the jazz repository, and run the app within the monorepo.
|
||||
2. Or create a new Jazz project using this example as a template.
|
||||
|
||||
|
||||
### Using the example as a template
|
||||
|
||||
Create a new Jazz project, and use this example as a template.
|
||||
|
||||
```bash
|
||||
npx create-jazz-app@latest passkey-svelte-app --example passkey-svelte
|
||||
```
|
||||
|
||||
Go to the new project directory.
|
||||
|
||||
```bash
|
||||
cd passkey-svelte-app
|
||||
```
|
||||
|
||||
Run the dev server.
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
@@ -39,21 +43,25 @@ npm run dev
|
||||
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
|
||||
|
||||
Clone the jazz repository.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/garden-co/jazz.git
|
||||
```
|
||||
|
||||
Install and build dependencies.
|
||||
|
||||
```bash
|
||||
pnpm i && npx turbo build
|
||||
```
|
||||
|
||||
Go to the example directory.
|
||||
|
||||
```bash
|
||||
cd jazz/examples/passkey-svelte/
|
||||
```
|
||||
|
||||
Start the dev server.
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "passkey-svelte",
|
||||
"version": "0.0.89",
|
||||
"version": "0.0.95",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const apiKey = "minimal-svelte-auth-passkey@garden.co"
|
||||
export const apiKey = 'minimal-svelte-auth-passkey@garden.co';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { JazzProvider, PasskeyAuthBasicUI } from 'jazz-svelte';
|
||||
import {apiKey} from '../apiKey';
|
||||
import { apiKey } from '../apiKey';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<JazzProvider
|
||||
sync={{
|
||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
|
||||
peer: `wss://cloud.jazz.tools/?key=${apiKey}`
|
||||
}}
|
||||
>
|
||||
<PasskeyAuthBasicUI appName="minimal-svelte-auth-passkey">
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { useAccount } from 'jazz-svelte';
|
||||
import { AccountCoState } from 'jazz-svelte';
|
||||
import { Account } from 'jazz-tools';
|
||||
|
||||
const account = useAccount({
|
||||
root: {}
|
||||
const account = new AccountCoState(Account, {
|
||||
resolve: {
|
||||
profile: true
|
||||
}
|
||||
});
|
||||
|
||||
$inspect(account);
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<h1>Welcome back, {account?.me?.profile?.name}</h1>
|
||||
<h1>Welcome back, {account?.current?.profile?.name}</h1>
|
||||
<button onclick={() => account.logOut()}>Log out</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# minimal-auth-passkey
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passkey",
|
||||
"private": true,
|
||||
"version": "0.0.99",
|
||||
"version": "0.0.104",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# passphrase
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passphrase",
|
||||
"private": true,
|
||||
"version": "0.0.96",
|
||||
"version": "0.0.101",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.125
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.124
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.123
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.122
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.121
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.120
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.120",
|
||||
"version": "0.0.125",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.223
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.222
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.221
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.220
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.219
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.218
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.218",
|
||||
"version": "0.0.223",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# reactions
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "reactions",
|
||||
"private": true,
|
||||
"version": "0.0.98",
|
||||
"version": "0.0.103",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# richtext-tiptap
|
||||
|
||||
## 0.1.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
- jazz-richtext-tiptap@0.1.16
|
||||
|
||||
## 0.1.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
- jazz-richtext-tiptap@0.1.15
|
||||
|
||||
## 0.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
- jazz-richtext-tiptap@0.1.14
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
- jazz-richtext-tiptap@0.1.13
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
- jazz-richtext-tiptap@0.1.12
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext-tiptap",
|
||||
"private": true,
|
||||
"version": "0.1.11",
|
||||
"version": "0.1.16",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# richtext
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
- jazz-richtext-prosemirror@0.1.27
|
||||
|
||||
## 0.0.92
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
- jazz-richtext-prosemirror@0.1.26
|
||||
|
||||
## 0.0.91
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
- jazz-richtext-prosemirror@0.1.25
|
||||
|
||||
## 0.0.90
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
- jazz-richtext-prosemirror@0.1.24
|
||||
|
||||
## 0.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
- jazz-richtext-prosemirror@0.1.23
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext",
|
||||
"private": true,
|
||||
"version": "0.0.88",
|
||||
"version": "0.0.93",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# todo-vue
|
||||
|
||||
## 0.0.107
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-browser@0.14.8
|
||||
- jazz-vue@0.14.8
|
||||
|
||||
## 0.0.106
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-browser@0.14.7
|
||||
- jazz-vue@0.14.7
|
||||
|
||||
## 0.0.105
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-browser@0.14.6
|
||||
- jazz-vue@0.14.6
|
||||
|
||||
## 0.0.104
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-browser@0.14.5
|
||||
- jazz-vue@0.14.5
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
- jazz-vue@0.14.4
|
||||
|
||||
## 0.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "todo-vue",
|
||||
"version": "0.0.102",
|
||||
"version": "0.0.107",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.222
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.221
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.220
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.219
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.218
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.217
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.217",
|
||||
"version": "0.0.222",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# version-history
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-inspector@0.14.8
|
||||
- jazz-react@0.14.8
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-inspector@0.14.7
|
||||
- jazz-react@0.14.7
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-inspector@0.14.6
|
||||
- jazz-react@0.14.6
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-inspector@0.14.5
|
||||
- jazz-react@0.14.5
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-inspector@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "version-history",
|
||||
"private": true,
|
||||
"version": "0.0.96",
|
||||
"version": "0.0.101",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -41,8 +41,6 @@ export function DocNav() {
|
||||
{items.map((item) => (
|
||||
<SideNavSection item={item} key={item.name} />
|
||||
))}
|
||||
|
||||
<SideNavHeader href="/api-reference">API Reference</SideNavHeader>
|
||||
</SideNavBody>
|
||||
</SideNav>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# Jazz Documentation: Actionable Task List
|
||||
|
||||
## Immediate Priority (Next 1-2 Weeks)
|
||||
|
||||
1. **Complete Link Audit**
|
||||
|
||||
- [x] Verify all links in Building with Jazz section
|
||||
- [ ] Replace generic links with section-specific links
|
||||
- [ ] Add backlinks from reference docs to concept docs
|
||||
|
||||
2. **Standardize Documentation Structure**
|
||||
|
||||
- [x] Create consistent format for "Further Reading" sections in all docs
|
||||
- [x] Standardize intro paragraphs to explain document purpose
|
||||
- [x] Ensure all Next Steps sections correctly link to next document
|
||||
|
||||
3. **Resolve Authentication Content Duplication**
|
||||
- [x] Decide approach (remove conceptual sections, cross-reference, or reorganize)
|
||||
- [x] Implement chosen approach
|
||||
- [x] Add appropriate links between documents
|
||||
|
||||
## High Priority (Next 3-4 Weeks)
|
||||
|
||||
4. **Create New Technical Reference Docs**
|
||||
|
||||
- [ ] Sync Server Configuration Guide
|
||||
- [ ] Group Patterns Cookbook
|
||||
- [ ] Data Loading Patterns Guide
|
||||
|
||||
5. **Develop Documentation Style Guide**
|
||||
|
||||
- [ ] Define standards for explanation vs reference content
|
||||
- [ ] Create terminology guide for consistent language
|
||||
- [ ] Establish code example formatting standards
|
||||
|
||||
6. **Technical Validation**
|
||||
- [ ] Review all code examples for correctness
|
||||
- [ ] Verify technical accuracy of explanations
|
||||
- [ ] Test code examples in real applications
|
||||
|
||||
## Medium Priority (Next 1-2 Months)
|
||||
|
||||
7. **Enhance Visual Elements**
|
||||
|
||||
- [ ] Create component relationship diagrams
|
||||
- [ ] Add flow charts for authentication and data processes
|
||||
- [ ] Design visual navigation aids
|
||||
|
||||
8. **Improve Discoverability**
|
||||
|
||||
- [ ] Review information architecture
|
||||
- [ ] Optimize section organization
|
||||
- [ ] Add cross-linking between related concepts
|
||||
|
||||
9. **Create Quick Reference Materials**
|
||||
- [ ] Develop downloadable cheat sheets
|
||||
- [ ] Create concept summaries
|
||||
- [ ] Build a glossary of terms
|
||||
|
||||
## Future Enhancements (2+ Months)
|
||||
|
||||
10. **Implement Analytics and Feedback**
|
||||
|
||||
- [ ] Set up documentation usage tracking
|
||||
- [ ] Add feedback collection mechanism
|
||||
- [ ] Create process for incorporating feedback
|
||||
|
||||
11. **Develop Interactive Elements**
|
||||
|
||||
- [ ] Create interactive code examples
|
||||
- [ ] Build mini-tutorials within documentation
|
||||
- [ ] Add "try it yourself" sections
|
||||
|
||||
12. **Add Real-World Context**
|
||||
- [ ] Develop case studies
|
||||
- [ ] Include real application examples
|
||||
- [ ] Add decision guides for architecture choices
|
||||
|
||||
Each task should be assigned an owner and delivery date when work begins.
|
||||
@@ -0,0 +1,136 @@
|
||||
# Technical Content for Reference Documentation
|
||||
|
||||
This document tracks content that was removed from the explanation-focused "Building with Jazz" section but should be preserved for technical reference documentation.
|
||||
|
||||
## Schemas
|
||||
|
||||
### Removed Content
|
||||
- Detailed information about specific CoValue types
|
||||
- In-depth explanation of field types and references
|
||||
- Code examples showing how to create and manipulate schema instances
|
||||
- Information about SchemaUnions and their usage
|
||||
- Examples of computed fields and methods
|
||||
- Specific details about optional fields and refs
|
||||
|
||||
### Source Location
|
||||
Original content from: `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/schemas/covalues.mdx`
|
||||
|
||||
## Providers
|
||||
|
||||
### Removed Content
|
||||
- Detailed provider configuration options:
|
||||
```tsx
|
||||
// Configure how your app connects to the Jazz network
|
||||
const syncConfig = {
|
||||
// Connect to Jazz Cloud (or your own sync server)
|
||||
peer: "wss://cloud.jazz.tools/?key=your-api-key",
|
||||
|
||||
// When to sync: "always" (default), "never", or "signedUp"
|
||||
when: "always"
|
||||
}
|
||||
```
|
||||
- Account Schema specific configuration details
|
||||
- Section on provider options including:
|
||||
- Guest mode configuration
|
||||
- Default profile name setting
|
||||
- Logout handling
|
||||
- Anonymous account data handling
|
||||
- References to authentication states and how they affect synchronization
|
||||
|
||||
### Source Location
|
||||
Original content from: `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/project-setup/providers/react.mdx`
|
||||
|
||||
## Authentication
|
||||
|
||||
### Removed Content
|
||||
- Detailed code examples showing implementation of authentication state detection
|
||||
- Specific code for migrating data from anonymous to authenticated accounts
|
||||
- Configuration code examples for providers related to authentication
|
||||
- Implementation details for controlling sync in different authentication states
|
||||
- Code examples for guest mode configuration
|
||||
|
||||
### Source Location
|
||||
Original content from: `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/authentication/overview.mdx` and `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/authentication/authentication-states.mdx`
|
||||
|
||||
Most of the conceptual content about authentication states was borrowed from authentication-states.mdx. Options for handling this duplication:
|
||||
|
||||
1. **Remove the conceptual sections**: Remove overlapping conceptual content from authentication-states.mdx, leaving only implementation details and code examples. Add a prominent link at the top directing users to the explanation document for conceptual understanding.
|
||||
|
||||
2. **Keep both but cross-reference**: Keep the original content but add clear cross-references between the documents, with explanation document for concepts and the original for implementation details.
|
||||
|
||||
3. **Complete reorganization**: Completely reorganize authentication-states.mdx to focus solely on implementation, moving all conceptual content to the explanation document.
|
||||
|
||||
For now, we're maintaining both documents but should decide on an approach when finalizing the documentation structure.
|
||||
|
||||
## Groups and Ownership
|
||||
|
||||
### Removed Content
|
||||
- Detailed implementation code examples for adding members to groups
|
||||
- Code examples for public sharing and invite links
|
||||
- Common Group Patterns section with examples for:
|
||||
- Organization Structure
|
||||
- Project Collaboration
|
||||
- Public Community
|
||||
|
||||
Note: The Common Group Patterns section contained valuable examples showing real-world usage patterns. This content should be preserved and potentially added to a patterns guide, cookbook, or examples section in the reference documentation.
|
||||
|
||||
### Source Location
|
||||
Original content from: `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/groups/intro.mdx`, `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/groups/sharing.mdx`, and `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/groups/inheritance.mdx`
|
||||
|
||||
## Sync and Storage
|
||||
|
||||
### Removed Content
|
||||
- Detailed instructions for using Jazz Cloud with API key examples
|
||||
- Command line instructions for running a self-hosted sync server
|
||||
- Command line options and parameters for configuring a sync server
|
||||
- References to the source code and GitHub repositories
|
||||
- Configuring Sync in Your Application section with code examples
|
||||
- Offline-First Approach section explaining offline capabilities
|
||||
- Sync and Authentication section explaining how sync relates to authentication states
|
||||
|
||||
### Source Location
|
||||
Original content from: `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/sync-and-storage.mdx`
|
||||
|
||||
### Technical Documentation Needed
|
||||
We should create a detailed technical reference document for sync server configuration that covers:
|
||||
- Complete configuration options for self-hosted sync servers
|
||||
- Performance tuning parameters
|
||||
- Security considerations
|
||||
- Deployment scenarios and best practices
|
||||
- Monitoring and maintenance
|
||||
|
||||
This would be valuable for users who need to self-host their sync server with specific configuration requirements.
|
||||
|
||||
## Server Workers
|
||||
|
||||
### Removed Content
|
||||
- Code example for generating Server Worker credentials
|
||||
- Instructions for storing credentials as environment variables
|
||||
- Code example for starting a Server Worker
|
||||
- Implementation details for loading/subscribing to CoValues
|
||||
- Specific implementation patterns with code examples
|
||||
|
||||
### Source Location
|
||||
Original content from: `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/project-setup/server-side.mdx` and `/Users/benjamin/projects/gcmp/jazz/homepage/homepage/content/docs/building-with-jazz/server-workers.mdx`
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Missing Topics to Address
|
||||
- ~~**Data Loading and Subscriptions**~~: Rather than creating a separate document, we've incorporated this topic into existing documents:
|
||||
- Added a substantial section about subscriptions and deep loading to the **Providers** document
|
||||
- Added an explanation of accessing shared data to the **Groups** document
|
||||
- Added links to the comprehensive [Subscription and Loading](/docs/react/using-covalues/subscription-and-loading) documentation in both documents
|
||||
|
||||
This approach ensures that data loading concepts are covered in relevant contexts rather than isolated in a separate document.
|
||||
|
||||
We've updated all Next Steps sections to reflect the current document flow:
|
||||
1. Installation → Schemas
|
||||
2. Schemas → Providers
|
||||
3. Providers → Accounts
|
||||
4. Accounts → Authentication
|
||||
5. Authentication → Groups
|
||||
6. Groups → Sync
|
||||
7. Sync → Server Workers
|
||||
8. Server Workers → (end of journey)
|
||||
|
||||
As we continue creating explanation-focused content for the "Building with Jazz" section, we should add to this document to ensure all technical reference material is preserved for the appropriate documentation.
|
||||
@@ -20,23 +20,21 @@ For this example, users within an `Organization` will be sharing `Project`s.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, CoMap, CoList } from "jazz-tools";
|
||||
import { co, z } from "jazz-tools";
|
||||
// ---cut---
|
||||
// schema.ts
|
||||
export class Project extends CoMap {
|
||||
name = coField.string;
|
||||
}
|
||||
export const Project = co.map({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
export class ListOfProjects extends CoList.Of(coField.ref(Project)) {}
|
||||
|
||||
export class Organization extends CoMap {
|
||||
name = coField.string;
|
||||
export const Organization = co.map({
|
||||
name: z.string(),
|
||||
|
||||
// shared data between users of each organization
|
||||
projects = coField.ref(ListOfProjects);
|
||||
}
|
||||
projects: co.list(Project),
|
||||
});
|
||||
|
||||
export class ListOfOrganizations extends CoList.Of(coField.ref(Organization)) {}
|
||||
export const ListOfOrganizations = co.list(Organization);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -48,54 +46,47 @@ Let's add the list of `Organization`s to the user's Account `root` so they can a
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, CoMap, CoList, Account, Group } from "jazz-tools";
|
||||
export class Project extends CoMap {
|
||||
name = co.string;
|
||||
}
|
||||
import { Group, co, z } from "jazz-tools";
|
||||
export const Project = co.map({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
export class ListOfProjects extends CoList.Of(co.ref(Project)) {}
|
||||
export const Organization = co.map({
|
||||
name: z.string(),
|
||||
|
||||
export class Organization extends CoMap {
|
||||
name = co.string;
|
||||
// shared data between users of each organization
|
||||
projects: co.list(Project),
|
||||
});
|
||||
|
||||
// shared data between users of each organization
|
||||
projects = co.ref(ListOfProjects);
|
||||
}
|
||||
|
||||
export class ListOfOrganizations extends CoList.Of(co.ref(Organization)) {}
|
||||
// ---cut---
|
||||
// schema.ts
|
||||
export class JazzAccountRoot extends CoMap {
|
||||
organizations = coField.ref(ListOfOrganizations);
|
||||
}
|
||||
export const JazzAccountRoot = co.map({
|
||||
organizations: co.list(Organization),
|
||||
});
|
||||
|
||||
export class JazzAccount extends Account {
|
||||
root = coField.ref(JazzAccountRoot);
|
||||
|
||||
async migrate() {
|
||||
if (this.root === undefined) {
|
||||
export const JazzAccount = co
|
||||
.account({
|
||||
root: JazzAccountRoot,
|
||||
profile: co.profile({}),
|
||||
})
|
||||
.withMigration((account) => {
|
||||
if (account.root === undefined) {
|
||||
// Using a Group as an owner allows you to give access to other users
|
||||
const organizationGroup = Group.create();
|
||||
|
||||
const organizations = ListOfOrganizations.create(
|
||||
[
|
||||
// Create the first Organization so users can start right away
|
||||
Organization.create(
|
||||
{
|
||||
name: "My organization",
|
||||
projects: ListOfProjects.create([], organizationGroup),
|
||||
},
|
||||
organizationGroup,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
this.root = JazzAccountRoot.create(
|
||||
{ organizations },
|
||||
);
|
||||
const organizations = co.list(Organization).create([
|
||||
// Create the first Organization so users can start right away
|
||||
Organization.create(
|
||||
{
|
||||
name: "My organization",
|
||||
projects: co.list(Project).create([], organizationGroup),
|
||||
},
|
||||
organizationGroup,
|
||||
),
|
||||
]);
|
||||
account.root = JazzAccountRoot.create({ organizations });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -120,44 +111,35 @@ When the user accepts the invite, add the `Organization` to the user's `organiza
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import { useAcceptInvite, useAccount } from "jazz-react";
|
||||
import { ID } from "jazz-tools";
|
||||
import { Account, CoList, CoMap, Group, co } from "jazz-tools";
|
||||
import * as React from "react";
|
||||
import { useAcceptInvite, useAccount } from "jazz-react";
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
export class Project extends CoMap {
|
||||
name = co.string;
|
||||
}
|
||||
const Project = z.object({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
export class ListOfProjects extends CoList.Of(co.ref(Project)) {}
|
||||
const Organization = co.map({
|
||||
name: z.string(),
|
||||
projects: co.list(Project),
|
||||
});
|
||||
|
||||
export class Organization extends CoMap {
|
||||
name = co.string;
|
||||
projects = co.ref(ListOfProjects);
|
||||
}
|
||||
const JazzAccountRoot = co.map({
|
||||
organizations: co.list(Organization),
|
||||
});
|
||||
|
||||
export class ListOfOrganizations extends CoList.Of(co.ref(Organization)) {}
|
||||
const JazzAccount = co.account({
|
||||
root: JazzAccountRoot,
|
||||
profile: co.profile({}),
|
||||
});
|
||||
|
||||
export class JazzAccountRoot extends CoMap {
|
||||
organizations = co.ref(ListOfOrganizations);
|
||||
}
|
||||
|
||||
export class JazzAccount extends Account {
|
||||
root = co.ref(JazzAccountRoot);
|
||||
}
|
||||
|
||||
declare module "jazz-react" {
|
||||
interface Register {
|
||||
Account: JazzAccount;
|
||||
}
|
||||
}
|
||||
// ---cut---
|
||||
export function AcceptInvitePage() {
|
||||
const { me } = useAccount({
|
||||
const { me } = useAccount(JazzAccount, {
|
||||
resolve: { root: { organizations: { $each: { $onError: null } } } },
|
||||
});
|
||||
|
||||
const onAccept = (organizationId: ID<Organization>) => {
|
||||
const onAccept = (organizationId: string) => {
|
||||
if (me) {
|
||||
Organization.load(organizationId).then((organization) => {
|
||||
if (organization) {
|
||||
|
||||
@@ -133,14 +133,14 @@ export const docNavigationItems = [
|
||||
// done: 100,
|
||||
// framework: "react-native",
|
||||
// },
|
||||
{
|
||||
// upgrade guides
|
||||
name: "0.9.2 - Local persistence on React Native Expo",
|
||||
href: "/docs/upgrade/react-native-local-persistence",
|
||||
done: 100,
|
||||
framework: "react-native-expo",
|
||||
excludeFromNavigation: true,
|
||||
},
|
||||
// {
|
||||
// // upgrade guides
|
||||
// name: "0.9.2 - Local persistence on React Native Expo",
|
||||
// href: "/docs/upgrade/react-native-local-persistence",
|
||||
// done: 100,
|
||||
// framework: "react-native-expo",
|
||||
// excludeFromNavigation: true,
|
||||
// },
|
||||
// {
|
||||
// // upgrade guides
|
||||
// name: "0.9.0 - Top level imports",
|
||||
|
||||
@@ -15,7 +15,9 @@ When a group extends another group, members of the parent group will become auto
|
||||
Here's how to extend a group:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
// ---cut---
|
||||
const playlistGroup = Group.create();
|
||||
const trackGroup = Group.create();
|
||||
|
||||
@@ -34,7 +36,11 @@ When you extend a group:
|
||||
In some cases you might want to inherit all members from a parent group but override/flatten their roles to the same specific role in the child group. You can do so by passing an "override role" as a second argument to `extend`:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
// ---cut---
|
||||
const organizationGroup = Group.create();
|
||||
organizationGroup.addMember(bob, "admin");
|
||||
|
||||
@@ -48,7 +54,12 @@ billingGroup.extend(organizationGroup, "reader");
|
||||
The "override role" works in both directions:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
const alice = await createJazzTestAccount();
|
||||
// ---cut---
|
||||
const parentGroup = Group.create();
|
||||
parentGroup.addMember(bob, "reader");
|
||||
parentGroup.addMember(alice, "admin");
|
||||
@@ -65,7 +76,9 @@ childGroup.extend(parentGroup, "writer");
|
||||
Groups can be extended multiple levels deep:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
// ---cut---
|
||||
const grandParentGroup = Group.create();
|
||||
const parentGroup = Group.create();
|
||||
const childGroup = Group.create();
|
||||
@@ -82,7 +95,12 @@ Members of the grandparent group will get access to all descendant groups based
|
||||
When you remove a member from a parent group, they automatically lose access to all child groups. We handle key rotation automatically to ensure security.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
const parentGroup = Group.create();
|
||||
// ---cut---
|
||||
// Remove member from parent
|
||||
await parentGroup.removeMember(bob);
|
||||
|
||||
@@ -94,7 +112,11 @@ await parentGroup.removeMember(bob);
|
||||
|
||||
If the account is already a member of the child group, it will get the more permissive role:
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
// ---cut---
|
||||
const parentGroup = Group.create();
|
||||
parentGroup.addMember(bob, "reader");
|
||||
|
||||
@@ -109,7 +131,11 @@ childGroup.extend(parentGroup);
|
||||
|
||||
When extending groups, only admin, writer and reader roles are inherited:
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
// ---cut---
|
||||
const parentGroup = Group.create();
|
||||
parentGroup.addMember(bob, "writeOnly");
|
||||
|
||||
@@ -126,7 +152,13 @@ To extend a group:
|
||||
2. The current account must be a member of the parent group
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group, co, z } from "jazz-tools";
|
||||
const Company = co.map({
|
||||
name: z.string(),
|
||||
});
|
||||
const company = Company.create({ name: "Garden Computing" });
|
||||
// ---cut---
|
||||
const companyGroup = company._owner.castAs(Group)
|
||||
const teamGroup = Group.create();
|
||||
|
||||
@@ -140,7 +172,9 @@ teamGroup.extend(companyGroup);
|
||||
You can revoke a group extension by using the `revokeExtend` method:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
// ---cut---
|
||||
const parentGroup = Group.create();
|
||||
const childGroup = Group.create();
|
||||
|
||||
@@ -156,7 +190,9 @@ await childGroup.revokeExtend(parentGroup);
|
||||
You can get all the parent groups of a group by calling the `getParentGroups` method:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
// ---cut---
|
||||
const childGroup = Group.create();
|
||||
const parentGroup = Group.create();
|
||||
childGroup.extend(parentGroup);
|
||||
@@ -170,7 +206,14 @@ console.log(childGroup.getParentGroups()); // [parentGroup]
|
||||
Here's a practical example of using group inheritance for team permissions:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const CEO = await createJazzTestAccount();
|
||||
const teamLead = await createJazzTestAccount();
|
||||
const developer = await createJazzTestAccount();
|
||||
const client = await createJazzTestAccount();
|
||||
// ---cut---
|
||||
// Company-wide group
|
||||
const companyGroup = Group.create();
|
||||
companyGroup.addMember(CEO, "admin");
|
||||
|
||||
@@ -16,7 +16,7 @@ have different roles, such as "writer", "reader" or "admin".
|
||||
Here's how you can create a `Group`.
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
|
||||
const group = Group.create();
|
||||
@@ -33,33 +33,54 @@ But if you already know their ID, you can add them directly (see below).
|
||||
You can add group members by ID by using `Account.load` and `Group.addMember`.
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
import { ID } from "jazz-tools";
|
||||
|
||||
const bobsID = "co_z123" as ID<Account>;
|
||||
|
||||
// ---cut---
|
||||
import { Group, Account } from "jazz-tools";
|
||||
|
||||
const group = Group.create();
|
||||
|
||||
const bob = await Account.load(bobsID, []);
|
||||
group.addMember(bob, "writer");
|
||||
const bob = await Account.load(bobsID);
|
||||
|
||||
if (bob) {
|
||||
group.addMember(bob, "writer");
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**Note:** if the account ID is of type `string`, because it comes from a URL parameter or something similar, you need to cast it to `ID<Account>` first:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
const bobsID = "co_z123" as ID<Account>;
|
||||
|
||||
const group = Group.create();
|
||||
|
||||
// ---cut---
|
||||
import { Group, Account, ID } from "jazz-tools";
|
||||
|
||||
const bob = await Account.load(bobsID as ID<Account>, []);
|
||||
group.addMember(bob, "writer");
|
||||
const bob = await Account.load(bobsID as ID<Account>);
|
||||
|
||||
if (bob) {
|
||||
group.addMember(bob, "writer");
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Change a member's role
|
||||
## Changing a member's role
|
||||
|
||||
To change a member's role, use the `addMember` method.
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, Account, ID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
const group = Group.create();
|
||||
// ---cut---
|
||||
group.addMember(bob, "reader");
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -73,7 +94,12 @@ Bob just went from a writer to a reader.
|
||||
To remove a member, use the `removeMember` method.
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, Account, ID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const bob = await createJazzTestAccount();
|
||||
const group = Group.create();
|
||||
// ---cut---
|
||||
group.removeMember(bob);
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -89,7 +115,16 @@ Rules:
|
||||
You can get the group of an existing CoValue by using `coValue._owner`.
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```ts twoslash
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
import { co, z } from "jazz-tools";
|
||||
const existingCoValue = await createJazzTestAccount();
|
||||
|
||||
const MyCoMap = co.map({
|
||||
color: z.string(),
|
||||
});
|
||||
|
||||
// ---cut---
|
||||
const group = existingCoValue._owner;
|
||||
const newValue = MyCoMap.create(
|
||||
{ color: "red"},
|
||||
@@ -101,13 +136,27 @@ const newValue = MyCoMap.create(
|
||||
Because `._owner` can be an `Account` or a `Group`, in cases where you specifically need to use `Group` methods (such as for adding members or getting your own role), you can cast it to assert it to be a Group:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```ts twoslash
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
import { co, z } from "jazz-tools";
|
||||
const bob = await createJazzTestAccount();
|
||||
|
||||
const MyCoMap = co.map({
|
||||
color: z.string(),
|
||||
});
|
||||
|
||||
const existingCoValue = MyCoMap.create(
|
||||
{ color: "red"},
|
||||
{ owner: bob }
|
||||
);
|
||||
|
||||
// ---cut---
|
||||
import { Group } from "jazz-tools";
|
||||
|
||||
const group = existingCoValue._owner.castAs(Group);
|
||||
group.addMember(bob, "writer");
|
||||
|
||||
const role = group.getRoleOf(bob);
|
||||
const role = group.getRoleOf(bob.id);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -116,8 +165,14 @@ const role = group.getRoleOf(bob);
|
||||
You can check the permissions of an account on a CoValue by using the `canRead`, `canWrite` and `canAdmin` methods.
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
const value = await MyCoMap.load(valueID, {});
|
||||
```ts twoslash
|
||||
import { co, z, Account } from "jazz-tools";
|
||||
|
||||
const MyCoMap = co.map({
|
||||
color: z.string(),
|
||||
});
|
||||
// ---cut---
|
||||
const value = await MyCoMap.create({ color: "red"})
|
||||
const me = Account.getMe();
|
||||
|
||||
if (me.canAdmin(value)) {
|
||||
@@ -135,18 +190,29 @@ if (me.canAdmin(value)) {
|
||||
To check the permissions of another account, you need to load it first:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
const value = await MyCoMap.load(valueID, {});
|
||||
const bob = await Account.load(accountID, []);
|
||||
```ts twoslash
|
||||
import { co, z, Account } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
|
||||
if (bob.canAdmin(value)) {
|
||||
console.log("Bob can share value with others");
|
||||
} else if (bob.canWrite(value)) {
|
||||
console.log("Bob can edit value");
|
||||
} else if (bob.canRead(value)) {
|
||||
console.log("Bob can view value");
|
||||
} else {
|
||||
console.log("Bob cannot access value");
|
||||
const MyCoMap = co.map({
|
||||
color: z.string(),
|
||||
});
|
||||
const account = await createJazzTestAccount();
|
||||
const accountID = account.id;
|
||||
// ---cut---
|
||||
const value = await MyCoMap.create({ color: "red"})
|
||||
const bob = await Account.load(accountID);
|
||||
|
||||
if (bob) {
|
||||
if (bob.canAdmin(value)) {
|
||||
console.log("Bob can share value with others");
|
||||
} else if (bob.canWrite(value)) {
|
||||
console.log("Bob can edit value");
|
||||
} else if (bob.canRead(value)) {
|
||||
console.log("Bob can view value");
|
||||
} else {
|
||||
console.log("Bob cannot access value");
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -12,10 +12,12 @@ You can share CoValues publicly by setting the `owner` to a `Group`, and grantin
|
||||
access to "everyone".
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
const group = Group.create();
|
||||
group.addMember("everyone", "writer"); // *highlight*
|
||||
```
|
||||
```ts twoslash
|
||||
import { Group } from "jazz-tools";
|
||||
// ---cut---
|
||||
const group = Group.create();
|
||||
group.addMember("everyone", "writer");
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
This is done in the [chat example](https://github.com/garden-co/jazz/tree/main/examples/chat) where anyone can join the chat, and send messages.
|
||||
@@ -29,52 +31,19 @@ You can grant users access to a CoValue by sending them an invite link.
|
||||
This is used in the [pet example](https://github.com/garden-co/jazz/tree/main/examples/pets)
|
||||
and the [todo example](https://github.com/garden-co/jazz/tree/main/examples/todo).
|
||||
|
||||
<ContentByFramework framework="react">
|
||||
<ContentByFramework framework={["react", "react-native", "react-native-expo", "vue", "svelte"]}>
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const Organization = co.map({
|
||||
name: z.string(),
|
||||
});
|
||||
const organization = Organization.create({ name: "Garden Computing" });
|
||||
// ---cut---
|
||||
import { createInviteLink } from "jazz-react";
|
||||
|
||||
createInviteLink(organization, "writer"); // or reader, or admin
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="react-native">
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { createInviteLink } from "jazz-react-native";
|
||||
|
||||
createInviteLink(organization, "writer"); // or reader, or admin
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="react-native-expo">
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { createInviteLink } from "jazz-expo";
|
||||
|
||||
createInviteLink(organization, "writer"); // or reader, or admin
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="vue">
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { createInviteLink } from "jazz-vue";
|
||||
|
||||
createInviteLink(organization, "writer"); // or reader, or admin
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="svelte">
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { createInviteLink } from "jazz-browser";
|
||||
|
||||
createInviteLink(organization, "writer"); // or reader, or admin
|
||||
createInviteLink(organization, "writer"); // or reader, admin, writeOnly
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
@@ -85,10 +54,23 @@ In your app, you need to handle this route, and let the user accept the invitati
|
||||
as done [here](https://github.com/garden-co/jazz/tree/main/examples/pets/src/2_main.tsx).
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const Organization = co.map({
|
||||
name: z.string(),
|
||||
});
|
||||
const organization = Organization.create({ name: "Garden Computing" });
|
||||
const organizationID = organization.id;
|
||||
// ---cut---
|
||||
import { useAcceptInvite } from "jazz-react";
|
||||
|
||||
useAcceptInvite({
|
||||
invitedObjectSchema: PetPost,
|
||||
onAccept: (petPostID) => navigate("/pet/" + petPostID),
|
||||
invitedObjectSchema: Organization,
|
||||
onAccept: (organizationID) => {
|
||||
console.log("Accepted invite!")
|
||||
// navigate to the organization page
|
||||
},
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -104,14 +86,14 @@ Create the data models.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { CoMap, co, CoValue, Account, CoList } from "jazz-tools";
|
||||
// ---cut-before---
|
||||
class JoinRequest extends CoMap {
|
||||
account = co.ref(Account);
|
||||
status = co.literal("pending", "approved", "rejected");
|
||||
}
|
||||
import { co, z, Account } from "jazz-tools";
|
||||
// ---cut---
|
||||
const JoinRequest = co.map({
|
||||
account: Account,
|
||||
status: z.literal(["pending", "approved", "rejected"]),
|
||||
});
|
||||
|
||||
class RequestsList extends CoList.Of(co.ref(JoinRequest)) {};
|
||||
const RequestsList = co.list(JoinRequest);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -119,15 +101,15 @@ Set up the request system with appropriate access controls.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, co, CoList, CoMap, Account } from "jazz-tools";
|
||||
import { co, z, Account, Group, Loaded } from "jazz-tools";
|
||||
import { createInviteLink } from "jazz-react";
|
||||
|
||||
export class JoinRequest extends CoMap {
|
||||
account = co.ref(Account);
|
||||
status = co.literal("pending", "approved", "rejected");
|
||||
}
|
||||
const JoinRequest = co.map({
|
||||
account: Account,
|
||||
status: z.literal(["pending", "approved", "rejected"]),
|
||||
});
|
||||
|
||||
export class RequestsList extends CoList.Of(co.ref(JoinRequest)) {};
|
||||
const RequestsList = co.list(JoinRequest);
|
||||
|
||||
// ---cut-before---
|
||||
function createRequestsToJoin() {
|
||||
@@ -138,7 +120,7 @@ function createRequestsToJoin() {
|
||||
}
|
||||
|
||||
async function sendJoinRequest(
|
||||
requestsList: RequestsList,
|
||||
requestsList: Loaded<typeof RequestsList>,
|
||||
account: Account,
|
||||
) {
|
||||
const request = JoinRequest.create(
|
||||
@@ -160,23 +142,23 @@ Using the write-only access users can submit requests that only administrators c
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, CoMap, CoList, ID, Account, Group, Resolved } from "jazz-tools";
|
||||
import { co, z, ID, Account, Group, Loaded } from "jazz-tools";
|
||||
|
||||
class JoinRequest extends CoMap {
|
||||
account = co.ref(Account);
|
||||
status = co.string; // Can be "pending", "approved", "rejected"
|
||||
}
|
||||
const JoinRequest = co.map({
|
||||
account: Account,
|
||||
status: z.literal(["pending", "approved", "rejected"]),
|
||||
});
|
||||
|
||||
export class RequestsList extends CoList.Of(co.ref(JoinRequest)) {};
|
||||
const RequestsList = co.list(JoinRequest);
|
||||
|
||||
export class RequestsToJoin extends CoMap {
|
||||
writeOnlyInvite = co.string;
|
||||
requests = co.ref(RequestsList);
|
||||
}
|
||||
const RequestsToJoin = co.map({
|
||||
writeOnlyInvite: z.string(),
|
||||
requests: RequestsList,
|
||||
});
|
||||
|
||||
// ---cut-before---
|
||||
async function approveJoinRequest(
|
||||
joinRequest: JoinRequest,
|
||||
joinRequest: Loaded<typeof JoinRequest, { account: true }>,
|
||||
targetGroup: Group,
|
||||
) {
|
||||
const account = await Account.load(joinRequest._refs.account.id);
|
||||
|
||||
@@ -46,10 +46,6 @@ Sync and persist your data by setting up a [sync and storage infrastructure](/do
|
||||
|
||||
Learn how to structure your data using [collaborative values](/docs/schemas/covalues).
|
||||
|
||||
## API Reference
|
||||
|
||||
Many of the packages provided are documented in the [API Reference](/api-reference).
|
||||
|
||||
## LLM Docs
|
||||
|
||||
Get better results with AI by [importing the Jazz docs](/docs/ai-tools) into your context window.
|
||||
|
||||
@@ -19,7 +19,6 @@ Server Workers typically have static credentials, consisting of a public Account
|
||||
To generate new credentials for a Server Worker, you can run:
|
||||
|
||||
<CodeGroup>
|
||||
{/* prettier-ignore */}
|
||||
```sh
|
||||
npx jazz-run account create --name "My Server Worker"
|
||||
```
|
||||
@@ -43,13 +42,15 @@ You can use `startWorker` from `jazz-nodejs` to start a Server Worker. Similarly
|
||||
`startWorker` expects credentials in the `JAZZ_WORKER_ACCOUNT` and `JAZZ_WORKER_SECRET` environment variables by default (as printed by `npx account create ...`), but you can also pass them manually as `accountID` and `accountSecret` parameters if you get them from elsewhere.
|
||||
|
||||
<CodeGroup>
|
||||
{/* prettier-ignore */}
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Account } from "jazz-tools";
|
||||
class MyWorkerAccount extends Account {}
|
||||
// ---cut---
|
||||
import { startWorker } from 'jazz-nodejs';
|
||||
|
||||
const { worker } = await startWorker({
|
||||
AccountSchema: MyWorkerAccount,
|
||||
syncServer: 'wss://cloud.jazz.tools/?key=you@example.com',
|
||||
AccountSchema: MyWorkerAccount,
|
||||
syncServer: 'wss://cloud.jazz.tools/?key=you@example.com',
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -87,6 +87,7 @@ Similar to Zod v4's new object syntax, recursive and mutually recursive types ar
|
||||
|
||||
### How to pass loaded CoValues
|
||||
|
||||
<ContentByFramework framework={["react", "react-native", "vue", "vanilla", "react-native-expo"]}>
|
||||
Calls to `useCoState()` work just the same, but they return a slightly different type than before.
|
||||
|
||||
And while you can still read from the type just as before...
|
||||
@@ -102,41 +103,14 @@ const Pet = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
type Pet = co.loaded<typeof Pet>;
|
||||
|
||||
const Person = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
|
||||
function MyComponent({ id }: { id: string }) {
|
||||
const person = useCoState(Person, id);
|
||||
|
||||
return person && <div>{person.name}</div>;
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
...you now need to specify the type differently **when passing CoValues as a parameter** or
|
||||
**whenever you need to refer to the type of a loaded CoValue instance:**
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import React from "react";
|
||||
// ---cut---
|
||||
import { z, co, Loaded } from "jazz-tools"; // [!code ++]
|
||||
import { useCoState } from "jazz-react";
|
||||
|
||||
const Pet = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
const Person = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
type Person = co.loaded<typeof Person>;
|
||||
|
||||
function MyComponent({ id }: { id: string }) {
|
||||
const person = useCoState(Person, id);
|
||||
@@ -144,31 +118,35 @@ function MyComponent({ id }: { id: string }) {
|
||||
return person && <PersonName person={person} />;
|
||||
}
|
||||
|
||||
function PersonName({ person }: { person: Loaded<typeof Person> }) { // [!code ++]
|
||||
function PersonName({ person }: {
|
||||
person: Person
|
||||
}) {
|
||||
return <div>{person.name}</div>;
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
`Loaded` can also take a second argument to specify the loading depth of the expected CoValue, mirroring the `resolve` options for `useCoState`, `load`, `subscribe`, etc.
|
||||
`co.loaded` can also take a second argument to specify the loading depth of the expected CoValue, mirroring the `resolve` options for `useCoState`, `load`, `subscribe`, etc.
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import React from "react";
|
||||
// ---cut---
|
||||
import { z, co, Loaded } from "jazz-tools";
|
||||
import { z, co } from "jazz-tools";
|
||||
import { useCoState } from "jazz-react";
|
||||
|
||||
const Pet = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
type Pet = co.loaded<typeof Pet>;
|
||||
|
||||
const Person = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
type Person = co.loaded<typeof Person>;
|
||||
|
||||
function MyComponent({ id }: { id: string }) {
|
||||
const personWithPets = useCoState(Person, id, {
|
||||
@@ -179,29 +157,277 @@ function MyComponent({ id }: { id: string }) {
|
||||
}
|
||||
|
||||
function PersonAndFirstPetName({ person }: {
|
||||
person: Loaded<typeof Person, { pets: { $each: true } }> // [!code ++]
|
||||
person: co.loaded<typeof Person, { pets: { $each: true } }> // [!code ++]
|
||||
}) {
|
||||
return <div>{person.name} & {person.pets[0].name}</div>;
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
<ContentByFramework framework="svelte">
|
||||
We've removed the `useCoState`, `useAccount` and `useAccountOrGuest` hooks.
|
||||
|
||||
You should now use the `CoState` and `AccountCoState` reactive classes instead. These provide greater stability and are significantly easier to work with.
|
||||
|
||||
Calls to `new CoState()` work just the same, but they return a slightly different type than before.
|
||||
|
||||
And while you can still read from the type just as before...
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash filename="schema.ts"
|
||||
// @filename: schema.ts
|
||||
import { z, co } from "jazz-tools";
|
||||
|
||||
const Pet = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
type Pet = co.loaded<typeof Pet>;
|
||||
|
||||
const Person = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
type Person = co.loaded<typeof Person>;
|
||||
```
|
||||
```svelte twoslash filename="app.svelte"
|
||||
// @filename: app.svelte
|
||||
<script lang="ts">
|
||||
import { CoState } from "jazz-svelte";
|
||||
import { Person } from "./schema";
|
||||
|
||||
const person = new CoState(Person, id);
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{person.current?.name}
|
||||
</div>
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
`co.loaded` can also take a second argument to specify the loading depth of the expected CoValue, mirroring the `resolve` options for `CoState`, `load`, `subscribe`, etc.
|
||||
|
||||
<CodeGroup>
|
||||
```svelte twoslash
|
||||
<script lang="ts" module>
|
||||
export type Props = {
|
||||
person: co.loaded<typeof Person, { pets: { $each: true } }>; // [!code ++]
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Person } from './schema';
|
||||
|
||||
let props: Props = $props();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{props.person.name}
|
||||
</div>
|
||||
<ul>
|
||||
{#each props.person.pets as pet}
|
||||
<li>{pet.name}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
### Removing AccountSchema registration
|
||||
|
||||
We have removed the Typescript AccountSchema registration.
|
||||
|
||||
It was causing some deal of confusion to new adopters so we have decided to replace the magic inference with a more explicit approach.
|
||||
|
||||
<ContentByFramework framework={["react", "react-native", "vue", "vanilla", "react-native-expo"]}>
|
||||
When using `useAccount` you should now pass the `Account` schema directly:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
// @filename: schema.ts
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
export const MyAccount = co.account({
|
||||
profile: co.profile(),
|
||||
root: co.map({})
|
||||
});
|
||||
|
||||
// @filename: app.tsx
|
||||
import React from "react";
|
||||
// ---cut---
|
||||
import { useAccount } from "jazz-react";
|
||||
import { MyAccount } from "./schema";
|
||||
|
||||
function MyComponent() {
|
||||
const { me } = useAccount(MyAccount, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
},
|
||||
});
|
||||
|
||||
return <div>{me?.profile.name}</div>;
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
<ContentByFramework framework="svelte">
|
||||
When using `AccountCoState` you should now pass the `Account` schema directly:
|
||||
|
||||
<CodeGroup>
|
||||
```svelte twoslash filename="app.svelte"
|
||||
<script lang="ts">
|
||||
import { AccountCoState } from "jazz-svelte";
|
||||
import { MyAccount } from "./schema";
|
||||
|
||||
const account = new AccountCoState(MyAccount, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{account.current?.profile.name}
|
||||
</div>
|
||||
```
|
||||
</CodeGroup>
|
||||
</ContentByFramework>
|
||||
|
||||
### Defining migrations
|
||||
|
||||
TODO
|
||||
Now account schemas need to be defined with `co.account()` and migrations can be declared using `withMigration()`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, z, Group } from "jazz-tools";
|
||||
|
||||
const Pet = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
const MyAppRoot = co.map({
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
|
||||
const MyAppProfile = co.profile({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
});
|
||||
|
||||
export const MyAppAccount = co.account({
|
||||
root: MyAppRoot,
|
||||
profile: MyAppProfile,
|
||||
}).withMigration((account, creationProps?: { name: string }) => {
|
||||
if (account.root === undefined) {
|
||||
account.root = MyAppRoot.create({
|
||||
pets: co.list(Pet).create([]),
|
||||
});
|
||||
}
|
||||
|
||||
if (account.profile === undefined) {
|
||||
const profileGroup = Group.create();
|
||||
profileGroup.addMember("everyone", "reader");
|
||||
|
||||
account.profile = MyAppProfile.create({
|
||||
name: creationProps?.name ?? "New user",
|
||||
}, profileGroup);
|
||||
}
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Defining Schema helper methods
|
||||
|
||||
TODO
|
||||
|
||||
### Removing AccountSchema registration
|
||||
|
||||
TODO
|
||||
|
||||
## Minor breaking changes
|
||||
|
||||
### `_refs` and `_edits` are now potentially null
|
||||
|
||||
TODO
|
||||
The type of `_refs` and `_edits` is now nullable.
|
||||
|
||||
### `members` and `by` now return basic `Account`s
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { z, co } from "jazz-tools";
|
||||
// ---cut---
|
||||
const Person = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
const person = Person.create({ name: "John", age: 30 });
|
||||
|
||||
person._refs; // now nullable
|
||||
person._edits; // now nullable
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### `members` and `by` now return basic `Account`
|
||||
|
||||
We have removed the Account schema registration, so now `members` and `by` methods now always return basic `Account`.
|
||||
|
||||
This means that you now need to rely on `useCoState` on them to load their using your account schema.
|
||||
|
||||
<CodeGroup>
|
||||
```tsx twoslash
|
||||
import React from "react";
|
||||
import { co, z, Group } from "jazz-tools";
|
||||
import { useCoState } from "jazz-react";
|
||||
|
||||
const Pet = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
const MyAppRoot = co.map({
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
|
||||
const MyAppProfile = co.profile({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
});
|
||||
|
||||
export const MyAppAccount = co.account({
|
||||
root: MyAppRoot,
|
||||
profile: MyAppProfile,
|
||||
});
|
||||
|
||||
// ---cut---
|
||||
function GroupMembers({ group }: { group: Group }) {
|
||||
const members = group.members;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{members.map((member) => (
|
||||
<GroupMemberDetails
|
||||
accountId={member.account.id}
|
||||
key={member.account.id}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function GroupMemberDetails({ accountId }: { accountId: string }) {
|
||||
const account = useCoState(MyAppAccount, accountId, {
|
||||
resolve: {
|
||||
profile: true,
|
||||
root: {
|
||||
pets: { $each: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>{account?.profile.name}</div>
|
||||
<ul>{account?.root.pets.map((pet) => <li>{pet.name}</li>)}</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -19,7 +19,9 @@ The following examples demonstrate a practical use of CoFeeds:
|
||||
CoFeeds are defined by specifying the type of items they'll contain, similar to how you define CoLists:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
// ---cut---
|
||||
// Define a schema for feed items
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
@@ -73,24 +75,54 @@ Since CoFeeds are made of entries from users over multiple sessions, you can acc
|
||||
To retrieve entries from a session:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const sessionId = `${me.id}_session_z1` as SessionID;
|
||||
|
||||
// ---cut---
|
||||
// Get the feed for a specific session
|
||||
const sessionFeed = activityFeed.perSession[sessionId];
|
||||
|
||||
// Latest entry from a session
|
||||
console.log(sessionFeed.value.action); // "watering"
|
||||
console.log(sessionFeed?.value?.action); // "watering"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
For convenience, you can also access the latest entry from the current session with `inCurrentSession`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const sessionId = `${me.id}_session_z1` as SessionID;
|
||||
|
||||
// ---cut---
|
||||
// Get the feed for the current session
|
||||
const currentSessionFeed = activityFeed.inCurrentSession;
|
||||
|
||||
// Latest entry from the current session
|
||||
console.log(currentSessionFeed.value.action); // "harvesting"
|
||||
console.log(currentSessionFeed?.value?.action); // "harvesting"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -99,24 +131,54 @@ console.log(currentSessionFeed.value.action); // "harvesting"
|
||||
To retrieve entries from a specific account (with entries from all sessions combined) use `perAccount`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const accountId = me.id;
|
||||
|
||||
// ---cut---
|
||||
// Get the feed for a specific account
|
||||
const accountFeed = activityFeed.perAccount[accountId];
|
||||
|
||||
// Latest entry from the account
|
||||
console.log(accountFeed.value.action); // "watering"
|
||||
console.log(accountFeed.value?.action); // "watering"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
For convenience, you can also access the latest entry from the current account with `byMe`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const accountId = me.id;
|
||||
|
||||
// ---cut---
|
||||
// Get the feed for the current account
|
||||
const myLatestEntry = activityFeed.byMe;
|
||||
|
||||
// Latest entry from the current account
|
||||
console.log(myLatestEntry.value.action); // "harvesting"
|
||||
console.log(myLatestEntry?.value?.action); // "harvesting"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -127,7 +189,23 @@ console.log(myLatestEntry.value.action); // "harvesting"
|
||||
To retrieve all entries from a CoFeed:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const accountId = me.id;
|
||||
const sessionId = `${me.id}_session_z1` as SessionID;
|
||||
|
||||
// ---cut---
|
||||
// Get the feeds for a specific account and session
|
||||
const accountFeed = activityFeed.perAccount[accountId];
|
||||
const sessionFeed = activityFeed.perSession[sessionId];
|
||||
@@ -149,11 +227,25 @@ for (const entry of sessionFeed.all) {
|
||||
To retrieve the latest entry from a CoFeed, ie. the last update:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
|
||||
// ---cut---
|
||||
// Get the latest entry from the current account
|
||||
const latestEntry = activityFeed.byMe;
|
||||
|
||||
console.log(`My last action was ${latestEntry.value.action}`);
|
||||
console.log(`My last action was ${latestEntry?.value?.action}`);
|
||||
// "My last action was harvesting"
|
||||
|
||||
// Get the latest entry from each account
|
||||
@@ -171,7 +263,21 @@ CoFeeds are append-only; you can add new items, but not modify existing ones. Th
|
||||
### Adding Items
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
|
||||
// ---cut---
|
||||
// Log a new activity
|
||||
activityFeed.push(Activity.create({
|
||||
timestamp: new Date(),
|
||||
@@ -188,23 +294,37 @@ Each item is automatically associated with the current user's session. You don't
|
||||
Each entry is automatically added to the current session's feed. When a user has multiple open sessions (like both a mobile app and web browser), each session creates its own separate entries:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const fromMobileFeed = ActivityFeed.create([]);
|
||||
const fromBrowserFeed = ActivityFeed.create([]);
|
||||
|
||||
// ---cut---
|
||||
// On mobile device:
|
||||
fromMobileFeed.push(Activity.create({
|
||||
timestamp: new Date(),
|
||||
action: "harvesting",
|
||||
location: "Vegetable patch"
|
||||
notes: "Vegetable patch"
|
||||
}));
|
||||
|
||||
// On web browser (same user):
|
||||
fromBrowserFeed.push(Activity.create({
|
||||
timestamp: new Date(),
|
||||
action: "planting",
|
||||
location: "Flower bed"
|
||||
notes: "Flower bed"
|
||||
}));
|
||||
|
||||
// These are separate entries in the same feed, from the same account
|
||||
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -217,7 +337,22 @@ CoFeeds support metadata, which is useful for tracking information about the fee
|
||||
The `by` property is the account that made the entry.
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const accountId = me.id;
|
||||
|
||||
// ---cut---
|
||||
const accountFeed = activityFeed.perAccount[accountId];
|
||||
|
||||
// Get the account that made the last entry
|
||||
@@ -230,7 +365,22 @@ console.log(accountFeed?.by);
|
||||
The `madeAt` property is a timestamp of when the entry was added to the feed.
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z, ID, Account, SessionID } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const Activity = co.map({
|
||||
timestamp: z.date(),
|
||||
action: z.literal(["watering", "planting", "harvesting", "maintenance"]),
|
||||
notes: z.optional(z.string()),
|
||||
});
|
||||
|
||||
const ActivityFeed = co.feed(Activity);
|
||||
const activityFeed = ActivityFeed.create([]);
|
||||
const accountId = me.id;
|
||||
|
||||
// ---cut---
|
||||
const accountFeed = activityFeed.perAccount[accountId];
|
||||
|
||||
// Get the timestamp of the last update
|
||||
|
||||
@@ -13,7 +13,13 @@ CoLists are ordered collections that work like JavaScript arrays. They provide i
|
||||
CoLists are defined by specifying the type of items they contain:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
});
|
||||
|
||||
// ---cut---
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const ListOfResources = co.list(z.string());
|
||||
@@ -25,7 +31,14 @@ const ListOfTasks = co.list(Task);
|
||||
To create a `CoList`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
});
|
||||
// ---cut---
|
||||
// Create an empty list
|
||||
const resources = co.list(z.string()).create([]);
|
||||
|
||||
@@ -68,7 +81,22 @@ See [Groups as permission scopes](/docs/groups/intro) for more information on ho
|
||||
CoLists support standard array access patterns:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
});
|
||||
|
||||
const ListOfTasks = co.list(Task);
|
||||
|
||||
const tasks = ListOfTasks.create([
|
||||
Task.create({ title: "Prepare soil beds", status: "todo" }),
|
||||
Task.create({ title: "Order compost", status: "todo" }),
|
||||
]);
|
||||
// ---cut---
|
||||
// Access by index
|
||||
const firstTask = tasks[0];
|
||||
console.log(firstTask.title); // "Prepare soil beds"
|
||||
@@ -94,7 +122,22 @@ console.log(todoTasks.length); // 1
|
||||
Update `CoList`s just like you would JavaScript arrays:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
});
|
||||
|
||||
const ListOfTasks = co.list(Task);
|
||||
|
||||
const ListOfResources = co.list(z.string());
|
||||
|
||||
const resources = ListOfResources.create([]);
|
||||
const tasks = ListOfTasks.create([]);
|
||||
|
||||
// ---cut---
|
||||
// Add items
|
||||
resources.push("Tomatoes"); // Add to end
|
||||
resources.unshift("Lettuce"); // Add to beginning
|
||||
@@ -116,7 +159,18 @@ tasks[0].status = "complete"; // Update properties of references
|
||||
Remove specific items by index with `splice`, or remove the first or last item with `pop` or `shift`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const ListOfResources = co.list(z.string());
|
||||
|
||||
const resources = ListOfResources.create([
|
||||
"Tomatoes",
|
||||
"Cucumber",
|
||||
"Peppers",
|
||||
]);
|
||||
|
||||
// ---cut---
|
||||
// Remove 2 items starting at index 1
|
||||
resources.splice(1, 2);
|
||||
console.log(resources); // ["Cucumber", "Peppers"]
|
||||
@@ -136,7 +190,14 @@ resources.shift(); // Remove first item
|
||||
`CoList`s support the standard JavaScript array methods you already know:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const ListOfResources = co.list(z.string());
|
||||
|
||||
const resources = ListOfResources.create([]);
|
||||
|
||||
// ---cut---
|
||||
// Add multiple items at once
|
||||
resources.push("Tomatoes", "Basil", "Peppers");
|
||||
|
||||
@@ -158,9 +219,23 @@ console.log(resources); // ["Basil", "Peppers", "Tomatoes"]
|
||||
CoLists maintain type safety for their items:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { co, z } from "jazz-tools";
|
||||
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
});
|
||||
|
||||
const ListOfTasks = co.list(Task);
|
||||
const ListOfResources = co.list(z.string());
|
||||
|
||||
const resources = ListOfResources.create([]);
|
||||
const tasks = ListOfTasks.create([]);
|
||||
// ---cut---
|
||||
// TypeScript catches type errors
|
||||
resources.push("Carrots"); // ✓ Valid string
|
||||
// @errors: 2345
|
||||
resources.push(42); // ✗ Type error: expected string
|
||||
|
||||
// For lists of references
|
||||
@@ -178,20 +253,30 @@ tasks.forEach(task => {
|
||||
CoLists work well with UI rendering libraries:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
import * as React from "react";
|
||||
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
});
|
||||
|
||||
// ---cut---
|
||||
import { co, z, Loaded } from "jazz-tools";
|
||||
const ListOfTasks = co.list(Task);
|
||||
|
||||
// React example
|
||||
function TaskList({ tasks: Loaded<typeof ListOfTasks> }) {
|
||||
return (
|
||||
<ul>
|
||||
{tasks.map(task => (
|
||||
function TaskList({ tasks }: { tasks: Loaded<typeof ListOfTasks> }) {
|
||||
return (
|
||||
<ul>
|
||||
{tasks.map(task => (
|
||||
task ? (
|
||||
<li key={task.id}>
|
||||
{task.title} - {task.status}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
): null
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -202,15 +287,34 @@ function TaskList({ tasks: Loaded<typeof ListOfTasks> }) {
|
||||
CoLists can be used to create one-to-many relationships:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { co, z } from "jazz-tools";
|
||||
```ts twoslash
|
||||
import { co, z, CoListSchema } from "jazz-tools";
|
||||
|
||||
const Task = co.map({
|
||||
title: z.string(),
|
||||
status: z.literal(["todo", "in-progress", "complete"]),
|
||||
|
||||
get project(): z.ZodOptional<typeof Project> {
|
||||
return z.optional(Project);
|
||||
}
|
||||
});
|
||||
|
||||
const ListOfTasks = co.list(Task);
|
||||
|
||||
const Project = co.map({
|
||||
name: z.string(),
|
||||
tasks: co.list(Task),
|
||||
|
||||
get tasks(): CoListSchema<typeof Task> {
|
||||
return ListOfTasks;
|
||||
}
|
||||
});
|
||||
|
||||
// ...
|
||||
const project = Project.create(
|
||||
{
|
||||
name: "Garden Project",
|
||||
tasks: ListOfTasks.create([]),
|
||||
},
|
||||
);
|
||||
|
||||
const task = Task.create({
|
||||
title: "Plant seedlings",
|
||||
|
||||
@@ -76,11 +76,11 @@ Create an empty FileStream when you want to manually [add binary data in chunks]
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, co } from "jazz-tools";
|
||||
import { Group, FileStream } from "jazz-tools";
|
||||
const myGroup = Group.create();
|
||||
// ---cut---
|
||||
// Create a new empty FileStream
|
||||
const fileStream = co.fileStream().create({ owner: myGroup } );
|
||||
const fileStream = FileStream.create({ owner: myGroup } );
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -90,7 +90,7 @@ Like other CoValues, you can specify ownership when creating FileStreams.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { Group, co } from "jazz-tools";
|
||||
import { Group, FileStream } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const colleagueAccount = await createJazzTestAccount();
|
||||
@@ -101,7 +101,7 @@ const teamGroup = Group.create();
|
||||
teamGroup.addMember(colleagueAccount, "writer");
|
||||
|
||||
// Create a FileStream with shared ownership
|
||||
const teamFileStream = co.fileStream().create({ owner: teamGroup });
|
||||
const teamFileStream = FileStream.create({ owner: teamGroup });
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -117,8 +117,8 @@ To access the raw binary data and metadata:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Get all chunks and metadata
|
||||
const fileData = fileStream.getChunks();
|
||||
@@ -142,8 +142,8 @@ By default, `getChunks()` only returns data for completely synced `FileStream`s.
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Get data even if the stream isn't complete
|
||||
const partialData = fileStream.getChunks({ allowUnfinished: true });
|
||||
@@ -156,8 +156,8 @@ For easier integration with web APIs, convert to a `Blob`:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Convert to a Blob
|
||||
const blob = fileStream.toBlob();
|
||||
@@ -187,16 +187,16 @@ You can directly load a `FileStream` as a `Blob` when you only have its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, type ID } from "jazz-tools";
|
||||
import { FileStream, type ID } from "jazz-tools";
|
||||
const fileStreamId = "co_z123" as ID<FileStream>;
|
||||
// ---cut---
|
||||
// Load directly as a Blob when you have an ID
|
||||
const blob = await co.fileStream().loadAsBlob(fileStreamId);
|
||||
const blob = await FileStream.loadAsBlob(fileStreamId);
|
||||
|
||||
// By default, waits for complete uploads
|
||||
// For in-progress uploads:
|
||||
const partialBlob = await co.fileStream().loadAsBlob(fileStreamId, {
|
||||
allowUnfinished: true
|
||||
const partialBlob = await FileStream.loadAsBlob(fileStreamId, {
|
||||
allowUnfinished: true,
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -207,8 +207,8 @@ Check if a `FileStream` is fully synced:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
if (fileStream.isBinaryStreamEnded()) {
|
||||
console.log('File is completely synced');
|
||||
@@ -236,11 +236,11 @@ Begin by providing metadata about the file:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, Group } from "jazz-tools";
|
||||
import { FileStream, Group } from "jazz-tools";
|
||||
const myGroup = Group.create();
|
||||
// ---cut---
|
||||
// Create an empty FileStream
|
||||
const fileStream = co.fileStream().create({ owner: myGroup });
|
||||
const fileStream = FileStream.create({ owner: myGroup });
|
||||
|
||||
// Initialize with metadata
|
||||
fileStream.start({
|
||||
@@ -257,8 +257,8 @@ Add binary data in chunks - this helps with large files and progress tracking:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, Group } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream, Group } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
const file = [0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64]; // "Hello World" in ASCII
|
||||
const bytes = new Uint8Array(file);
|
||||
const arrayBuffer = bytes.buffer;
|
||||
@@ -288,8 +288,8 @@ Once all chunks are pushed, mark the `FileStream` as complete:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Finalize the upload
|
||||
fileStream.end();
|
||||
@@ -308,11 +308,11 @@ Load a `FileStream` when you have its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, type ID } from "jazz-tools";
|
||||
const fileStreamId = "co_z123" as ID<FileStream>;
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStreamId = "co_z123";
|
||||
// ---cut---
|
||||
// Load a FileStream by ID
|
||||
const fileStream = await co.fileStream().load(fileStreamId);
|
||||
const fileStream = await FileStream.load(fileStreamId);
|
||||
|
||||
if (fileStream) {
|
||||
console.log('FileStream loaded successfully');
|
||||
@@ -332,12 +332,12 @@ Subscribe to a `FileStream` to be notified when chunks are added or when the upl
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co, type ID } from "jazz-tools";
|
||||
import { FileStream } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const fileStreamId = "co_z123" as ID<FileStream>;
|
||||
const fileStreamId = "co_z123";
|
||||
// ---cut---
|
||||
// Subscribe to a FileStream by ID
|
||||
const unsubscribe = co.fileStream().subscribe(fileStreamId, (fileStream: FileStream) => {
|
||||
const unsubscribe = FileStream.subscribe(fileStreamId, (fileStream: FileStream) => {
|
||||
// Called whenever the FileStream changes
|
||||
console.log('FileStream updated');
|
||||
|
||||
@@ -369,8 +369,8 @@ If you need to wait for a `FileStream` to be fully synchronized across devices:
|
||||
|
||||
<CodeGroup>
|
||||
```ts twoslash
|
||||
import { co } from "jazz-tools";
|
||||
const fileStream = co.fileStream().create();
|
||||
import { FileStream } from "jazz-tools";
|
||||
const fileStream = FileStream.create();
|
||||
// ---cut---
|
||||
// Wait for the FileStream to be fully synced
|
||||
await fileStream.waitForSync({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
export const metadata = {
|
||||
export const metadata = {
|
||||
description: "ImageDefinition is a CoValue for managing images, storage of multiple resolutions, and progressive loading."
|
||||
};
|
||||
|
||||
@@ -19,26 +19,55 @@ The [Image Upload example](https://github.com/gardencmp/jazz/tree/main/examples/
|
||||
The easiest way to create and use images in your Jazz application is with the `createImage()` function:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z } from "jazz-tools";
|
||||
|
||||
const MyProfile = co.profile({
|
||||
name: z.string(),
|
||||
image: z.optional(co.image()),
|
||||
});
|
||||
|
||||
const MyAccount = co.account({
|
||||
root: co.map({}),
|
||||
profile: MyProfile,
|
||||
});
|
||||
|
||||
MyAccount.withMigration((account, creationProps) => {
|
||||
if (account.profile === undefined) {
|
||||
const profileGroup = Group.create();
|
||||
profileGroup.addMember("everyone", "reader");
|
||||
account.profile = MyProfile.create(
|
||||
{
|
||||
name: creationProps?.name ?? "New user",
|
||||
},
|
||||
profileGroup,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const me = await MyAccount.create({ creationProps: { name: "John Doe" } });
|
||||
|
||||
const myGroup = Group.create();
|
||||
|
||||
// ---cut---
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
|
||||
// Create an image from a file input
|
||||
async function handleFileUpload(event) {
|
||||
const file = event.target.files[0];
|
||||
async function handleFileUpload(event: Event) {
|
||||
const file = (event.target as HTMLInputElement).files?.[0];
|
||||
if (file) {
|
||||
// Creates ImageDefinition with multiple resolutions automatically
|
||||
const image = await createImage(file, {
|
||||
owner: me.profile._owner,
|
||||
});
|
||||
const image = await createImage(file, { owner: myGroup });
|
||||
|
||||
// Store the image in your application data
|
||||
me.profile.image = image;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
> Note: `createImage()` requires a browser environment as it uses browser APIs to process images.
|
||||
**Note:** `createImage()` requires a browser environment as it uses browser APIs to process images.
|
||||
|
||||
The `createImage()` function:
|
||||
- Creates an `ImageDefinition` with the right properties
|
||||
@@ -51,11 +80,16 @@ The `createImage()` function:
|
||||
You can configure `createImage()` with additional options:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const file = new File([], "test.jpg", { type: "image/jpeg" });
|
||||
// ---cut---
|
||||
// Configuration options
|
||||
const options = {
|
||||
owner: me, // Owner for access control
|
||||
maxSize: 1024 // Maximum resolution to generate
|
||||
maxSize: 1024 as 1024 // Maximum resolution to generate
|
||||
};
|
||||
|
||||
// Setting maxSize controls which resolutions are generated:
|
||||
@@ -98,7 +132,7 @@ See [Groups as permission scopes](/docs/groups/intro) for more information on ho
|
||||
Create an `ImageDefinition` by specifying the original dimensions and an optional placeholder:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { ImageDefinition } from "jazz-tools";
|
||||
|
||||
// Create with original dimensions
|
||||
@@ -109,7 +143,7 @@ const image = ImageDefinition.create({
|
||||
// With a placeholder for immediate display
|
||||
const imageWithPlaceholder = ImageDefinition.create({
|
||||
originalSize: [1920, 1080],
|
||||
placeholderDataURL: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAP...",
|
||||
placeholderDataURL: "data:image/jpeg;base64,/9j/4AAQSkZJ...",
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -124,15 +158,13 @@ const imageWithPlaceholder = ImageDefinition.create({
|
||||
Each resolution is stored with a key in the format `"widthxheight"` (e.g., `"1920x1080"`, `"800x450"`).
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
import { CoMap, CoList, ImageDefinition, coField } from "jazz-tools";
|
||||
```ts twoslash
|
||||
import { ImageDefinition, co, z } from "jazz-tools";
|
||||
|
||||
class ListOfImages extends CoList.Of(coField.ref(ImageDefinition)) {}
|
||||
|
||||
class Gallery extends CoMap {
|
||||
title = coField.string;
|
||||
images = coField.ref(ListOfImages);
|
||||
}
|
||||
const Gallery = co.map({
|
||||
title: z.string(),
|
||||
images: co.list(co.image()),
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -141,7 +173,19 @@ class Gallery extends CoMap {
|
||||
Add multiple resolutions to an `ImageDefinition` by creating `FileStream`s for each size:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream, ImageDefinition } from "jazz-tools";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const fullSizeBlob = new Blob([], { type: "image/jpeg" });
|
||||
const mediumSizeBlob = new Blob([], { type: "image/jpeg" });
|
||||
const thumbnailBlob = new Blob([], { type: "image/jpeg" });
|
||||
|
||||
const image = ImageDefinition.create({
|
||||
originalSize: [1920, 1080],
|
||||
}, { owner: me });
|
||||
// ---cut---
|
||||
// Create FileStreams for different resolutions
|
||||
const fullRes = await FileStream.createFromBlob(fullSizeBlob);
|
||||
const mediumRes = await FileStream.createFromBlob(mediumSizeBlob);
|
||||
@@ -159,28 +203,46 @@ image["320x180"] = thumbnailRes;
|
||||
The `highestResAvailable` method helps select the best image resolution for the current context:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
// Get the highest resolution available
|
||||
const highestRes = image.highestResAvailable();
|
||||
if (highestRes) {
|
||||
console.log(`Found resolution: ${highestRes.res}`);
|
||||
```ts twoslash
|
||||
import { ImageDefinition, FileStream } from "jazz-tools";
|
||||
import { createJazzTestAccount } from "jazz-tools/testing";
|
||||
|
||||
// Convert to a usable blob
|
||||
// Simple document environment
|
||||
global.document = {
|
||||
createElement: () =>
|
||||
({ src: "", onload: null }) as unknown as HTMLImageElement,
|
||||
} as unknown as Document;
|
||||
global.window = { innerWidth: 1000 } as unknown as Window & typeof globalThis;
|
||||
|
||||
// Setup
|
||||
const fakeBlob = new Blob(["fake image data"], { type: "image/jpeg" });
|
||||
const me = await createJazzTestAccount();
|
||||
const image = ImageDefinition.create(
|
||||
{ originalSize: [1920, 1080] },
|
||||
{ owner: me },
|
||||
);
|
||||
image["1920x1080"] = await FileStream.createFromBlob(fakeBlob, { owner: me });
|
||||
const imageElement = document.createElement("img");
|
||||
|
||||
// ---cut---
|
||||
// Get highest resolution available (unconstrained)
|
||||
const highestRes = ImageDefinition.highestResAvailable(image);
|
||||
console.log(highestRes);
|
||||
if (highestRes) {
|
||||
const blob = highestRes.stream.toBlob();
|
||||
if (blob) {
|
||||
// Create a URL for the blob
|
||||
const url = URL.createObjectURL(blob);
|
||||
imageElement.src = url;
|
||||
|
||||
// Remember to revoke the URL when no longer needed
|
||||
imageElement.onload = () => {
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
// Revoke the URL when the image is loaded
|
||||
imageElement.onload = () => URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Or constrain by maximum width
|
||||
const targetWidth = window.innerWidth;
|
||||
const appropriateRes = image.highestResAvailable({ targetWidth });
|
||||
// Get appropriate resolution for specific width
|
||||
const appropriateRes = ImageDefinition.highestResAvailable(image, {
|
||||
targetWidth: window.innerWidth,
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -189,7 +251,11 @@ const appropriateRes = image.highestResAvailable({ targetWidth });
|
||||
`highestResAvailable` returns the largest resolution that fits your constraints. If a resolution has incomplete data, it falls back to the next available lower resolution.
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { ImageDefinition, FileStream } from "jazz-tools";
|
||||
|
||||
const mediumSizeBlob = new Blob([], { type: "image/jpeg" });
|
||||
// ---cut---
|
||||
const image = ImageDefinition.create({
|
||||
originalSize: [1920, 1080],
|
||||
});
|
||||
@@ -197,8 +263,8 @@ const image = ImageDefinition.create({
|
||||
image["1920x1080"] = FileStream.create(); // Empty image upload
|
||||
image["800x450"] = await FileStream.createFromBlob(mediumSizeBlob);
|
||||
|
||||
const highestRes = image.highestResAvailable();
|
||||
console.log(highestRes.res); // 800x450
|
||||
const highestRes = ImageDefinition.highestResAvailable(image);
|
||||
console.log(highestRes?.res); // 800x450
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -207,7 +273,31 @@ console.log(highestRes.res); // 800x450
|
||||
`ImageDefinition` supports simple progressive loading with placeholders and resolution selection:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { FileStream, ImageDefinition } from "jazz-tools";
|
||||
import { createJazzTestAccount } from "jazz-tools/testing";
|
||||
|
||||
// Simple document environment
|
||||
global.document = {
|
||||
createElement: () =>
|
||||
({ src: "", onload: null }) as unknown as HTMLImageElement,
|
||||
} as unknown as Document;
|
||||
global.window = { innerWidth: 1000 } as unknown as Window & typeof globalThis;
|
||||
|
||||
const me = await createJazzTestAccount();
|
||||
|
||||
const mediumSizeBlob = new Blob([], { type: "image/jpeg" });
|
||||
const image = ImageDefinition.create(
|
||||
{
|
||||
originalSize: [1920, 1080],
|
||||
},
|
||||
{ owner: me },
|
||||
);
|
||||
image["1920x1080"] = await FileStream.createFromBlob(mediumSizeBlob, {
|
||||
owner: me,
|
||||
});
|
||||
const imageElement = document.createElement("img");
|
||||
// ---cut---
|
||||
// Start with placeholder for immediate display
|
||||
if (image.placeholderDataURL) {
|
||||
imageElement.src = image.placeholderDataURL;
|
||||
@@ -215,7 +305,9 @@ if (image.placeholderDataURL) {
|
||||
|
||||
// Then load the best resolution for the current display
|
||||
const screenWidth = window.innerWidth;
|
||||
const bestRes = image.highestResAvailable({ targetWidth: screenWidth });
|
||||
const bestRes = ImageDefinition.highestResAvailable(image, {
|
||||
targetWidth: screenWidth,
|
||||
});
|
||||
|
||||
if (bestRes) {
|
||||
const blob = bestRes.stream.toBlob();
|
||||
@@ -229,6 +321,7 @@ if (bestRes) {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
</CodeGroup>
|
||||
## Best Practices
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CodeGroup } from "@/components/forMdx";
|
||||
|
||||
export const metadata = {
|
||||
export const metadata = {
|
||||
description: "ImageDefinition is a CoValue for managing images, storage of multiple resolutions, and progressive loading."
|
||||
};
|
||||
|
||||
@@ -20,26 +20,55 @@ The [Image Upload example](https://github.com/gardencmp/jazz/tree/main/examples/
|
||||
The easiest way to create and use images in your Jazz application is with the `createImage()` function:
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { Group, co, z } from "jazz-tools";
|
||||
|
||||
const MyProfile = co.profile({
|
||||
name: z.string(),
|
||||
image: z.optional(co.image()),
|
||||
});
|
||||
|
||||
const MyAccount = co.account({
|
||||
root: co.map({}),
|
||||
profile: MyProfile,
|
||||
});
|
||||
|
||||
MyAccount.withMigration((account, creationProps) => {
|
||||
if (account.profile === undefined) {
|
||||
const profileGroup = Group.create();
|
||||
profileGroup.addMember("everyone", "reader");
|
||||
account.profile = MyProfile.create(
|
||||
{
|
||||
name: creationProps?.name ?? "New user",
|
||||
},
|
||||
profileGroup,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const me = await MyAccount.create({});
|
||||
|
||||
const myGroup = Group.create();
|
||||
|
||||
// ---cut---
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
|
||||
// Create an image from a file input
|
||||
async function handleFileUpload(event) {
|
||||
const file = event.target.files[0];
|
||||
async function handleFileUpload(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
const file = event.target.files?.[0];
|
||||
if (file) {
|
||||
// Creates ImageDefinition with multiple resolutions automatically
|
||||
const image = await createImage(file, {
|
||||
owner: me.profile._owner,
|
||||
});
|
||||
|
||||
const image = await createImage(file, { owner: myGroup });
|
||||
|
||||
// Store the image in your application data
|
||||
me.profile.image = image;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
> Note: `createImage()` requires a browser environment as it uses browser APIs to process images.
|
||||
**Note:** `createImage()` requires a browser environment as it uses browser APIs to process images.
|
||||
|
||||
The `createImage()` function:
|
||||
- Creates an `ImageDefinition` with the right properties
|
||||
@@ -52,11 +81,16 @@ The `createImage()` function:
|
||||
You can configure `createImage()` with additional options:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```ts twoslash
|
||||
import { createImage } from "jazz-browser-media-images";
|
||||
import { createJazzTestAccount } from 'jazz-tools/testing';
|
||||
const me = await createJazzTestAccount();
|
||||
const file = new File([], "test.jpg", { type: "image/jpeg" });
|
||||
// ---cut---
|
||||
// Configuration options
|
||||
const options = {
|
||||
owner: me, // Owner for access control
|
||||
maxSize: 1024 // Maximum resolution to generate
|
||||
maxSize: 1024 as 1024 // Maximum resolution to generate
|
||||
};
|
||||
|
||||
// Setting maxSize controls which resolutions are generated:
|
||||
@@ -99,10 +133,14 @@ See [Groups as permission scopes](/docs/groups/intro) for more information on ho
|
||||
For a complete progressive loading experience, use the `ProgressiveImg` component:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
import * as React from "react";
|
||||
// ---cut---
|
||||
import { ProgressiveImg } from "jazz-react";
|
||||
import { Loaded, co } from "jazz-tools";
|
||||
const Image = co.image();
|
||||
|
||||
function GalleryView({ image }) {
|
||||
function GalleryView({ image }: { image: Loaded<typeof Image> }) {
|
||||
return (
|
||||
<div className="image-container">
|
||||
<ProgressiveImg
|
||||
@@ -134,10 +172,14 @@ The `ProgressiveImg` component handles:
|
||||
For more control over image loading, you can implement your own progressive image component:
|
||||
|
||||
<CodeGroup>
|
||||
```tsx
|
||||
```tsx twoslash
|
||||
import * as React from "react";
|
||||
import { Loaded, co } from "jazz-tools";
|
||||
const Image = co.image();
|
||||
// ---cut---
|
||||
import { useProgressiveImg } from "jazz-react";
|
||||
|
||||
function CustomImageComponent({ image }) {
|
||||
function CustomImageComponent({ image }: { image: Loaded<typeof Image> }) {
|
||||
const {
|
||||
src, // Data URI containing the image data as a base64 string,
|
||||
// or a placeholder image URI
|
||||
@@ -186,7 +228,9 @@ Behind the scenes, `ImageDefinition` is a specialized CoValue that stores:
|
||||
Each resolution is stored with a key in the format `"widthxheight"` (e.g., `"1920x1080"`, `"800x450"`).
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { ImageDefinition } from "jazz-tools";
|
||||
// ---cut---
|
||||
// Structure of an ImageDefinition
|
||||
const image = ImageDefinition.create({
|
||||
originalSize: [1920, 1080],
|
||||
@@ -194,7 +238,7 @@ const image = ImageDefinition.create({
|
||||
});
|
||||
|
||||
// Accessing the highest available resolution
|
||||
const highestRes = image.highestResAvailable();
|
||||
const highestRes = ImageDefinition.highestResAvailable(image);
|
||||
if (highestRes) {
|
||||
console.log(`Found resolution: ${highestRes.res}`);
|
||||
console.log(`Stream: ${highestRes.stream}`);
|
||||
@@ -209,7 +253,11 @@ For more details on using `ImageDefinition` directly, see the [VanillaJS docs](/
|
||||
`highestResAvailable` returns the largest resolution that fits your constraints. If a resolution has incomplete data, it falls back to the next available lower resolution.
|
||||
|
||||
<CodeGroup>
|
||||
```ts
|
||||
```ts twoslash
|
||||
import { ImageDefinition, FileStream } from "jazz-tools";
|
||||
const mediumSizeBlob = new Blob([], { type: "image/jpeg" });
|
||||
|
||||
// ---cut---
|
||||
const image = ImageDefinition.create({
|
||||
originalSize: [1920, 1080],
|
||||
});
|
||||
@@ -217,7 +265,7 @@ const image = ImageDefinition.create({
|
||||
image["1920x1080"] = FileStream.create(); // Empty image upload
|
||||
image["800x450"] = await FileStream.createFromBlob(mediumSizeBlob);
|
||||
|
||||
const highestRes = image.highestResAvailable();
|
||||
console.log(highestRes.res); // 800x450
|
||||
const highestRes = ImageDefinition.highestResAvailable(image);
|
||||
console.log(highestRes?.res); // 800x450
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
@@ -11,10 +11,10 @@ export const navigationItems: NavItemProps[] = [
|
||||
title: "Examples",
|
||||
href: "/examples",
|
||||
},
|
||||
{
|
||||
title: "API ref",
|
||||
href: "/api-reference",
|
||||
},
|
||||
// {
|
||||
// title: "API ref",
|
||||
// href: "/api-reference",
|
||||
// },
|
||||
{
|
||||
title: "Built with Jazz",
|
||||
href: "/showcase",
|
||||
|
||||
@@ -304,185 +304,6 @@ async function generateDetailedDocs(docs) {
|
||||
}
|
||||
}
|
||||
|
||||
// API Reference by package
|
||||
output.push("## API Reference\n\n");
|
||||
// for (const [packageName, packageDocs] of Object.entries(docs)) {
|
||||
// const project = deserializer.reviveProject(packageDocs, packageName);
|
||||
|
||||
// // Add package heading with description
|
||||
// output.push(`### ${packageName}\n`);
|
||||
// output.push(`${getPackageDescription(packageName)}\n\n`);
|
||||
// output.push(
|
||||
// `[API Reference](https://jazz.tools/api-reference/${packageName})\n\n`,
|
||||
// );
|
||||
|
||||
// // Process each category
|
||||
// project.categories?.forEach((category) => {
|
||||
// output.push(`#### ${category.title}\n`);
|
||||
|
||||
// category.children.forEach((child) => {
|
||||
// // Add name, kind, and API reference link
|
||||
// const apiLink = `[API Reference](https://jazz.tools/api-reference/${packageName}#${child.name})`;
|
||||
// output.push(
|
||||
// `##### ${child.name} (${ReflectionKind[child.kind]}) ${apiLink}\n`,
|
||||
// );
|
||||
|
||||
// // Add description if available
|
||||
// const description = formatComment(child.comment);
|
||||
// if (description) {
|
||||
// output.push(`${description}\n`);
|
||||
// }
|
||||
|
||||
// output.push("\n");
|
||||
|
||||
// // Add properties for classes/interfaces
|
||||
// if (child.children) {
|
||||
// output.push("Properties:\n");
|
||||
|
||||
// // Group overloaded methods by name
|
||||
// const methodGroups = new Map();
|
||||
// child.children.forEach((prop) => {
|
||||
// if (prop.signatures?.length > 0) {
|
||||
// const existing = methodGroups.get(prop.name) || [];
|
||||
// methodGroups.set(prop.name, [...existing, prop]);
|
||||
// }
|
||||
// });
|
||||
|
||||
// child.children.forEach((prop) => {
|
||||
// // Skip if this is an overloaded method that we'll handle later
|
||||
// if (
|
||||
// prop.signatures?.length > 0 &&
|
||||
// methodGroups.get(prop.name)?.length > 1
|
||||
// ) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const type = formatType(prop.type);
|
||||
// const description = formatComment(prop.comment);
|
||||
|
||||
// // Output the property name and type, but skip the type for methods since we'll show signatures
|
||||
// if (prop.signatures?.length > 0) {
|
||||
// output.push(
|
||||
// `- ${prop.name}${description ? ` - ${description}` : ""}\n`,
|
||||
// );
|
||||
// } else {
|
||||
// output.push(
|
||||
// `- ${prop.name}: ${type}${description ? ` - ${description}` : ""}\n`,
|
||||
// );
|
||||
// }
|
||||
|
||||
// // Handle method signatures with proper indentation
|
||||
// if (prop.signatures) {
|
||||
// prop.signatures.forEach((sig) => {
|
||||
// const params = sig.parameters
|
||||
// ?.map((p) => {
|
||||
// const paramType = formatType(p.type);
|
||||
// return `${p.name}: ${paramType}`;
|
||||
// })
|
||||
// .join(", ");
|
||||
|
||||
// output.push(
|
||||
// ` Method signature: \`(${params || ""}) => ${formatType(sig.type)}\`\n`,
|
||||
// );
|
||||
|
||||
// // Add API reference URL for the method
|
||||
// output.push(
|
||||
// ` [API Reference](https://jazz.tools/api-reference/${packageName}#${child.name}.${prop.name})\n`,
|
||||
// );
|
||||
|
||||
// const methodDesc = formatComment(sig.comment);
|
||||
// if (methodDesc) {
|
||||
// // Indent each line of the description
|
||||
// const indentedDesc = methodDesc
|
||||
// .split("\n")
|
||||
// .map((line) => ` ${line}`)
|
||||
// .join("\n");
|
||||
// output.push(`${indentedDesc}\n`);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// // Handle overloaded methods
|
||||
// methodGroups.forEach((props, name) => {
|
||||
// if (props.length <= 1) return;
|
||||
|
||||
// const firstProp = props[0];
|
||||
// const description = formatComment(firstProp.comment);
|
||||
|
||||
// output.push(`- ${name}${description ? ` - ${description}` : ""}\n`);
|
||||
|
||||
// // Combine all signatures with proper indentation
|
||||
// const allSignatures = props.flatMap((p) => p.signatures || []);
|
||||
// allSignatures.forEach((sig) => {
|
||||
// const params = sig.parameters
|
||||
// ?.map((p) => {
|
||||
// const paramType = formatType(p.type);
|
||||
// return `${p.name}: ${paramType}`;
|
||||
// })
|
||||
// .join(", ");
|
||||
|
||||
// output.push(
|
||||
// ` Method signature: \`(${params || ""}) => ${formatType(sig.type)}\`\n`,
|
||||
// );
|
||||
|
||||
// // Add API reference URL for the overloaded method
|
||||
// output.push(
|
||||
// ` [API Reference](https://jazz.tools/api-reference/${packageName}#${child.name}.${name})\n`,
|
||||
// );
|
||||
|
||||
// const methodDesc = formatComment(sig.comment);
|
||||
// if (methodDesc) {
|
||||
// // Indent each line of the description
|
||||
// const indentedDesc = methodDesc
|
||||
// .split("\n")
|
||||
// .map((line) => ` ${line}`)
|
||||
// .join("\n");
|
||||
// output.push(`${indentedDesc}\n`);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Add signatures for functions/methods
|
||||
// if (child.signatures) {
|
||||
// child.signatures.forEach((sig) => {
|
||||
// const params = sig.parameters
|
||||
// ?.map((p) => {
|
||||
// const type = formatType(p.type);
|
||||
// const desc = formatComment(p.comment);
|
||||
// return `${p.name}: ${type}${desc ? ` - ${desc}` : ""}`;
|
||||
// })
|
||||
// .join(", ");
|
||||
|
||||
// output.push(`Signature: ${child.name}(${params || ""})`);
|
||||
|
||||
// if (sig.type) {
|
||||
// output.push(`Returns: ${formatType(sig.type)}`);
|
||||
// if (sig.comment?.returns) {
|
||||
// output.push(
|
||||
// `Return description: ${sig.comment.returns
|
||||
// .map((part) => part.text)
|
||||
// .join("")
|
||||
// .trim()}`,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// const sigComment = formatComment(sig.comment);
|
||||
// if (sigComment) {
|
||||
// output.push(`\n${sigComment}`);
|
||||
// }
|
||||
|
||||
// output.push("\n");
|
||||
// });
|
||||
// }
|
||||
|
||||
// output.push("\n");
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
// Optional section for additional resources
|
||||
output.push("## Resources\n\n");
|
||||
output.push(
|
||||
|
||||
@@ -28,9 +28,6 @@ export const PACKAGES = [
|
||||
packageName: "jazz-react",
|
||||
entryPoint: "index.ts",
|
||||
description: "React bindings for Jazz, a framework for distributed state.",
|
||||
typedocOptions: {
|
||||
skipErrorChecking: true, // TODO: remove this. Temporary workaround
|
||||
},
|
||||
},
|
||||
{
|
||||
packageName: "jazz-browser",
|
||||
|
||||
@@ -1,5 +1,52 @@
|
||||
# jazz-auth-betterauth
|
||||
|
||||
## 0.14.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-browser@0.14.8
|
||||
- jazz-betterauth-client-plugin@0.14.8
|
||||
|
||||
## 0.14.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-browser@0.14.7
|
||||
- jazz-betterauth-client-plugin@0.14.7
|
||||
|
||||
## 0.14.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-browser@0.14.6
|
||||
- jazz-betterauth-client-plugin@0.14.6
|
||||
|
||||
## 0.14.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-browser@0.14.5
|
||||
- jazz-betterauth-client-plugin@0.14.5
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
- jazz-betterauth-client-plugin@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-auth-betterauth",
|
||||
"version": "0.14.2",
|
||||
"version": "0.14.8",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
|
||||
@@ -1,5 +1,47 @@
|
||||
# jazz-auth-clerk
|
||||
|
||||
## 0.14.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [637ae13]
|
||||
- jazz-tools@0.14.8
|
||||
- jazz-browser@0.14.8
|
||||
|
||||
## 0.14.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [365b0ea]
|
||||
- jazz-tools@0.14.7
|
||||
- jazz-browser@0.14.7
|
||||
|
||||
## 0.14.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- Updated dependencies [9d6d9fe]
|
||||
- jazz-tools@0.14.6
|
||||
- jazz-browser@0.14.6
|
||||
|
||||
## 0.14.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [91cbb2f]
|
||||
- Updated dependencies [20b3d88]
|
||||
- jazz-tools@0.14.5
|
||||
- jazz-browser@0.14.5
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "jazz-auth-clerk",
|
||||
"version": "0.14.2",
|
||||
"version": "0.14.8",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.14.1",
|
||||
"jazz-browser": "workspace:0.14.2",
|
||||
"jazz-tools": "workspace:0.14.2"
|
||||
"jazz-browser": "workspace:0.14.8",
|
||||
"jazz-tools": "workspace:0.14.8"
|
||||
},
|
||||
"scripts": {
|
||||
"format-and-lint": "biome check .",
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# jazz-betterauth-client-plugin
|
||||
|
||||
## 0.14.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.8
|
||||
|
||||
## 0.14.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.7
|
||||
|
||||
## 0.14.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.6
|
||||
|
||||
## 0.14.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.5
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-betterauth-client-plugin",
|
||||
"version": "0.14.2",
|
||||
"version": "0.14.8",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user