Subscriptions & Deep Loading
Jazz's Collaborative Values (such as CoMaps or CoLists) work like reactive state. By subscribing to them, you can react to both local and remote updates. This is the main way to consume data in your application.
Subscriptions also take care of loading CoValues that are not yet loaded locally and can do so deeply — by resolving nested CoValues. To make use of this, we'll show you how to specify the depth of data you need with resolve queries.
With each update you can also handle loading states and inaccessible CoValues.
Manual subscriptions
You can subscribe to a CoValue from anywhere in your code (if you have its ID) by using CoValue.subscribe()
.
const
Task =
const Task: CoMapSchema<{ title: z.z.ZodString; description: z.z.ZodString; status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">; assignedTo: z.ZodOptional<z.z.ZodString>; }>
import co
co.map({
map<{ title: z.z.ZodString; description: z.z.ZodString; status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">; assignedTo: z.ZodOptional<z.z.ZodString>; }>(shape: { title: z.z.ZodString; description: z.z.ZodString; status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">; assignedTo: z.ZodOptional<z.z.ZodString>; }): CoMapSchema<...> export map
title: z.z.ZodString
title:import z
z.string(),
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
description: z.z.ZodString
description:import z
z.string(),
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">
status:import z
z.literal(["todo", "in-progress", "completed"]),
literal<["todo", "in-progress", "completed"]>(value: ["todo", "in-progress", "completed"], params?: string | z.z.core.$ZodLiteralParams): z.z.ZodLiteral<"todo" | "in-progress" | "completed"> (+1 overload) export literal
assignedTo: z.ZodOptional<z.z.ZodString>
assignedTo:import z
z.optional(
optional<z.z.ZodString>(innerType: z.z.ZodString): z.ZodOptional<z.z.ZodString> export optional
import z
z.string()), }); // ... // Subscribe to a Task by ID const
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
const unsubscribe: () => void
unsubscribe =Task.
const Task: CoMapSchema<{ title: z.z.ZodString; description: z.z.ZodString; status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">; assignedTo: z.ZodOptional<z.z.ZodString>; }>
subscribe(
subscribe<true>(id: string, options: SubscribeListenerOptions<{ title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap, true>, listener: (value: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap, unsubscribe: () => void) => void): () => void
const taskId: "co_123"
taskId, {}, (updatedTask) => {
updatedTask: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log("Task updated:",updatedTask.
updatedTask: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
title: string
title);var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log("New status:",updatedTask.
updatedTask: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
status: "todo" | "in-progress" | "completed"
status); }); // Clean up when you're doneconst unsubscribe: () => void
unsubscribe();
If you already have a CoValue instance, you can subscribe to it by calling its subscribe
method.
const
task =
const task: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
Task.
const Task: CoMapSchema<{ title: z.z.ZodString; description: z.z.ZodString; status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">; assignedTo: z.ZodOptional<z.z.ZodString>; }>
create({
create: (init: { assignedTo?: string | undefined; title: string; description: string; status: NonNullable<"todo" | "in-progress" | "completed">; }, options?: Account | Group | { ...; } | undefined) => { ...; } & CoMap
title: string
title: "Cut the grass", ...const otherProps: any
otherProps }); constconst unsubscribe: () => void
unsubscribe =task.
const task: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
CoMap.subscribe<{ title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap, true>(this: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap, listener: (value: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap, unsubscribe: () => void) => void): () => void (+1 overload)
Given an already loaded `CoMap`, subscribe to updates to the `CoMap` and ensure that the specified fields are loaded to the specified depth. Works like `CoMap.subscribe()`, but you don't need to pass the ID or the account to load as again. Returns an unsubscribe function that you should call when you no longer need updates.subscribe((updatedTask) => {
updatedTask: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log("Task updated:",updatedTask.
updatedTask: { title: string; description: string; status: "todo" | "in-progress" | "completed"; assignedTo: string | undefined; } & CoMap
title: string
title); }); // Clean up when you're doneconst unsubscribe: () => void
unsubscribe();
Loading States and Permission Checking
When subscribing to or loading a CoValue, you need to handle three possible states:
undefined
: The initial loading state, indicating the value is being fetchednull
: The CoValue was not found or is not accessible (e.g., due to permissions)Value
: The successfully loaded CoValue instance
This allows you to handle loading, error, and success states in your application:
Task.
const Task: CoMapSchema<{ title: z.z.ZodString; }>
subscribe(
subscribe<true>(id: string, options: SubscribeListenerOptions<{ title: string; } & CoMap, true>, listener: (value: { title: string; } & CoMap, unsubscribe: () => void) => void): () => void
const taskId: "co_123"
taskId, {}, (task:
task: { title: string; } & CoMap
import co
co.loaded<typeof
type loaded<T extends CoValueClass | AnyCoSchema, R extends ResolveQuery<T> = true> = R extends boolean | undefined ? NonNullable<InstanceOfSchemaCoValuesNullable<T>> : [NonNullable<InstanceOfSchemaCoValuesNullable<T>>] extends [...] ? Exclude<...> extends CoValue ? R extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<... export loaded
Task>) => { if (
const Task: CoMapSchema<{ title: z.z.ZodString; }>
task ===
task: { title: string; } & CoMap
var undefined
undefined) {var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log("Task is loading..."); } else if (task === null) {
task: { title: string; } & CoMap
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log("Task not found or not accessible"); } else {var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log("Task loaded:",task.
task: { title: string; } & CoMap
title: string
title); } });
Deep Loading
When working with related CoValues (like tasks in a project), you often need to load not just the top-level object but also its nested references. This is especially important when working with CoMaps that contain references to other CoValues or with CoLists that contain multiple items. Jazz provides a flexible mechanism for specifying exactly how much of the object graph to load.
Resolve queries
Resolve queries let you declare exactly which references to load and how deep to go using the resolve
property:
const
TeamMember =
const TeamMember: CoMapSchema<{ name: z.z.ZodString; }>
import co
co.map({
map<{ name: z.z.ZodString; }>(shape: { name: z.z.ZodString; }): CoMapSchema<{ name: z.z.ZodString; }> export map
name: z.z.ZodString
name:import z
z.string(), }); const
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
Task =
const Task: CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>
import co
co.map({
map<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>(shape: { title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }): CoMapSchema<...> export map
title: z.z.ZodString
title:import z
z.string(),
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
assignee:
assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>
import z
z.optional(
optional<CoMapSchema<{ name: z.z.ZodString; }>>(innerType: CoMapSchema<{ name: z.z.ZodString; }>): z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>> export optional
TeamMember), get
const TeamMember: CoMapSchema<{ name: z.z.ZodString; }>
subtasks():
subtasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>
CoListSchema<typeof
type CoListSchema<T extends z.core.$ZodType> = z.z.core.$ZodArray<T> & { collaborative: true; create: (items: CoListInit<T>, options?: { owner: Account | Group; } | Account | Group) => CoList<InstanceOrPrimitiveOfSchema<T>>; load<const R extends RefsToResolve<CoListInstanceCoValuesNullable<T>> = true>(id: string, options?: { resolve?: RefsToResolveStrict<CoListInstanceCoValuesNullable<T>, R>; loadAs?: Account | AnonymousJazzAgent; }): Promise<Resolved<CoListInstanceCoValuesNullable<T>, R> | null>; subscribe<const R extends RefsToResolve<CoListInstanceCoValuesNullable<T>> = true>(id: string, options: SubscribeListenerOptions<CoListInstanceCoValuesNullable<T>, R>, listener: (value: Resolved<CoListInstanceCoValuesNullable<T>, R>, unsubscribe: () => void) => void): () => void; withHelpers<S extends z.z.core.$ZodType, T extends object>(this: S, helpers: (Self: S) => T): WithHelpers<S, T>; }
Task> { return
const Task: CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>
import co
co.list(
list<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>(element: CoMapSchema<...>): CoListSchema<...> export list
Task) }, }); const
const Task: CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>
Project =
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
import co
co.map({
map<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>(shape: { name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }): CoMapSchema<...> export map
name: z.z.ZodString
name:import z
z.string(),
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
tasks:
tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>
import co
co.list(
list<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>(element: CoMapSchema<...>): CoListSchema<...> export list
Task),
const Task: CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>
owner:
owner: CoMapSchema<{ name: z.z.ZodString; }>
TeamMember, }); // Load just the project, not its references const
const TeamMember: CoMapSchema<{ name: z.z.ZodString; }>
project = await
const project: ({ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<true>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const projectId: "co_123"
projectId); if (!project) { throw new
const project: ({ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Error("Project not found or not accessible"); } // string - primitive fields are always loaded
var Error: ErrorConstructor new (message?: string, options?: ErrorOptions) => Error (+1 overload)
project.
const project: { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
name: string
name; // undefined | null | ListOfTasks - non-requested references might not be loaded, or inaccessibleproject.
const project: { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks; // Load the project and shallowly load its list of tasks const
tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null
projectWithTasksShallow = await
const projectWithTasksShallow: ({ tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<{ tasks: true; }>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const projectId: "co_123"
projectId, {resolve: {
resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined
tasks: true } }); if (!
tasks?: RefsToResolve<CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>, 10, [0]> | undefined
projectWithTasksShallow) { throw new
const projectWithTasksShallow: ({ tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Error("Project or required references not found or not accessible"); } // ListOfTasks - shallowly loaded
var Error: ErrorConstructor new (message?: string, options?: ErrorOptions) => Error (+1 overload)
projectWithTasksShallow.
const projectWithTasksShallow: { tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks; // number - length of the list
tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
projectWithTasksShallow.
const projectWithTasksShallow: { tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks.
tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.length; // undefined | null | Task - items might not be loaded, or inaccessibleprojectWithTasksShallow.
const projectWithTasksShallow: { tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks[0]; // Load the project and its tasks const
tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
projectWithTasks = await
const projectWithTasks: ({ tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<{ tasks: { $each: true; }; }>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const projectId: "co_123"
projectId, {resolve: {
resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined
tasks: {
tasks?: RefsToResolve<CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>, 10, [0]> | undefined
$each: true } } }); if (!
$each: RefsToResolve<{ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, [0, 0]>
projectWithTasks) { throw new
const projectWithTasks: ({ tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Error("Project or required references not found or not accessible"); } // ListOfTasks - fully loaded
var Error: ErrorConstructor new (message?: string, options?: ErrorOptions) => Error (+1 overload)
projectWithTasks.
const projectWithTasks: { tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks; // Task - fully loaded
tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
projectWithTasks.
const projectWithTasks: { tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks[0]; // string - primitive fields are always loaded
tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
projectWithTasks.
const projectWithTasks: { tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks[0].
tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
title: string
title; // undefined | null | ListOfTasks - subtasks might not be loaded, or inaccessibleprojectWithTasks.
const projectWithTasks: { tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks[0].
tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
subtasks; // Load the project, its tasks, and their subtasks const
subtasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null
projectDeep = await
const projectDeep: ({ tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap & { subtasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; assignee: ({ name: string; } & CoMap) | undefined; })[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<{ tasks: { $each: { subtasks: { $each: true; }; assignee: true; }; }; }>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const projectId: "co_123"
projectId, {resolve: {
resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined
tasks: {
tasks?: RefsToResolve<CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>, 10, [0]> | undefined
$each: {
$each: RefsToResolve<{ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, [0, 0]>
subtasks: {
subtasks?: RefsToResolve<CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>, 10, [0, 0, 0]> | undefined
$each: true },
$each: RefsToResolve<{ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, [0, 0, 0, 0]>
assignee: true } } } }); if (!
assignee?: RefsToResolve<{ name: string; } & CoMap, 10, [0, 0, 0]> | undefined
projectDeep) { throw new
const projectDeep: ({ tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap & { subtasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; assignee: ({ name: string; } & CoMap) | undefined; })[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Error("Project or required references not found or not accessible"); } // string - primitive fields are always loaded
var Error: ErrorConstructor new (message?: string, options?: ErrorOptions) => Error (+1 overload)
projectDeep.
const projectDeep: { tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap & { subtasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; assignee: ({ name: string; } & CoMap) | undefined; })[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks[0].
tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap & { subtasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; assignee: ({ name: string; } & CoMap) | undefined; })[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
subtasks[0].
subtasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> & ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[]
title: string
title; // undefined | null | TeamMember - since assignee is optional: // TeamMember - set and definitely loaded // null - set but unavailable/inaccessible // undefined - not set, or loading (in case of subscription)projectDeep.
const projectDeep: { tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap & { subtasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; assignee: ({ name: string; } & CoMap) | undefined; })[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap
tasks[0].
tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap & { subtasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; assignee: ({ name: string; } & CoMap) | undefined; })[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
assignee;
assignee: ({ name: string; } & CoMap) | undefined
The resolve query defines which parts of the graph you want to load, making it intuitive to express complex loading patterns.
Loading states and permissions
When loading data with references, the load operation will fail if one of the references is unavailable or if the user doesn't have read access to it. Let's explore what happens in various scenarios:
Resolved References
When a user tries to load a reference they don't have access to:
// If assignee is not accessible to the user: const
task = await
const task: ({ assignee: ({ name: string; } & CoMap) | undefined; } & { title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null
Task.
const Task: CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>
load(
load<{ assignee: true; }>(id: string, options?: { resolve?: RefsToResolve<{ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const taskId: "co_123"
taskId, {resolve: {
resolve?: RefsToResolve<{ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, []> | undefined
assignee: true } });
assignee?: RefsToResolve<{ name: string; } & CoMap, 10, [0]> | undefined
task // => null
const task: ({ assignee: ({ name: string; } & CoMap) | undefined; } & { title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null
The load operation will fail and return null
if any requested reference is inaccessible. This maintains data consistency by ensuring all requested references are available before returning the object.
The behavior is the same for optional and required references.
List References
When a list contains references to items the user can't access:
// If any item in the list is not accessible: const
project = await
const project: ({ tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { ...; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<{ tasks: { $each: true; }; }>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const projectId: "co_123"
projectId, {resolve: {
resolve?: RefsToResolve<{ ...; } & CoMap, 10, []> | undefined
tasks: {
tasks?: RefsToResolve<CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>, 10, [0]> | undefined
$each: true } } });
$each: RefsToResolve<{ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, [0, 0]>
project // => null
const project: ({ tasks: ({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { ...; } & CoMap) | null
If any item in a list is inaccessible to the user, the entire load operation will fail and return null
. This is because lists expect all their items to be accessible - a partially loaded list could lead to data inconsistencies.
Reading a non-resolved inaccessible reference
When trying to load an object with an inaccessible reference without directly resolving it:
const
project = await
const project: ({ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; assignee: z.ZodOptional<CoMapSchema<{ name: z.z.ZodString; }>>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<true>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
const projectId: "co_123"
projectId, {resolve: true });
resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap, 10, []> | undefined
project // => Project // The user doesn't have access to the owner
const project: ({ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
project?.
const project: ({ name: string; tasks: CoList<({ title: string; assignee: ({ name: string; } & CoMap) | null | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ name: string; } & CoMap) | null; } & CoMap) | null
owner // => always null
owner: ({ name: string; } & CoMap) | null | undefined
The load operation will succeed and return the object, but the inaccessible reference will always be null
.
Deep loading lists with shared items
When loading a list with shared items, you can use the $onError
option to safely load the list skipping any inaccessible items.
This is especially useful when in your app access to these items might be revoked.
This way the inaccessible items are replaced with null
in the returned list.
const
source =
const source: CoList<{ name: string; } & CoMap>
import co
co.list(
list<CoMapSchema<{ name: z.z.ZodString; }>>(element: CoMapSchema<{ name: z.z.ZodString; }>): CoListSchema<CoMapSchema<{ name: z.z.ZodString; }>> export list
Person).
const Person: CoMapSchema<{ name: z.z.ZodString; }>
create( [
create: (items: CoListInit<CoMapSchema<{ name: z.z.ZodString; }>>, options?: { owner: Account | Group; } | Account | Group) => CoList<...>
Person.
const Person: CoMapSchema<{ name: z.z.ZodString; }>
create( {
create: (init: { name: string; }, options?: Account | Group | { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | undefined) => { ...; } & CoMap
name: string
name: "Jane", },const privateGroup: Group
privateGroup, // We don't have access to Jane ),Person.
const Person: CoMapSchema<{ name: z.z.ZodString; }>
create( {
create: (init: { name: string; }, options?: Account | Group | { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | undefined) => { ...; } & CoMap
name: string
name: "Alice", },const publicGroup: Group
publicGroup, // We have access to Alice ), ],const publicGroup: Group
publicGroup, ); constfriends = await
const friends: ((({ name: string; } & CoMap & { $onError: never; }) | null)[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; }>>) | null
import co
co.list(
list<CoMapSchema<{ name: z.z.ZodString; }>>(element: CoMapSchema<{ name: z.z.ZodString; }>): CoListSchema<CoMapSchema<{ name: z.z.ZodString; }>> export list
Person).
const Person: CoMapSchema<{ name: z.z.ZodString; }>
load(
load<{ $each: { $onError: null; }; }>(id: string, options?: { resolve?: RefsToResolve<CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; }>>, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
source.
const source: CoList<{ name: string; } & CoMap>
CoList<{ name: string; } & CoMap>.id: string
The ID of this `CoList`id, {resolve: {
resolve?: RefsToResolve<CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; }>>, 10, []> | undefined
$each: {
$each: RefsToResolve<{ name: string; } & CoMap, 10, [0]>
$onError?: null | undefined
$onError: null } },loadAs?: Account | AnonymousJazzAgent | undefined
loadAs:me, }); // Thanks to $onError catching the errors, the list is loaded // because we have access to friends
const me: Account | ({ [x: string]: any; } & Account)
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(friends); // Person[] // Jane is null because we lack access rights // and we have used $onError to catch the error on the list items
const friends: ((({ name: string; } & CoMap & { $onError: never; }) | null)[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; }>>) | null
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(friends?.[0]); // null // Alice is not null because we have access // the type is nullable because we have used $onError
const friends: ((({ name: string; } & CoMap & { $onError: never; }) | null)[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; }>>) | null
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(friends?.[1]); // Person
const friends: ((({ name: string; } & CoMap & { $onError: never; }) | null)[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; }>>) | null
The $onError
works as a "catch" clause option to block any error in the resolved children.
const
source =
const source: CoList<{ name: string; dog: { name: string; } & CoMap; } & CoMap>
import co
co.list(
list<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>(element: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>): CoListSchema<...> export list
Person).
const Person: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>
create( [
create: (items: CoListInit<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>, options?: { owner: Account | Group; } | Account | Group) => CoList<...>
Person.
const Person: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>
create( {
create: (init: { name: string; dog: { name: string; } & CoMap; }, options?: Account | Group | { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | undefined) => { ...; } & CoMap
name: string
name: "Jane",dog:
dog: { name: string; } & CoMap
Dog.
const Dog: CoMapSchema<{ name: z.z.ZodString; }>
create( {
create: (init: { name: string; }, options?: Account | Group | { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | undefined) => { ...; } & CoMap
name: string
name: "Rex" },const privateGroup: Group
privateGroup, ), // We don't have access to Rex },const publicGroup: Group
publicGroup, ), ],const publicGroup: Group
publicGroup, ); constfriends = await
const friends: ((({ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap & { dog: { name: string; } & CoMap; $onError: never; }) | null)[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>) | null
import co
co.list(
list<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>(element: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>): CoListSchema<...> export list
Person).
const Person: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>
load(
load<{ $each: { dog: true; $onError: null; }; }>(id: string, options?: { resolve?: RefsToResolve<CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
source.
const source: CoList<{ name: string; dog: { name: string; } & CoMap; } & CoMap>
CoList<{ name: string; dog: { name: string; } & CoMap; } & CoMap>.id: string
The ID of this `CoList`id, {resolve: {
resolve?: RefsToResolve<CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>, 10, []> | undefined
$each: {
$each: RefsToResolve<{ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap, 10, [0]>
dog: true,
dog?: RefsToResolve<{ name: string; } & CoMap, 10, [0, 0]> | undefined
$onError?: null | undefined
$onError: null } },loadAs?: Account | AnonymousJazzAgent | undefined
loadAs:me, }); // Jane is null because we don't have access to Rex // and we have used $onError to catch the error on the list items
const me: Account | ({ [x: string]: any; } & Account)
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(friends?.[0]); // null
const friends: ((({ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap & { dog: { name: string; } & CoMap; $onError: never; }) | null)[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>) | null
We can actually use $onError
everywhere in the resolve query, so we can use it to catch the error on dog:
const
friends = await
const friends: (({ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap & { dog: ({ $onError: never; } & { name: string; } & CoMap) | null; })[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<...>; }>>) | null
import co
co.list(
list<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>(element: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>): CoListSchema<...> export list
Person).
const Person: CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<...>; }>
load(
load<{ $each: { dog: { $onError: null; }; }; }>(id: string, options?: { resolve?: RefsToResolve<CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<{ name: z.z.ZodString; }>; }>>, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
source.
const source: CoList<{ name: string; dog: { name: string; } & CoMap; } & CoMap>
CoList<{ name: string; dog: { name: string; } & CoMap; } & CoMap>.id: string
The ID of this `CoList`id, {resolve: {
resolve?: RefsToResolve<CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<...>; }>>, 10, []> | undefined
$each: {
$each: RefsToResolve<{ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap, 10, [0]>
dog: {
dog?: RefsToResolve<{ name: string; } & CoMap, 10, [0, 0]> | undefined
$onError?: null | undefined
$onError: null } } },loadAs?: Account | AnonymousJazzAgent | undefined
loadAs:me, }); // Jane now is not-nullable at type level because // we have moved $onError down to the dog field // // This also means that if we don't have access to Jane // the entire friends list will be null
const me: Account | ({ [x: string]: any; } & Account)
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(friends?.[0]); // => Person // Jane's dog is null because we don't have access to Rex // and we have used $onError to catch the error
const friends: (({ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap & { dog: ({ $onError: never; } & { name: string; } & CoMap) | null; })[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<...>; }>>) | null
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(friends?.[0]?.
const friends: (({ name: string; dog: ({ name: string; } & CoMap) | null; } & CoMap & { dog: ({ $onError: never; } & { name: string; } & CoMap) | null; })[] & CoListInstanceCoValuesNullable<CoMapSchema<{ name: z.z.ZodString; dog: CoMapSchema<...>; }>>) | null
dog); // => null
dog: ({ name: string; } & CoMap & { $onError: never; }) | null | undefined
Type Safety with co.loaded
Type
Jazz provides the co.loaded
type to help you define and enforce the structure of deeply loaded data in your application. This makes it easier to ensure that components receive the data they expect with proper TypeScript validation.
The co.loaded
type is especially useful when passing data between components, as it guarantees that all necessary nested data has been loaded:
Using the co.loaded
type helps catch errors at compile time rather than runtime, ensuring that your components and functions receive data with the proper resolution depth. This is especially useful for larger applications where data is passed between many components.
Ensuring Data is Loaded
Sometimes you need to make sure data is loaded before proceeding with an operation. The ensureLoaded
method lets you guarantee that a CoValue and its referenced data are loaded to a specific depth:
async function
function completeAllTasks(projectId: string): Promise<void>
completeAllTasks(projectId: string
projectId: string) { // Ensure the project is loaded constproject = await
const project: ({ name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap) | null
Project.
const Project: CoMapSchema<{ name: z.z.ZodString; tasks: CoListSchema<CoMapSchema<{ title: z.z.ZodString; status: z.z.ZodLiteral<"todo" | "in-progress" | "completed">; assignee: z.ZodOptional<z.z.ZodString>; readonly subtasks: CoListSchema<typeof Task>; }>>; owner: CoMapSchema<...>; }>
load(
load<true>(id: string, options?: { resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap, 10, []> | undefined; loadAs?: Account | AnonymousJazzAgent; } | undefined): Promise<...>
projectId: string
projectId, {resolve: true }); if (!
resolve?: RefsToResolve<{ name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap, 10, []> | undefined
project) return; // Ensure tasks are loaded const
const project: ({ name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap) | null
loadedProject = await
const loadedProject: { tasks: ({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap
project.
const project: { name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap
CoMap.ensureLoaded<{ name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap, { ...; }>(this: { name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap, options: { ...; }): Promise<...>
Given an already loaded `CoMap`, ensure that the specified fields are loaded to the specified depth. Works like `CoMap.load()`, but you don't need to pass the ID or the account to load as again.ensureLoaded({resolve: {
resolve: RefsToResolve<{ name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap, 10, []>
tasks: {
tasks?: RefsToResolve<CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>, 10, [...]> | undefined
$each: true, }, }, }); // Now we can safely access and modify tasks
$each: RefsToResolve<{ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, 10, [0, 0]>
loadedProject.
const loadedProject: { tasks: ({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>; } & { name: string; tasks: CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null> | null; owner: ({ ...; } & CoMap) | null; } & CoMap
tasks.
tasks: ({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[] & CoList<({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap) | null>
Array<T>.forEach(callbackfn: (value: { title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap, index: number, array: ({ title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap)[]) => void, thisArg?: any): void (+1 overload)
Performs the specified action for each element in an array.forEach((task) => {
task: { title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap
task.
task: { title: string; status: "todo" | "in-progress" | "completed"; assignee: string | undefined; subtasks: CoListSchema<typeof Task>; } & CoMap
status: "todo" | "in-progress" | "completed"
status = "completed"; }); }
Best Practices
- Be explicit about resolution depths: Always specify exactly what you need
- Use framework integrations: They handle subscription lifecycle automatically
- Clean up subscriptions: Always store and call the unsubscribe function when you're done
- Handle all loading states: Check for undefined (loading), null (not found), and success states
- Use the
co.loaded
type: Add compile-time type safety for components that require specific resolution patterns