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: Group
group =class Group
Group.create();
Group.create<Group>(this: CoValueClass<Group>, options?: { owner: Account; } | Account): Group
const group: Group
group.Group.addMember(member: Everyone, role: "writer" | "reader" | "writeOnly"): void (+3 overloads)
addMember("everyone", "writer");
You can also use makePublic(role)
alias to grant access to everyone with a specific role (defaults to reader
).
const
const group: Group
group =class Group
Group.create();
Group.create<Group>(this: CoValueClass<Group>, options?: { owner: Account; } | Account): Group
const group: Group
group.Group.addMember(member: Everyone, role: "writer" | "reader" | "writeOnly"): void (+3 overloads)
addMember("everyone", "writer");const group: Group
group.Group.makePublic(role?: "reader" | "writer"): Group
Make the group public, so that everyone can read it. Alias for `addMember("everyone", role)`.makePublic("writer"); // group.makePublic(); // Defaults to "reader" access
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 todo example.
import {
createInviteLink } from "jazz-tools/react";
function createInviteLink<C extends CoValue>(value: C, role: "reader" | "writer" | "admin" | "writeOnly", { baseURL, valueHint, }?: { baseURL?: string; valueHint?: string; }): string
createInviteLink(
createInviteLink<{ readonly name: string; } & CoMap>(value: { readonly name: string; } & CoMap, role: "reader" | "writer" | "admin" | "writeOnly", { baseURL, valueHint, }?: { baseURL?: string; valueHint?: string; }): string
organization, "writer"); // or reader, admin, writeOnly
const organization: { readonly name: string; } & CoMap
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 {
useAcceptInvite } from "jazz-tools/react";
function useAcceptInvite<S extends CoValueClassOrSchema>({ invitedObjectSchema, onAccept, forValueHint, }: { invitedObjectSchema: S; onAccept: (valueID: string) => void; forValueHint?: string; }): void
useAcceptInvite({
useAcceptInvite<co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>>({ invitedObjectSchema, onAccept, forValueHint, }: { invitedObjectSchema: co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>; onAccept: (valueID: string) => void; forValueHint?: string; }): void
invitedObjectSchema:
invitedObjectSchema: co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>
Organization,
const Organization: co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>
onAccept: (valueID: string) => void
onAccept: (organizationID: string
organizationID) => {var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+2 overloads)
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log("Accepted invite!") // navigate to the organization page }, });
You can accept an invitation programmatically by using the acceptInvite
method on an account.
Pass the ID of the CoValue you're being invited to, the secret from the invite link, and the schema of the CoValue.
await
const account: Account
account.
Account.acceptInvite<co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>>(valueID: string, inviteSecret: InviteSecret, coValueClass: co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>): Promise<...>
Accept an invite to a `CoValue` or `Group`.acceptInvite(const organizationId: ""
organizationId,const inviteSecret: "inviteSecret_z"
inviteSecret,Organization );
const Organization: co.Map<{ name: z.z.ZodString; }, unknown, Account | Group>
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
JoinRequest =
const JoinRequest: co.Map<{ account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>
import co
co.map({
map<{ account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }>(shape: { ...; }): co.Map<...> export map
account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape>
account:import co
co.
const account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape> export account
Defines a collaborative account schema for Jazz applications. Creates an account schema that represents a user account with profile and root data. Accounts are the primary way to identify and manage users in Jazz applications.account,status: z.z.ZodLiteral<"pending" | "approved" | "rejected">
status:import z
z.literal(["pending", "approved", "rejected"]), }); const
literal<readonly ["pending", "approved", "rejected"]>(value: readonly ["pending", "approved", "rejected"], params?: string | z.z.core.$ZodLiteralParams): z.z.ZodLiteral<"pending" | "approved" | "rejected"> (+1 overload) export literal
RequestsList =
const RequestsList: co.List<co.Map<{ account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>>
import co
co.list(
list<co.Map<{ account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>>(element: co.Map<...>): co.List<...> export list
JoinRequest);
const JoinRequest: co.Map<{ account: <Shape extends BaseAccountShape>(shape?: Shape) => co.Account<Shape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>
Set up the request system with appropriate access controls.
function
createRequestsToJoin() { const
function createRequestsToJoin(): CoListInstance<co.Map<{ account: co.Account<BaseAccountShape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>>
const requestsGroup: Group
requestsGroup =class Group
Group.create();
Group.create<Group>(this: CoValueClass<Group>, options?: { owner: Account; } | Account): Group
const requestsGroup: Group
requestsGroup.Group.addMember(member: Everyone, role: "writer" | "reader" | "writeOnly"): void (+3 overloads)
addMember("everyone", "writeOnly"); returnRequestsList.
const RequestsList: co.List<co.Map<{ account: co.Account<BaseAccountShape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>>
create([],
CoListSchema<CoMapSchema<{ account: AccountSchema<BaseAccountShape>; status: ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>>.create(items: readonly (({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | { ...; })[], options?: { owner: Group; unique?: CoValueUniqueness["uniqueness"]; } | Group): CoListInstance<...> (+1 overload)
const requestsGroup: Group
requestsGroup); } async functionsendJoinRequest(
function sendJoinRequest(requestsList: co.loaded<typeof RequestsList>, account: Account): Promise<{ readonly account: { readonly profile: { readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap; readonly root: { ...; } & CoMap; } & Account; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap>
requestsList:
requestsList: CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>
import co
co.loaded<typeof
type loaded<T extends CoValueClassOrSchema, R extends ResolveQuery<T> = true> = R extends boolean | undefined ? NonNullable<InstanceOfSchemaCoValuesNullable<T>> : [NonNullable<InstanceOfSchemaCoValuesNullable<T>>] extends [...] ? Exclude<...> extends CoValue ? R extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean ... export loaded
RequestsList>,
const RequestsList: co.List<co.Map<{ account: co.Account<BaseAccountShape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>>
account:
account: { readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account
Account, ) { const
type Account = { readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account
request =
const request: { readonly account: { readonly profile: { readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap; readonly root: { readonly [x: string]: any; } & CoMap; } & Account; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap
JoinRequest.
const JoinRequest: co.Map<{ account: co.Account<BaseAccountShape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>
create( {
CoMapSchema<{ account: AccountSchema<BaseAccountShape>; status: ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>.create(init: { account: { readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ readonly [x: string]: any; } & CoMap) | null; } & Account; status: "pending" | ... 1 more ... | "rejected"; }, options?: { owner?: Group; unique?: CoValueUniqueness["uniqueness"]; } | Group): { ...; } & CoMap (+1 overload)
account,
account: { readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account
status: "pending" | "approved" | "rejected"
status: "pending", },requestsList.
requestsList: CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>
$jazz.
CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>.$jazz: CoListJazzApi<CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>>
CoListJazzApi<CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>>.owner: Group
owner // Inherit the access controls of the requestsList );requestsList.
requestsList: CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>
$jazz.
CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>.$jazz: CoListJazzApi<CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>>
CoListJazzApi<CoList<({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | null>>.push(...items: (({ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap) | CoMapInit<...> | null)[]): number
Appends new elements to the end of an array, and returns the new length of the array.push(request); return
const request: { readonly account: { readonly profile: { readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap; readonly root: { readonly [x: string]: any; } & CoMap; } & Account; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap
request; }
const request: { readonly account: { readonly profile: { readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap; readonly root: { readonly [x: string]: any; } & CoMap; } & Account; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap
Using the write-only access users can submit requests that only administrators can review and approve.
async function
approveJoinRequest(
function approveJoinRequest(joinRequest: co.loaded<typeof JoinRequest, { account: true; }>, targetGroup: Group): Promise<boolean>
joinRequest:
joinRequest: CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>
import co
co.loaded<typeof
type loaded<T extends CoValueClassOrSchema, R extends ResolveQuery<T> = true> = R extends boolean | undefined ? NonNullable<InstanceOfSchemaCoValuesNullable<T>> : [NonNullable<InstanceOfSchemaCoValuesNullable<T>>] extends [...] ? Exclude<...> extends CoValue ? R extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean | undefined ? CoValue & Exclude<...> : [...] extends [...] ? Exclude<...> extends CoValue ? ItemDepth extends { ...; } ? readonly ((CoValue & ... 1 more ... & (ItemDepth extends boolean ... export loaded
JoinRequest, {
const JoinRequest: co.Map<{ account: co.Account<BaseAccountShape>; status: z.z.ZodLiteral<"pending" | "approved" | "rejected">; }, unknown, Account | Group>
account: true
account: true }>,targetGroup: Group
targetGroup:class Group
Group, ) { constaccount = await
const account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | CoMapLikeLoaded<...> | null
const Account: co.Account<BaseAccountShape>
Account.load(
AccountSchema<BaseAccountShape>.load: <ResolveQuery<co.Account<BaseAccountShape>>>(id: string, options?: { loadAs?: Account | AnonymousJazzAgent; resolve?: ({ ...; } & { ...; }) | ... 1 more ... | undefined; } | undefined) => Promise<...>
joinRequest.
joinRequest: CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>
CoMap.$jazz: CoMapJazzApi<CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>>
Jazz methods for CoMaps are inside this property. This allows CoMaps to be used as plain objects while still having access to Jazz methods, and also doesn't limit which key names can be used inside CoMaps.$jazz.
CoMapJazzApi<CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>>.refs: { account: Ref<NonNullable<{ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account>>; }
If property `prop` is a `coField.ref(...)`, you can use `coMap.$jazz.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.refs.account.
account: Ref<NonNullable<{ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account>>
Ref<NonNullable<{ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account>>.id: string
id); if (account) {
const account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | CoMapLikeLoaded<...> | null
targetGroup: Group
targetGroup.Group.addMember(member: Account, role: AccountRole): void (+3 overloads)
addMember(account, "reader");
const account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | CoMapLikeLoaded<...>
joinRequest.
joinRequest: CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>
CoMap.$jazz: CoMapJazzApi<CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>>
Jazz methods for CoMaps are inside this property. This allows CoMaps to be used as plain objects while still having access to Jazz methods, and also doesn't limit which key names can be used inside CoMaps.$jazz.CoMapJazzApi<CoMapLikeLoaded<{ readonly account: ({ readonly profile: ({ readonly name: string; readonly inbox?: string | undefined; readonly inboxInvite?: string | undefined; } & CoMap) | null; readonly root: ({ ...; } & CoMap) | null; } & Account) | null; readonly status: "pending" | ... 1 more ... | "rejected"; } & CoMap, { ...; }, 10, []>>.set<"status">(key: "status", value: "pending" | "approved" | "rejected"): void
Set a value on the CoMapset("status", "approved"); return true; } else { return false; } }