Compare commits

...

12 Commits

Author SHA1 Message Date
Guido D'Orsi
114898d8a9 Merge pull request #2643 from garden-co/changeset-release/main
Version Packages
2025-07-14 21:25:21 +02:00
github-actions[bot]
962213c712 Version Packages 2025-07-14 15:04:25 +00:00
Guido D'Orsi
427df8fcbb Merge pull request #2644 from garden-co/chore/lefthook-autoinstall
chore: auto-install lefthook using `postinstall` script
2025-07-14 17:02:16 +02:00
Matteo Manchi
c40aad55dc chore: auto-install lefthook using postinstall script 2025-07-14 14:38:48 +02:00
Guido D'Orsi
dfca5926de Merge pull request #2640 from garden-co/GCO-621-Adds-documentation-for-descriminatedUnion-workaround
Closes GCO-621 - Add documentation for discriminated union workaround
2025-07-14 12:50:16 +02:00
Guido D'Orsi
9815ec61f0 feat: export the z.ZodDiscriminatedUnion type and improve the recursive types docs 2025-07-14 11:14:59 +02:00
Guido D'Orsi
fca60d213e Merge pull request #2641 from garden-co/GCO-655-user-id-on-unauthorized
Expose current Account id in unauthorized error message
2025-07-14 11:12:49 +02:00
Matteo Manchi
b4fdab475b chore: add changeset 2025-07-14 11:03:59 +02:00
Matteo Manchi
958c122c36 chore(jazz-tools/tools): expose current user id in unauthorized error message 2025-07-12 21:01:44 +02:00
Margaret Culotta
5842838371 Add examples but remove twoslash because of limitations in how Twoslash parses advanced TypeScript types 2025-07-11 14:36:07 -05:00
Margaret Culotta
acd908fbc2 add docs for recursive connection 2025-07-11 10:41:50 -05:00
Margaret Culotta
4e61d1d191 add docs for recursive connections 2025-07-11 10:37:31 -05:00
32 changed files with 180 additions and 30 deletions

View File

@@ -1,5 +1,13 @@
# passkey-svelte
## 0.0.99
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
## 0.0.98
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-svelte",
"version": "0.0.98",
"version": "0.0.99",
"type": "module",
"private": true,
"scripts": {

View File

@@ -6,7 +6,7 @@ export const metadata = {
# Connecting CoValues with direct linking
CoValues can form relationships with each other by **linking directly to other CoValues**. This creates a powerful connection where one CoValue can point to the unique identity of another.
Instead of embedding all of the details of one coValue directly within another, you use its Jazz-Tools schema as the field type. This allows multiple CoValues to point to the same piece of data effortlessly.
Instead of embedding all the details of one CoValue directly within another, you use its Jazz-Tools schema as the field type. This allows multiple CoValues to point to the same piece of data effortlessly.
<CodeGroup>
```ts twoslash
@@ -50,3 +50,51 @@ export type User = co.loaded<typeof User>;
This direct linking approach offers a single source of truth. When you update a referenced CoValue, all other CoValues that point to it are automatically updated, ensuring data consistency across your application.
By connecting CoValues through these direct references, you can build robust and collaborative applications where data is consistent, efficient to manage, and relationships are clearly defined. The ability to link different CoValue types to the same underlying data is fundamental to building complex applications with Jazz.
## Recursive references with DiscriminatedUnion
In advanced schemas, you may want a CoValue that recursively references itself. For example, a `ReferenceItem` that contains a list of other items like `NoteItem` or `AttachmentItem`. This is common in tree-like structures such as threaded comments or nested project outlines.
You can model this with a Zod `z.discriminatedUnion`, but TypeScripts type inference doesn't handle recursive unions well without a workaround.
Heres how to structure your schema to avoid circular reference errors.
### Use this pattern for recursive discriminated unions
<CodeGroup>
```ts twoslash
import { CoListSchema, co, z } from "jazz-tools";
// Recursive item modeling pattern using discriminated unions
// First, define the non-recursive types
export const NoteItem = co.map({
type: z.literal("note"),
internal: z.boolean(),
content: co.plainText(),
});
export const AttachmentItem = co.map({
type: z.literal("attachment"),
internal: z.boolean(),
content: co.fileStream(),
});
export const ReferenceItem = co.map({
type: z.literal("reference"),
internal: z.boolean(),
content: z.string(),
// Workaround: declare the field type using CoListSchema and ZodDiscriminatedUnion so TS can safely recurse
get children(): CoListSchema<z.ZodDiscriminatedUnion<[typeof NoteItem, typeof AttachmentItem, typeof ReferenceItem]>> {
return ProjectContextItemList;
},
});
// Create the recursive union
export const ProjectContextItem = z.discriminatedUnion("type", [NoteItem, AttachmentItem, ReferenceItem]);
// Final list of recursive types
export const ProjectContextItemList = co.list(ProjectContextItem);
```
</CodeGroup>
Even though this seems like a shortcut, TypeScript and Zod can't resolve the circular reference this way. Always define the discriminated union before introducing recursive links.

View File

@@ -39,6 +39,7 @@
"changeset-version": "changeset version && pnpm i --no-frozen-lockfile",
"release": "turbo run build --filter='./packages/*' && pnpm changeset publish && git push --follow-tags",
"clean": "rm -rf ./packages/*/dist && rm -rf ./packages/*/node_modules && rm -rf ./examples/*/node_modules && rm -rf ./examples/*/dist",
"postinstall": "lefthook install",
"check-catalog-deps": "node scripts/check-catalog-deps.js"
},
"version": "0.0.0",

View File

@@ -1,5 +1,11 @@
# cojson-storage-indexeddb
## 0.15.10
### Patch Changes
- cojson@0.15.10
## 0.15.9
### Patch Changes

View File

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

View File

@@ -1,5 +1,11 @@
# cojson-storage-sqlite
## 0.15.10
### Patch Changes
- cojson@0.15.10
## 0.15.9
### Patch Changes

View File

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

View File

@@ -1,5 +1,11 @@
# cojson-transport-nodejs-ws
## 0.15.10
### Patch Changes
- cojson@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "cojson-transport-ws",
"type": "module",
"version": "0.15.9",
"version": "0.15.10",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",

View File

@@ -1,5 +1,7 @@
# cojson
## 0.15.10
## 0.15.9
### Patch Changes

View File

@@ -25,7 +25,7 @@
},
"type": "module",
"license": "MIT",
"version": "0.15.9",
"version": "0.15.10",
"devDependencies": {
"@opentelemetry/sdk-metrics": "^2.0.0",
"libsql": "^0.5.13",

View File

@@ -1,5 +1,15 @@
# jazz-auth-betterauth
## 0.15.10
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
- jazz-betterauth-client-plugin@0.15.10
- cojson@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-auth-betterauth",
"version": "0.15.9",
"version": "0.15.10",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,11 @@
# jazz-betterauth-client-plugin
## 0.15.10
### Patch Changes
- jazz-betterauth-server-plugin@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-betterauth-client-plugin",
"version": "0.15.9",
"version": "0.15.10",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,14 @@
# jazz-betterauth-server-plugin
## 0.15.10
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
- cojson@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-betterauth-server-plugin",
"version": "0.15.9",
"version": "0.15.10",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,16 @@
# jazz-react-auth-betterauth
## 0.15.10
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
- jazz-auth-betterauth@0.15.10
- jazz-betterauth-client-plugin@0.15.10
- cojson@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-auth-betterauth",
"version": "0.15.9",
"version": "0.15.10",
"type": "module",
"main": "dist/index.js",
"types": "src/index.tsx",

View File

@@ -1,5 +1,16 @@
# jazz-run
## 0.15.10
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
- cojson@0.15.10
- cojson-storage-sqlite@0.15.10
- cojson-transport-ws@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -3,7 +3,7 @@
"bin": "./dist/index.js",
"type": "module",
"license": "MIT",
"version": "0.15.9",
"version": "0.15.10",
"exports": {
"./startSyncServer": {
"import": "./dist/startSyncServer.js",
@@ -28,11 +28,11 @@
"@effect/printer-ansi": "^0.34.5",
"@effect/schema": "^0.71.1",
"@effect/typeclass": "^0.25.5",
"cojson": "workspace:0.15.9",
"cojson-storage-sqlite": "workspace:0.15.9",
"cojson-transport-ws": "workspace:0.15.9",
"cojson": "workspace:0.15.10",
"cojson-storage-sqlite": "workspace:0.15.10",
"cojson-transport-ws": "workspace:0.15.10",
"effect": "^3.6.5",
"jazz-tools": "workspace:0.15.9",
"jazz-tools": "workspace:0.15.10",
"ws": "^8.14.2"
},
"devDependencies": {

View File

@@ -1,5 +1,15 @@
# jazz-tools
## 0.15.10
### Patch Changes
- 9815ec6: Export the z.ZodDiscriminatedUnion type
- b4fdab4: Exposed the current Account's ID in unauthorized error message
- cojson@0.15.10
- cojson-storage-indexeddb@0.15.10
- cojson-transport-ws@0.15.10
## 0.15.9
### Patch Changes

View File

@@ -139,7 +139,7 @@
},
"type": "module",
"license": "MIT",
"version": "0.15.9",
"version": "0.15.10",
"dependencies": {
"@manuscripts/prosemirror-recreate-steps": "^0.1.4",
"@scure/base": "1.2.1",

View File

@@ -39,5 +39,6 @@ export {
type ZodDefault,
type ZodCatch,
type output as infer,
type ZodDiscriminatedUnion,
z,
} from "zod/v4";

View File

@@ -126,8 +126,7 @@ export class SubscriptionScope<D extends CoValue> {
new JazzError(this.id, "unauthorized", [
{
code: "unauthorized",
message:
"The current user is not authorized to access this value",
message: `The current user (${this.node.getCurrentAgent().id}) is not authorized to access this value`,
params: {
id: this.id,
},

View File

@@ -409,7 +409,7 @@ describe("Deep loading with unauthorized account", async () => {
expect(mapOnAlice).toBe(null);
expect(errorSpy).toHaveBeenCalledWith(
`The current user is not authorized to access this value from ${map.id}`,
`The current user (${alice.id}) is not authorized to access this value from ${map.id}`,
);
errorSpy.mockReset();
@@ -431,7 +431,7 @@ describe("Deep loading with unauthorized account", async () => {
expect(mapWithListOnAlice).toBe(null);
expect(errorSpy).toHaveBeenCalledWith(
`The current user is not authorized to access this value from ${map.id} on path list`,
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list`,
);
errorSpy.mockReset();
@@ -465,7 +465,7 @@ describe("Deep loading with unauthorized account", async () => {
expect(mapOnAlice).toBe(null);
expect(errorSpy).toHaveBeenCalledWith(
`The current user is not authorized to access this value from ${map.id} on path list.0`,
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list.0`,
);
errorSpy.mockReset();
@@ -492,7 +492,7 @@ describe("Deep loading with unauthorized account", async () => {
expect(mapOnAlice?.optionalRef?.value).toBe(undefined);
expect(errorSpy).toHaveBeenCalledWith(
`The current user is not authorized to access this value from ${map.id} on path optionalRef`,
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path optionalRef`,
);
errorSpy.mockReset();
@@ -551,7 +551,7 @@ describe("Deep loading with unauthorized account", async () => {
expect(mapOnAlice).toBe(null);
expect(errorSpy).toHaveBeenCalledWith(
`The current user is not authorized to access this value from ${map.id} on path list.0.stream`,
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list.0.stream`,
);
errorSpy.mockReset();
@@ -587,7 +587,7 @@ describe("Deep loading with unauthorized account", async () => {
expect(mapOnAlice).toBe(null);
expect(errorSpy).toHaveBeenCalledWith(
`The current user is not authorized to access this value from ${map.id} on path list.0.stream.${value.id}`,
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list.0.stream.${value.id}`,
);
errorSpy.mockReset();

8
pnpm-lock.yaml generated
View File

@@ -1772,19 +1772,19 @@ importers:
specifier: ^0.25.5
version: 0.25.8(effect@3.11.9)
cojson:
specifier: workspace:0.15.9
specifier: workspace:0.15.10
version: link:../cojson
cojson-storage-sqlite:
specifier: workspace:0.15.9
specifier: workspace:0.15.10
version: link:../cojson-storage-sqlite
cojson-transport-ws:
specifier: workspace:0.15.9
specifier: workspace:0.15.10
version: link:../cojson-transport-ws
effect:
specifier: ^3.6.5
version: 3.11.9
jazz-tools:
specifier: workspace:0.15.9
specifier: workspace:0.15.10
version: link:../jazz-tools
ws:
specifier: ^8.14.2

View File

@@ -1,5 +1,13 @@
# jazz-react-tailwind-starter
## 0.0.130
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
## 0.0.129
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-react-passkey-auth-starter",
"private": true,
"version": "0.0.129",
"version": "0.0.130",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# svelte-passkey-auth
## 0.0.104
### Patch Changes
- Updated dependencies [9815ec6]
- Updated dependencies [b4fdab4]
- jazz-tools@0.15.10
## 0.0.103
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "svelte-passkey-auth",
"version": "0.0.103",
"version": "0.0.104",
"type": "module",
"private": true,
"scripts": {