Compare commits
32 Commits
0-14-0
...
jazz-auth-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
0088aa8b25 | ||
|
|
35a66df1e4 |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"jazz-tools": patch
|
||||
---
|
||||
|
||||
Make possible to extend a group without having access to it
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
"jazz-react-native-media-images": minor
|
||||
"jazz-browser-media-images": minor
|
||||
"jazz-richtext-prosemirror": minor
|
||||
"jazz-inspector-element": minor
|
||||
"jazz-react-native-core": minor
|
||||
"jazz-react-auth-clerk": minor
|
||||
"jazz-react-native": minor
|
||||
"jazz-auth-clerk": minor
|
||||
"jazz-react-core": minor
|
||||
"jazz-inspector": minor
|
||||
"jazz-browser": minor
|
||||
"jazz-nodejs": minor
|
||||
"jazz-svelte": minor
|
||||
"jazz-react": minor
|
||||
"jazz-expo": minor
|
||||
"jazz-run": minor
|
||||
"jazz-vue": minor
|
||||
---
|
||||
|
||||
Make jazz-tools a peerDependency, to reduce risks of having multiple versions of it
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"jazz-tools": patch
|
||||
---
|
||||
|
||||
Fix custom AccountSchema support in testing utils
|
||||
@@ -1,5 +1,30 @@
|
||||
# betterauth
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-betterauth-server-plugin@0.14.2
|
||||
- jazz-inspector@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
- jazz-react-auth-betterauth@0.14.2
|
||||
- jazz-betterauth-client-plugin@0.14.2
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "betterauth",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.8",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# chat-rn-expo-clerk
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-expo@0.14.2
|
||||
- jazz-react-native-media-images@0.14.2
|
||||
|
||||
## 1.0.125
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-expo-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.125",
|
||||
"version": "1.0.127",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-rn-expo
|
||||
|
||||
## 1.0.114
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-expo@0.14.4
|
||||
|
||||
## 1.0.113
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-expo@0.14.2
|
||||
|
||||
## 1.0.112
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn-expo",
|
||||
"version": "1.0.112",
|
||||
"version": "1.0.114",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "tsc --noEmit && expo export -p ios",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.122
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react-native@0.14.4
|
||||
|
||||
## 1.0.121
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react-native@0.14.2
|
||||
|
||||
## 1.0.120
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.120",
|
||||
"version": "1.0.122",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# chat-vue
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
- jazz-vue@0.14.2
|
||||
|
||||
## 0.0.103
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.103",
|
||||
"version": "0.0.105",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-inspector@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.201
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.201",
|
||||
"version": "0.0.203",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
- jazz-react-auth-clerk@0.14.2
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.100",
|
||||
"version": "0.0.102",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-inspector-element@0.14.2
|
||||
- jazz-svelte@0.14.2
|
||||
|
||||
## 0.0.84
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.84",
|
||||
"version": "0.0.87",
|
||||
"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 { FileStream, 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: 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,24 @@
|
||||
# jazz-tailwind-demo-auth-starter
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-inspector@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.40
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filestream",
|
||||
"private": true,
|
||||
"version": "0.0.40",
|
||||
"version": "0.0.42",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# form
|
||||
|
||||
## 0.1.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.1.42
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.1.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.1.41",
|
||||
"version": "0.1.43",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.97",
|
||||
"version": "0.0.99",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.152
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.4
|
||||
|
||||
## 0.0.151
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.14.2
|
||||
|
||||
## 0.0.150
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector-app",
|
||||
"private": true,
|
||||
"version": "0.0.150",
|
||||
"version": "0.0.152",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# multi-cursors
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multi-cursors",
|
||||
"private": true,
|
||||
"version": "0.0.93",
|
||||
"version": "0.0.95",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# multiauth
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
- jazz-react-auth-clerk@0.14.2
|
||||
|
||||
## 0.0.41
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multiauth",
|
||||
"private": true,
|
||||
"version": "0.0.41",
|
||||
"version": "0.0.43",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-inspector@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.122
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.122",
|
||||
"version": "0.0.124",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# organization
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.94
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.93
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.93",
|
||||
"version": "0.0.95",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-svelte@0.14.2
|
||||
|
||||
## 0.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "passkey-svelte",
|
||||
"version": "0.0.88",
|
||||
"version": "0.0.91",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# minimal-auth-passkey
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passkey",
|
||||
"private": true,
|
||||
"version": "0.0.98",
|
||||
"version": "0.0.100",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# passphrase
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passphrase",
|
||||
"private": true,
|
||||
"version": "0.0.95",
|
||||
"version": "0.0.97",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.121
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.120
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.119
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.119",
|
||||
"version": "0.0.121",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.219
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.218
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.217
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.217",
|
||||
"version": "0.0.219",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# reactions
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "reactions",
|
||||
"private": true,
|
||||
"version": "0.0.97",
|
||||
"version": "0.0.99",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# richtext-tiptap
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
- jazz-richtext-tiptap@0.1.11
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext-tiptap",
|
||||
"private": true,
|
||||
"version": "0.1.10",
|
||||
"version": "0.1.12",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# richtext
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
- jazz-richtext-prosemirror@0.1.22
|
||||
|
||||
## 0.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "richtext",
|
||||
"private": true,
|
||||
"version": "0.0.87",
|
||||
"version": "0.0.89",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# todo-vue
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
- jazz-vue@0.14.2
|
||||
|
||||
## 0.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "todo-vue",
|
||||
"version": "0.0.101",
|
||||
"version": "0.0.103",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.218
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.0.217
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.216
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.216",
|
||||
"version": "0.0.218",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# version-history
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-inspector@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "version-history",
|
||||
"private": true,
|
||||
"version": "0.0.95",
|
||||
"version": "0.0.97",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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...
|
||||
@@ -185,23 +186,293 @@ function PersonAndFirstPetName({ person }: {
|
||||
}
|
||||
```
|
||||
</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(),
|
||||
});
|
||||
|
||||
const Person = co.map({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
pets: co.list(Pet),
|
||||
});
|
||||
```
|
||||
```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>
|
||||
|
||||
...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>
|
||||
```svelte twoslash
|
||||
<script lang="ts" module>
|
||||
export type Props = {
|
||||
person: Loaded<typeof Person>; // [!code ++]
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Person } from './schema';
|
||||
|
||||
let props: Props = $props();
|
||||
</script>
|
||||
|
||||
|
||||
<div>
|
||||
{props.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 `CoState`, `load`, `subscribe`, etc.
|
||||
|
||||
<CodeGroup>
|
||||
```svelte twoslash
|
||||
<script lang="ts" module>
|
||||
export type Props = {
|
||||
person: 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, Loaded, 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: Loaded<typeof 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>
|
||||
|
||||
@@ -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,24 @@
|
||||
# jazz-auth-betterauth
|
||||
|
||||
## 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
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
- jazz-betterauth-client-plugin@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-auth-betterauth",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-auth-clerk
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
{
|
||||
"name": "jazz-auth-clerk",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:*",
|
||||
"jazz-browser": "workspace:*"
|
||||
"cojson": "workspace:0.14.1",
|
||||
"jazz-browser": "workspace:0.14.4",
|
||||
"jazz-tools": "workspace:0.14.4"
|
||||
},
|
||||
"scripts": {
|
||||
"format-and-lint": "biome check .",
|
||||
@@ -21,7 +19,6 @@
|
||||
"dev": " tsc --sourceMap --outDir dist --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# jazz-betterauth-client-plugin
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-betterauth-server-plugin@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-betterauth-client-plugin",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-betterauth-server-plugin
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-betterauth-server-plugin",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
{
|
||||
"name": "jazz-browser-media-images",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/image-blob-reduce": "^4.1.1",
|
||||
"image-blob-reduce": "^4.1.0",
|
||||
"jazz-browser": "workspace:*",
|
||||
"jazz-browser": "workspace:0.14.4",
|
||||
"jazz-tools": "workspace:0.14.4",
|
||||
"pica": "^9.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -21,7 +19,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/pica": "^9.0.4",
|
||||
"typescript": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
{
|
||||
"name": "jazz-browser",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"cojson": "workspace:*",
|
||||
"cojson-storage-indexeddb": "workspace:*",
|
||||
"cojson-transport-ws": "workspace:*"
|
||||
"cojson-transport-ws": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"fake-indexeddb": "^6.0.0",
|
||||
"typescript": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"scripts": {
|
||||
"format-and-lint": "biome check .",
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-auth-clerk@0.14.4
|
||||
- jazz-react-core@0.14.4
|
||||
- jazz-react-native-core@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-auth-clerk@0.14.2
|
||||
- jazz-react-core@0.14.2
|
||||
- jazz-react-native-core@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-expo",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
@@ -41,21 +41,20 @@
|
||||
"expo-sqlite": "15.2.9",
|
||||
"jazz-auth-clerk": "workspace:*",
|
||||
"jazz-react-core": "workspace:*",
|
||||
"jazz-react-native-core": "workspace:*"
|
||||
"jazz-react-native-core": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/netinfo": "*",
|
||||
"expo-secure-store": "*",
|
||||
"react-native": "*",
|
||||
"jazz-tools": "workspace:*"
|
||||
"react-native": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/netinfo": "11.4.1",
|
||||
"expo-secure-store": "~14.2.3",
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.76.7",
|
||||
"typescript": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"react-native": "0.79.2",
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-inspector-element
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-inspector@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-inspector@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-inspector-element",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "./dist/main.js",
|
||||
"types": "./dist/main.d.ts",
|
||||
@@ -17,19 +17,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"jazz-inspector": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"rollup-plugin-node-externals": "^8.0.0",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"vite": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-inspector
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-react-core@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-react-core@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-inspector",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "./dist/app.js",
|
||||
"types": "./dist/app.d.ts",
|
||||
@@ -19,11 +19,11 @@
|
||||
"clsx": "^2.0.0",
|
||||
"cojson": "workspace:*",
|
||||
"goober": "^2.1.16",
|
||||
"jazz-react-core": "workspace:*"
|
||||
"jazz-react-core": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"jazz-tools": "workspace:*"
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.12",
|
||||
@@ -31,7 +31,6 @@
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"rollup-plugin-node-externals": "^8.0.0",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"vite": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-autosub
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -5,18 +5,15 @@
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:*",
|
||||
"cojson-transport-ws": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"cojson-transport-ws": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jazz-run": "workspace:*",
|
||||
"typescript": "catalog:",
|
||||
"jazz-tools": "workspace:*"
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc --watch --sourceMap --outDir dist",
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# jazz-react-auth-betterauth
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-auth-betterauth@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
- jazz-betterauth-client-plugin@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-auth-betterauth@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
- jazz-betterauth-client-plugin@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-react-auth-betterauth",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.4",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.tsx",
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.14.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [011af55]
|
||||
- jazz-tools@0.14.4
|
||||
- jazz-auth-clerk@0.14.4
|
||||
- jazz-browser@0.14.4
|
||||
- jazz-react@0.14.4
|
||||
|
||||
## 0.14.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [3d1027f]
|
||||
- Updated dependencies [c240eed]
|
||||
- jazz-tools@0.14.2
|
||||
- jazz-auth-clerk@0.14.2
|
||||
- jazz-browser@0.14.2
|
||||
- jazz-react@0.14.2
|
||||
|
||||
## 0.14.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user