Public sharing and invites

Public sharing

You can share CoValues publicly by setting the owner to a Group, and granting access to "everyone".

const const group: Groupgroup = class Group
@categoryIdentity & Permissions
Group
.
Group.create<Group>(this: CoValueClass<Group>, options?: {
    owner: Account;
} | Account): Group
create
();
const group: Groupgroup.Group.addMember(member: Everyone, role: "writer" | "reader" | "writeOnly"): void (+1 overload)addMember("everyone", "writer");

This is done in the chat example where anyone can join the chat, and send messages.

You can also add members by Account ID.

Invites

You can grant users access to a CoValue by sending them an invite link.

This is used in the pet example and the todo example.

import { 
function createInviteLink<C extends CoValue>(value: C, role: "reader" | "writer" | "admin" | "writeOnly", { baseURL, valueHint, }?: {
    baseURL?: string;
    valueHint?: string;
}): string
@categoryInvite Links
createInviteLink
} from "jazz-react";
createInviteLink<{
    name: string;
} & CoMap>(value: {
    name: string;
} & CoMap, role: "reader" | "writer" | "admin" | "writeOnly", { baseURL, valueHint, }?: {
    baseURL?: string;
    valueHint?: string;
}): string
@categoryInvite Links
createInviteLink
(
const organization: {
    name: string;
} & CoMap
organization
, "writer"); // or reader, admin, writeOnly

It generates a URL that looks like .../invite/[CoValue ID]/[inviteSecret]

In your app, you need to handle this route, and let the user accept the invitation, as done here.

import { 
function useAcceptInvite<S extends CoValueOrZodSchema>({ invitedObjectSchema, onAccept, forValueHint, }: {
    invitedObjectSchema: S;
    onAccept: (valueID: string) => void;
    forValueHint?: string;
}): void
useAcceptInvite
} from "jazz-react";
useAcceptInvite<CoMapSchema<{
    name: z.z.ZodString;
}>>({ invitedObjectSchema, onAccept, forValueHint, }: {
    invitedObjectSchema: CoMapSchema<{
        name: z.z.ZodString;
    }>;
    onAccept: (valueID: string) => void;
    forValueHint?: string;
}): void
useAcceptInvite
({
invitedObjectSchema: CoMapSchema<{
    name: z.z.ZodString;
}>
invitedObjectSchema
:
const Organization: CoMapSchema<{
    name: z.z.ZodString;
}>
Organization
,
onAccept: (valueID: string) => voidonAccept: (organizationID: stringorganizationID) => { 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 ```
@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
("Accepted invite!")
// navigate to the organization page }, });

Requesting Invites

To allow a non-group member to request an invitation to a group you can use the writeOnly role. This means that users only have write access to a specific requests list (they can't read other requests). However, Administrators can review and approve these requests.

Create the data models.

const 
const JoinRequest: CoMapSchema<{
    account: <Shape extends {
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>(shape?: Shape) => AccountSchema<Shape>;
    status: z.z.ZodLiteral<...>;
}>
JoinRequest
= import coco.
map<{
    account: <Shape extends {
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>(shape?: Shape) => AccountSchema<Shape>;
    status: z.z.ZodLiteral<...>;
}>(shape: {
    account: <Shape extends {
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>(shape?: Shape) => AccountSchema<Shape>;
    status: z.z.ZodLiteral<...>;
}): CoMapSchema<...>
export map
map
({
account: <Shape extends {
    profile: AnyCoMapSchema<{
        name: z.z.core.$ZodString<string>;
        inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
    }>;
    root: AnyCoMapSchema;
}>(shape?: Shape) => AccountSchema<Shape>
account
: import coco.
const account: <Shape extends {
    profile: AnyCoMapSchema<{
        name: z.z.core.$ZodString<string>;
        inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
    }>;
    root: AnyCoMapSchema;
}>(shape?: Shape) => AccountSchema<Shape>
export account
account
,
status: z.z.ZodLiteral<"pending" | "approved" | "rejected">status: import zz.
literal<["pending", "approved", "rejected"]>(value: ["pending", "approved", "rejected"], params?: string | z.z.core.$ZodLiteralParams): z.z.ZodLiteral<"pending" | "approved" | "rejected"> (+1 overload)
export literal
literal
(["pending", "approved", "rejected"]),
}); const
const RequestsList: CoListSchema<CoMapSchema<{
    account: <Shape extends {
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>(shape?: Shape) => AccountSchema<Shape>;
    status: z.z.ZodLiteral<...>;
}>>
RequestsList
= import coco.
list<CoMapSchema<{
    account: <Shape extends {
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>(shape?: Shape) => AccountSchema<Shape>;
    status: z.z.ZodLiteral<...>;
}>>(element: CoMapSchema<...>): CoListSchema<...>
export list
list
(
const JoinRequest: CoMapSchema<{
    account: <Shape extends {
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>(shape?: Shape) => AccountSchema<Shape>;
    status: z.z.ZodLiteral<...>;
}>
JoinRequest
);

Set up the request system with appropriate access controls.

function 
function createRequestsToJoin(): CoList<{
    account: {
        profile: {
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap;
        root: {
            [x: string]: any;
        } & CoMap;
    } & {
        profile: Profile;
    } & Account;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap>
createRequestsToJoin
() {
const const requestsGroup: GrouprequestsGroup = class Group
@categoryIdentity & Permissions
Group
.
Group.create<Group>(this: CoValueClass<Group>, options?: {
    owner: Account;
} | Account): Group
create
();
const requestsGroup: GrouprequestsGroup.Group.addMember(member: Everyone, role: "writer" | "reader" | "writeOnly"): void (+1 overload)addMember("everyone", "writeOnly"); return
const RequestsList: CoListSchema<CoMapSchema<{
    account: AccountSchema<{
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>;
    status: z.z.ZodLiteral<...>;
}>>
RequestsList
.
create: (items: CoListInit<CoMapSchema<{
    account: AccountSchema<{
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>;
    status: z.z.ZodLiteral<...>;
}>>, options?: {
    owner: Account | Group;
} | Account | Group) => CoList<...>
create
([], const requestsGroup: GrouprequestsGroup);
} async function
function sendJoinRequest(requestsList: co.loaded<typeof RequestsList>, account: Account): Promise<{
    account: {
        profile: {
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap;
        root: {
            ...;
        } & CoMap;
    } & {
        ...;
    } & Account;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap>
sendJoinRequest
(
requestsList: CoList<({
    account: ({
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account) | null;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap) | null>
requestsList
: import coco.
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
loaded
<typeof
const RequestsList: CoListSchema<CoMapSchema<{
    account: AccountSchema<{
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>;
    status: z.z.ZodLiteral<...>;
}>>
RequestsList
>,
account: {
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & Account
account
:
type Account = {
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & Account
Account
,
) { const
const request: {
    account: {
        profile: {
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap;
        root: {
            [x: string]: any;
        } & CoMap;
    } & {
        profile: Profile;
    } & Account;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap
request
=
const JoinRequest: CoMapSchema<{
    account: AccountSchema<{
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>;
    status: z.z.ZodLiteral<...>;
}>
JoinRequest
.
create: (init: {
    account: {
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account;
    status: NonNullable<...>;
}, options?: Account | ... 2 more ... | undefined) => {
    ...;
} & CoMap
create
(
{
account: {
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & {
    profile: Profile | null;
} & Account
account
,
status: NonNullable<"pending" | "approved" | "rejected">status: "pending", },
requestsList: CoList<({
    account: ({
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account) | null;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap) | null>
requestsList
.CoList<({ account: ({ profile: ({ name: string; inbox?: string | undefined; inboxInvite?: string | undefined; } & CoMap) | null; root: ({ [x: string]: any; } & CoMap) | null; } & { ...; } & Account) | null; status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>._owner: Account | Group
@categoryCollaboration
_owner
// Inherit the access controls of the requestsList
);
requestsList: CoList<({
    account: ({
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account) | null;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap) | null>
requestsList
.
CoList<({ account: ({ profile: ({ name: string; inbox?: string | undefined; inboxInvite?: string | undefined; } & CoMap) | null; root: ({ [x: string]: any; } & CoMap) | null; } & { ...; } & Account) | null; status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>.push(...items: (({
    account: ({
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account) | null;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap) | null)[]): number
Appends new elements to the end of an array, and returns the new length of the array.
@paramitems New elements to add to the array.
push
(
const request: {
    account: {
        profile: {
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap;
        root: {
            [x: string]: any;
        } & CoMap;
    } & {
        profile: Profile;
    } & Account;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap
request
);
return
const request: {
    account: {
        profile: {
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap;
        root: {
            [x: string]: any;
        } & CoMap;
    } & {
        profile: Profile;
    } & Account;
    status: "pending" | ... 1 more ... | "rejected";
} & CoMap
request
;
}

Using the write-only access users can submit requests that only administrators can review and approve.

async function 
function approveJoinRequest(joinRequest: co.loaded<typeof JoinRequest, {
    account: true;
}>, targetGroup: Group): Promise<boolean>
approveJoinRequest
(
joinRequest: {
    account: {
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account;
} & {
    ...;
} & CoMap
joinRequest
: import coco.
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
loaded
<typeof
const JoinRequest: CoMapSchema<{
    account: AccountSchema<{
        profile: AnyCoMapSchema<{
            name: z.z.core.$ZodString<string>;
            inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
            inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        }>;
        root: AnyCoMapSchema;
    }>;
    status: z.z.ZodLiteral<...>;
}>
JoinRequest
, { account: trueaccount: true }>,
targetGroup: GrouptargetGroup: class Group
@categoryIdentity & Permissions
Group
,
) { const
const account: ({
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & Account) | ({
    ...;
} & ... 1 more ... & Account) | null
account
= await
const Account: AccountSchema<{
    profile: AnyCoMapSchema<{
        name: z.z.core.$ZodString<string>;
        inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
    }>;
    root: AnyCoMapSchema;
}>
Account
.
load: <ResolveQuery<AccountSchema<{
    profile: AnyCoMapSchema<{
        name: z.z.core.$ZodString<string>;
        inbox?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
        inboxInvite?: z.z.core.$ZodOptional<z.z.core.$ZodString>;
    }>;
    root: AnyCoMapSchema;
}>>>(id: string, options?: {
    ...;
} | undefined) => Promise<...>
load
(
joinRequest: {
    account: {
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account;
} & {
    ...;
} & CoMap
joinRequest
.
CoMap._refs: {
    account: Ref<NonNullable<{
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account>>;
}
If property `prop` is a `coField.ref(...)`, you can use `coMaps._refs.prop` to access the `Ref` instead of the potentially loaded/null value. This allows you to always get the ID or load the value manually.
@example```ts person._refs.pet.id; // => ID<Animal> person._refs.pet.value; // => Animal | null const pet = await person._refs.pet.load(); ```@categoryContent
_refs
.
account: Ref<NonNullable<{
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & {
    profile: Profile | null;
} & Account>>
account
.Ref<NonNullable<{ profile: ({ name: string; inbox?: string | undefined; inboxInvite?: string | undefined; } & CoMap) | null; root: ({ [x: string]: any; } & CoMap) | null; } & { profile: Profile | null; } & Account>>.id: stringid);
if (
const account: ({
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & Account) | ({
    ...;
} & ... 1 more ... & Account) | null
account
) {
targetGroup: GrouptargetGroup.Group.addMember(member: Account, role: AccountRole): void (+1 overload)addMember(
const account: ({
    profile: ({
        name: string;
        inbox?: string | undefined;
        inboxInvite?: string | undefined;
    } & CoMap) | null;
    root: ({
        [x: string]: any;
    } & CoMap) | null;
} & Account) | ({
    ...;
} & ... 1 more ... & Account)
account
, "reader");
joinRequest: {
    account: {
        profile: ({
            name: string;
            inbox?: string | undefined;
            inboxInvite?: string | undefined;
        } & CoMap) | null;
        root: ({
            [x: string]: any;
        } & CoMap) | null;
    } & {
        ...;
    } & Account;
} & {
    ...;
} & CoMap
joinRequest
.status: "pending" | "approved" | "rejected"status = "approved";
return true; } else { return false; } }