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().

Note: Unless you're using vanilla JavaScript, this is only used outside of React components - for example in server-side code or in tests. See the section below for convenient subscription hooks that you typically use in React.

class class TaskTask extends class CoMap
CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
@categoryDescriptionDeclaration Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`. Optional `co.ref(...)` fields must be marked with `{ optional: true }`. ```ts import { co, CoMap } from "jazz-tools"; class Person extends CoMap { name = co.string; age = co.number; pet = co.ref(Animal); car = co.ref(Car, { optional: true }); } ```@categoryDescriptionContent You can access properties you declare on a `CoMap` (using `co`) as if they were normal properties on a plain object, using dot notation, `Object.keys()`, etc. ```ts person.name; person["age"]; person.age = 42; person.pet?.name; Object.keys(person); // => ["name", "age", "pet"] ```@categoryCoValues
CoMap
{
Task.title: co<string>title =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.string: co<string>string;
Task.description: co<string>description =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.string: co<string>string;
Task.status: co<"todo" | "in-progress" | "completed">status =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.literal<["todo", "in-progress", "completed"]>(_lit_0: "todo", _lit_1: "in-progress", _lit_2: "completed"): co<"todo" | "in-progress" | "completed">literal("todo", "in-progress", "completed");
Task.assignedTo: co<string | undefined>assignedTo =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.
optional: {
    ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
    ... 7 more ...;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
}
optional
.string: co<string | undefined>string;
} // ... // Subscribe to a Task by ID const const unsubscribe: () => voidunsubscribe = class TaskTask.CoMap.subscribe<Task, true>(this: CoValueClass<Task>, id: ID<Task>, listener: (value: Task, unsubscribe: () => void) => void): () => void (+1 overload)
Load and subscribe to a `CoMap` with a given ID, as a given account. Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener. `depth` specifies which (if any) fields that reference other CoValues to load as well before calling `listener` for the first time. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest. Returns an unsubscribe function that you should call when you no longer need updates. Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
@example```ts const unsub = Person.subscribe( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} }, (person) => console.log(person) ); ```@categorySubscription & Loading
subscribe
(const taskId: ID<Task>taskId, (updatedTask: TaskupdatedTask) => {
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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
("Task updated:", updatedTask: TaskupdatedTask.Task.title: co<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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
("New status:", updatedTask: TaskupdatedTask.Task.status: co<"todo" | "in-progress" | "completed">status);
}); // Clean up when you're done const unsubscribe: () => voidunsubscribe();

If you already have a CoValue instance, you can subscribe to it by calling its subscribe method.

const const task: Tasktask = class TaskTask.
CoMap.create<Task>(this: CoValueClass<...>, init: {
    title: co<string> & (co<string> | undefined);
    description: co<string> & (co<string> | undefined);
    status: co<"todo" | "in-progress" | "completed"> & (co<...> | undefined);
    assignedTo?: string | ... 2 more ... | undefined;
}, options?: {
    owner: Account | Group;
    unique?: CoValueUniqueness["uniqueness"];
} | Account | Group): Task
Create a new CoMap with the given initial values and owner. The owner (a Group or Account) determines access rights to the CoMap. The CoMap will immediately be persisted and synced to connected peers.
@example```ts const person = Person.create({ name: "Alice", age: 42, pet: cat, }, { owner: friendGroup }); ```@categoryCreation
create
({
title: co<string> & (co<string> | undefined)title: "Cut the grass", ...const otherProps: anyotherProps }); const const unsubscribe: () => voidunsubscribe = const task: Tasktask.CoMap.subscribe<Task, true>(this: Task, listener: (value: Task, 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.
@categorySubscription & Loading
subscribe
((updatedTask: TaskupdatedTask) => {
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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
("Task updated:", updatedTask: TaskupdatedTask.Task.title: co<string>title);
}); // Clean up when you're done const unsubscribe: () => voidunsubscribe();

Subscription hooks

useCoState

Jazz provides a useCoState hook that provides a convenient way to subscribe to CoValues and handle loading states:

import { 
function useCoState<V extends CoValue, const R extends RefsToResolve<V> = true>(Schema: CoValueClass<V>, id: ID<CoValue> | undefined, options?: {
    resolve?: RefsToResolveStrict<V, R>;
}): Resolved<V, R> | undefined | null
useCoState
} from "jazz-react";
function
function GardenPlanner({ projectId }: {
    projectId: ID<Project>;
}): "Project not found or not accessible" | "Loading project ..." | React.JSX.Element
GardenPlanner
({ projectId: ID<Project>projectId }: { projectId: ID<Project>projectId: type ID<T> = `co_z${string}` & IDMarker<T>
IDs are unique identifiers for `CoValue`s. Can be used with a type argument to refer to a specific `CoValue` type.
@example```ts type AccountID = ID<Account>; ```@categoryCoValues
ID
<class ProjectProject> }) {
// Subscribe to a project and its tasks const
const project: ({
    tasks: Task[] & ListOfTasks;
} & Project) | null | undefined
project
=
useCoState<Project, {
    tasks: {
        $each: boolean;
    };
}>(Schema: CoValueClass<Project>, id: ID<CoValue> | undefined, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
} | undefined): ({
    ...;
} & Project) | ... 1 more ... | undefined
useCoState
(class ProjectProject, projectId: ID<Project>projectId, {
resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: { tasks?: RefsToResolve<ListOfTasks, 10, [0]> | undefinedtasks: { $each: RefsToResolve<Task, 10, [0, 0]>$each: true }, }, }); if (!
const project: ({
    tasks: Task[] & ListOfTasks;
} & Project) | null | undefined
project
) {
return const project: null | undefinedproject === null ? "Project not found or not accessible" : "Loading project ..."; } return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.h1: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h1>{
const project: {
    tasks: Task[] & ListOfTasks;
} & Project
project
.Project.name: co<string>name}</JSX.IntrinsicElements.h1: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h1>
<
function TaskList({ tasks }: {
    tasks: Task[];
}): React.JSX.Element
TaskList
tasks: Task[]tasks={
const project: {
    tasks: Task[] & ListOfTasks;
} & Project
project
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks} />
</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); } function
function TaskList({ tasks }: {
    tasks: Task[];
}): React.JSX.Element
TaskList
({ tasks: Task[]tasks }: { tasks: Task[]tasks: class TaskTask[] }) {
return ( <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> {tasks: Task[]tasks.Array<Task>.map<React.JSX.Element>(callbackfn: (value: Task, index: number, array: Task[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((task: Tasktask) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={task: Tasktask.CoMap.id: ID<Task>
The ID of this `CoMap`
@categoryContent
id
}>
<JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>{task: Tasktask.Task.title: co<string>title}</JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>{task: Tasktask.Task.status: co<"todo" | "in-progress" | "completed">status}</JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> ); }

The useCoState hook handles subscribing when the component mounts and unsubscribing when it unmounts, making it easy to keep your UI in sync with the underlying data.

useAccount

useAccount is used to access the current user's account. You can use this at the top-level of your app to subscribe to the current user's account profile and root.

Like useCoState, you can specify a resolve query to also subscribe to CoValues referenced in the account profile or root.

import { 
function useAccount<A extends RegisteredAccount>(): {
    me: A;
    logOut: () => void;
} (+1 overload)
useAccount
} from "jazz-react";
function function ProjectList(): React.JSX.ElementProjectList() { const {
const me: ({
    profile: Profile;
    root: {
        myProjects: (Project & {
            tasks: ListOfTasks;
        })[] & ListOfProjects;
    } & AccountRoot;
} & MyAppAccount) | null | undefined
me
} =
useAccount<MyAppAccount, {
    profile: true;
    root: {
        myProjects: {
            $each: {
                tasks: true;
            };
        };
    };
}>(options?: {
    resolve?: RefsToResolve<MyAppAccount, 10, []> | undefined;
} | undefined): {
    ...;
} (+1 overload)
useAccount
({
resolve?: RefsToResolve<MyAppAccount, 10, []> | undefinedresolve: { profile?: RefsToResolve<Profile, 10, [0]> | undefinedprofile: true, root?: RefsToResolve<AccountRoot, 10, [0]> | undefinedroot: { myProjects?: RefsToResolve<ListOfProjects, 10, [0, 0]> | undefinedmyProjects: { $each: RefsToResolve<Project, 10, [0, 0, 0]>$each: { tasks?: RefsToResolve<ListOfTasks, 10, [0, 0, 0, 0]> | undefinedtasks: true } } }, }, }); if (!
const me: ({
    profile: Profile;
    root: {
        myProjects: (Project & {
            tasks: ListOfTasks;
        })[] & ListOfProjects;
    } & AccountRoot;
} & MyAppAccount) | null | undefined
me
) {
return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>Loading...</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div>; } return <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.h1: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h1>{
const me: {
    profile: Profile;
    root: {
        myProjects: (Project & {
            tasks: ListOfTasks;
        })[] & ListOfProjects;
    } & AccountRoot;
} & MyAppAccount
me
.Account.profile: Profileprofile.Profile.name: co<string>name}'s projects</JSX.IntrinsicElements.h1: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h1>
<JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> {
const me: {
    profile: Profile;
    root: {
        myProjects: (Project & {
            tasks: ListOfTasks;
        })[] & ListOfProjects;
    } & AccountRoot;
} & MyAppAccount
me
.
MyAppAccount.root: {
    myProjects: (Project & {
        tasks: ListOfTasks;
    })[] & ListOfProjects;
} & AccountRoot & co<AccountRoot | null>
root
.
AccountRoot.myProjects: (Project & {
    tasks: ListOfTasks;
})[] & ListOfProjects & co<ListOfProjects | null>
myProjects
.
Array<T>.map<React.JSX.Element>(callbackfn: (value: Project & {
    tasks: ListOfTasks;
}, index: number, array: (Project & {
    tasks: ListOfTasks;
})[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[] (+1 overload)
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
(
project: Project & {
    tasks: ListOfTasks;
}
project
=> (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={
project: Project & {
    tasks: ListOfTasks;
}
project
.
CoMap.id: ID<Project & {
    tasks: ListOfTasks;
}>
The ID of this `CoMap`
@categoryContent
id
}>
{
project: Project & {
    tasks: ListOfTasks;
}
project
.Project.name: co<string>name} ({
project: Project & {
    tasks: ListOfTasks;
}
project
.Project.tasks: co<ListOfTasks | null> & ListOfTaskstasks.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
} tasks)
</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> }

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 fetched
  • null: 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:

class TaskTask.CoMap.subscribe<Task, true>(this: CoValueClass<Task>, id: ID<Task>, listener: (value: Task, unsubscribe: () => void) => void): () => void (+1 overload)
Load and subscribe to a `CoMap` with a given ID, as a given account. Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener. `depth` specifies which (if any) fields that reference other CoValues to load as well before calling `listener` for the first time. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest. Returns an unsubscribe function that you should call when you no longer need updates. Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
@example```ts const unsub = Person.subscribe( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} }, (person) => console.log(person) ); ```@categorySubscription & Loading
subscribe
(const taskId: ID<Task>taskId, (task: Tasktask) => {
if (task: Tasktask === var undefinedundefined) { 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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
("Task is loading...");
} else if (task: Tasktask === 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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
("Task loaded:", task: Tasktask.Task.title: co<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:

class class ProjectProject extends class CoMap
CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
@categoryDescriptionDeclaration Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`. Optional `co.ref(...)` fields must be marked with `{ optional: true }`. ```ts import { co, CoMap } from "jazz-tools"; class Person extends CoMap { name = co.string; age = co.number; pet = co.ref(Animal); car = co.ref(Car, { optional: true }); } ```@categoryDescriptionContent You can access properties you declare on a `CoMap` (using `co`) as if they were normal properties on a plain object, using dot notation, `Object.keys()`, etc. ```ts person.name; person["age"]; person.age = 42; person.pet?.name; Object.keys(person); // => ["name", "age", "pet"] ```@categoryCoValues
CoMap
{
Project.name: co<string>name =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.string: co<string>string;
Project.tasks: co<ListOfTasks | null>tasks =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.ref: <typeof ListOfTasks>(arg: typeof ListOfTasks | ((_raw: RawCoList<JsonValue, JsonObject | null>) => typeof ListOfTasks), options?: never) => co<...> (+1 overload)ref(class ListOfTasksListOfTasks);
Project.owner: co<TeamMember | null>owner =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.
ref: <typeof TeamMember>(arg: typeof TeamMember | ((_raw: RawCoMap<{
    [key: string]: JsonValue | undefined;
}, JsonObject | null>) => typeof TeamMember), options?: never) => co<...> (+1 overload)
ref
(class TeamMemberTeamMember);
} class class TaskTask extends class CoMap
CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
@categoryDescriptionDeclaration Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`. Optional `co.ref(...)` fields must be marked with `{ optional: true }`. ```ts import { co, CoMap } from "jazz-tools"; class Person extends CoMap { name = co.string; age = co.number; pet = co.ref(Animal); car = co.ref(Car, { optional: true }); } ```@categoryDescriptionContent You can access properties you declare on a `CoMap` (using `co`) as if they were normal properties on a plain object, using dot notation, `Object.keys()`, etc. ```ts person.name; person["age"]; person.age = 42; person.pet?.name; Object.keys(person); // => ["name", "age", "pet"] ```@categoryCoValues
CoMap
{
Task.title: co<string>title =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.string: co<string>string;
Task.subtasks: co<ListOfTasks | null>subtasks =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.ref: <typeof ListOfTasks>(arg: typeof ListOfTasks | ((_raw: RawCoList<JsonValue, JsonObject | null>) => typeof ListOfTasks), options?: never) => co<...> (+1 overload)ref(class ListOfTasksListOfTasks);
Task.assignee: co<TeamMember | null | undefined>assignee =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.
optional: {
    ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
    ... 7 more ...;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
}
optional
.
ref: <typeof TeamMember>(arg: typeof TeamMember | ((_raw: RawCoMap<{
    [key: string]: JsonValue | undefined;
}, JsonObject | null>) => typeof TeamMember)) => co<...>
ref
(class TeamMemberTeamMember);
} class class TeamMemberTeamMember extends class CoMap
CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
@categoryDescriptionDeclaration Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`. Optional `co.ref(...)` fields must be marked with `{ optional: true }`. ```ts import { co, CoMap } from "jazz-tools"; class Person extends CoMap { name = co.string; age = co.number; pet = co.ref(Animal); car = co.ref(Car, { optional: true }); } ```@categoryDescriptionContent You can access properties you declare on a `CoMap` (using `co`) as if they were normal properties on a plain object, using dot notation, `Object.keys()`, etc. ```ts person.name; person["age"]; person.age = 42; person.pet?.name; Object.keys(person); // => ["name", "age", "pet"] ```@categoryCoValues
CoMap
{
TeamMember.name: co<string>name =
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.string: co<string>string;
} class class ListOfTasksListOfTasks extends class CoList<Item = any>
CoLists are collaborative versions of plain arrays.
@categoryDescriptionContent You can access items on a `CoList` as if they were normal items on a plain array, using `[]` notation, etc. Since `CoList` is a subclass of `Array`, you can use all the normal array methods like `push`, `pop`, `splice`, etc. ```ts colorList[0]; colorList[3] = "yellow"; colorList.push("Kawazaki Green"); colorList.splice(1, 1); ```@categoryCoValues
CoList
.
CoList<Item = any>.Of<co<Task | null>>(item: co<Task | null>): {
    new (options: {
        fromRaw: RawCoList;
    } | undefined): CoList<co<Task | null>>;
    ... 12 more ...;
    fromAsync<T>(iterableOrArrayLike: AsyncIterable<T> | Iterable<T | PromiseLike<T>> | ArrayLike<T | PromiseLike<T>>): Promise<T[]>;
    fromAsync<T, U>(iterableOrArrayLike: AsyncIterable<T> | Iterable<T> | ArrayLike<T>, mapFn: (value: Awaited<T>, index: number) => U, thisArg?: any): Promise<Awaited<U>[]>;
}
Declare a `CoList` by subclassing `CoList.Of(...)` and passing the item schema using `co`.
@example```ts class ColorList extends CoList.Of( co.string ) {} class AnimalList extends CoList.Of( co.ref(Animal) ) {} ```@categoryDeclaration
Of
(
const co: {
    string: co<string>;
    number: co<number>;
    boolean: co<boolean>;
    null: co<null>;
    Date: co<Date>;
    literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number]>;
    json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T>;
    encoded<T>(arg: Encoder<T>): co<T>;
    ref: {
        ...;
    };
    items: ItemsSym;
    optional: {
        ref: <C extends CoValueClass>(arg: C | ((_raw: InstanceType<C>["_raw"]) => C)) => co<InstanceType<C> | null | undefined>;
        json<T extends CojsonInternalTypes.CoJsonValue<T>>(): co<T | undefined>;
        encoded<T>(arg: OptionalEncoder<T>): co<T | undefined>;
        string: co<string | undefined>;
        number: co<number | undefined>;
        boolean: co<boolean | undefined>;
        null: co<null | undefined>;
        Date: co<Date | undefined>;
        literal<T extends (string | number | boolean)[]>(..._lit: T): co<T[number] | undefined>;
    };
}
@categorySchema definition@categorySchema definition
co
.
ref: <typeof Task>(arg: typeof Task | ((_raw: RawCoMap<{
    [key: string]: JsonValue | undefined;
}, JsonObject | null>) => typeof Task), options?: never) => co<...> (+1 overload)
ref
(class TaskTask)) {}
// Load just the project, not its references const const project: Project | nullproject = await class ProjectProject.
CoMap.load<Project, true>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const projectId: ID<Project>projectId);
if (!const project: Project | nullproject) { throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
("Project not found or not accessible"); }
// string - primitive fields are always loaded const project: Projectproject.Project.name: co<string>name; // undefined | null | ListOfTasks - non-requested references might not be loaded, or inaccessible const project: Projectproject.Project.tasks: co<ListOfTasks | null>tasks; // Load the project and shallowly load its list of tasks const
const projectWithTasksShallow: ({
    tasks: ListOfTasks;
} & Project) | null
projectWithTasksShallow
= await class ProjectProject.
CoMap.load<Project, {
    tasks: boolean;
}>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const projectId: ID<Project>projectId, {
resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: { tasks?: RefsToResolve<ListOfTasks, 10, [0]> | undefinedtasks: true } }); if (!
const projectWithTasksShallow: ({
    tasks: ListOfTasks;
} & Project) | null
projectWithTasksShallow
) { throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
("Project or required references not found or not accessible"); }
// ListOfTasks - shallowly loaded
const projectWithTasksShallow: {
    tasks: ListOfTasks;
} & Project
projectWithTasksShallow
.Project.tasks: ListOfTasks & co<ListOfTasks | null>tasks;
// number - length of the list
const projectWithTasksShallow: {
    tasks: ListOfTasks;
} & Project
projectWithTasksShallow
.Project.tasks: ListOfTasks & co<ListOfTasks | null>tasks.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 inaccessible
const projectWithTasksShallow: {
    tasks: ListOfTasks;
} & Project
projectWithTasksShallow
.Project.tasks: ListOfTasks & co<ListOfTasks | null>tasks[0];
// Load the project and its tasks const
const projectWithTasks: ({
    tasks: Task[] & ListOfTasks;
} & Project) | null
projectWithTasks
= await class ProjectProject.
CoMap.load<Project, {
    tasks: {
        $each: boolean;
    };
}>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const projectId: ID<Project>projectId, {
resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: { tasks?: RefsToResolve<ListOfTasks, 10, [0]> | undefinedtasks: { $each: RefsToResolve<Task, 10, [0, 0]>$each: true } } }); if (!
const projectWithTasks: ({
    tasks: Task[] & ListOfTasks;
} & Project) | null
projectWithTasks
) { throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
("Project or required references not found or not accessible"); }
// ListOfTasks - fully loaded
const projectWithTasks: {
    tasks: Task[] & ListOfTasks;
} & Project
projectWithTasks
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks;
// Task - fully loaded
const projectWithTasks: {
    tasks: Task[] & ListOfTasks;
} & Project
projectWithTasks
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks[0];
// string - primitive fields are always loaded
const projectWithTasks: {
    tasks: Task[] & ListOfTasks;
} & Project
projectWithTasks
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks[0].Task.title: co<string>title;
// undefined | null | ListOfTasks - subtasks might not be loaded, or inaccessible
const projectWithTasks: {
    tasks: Task[] & ListOfTasks;
} & Project
projectWithTasks
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks[0].Task.subtasks: co<ListOfTasks | null>subtasks;
// Load the project, its tasks, and their subtasks const
const projectDeep: ({
    tasks: (Task & {
        subtasks: Task[] & ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
} & Project) | null
projectDeep
= await class ProjectProject.
CoMap.load<Project, {
    tasks: {
        $each: {
            subtasks: {
                $each: boolean;
            };
            assignee: boolean;
        };
    };
}>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const projectId: ID<Project>projectId, {
resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: { tasks?: RefsToResolve<ListOfTasks, 10, [0]> | undefinedtasks: { $each: RefsToResolve<Task, 10, [0, 0]>$each: { subtasks?: RefsToResolve<ListOfTasks, 10, [0, 0, 0]> | undefinedsubtasks: { $each: RefsToResolve<Task, 10, [0, 0, 0, 0]>$each: true }, assignee?: RefsToResolve<TeamMember, 10, [0, 0, 0]> | undefinedassignee: true } } } }); if (!
const projectDeep: ({
    tasks: (Task & {
        subtasks: Task[] & ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
} & Project) | null
projectDeep
) { throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
("Project or required references not found or not accessible"); }
// string - primitive fields are always loaded
const projectDeep: {
    tasks: (Task & {
        subtasks: Task[] & ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
} & Project
projectDeep
.
Project.tasks: (Task & {
    subtasks: Task[] & ListOfTasks;
    assignee: TeamMember | undefined;
})[] & ListOfTasks & co<ListOfTasks | null>
tasks
[0].Task.subtasks: co<ListOfTasks | null> & Task[] & ListOfTaskssubtasks[0].Task.title: co<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)
const projectDeep: {
    tasks: (Task & {
        subtasks: Task[] & ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
} & Project
projectDeep
.
Project.tasks: (Task & {
    subtasks: Task[] & ListOfTasks;
    assignee: TeamMember | undefined;
})[] & ListOfTasks & co<ListOfTasks | null>
tasks
[0].Task.assignee: TeamMember | (TeamMember & CoMarker) | undefinedassignee;

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 
const task: ({
    assignee: TeamMember | undefined;
} & Task) | null
task
= await class TaskTask.
CoMap.load<Task, {
    assignee: boolean;
}>(this: CoValueClass<...>, id: ID<Task>, options?: {
    resolve?: RefsToResolve<Task, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const taskId: ID<Task>taskId, {
resolve?: RefsToResolve<Task, 10, []> | undefinedresolve: { assignee?: RefsToResolve<TeamMember, 10, [0]> | undefinedassignee: true } });
const task: ({
    assignee: TeamMember | undefined;
} & Task) | null
task
// => 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 
const project: ({
    tasks: Task[] & ListOfTasks;
} & Project) | null
project
= await class ProjectProject.
CoMap.load<Project, {
    tasks: {
        $each: boolean;
    };
}>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const projectId: ID<Project>projectId, {
resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: { tasks?: RefsToResolve<ListOfTasks, 10, [0]> | undefinedtasks: { $each: RefsToResolve<Task, 10, [0, 0]>$each: true } } });
const project: ({
    tasks: Task[] & ListOfTasks;
} & Project) | null
project
// => 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 const project: Project | nullproject = await class ProjectProject.
CoMap.load<Project, true>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(const projectId: ID<Project>projectId, {
resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: true }); const project: Project | nullproject // => Project // The user doesn't have access to the owner const project: Project | nullproject?.Project.owner: co<TeamMember | null> | undefinedowner // => always null

The load operation will succeed and return the object, but the inaccessible reference will always be null.

Type Safety with Resolved Type

Jazz provides the Resolved 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 Resolved type is especially useful when passing data between components, as it guarantees that all necessary nested data has been loaded:

// Define a type that includes resolved nested data
type 
type ProjectWithTasks = {
    tasks: Task[] & ListOfTasks;
} & Project
ProjectWithTasks
=
type Resolved<T, R extends RefsToResolve<T> | undefined> = R extends boolean | undefined ? T : [T] extends [(infer Item)[]] ? UnCo<Exclude<Item, null>> extends CoValue ? R extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue ...
Resolved
<class ProjectProject, {
tasks: {
    $each: true;
}
tasks
: { $each: true$each: true }
}>; // Component that expects a fully resolved project function
function TaskList({ project }: {
    project: ProjectWithTasks;
}): React.JSX.Element
TaskList
({
project: {
    tasks: Task[] & ListOfTasks;
} & Project
project
}: {
project: {
    tasks: Task[] & ListOfTasks;
} & Project
project
:
type ProjectWithTasks = {
    tasks: Task[] & ListOfTasks;
} & Project
ProjectWithTasks
}) {
// TypeScript knows tasks are loaded, so this is type-safe return ( <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> {
project: {
    tasks: Task[] & ListOfTasks;
} & Project
project
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks.Array<T>.map<React.JSX.Element>(callbackfn: (value: Task, index: number, array: Task[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[] (+1 overload)
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
(task: Tasktask => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={task: Tasktask.CoMap.id: ID<Task>
The ID of this `CoMap`
@categoryContent
id
}>{task: Tasktask.Task.title: co<string>title}</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li>
))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> ); } // For more complex resolutions type
type FullyLoadedProject = {
    tasks: (Task & {
        subtasks: ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
    owner: TeamMember;
} & Project
FullyLoadedProject
=
type Resolved<T, R extends RefsToResolve<T> | undefined> = R extends boolean | undefined ? T : [T] extends [(infer Item)[]] ? UnCo<Exclude<Item, null>> extends CoValue ? R extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & UnCo<...> : [...] extends [...] ? UnCo<...> extends CoValue ? ItemDepth extends {
    ...;
} ? (CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue ...
Resolved
<class ProjectProject, {
tasks: {
    $each: {
        subtasks: true;
        assignee: true;
    };
}
tasks
: {
$each: {
    subtasks: true;
    assignee: true;
}
$each
: {
subtasks: truesubtasks: true, assignee: trueassignee: true } }, owner: trueowner: true }>; // Function that requires deeply resolved data function function processProject(project: FullyLoadedProject): voidprocessProject(
project: {
    tasks: (Task & {
        subtasks: ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
    owner: TeamMember;
} & Project
project
:
type FullyLoadedProject = {
    tasks: (Task & {
        subtasks: ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
    owner: TeamMember;
} & Project
FullyLoadedProject
) {
// Safe access to all resolved properties 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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
(`Project ${
project: {
    tasks: (Task & {
        subtasks: ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
    owner: TeamMember;
} & Project
project
.Project.name: co<string>name} owned by ${
project: {
    tasks: (Task & {
        subtasks: ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
    owner: TeamMember;
} & Project
project
.Project.owner: TeamMember & co<TeamMember | null>owner.TeamMember.name: co<string>name}`);
project: {
    tasks: (Task & {
        subtasks: ListOfTasks;
        assignee: TeamMember | undefined;
    })[] & ListOfTasks;
    owner: TeamMember;
} & Project
project
.
Project.tasks: (Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
})[] & ListOfTasks & co<ListOfTasks | null>
tasks
.
Array<T>.forEach(callbackfn: (value: Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
}, index: number, array: (Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
})[]) => void, thisArg?: any): void (+1 overload)
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
(
task: Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
}
task
=> {
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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
(`Task: ${
task: Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
}
task
.Task.title: co<string>title}, Assigned to: ${
task: Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
}
task
.Task.assignee: TeamMember | (TeamMember & CoMarker) | undefinedassignee?.TeamMember.name: co<string> | undefinedname}`);
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 calling `require('console')`. _**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 ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
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.
@sincev0.1.100
log
(`Subtasks: ${
task: Task & {
    subtasks: ListOfTasks;
    assignee: TeamMember | undefined;
}
task
.Task.subtasks: co<ListOfTasks | null> & ListOfTaskssubtasks.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
}`);
}); }

Using the Resolved 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: ID<Project>): Promise<void>completeAllTasks(projectId: ID<Project>projectId: type ID<T> = `co_z${string}` & IDMarker<T>
IDs are unique identifiers for `CoValue`s. Can be used with a type argument to refer to a specific `CoValue` type.
@example```ts type AccountID = ID<Account>; ```@categoryCoValues
ID
<class ProjectProject>) {
// Ensure the project is loaded const const project: Project | nullproject = await class ProjectProject.
CoMap.load<Project, true>(this: CoValueClass<...>, id: ID<Project>, options?: {
    resolve?: RefsToResolve<Project, 10, []> | undefined;
    loadAs?: Account | AnonymousJazzAgent;
} | undefined): Promise<...>
Load a `CoMap` with a given ID, as a given account. `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving. The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth. You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues. Check out the `load` methods on `CoMap`/`CoList`/`CoFeed`/`Group`/`Account` to see which depth structures are valid to nest.
@example```ts const person = await Person.load( "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax", { pet: {} } ); ```@categorySubscription & Loading
load
(projectId: ID<Project>projectId, { resolve?: RefsToResolve<Project, 10, []> | undefinedresolve: true });
if (!const project: Project | nullproject) return; // Ensure tasks are loaded const
const loadedProject: {
    tasks: Task[] & ListOfTasks;
} & Project
loadedProject
= await const project: Projectproject.
CoMap.ensureLoaded<Project, {
    tasks: {
        $each: boolean;
    };
}>(this: Project, options: {
    resolve: RefsToResolve<Project, 10, []>;
}): Promise<{
    tasks: Task[] & ListOfTasks;
} & Project>
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.
@categorySubscription & Loading
ensureLoaded
({
resolve: RefsToResolve<Project, 10, []>resolve: { tasks?: RefsToResolve<ListOfTasks, 10, [0]> | undefinedtasks: { $each: RefsToResolve<Task, 10, [0, 0]>$each: true } } }); // Now we can safely access and modify tasks
const loadedProject: {
    tasks: Task[] & ListOfTasks;
} & Project
loadedProject
.Project.tasks: Task[] & ListOfTasks & co<ListOfTasks | null>tasks.Array<T>.forEach(callbackfn: (value: Task, index: number, array: Task[]) => void, thisArg?: any): void (+1 overload)
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
(task: Tasktask => {
task: Tasktask.Task.status: co<"todo" | "in-progress" | "completed">status = "completed"; }); }

Best Practices

  1. Be explicit about resolution depths: Always specify exactly what you need
  2. Use framework integrations: They handle subscription lifecycle automatically
  3. Clean up subscriptions: Always store and call the unsubscribe function when you're done
  4. Handle all loading states: Check for undefined (loading), null (not found), and success states
  5. Use the Resolved type: Add compile-time type safety for components that require specific resolution patterns