CoFeeds
CoFeeds are append-only data structures that track entries from different user sessions and accounts. Unlike other CoValues where everyone edits the same data, CoFeeds maintain separate streams for each session.
Each account can have multiple sessions (different browser tabs, devices, or app instances), making CoFeeds ideal for building features like activity logs, presence indicators, and notification systems.
The following examples demonstrate a practical use of CoFeeds:
- Multi-cursors - track user presence on a canvas with multiple cursors and out of bounds indicators
- Reactions - store per-user emoji reaction using a CoFeed
Creating CoFeeds
CoFeeds are defined by specifying the type of items they'll contain, similar to how you define CoLists:
// Define a schema for feed items const
Activity =
const Activity: CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>
import co
co.map({
map<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>(shape: { timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }): CoMapSchema<...> export map
timestamp: z.z.ZodDate
timestamp:import z
z.date(),
function date(params?: string | z.z.core.$ZodDateParams): z.z.ZodDate export date
action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">
action:import z
z.literal(["watering", "planting", "harvesting", "maintenance"]),
literal<["watering", "planting", "harvesting", "maintenance"]>(value: ["watering", "planting", "harvesting", "maintenance"], params?: string | z.z.core.$ZodLiteralParams): z.z.ZodLiteral<...> (+1 overload) export literal
notes: z.ZodOptional<z.z.ZodString>
notes:import z
z.optional(
optional<z.z.ZodString>(innerType: z.z.ZodString): z.ZodOptional<z.z.ZodString> export optional
import z
z.string()), }); // Define a feed of garden activities const
function string(params?: string | z.z.core.$ZodStringParams): z.z.ZodString export string
ActivityFeed =
const ActivityFeed: CoFeedSchema<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
import co
co.feed(
feed<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>(element: CoMapSchema<...>): CoFeedSchema<...> export feed
Activity); // Create a feed instance const
const Activity: CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>
activityFeed =
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
ActivityFeed.
const ActivityFeed: CoFeedSchema<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
create([]);
function create(init: CoFeedInit<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>, options?: { owner: Account | Group; } | Account | Group): CoFeedInstance<...>
Ownership
Like other CoValues, you can specify ownership when creating CoFeeds.
const
const teamGroup: Group
teamGroup =class Group
Group.create();
Group.create<Group>(this: CoValueClass<Group>, options?: { owner: Account; } | Account): Group
const teamGroup: Group
teamGroup.Group.addMember(member: Account, role: AccountRole): void (+1 overload)
addMember(colleagueAccount, "writer"); const
const colleagueAccount: Account | ({ [x: string]: any; } & Account)
teamFeed =
const teamFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
ActivityFeed.
const ActivityFeed: CoFeedSchema<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
create([], {
function create(init: CoFeedInit<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>, options?: { owner: Account | Group; } | Account | Group): CoFeedInstance<...>
owner: Group | Account
owner:const teamGroup: Group
teamGroup });
See Groups as permission scopes for more information on how to use groups to control access to CoFeeds.
Reading from CoFeeds
Since CoFeeds are made of entries from users over multiple sessions, you can access entries in different ways - from a specific user's session or from their account as a whole.
Per-Session Access
To retrieve entries from a session:
// Get the feed for a specific session const
sessionFeed =
const sessionFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perSession: { [key: `${RawAccountID}_session_z${string}`]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; [key: `sealer_z${string}/signer_z${string}_session_z${string}`]: CoFeedEntry<...>; }
The per-session view of this `CoFeed`perSession[const sessionId: `${RawAccountID}_session_z${string}` | `sealer_z${string}/signer_z${string}_session_z${string}`
sessionId]; // Latest entry from a sessionvar console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(sessionFeed?.
const sessionFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
value?.
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null
action: "watering" | "planting" | "harvesting" | "maintenance" | undefined
action); // "watering"
For convenience, you can also access the latest entry from the current session with inCurrentSession
:
// Get the feed for the current session const
currentSessionFeed =
const currentSessionFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.inCurrentSession: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
The current session's view of this `CoFeed` This is a shortcut for `this.perSession` where the session ID is the current session ID.inCurrentSession; // Latest entry from the current sessionvar console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(currentSessionFeed?.
const currentSessionFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
value?.
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null | undefined
action: "watering" | "planting" | "harvesting" | "maintenance" | undefined
action); // "harvesting"
Per-Account Access
To retrieve entries from a specific account (with entries from all sessions combined) use perAccount
:
// Get the feed for a specific account const
accountFeed =
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perAccount: { [key: string]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; }
The per-account view of this `CoFeed`perAccount[const accountId: string
accountId]; // Latest entry from the accountvar console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(accountFeed.
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
value?.
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null
action: "watering" | "planting" | "harvesting" | "maintenance" | undefined
action); // "watering"
For convenience, you can also access the latest entry from the current account with byMe
:
// Get the feed for the current account const
myLatestEntry =
const myLatestEntry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.byMe: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
The current account's view of this `CoFeed`byMe; // Latest entry from the current accountvar console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(myLatestEntry?.
const myLatestEntry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
value?.
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null | undefined
action: "watering" | "planting" | "harvesting" | "maintenance" | undefined
action); // "harvesting"
Feed Entries
All Entries
To retrieve all entries from a CoFeed:
// Get the feeds for a specific account and session const
accountFeed =
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perAccount: { [key: string]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; }
The per-account view of this `CoFeed`perAccount[const accountId: string
accountId]; constsessionFeed =
const sessionFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perSession: { [key: `${RawAccountID}_session_z${string}`]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; [key: `sealer_z${string}/signer_z${string}_session_z${string}`]: CoFeedEntry<...>; }
The per-session view of this `CoFeed`perSession[const sessionId: `${RawAccountID}_session_z${string}` | `sealer_z${string}/signer_z${string}_session_z${string}`
sessionId]; // Iterate over all entries from the account for (constentry of
const entry: SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
accountFeed.
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
all) {
all: IterableIterator<SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>>
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(entry.
const entry: SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
value); } // Iterate over all entries from the session for (const
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null
entry of
const entry: SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
sessionFeed.
const sessionFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
all) {
all: IterableIterator<SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>>
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(entry.
const entry: SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
value); }
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null
Latest Entry
To retrieve the latest entry from a CoFeed, ie. the last update:
// Get the latest entry from the current account const
latestEntry =
const latestEntry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.byMe: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
The current account's view of this `CoFeed`byMe;var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(`My last action was ${latestEntry?.
const latestEntry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | undefined
value?.
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null | undefined
action: "watering" | "planting" | "harvesting" | "maintenance" | undefined
action}`); // "My last action was harvesting" // Get the latest entry from each account constlatestEntriesByAccount =
const latestEntriesByAccount: { accountName: string | undefined; value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null; }[]
var Object: ObjectConstructor
Provides functionality common to all JavaScript objects.Object.
ObjectConstructor.values<CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>>(o: { [s: string]: CoFeedEntry<{ ...; } & CoMap>; } | ArrayLike<...>): CoFeedEntry<...>[] (+1 overload)
Returns an array of values of the enumerable own properties of an objectvalues(activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perAccount: { [key: string]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; }
The per-account view of this `CoFeed`perAccount).
Array<CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>>.map<{ accountName: string | undefined; value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null; }>(callbackfn: (value: CoFeedEntry<...>, index: number, array: CoFeedEntry<...>[]) => { accountName: string | undefined; value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null; }, thisArg?: any): { accountName: string | undefined; value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null; }[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.map(entry => ({
entry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
accountName: string | undefined
accountName:entry.
entry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
by: Account | null
by?.Account.profile: Profile | null | undefined
profile?.Profile.name: string | undefined
name,value:
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null
entry.
entry: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
value, }));
value: NonNullable<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap> | null
Writing to CoFeeds
CoFeeds are append-only; you can add new items, but not modify existing ones. This creates a chronological record of events or activities.
Adding Items
// Log a new activity
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.push(...items: ({ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap)[]): void
Push items to this `CoFeed` Items are appended to the current session's log. Each session (tab, device, app instance) maintains its own append-only log, which is then aggregated into the per-account view.push(Activity.
const Activity: CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>
create({
create: (init: { notes?: string | undefined; timestamp: Date; action: NonNullable<"watering" | "planting" | "harvesting" | "maintenance">; }, options?: { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | Account | Group) => { ...; } & CoMap
timestamp: Date
timestamp: newDate(),
var Date: DateConstructor new () => Date (+4 overloads)
action: NonNullable<"watering" | "planting" | "harvesting" | "maintenance">
action: "watering",notes?: string | undefined
notes: "Extra water for new seedlings" }));
Each item is automatically associated with the current user's session. You don't need to specify which session the item belongs to - Jazz handles this automatically.
Understanding Session Context
Each entry is automatically added to the current session's feed. When a user has multiple open sessions (like both a mobile app and web browser), each session creates its own separate entries:
// On mobile device:
fromMobileFeed.
const fromMobileFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.push(...items: ({ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap)[]): void
Push items to this `CoFeed` Items are appended to the current session's log. Each session (tab, device, app instance) maintains its own append-only log, which is then aggregated into the per-account view.push(Activity.
const Activity: CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>
create({
create: (init: { notes?: string | undefined; timestamp: Date; action: NonNullable<"watering" | "planting" | "harvesting" | "maintenance">; }, options?: { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | Account | Group) => { ...; } & CoMap
timestamp: Date
timestamp: newDate(),
var Date: DateConstructor new () => Date (+4 overloads)
action: NonNullable<"watering" | "planting" | "harvesting" | "maintenance">
action: "harvesting",notes?: string | undefined
notes: "Vegetable patch" })); // On web browser (same user):fromBrowserFeed.
const fromBrowserFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.push(...items: ({ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap)[]): void
Push items to this `CoFeed` Items are appended to the current session's log. Each session (tab, device, app instance) maintains its own append-only log, which is then aggregated into the per-account view.push(Activity.
const Activity: CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>
create({
create: (init: { notes?: string | undefined; timestamp: Date; action: NonNullable<"watering" | "planting" | "harvesting" | "maintenance">; }, options?: { owner: Account | Group; unique?: CoValueUniqueness["uniqueness"]; } | Account | Group) => { ...; } & CoMap
timestamp: Date
timestamp: newDate(),
var Date: DateConstructor new () => Date (+4 overloads)
action: NonNullable<"watering" | "planting" | "harvesting" | "maintenance">
action: "planting",notes?: string | undefined
notes: "Flower bed" })); // These are separate entries in the same feed, from the same account
Metadata
CoFeeds support metadata, which is useful for tracking information about the feed itself.
By
The by
property is the account that made the entry.
const
accountFeed =
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perAccount: { [key: string]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; }
The per-account view of this `CoFeed`perAccount[const accountId: string
accountId]; // Get the account that made the last entryvar console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(accountFeed?.
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
by: Account | null
by);
MadeAt
The madeAt
property is a timestamp of when the entry was added to the feed.
const
accountFeed =
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
activityFeed.
const activityFeed: CoFeedInstance<CoMapSchema<{ timestamp: z.z.ZodDate; action: z.z.ZodLiteral<"watering" | "planting" | "harvesting" | "maintenance">; notes: z.ZodOptional<z.z.ZodString>; }>>
CoFeed<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>.perAccount: { [key: string]: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>; }
The per-account view of this `CoFeed`perAccount[const accountId: string
accountId]; // Get the timestamp of the last updatevar console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(accountFeed?.
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
madeAt: Date
madeAt); // Get the timestamp of each entry for (constentry of
const entry: SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
accountFeed.
const accountFeed: CoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
all) {
all: IterableIterator<SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>>
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```console.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.log(entry.
const entry: SingleCoFeedEntry<{ timestamp: Date; action: "watering" | "planting" | "harvesting" | "maintenance"; notes: string | undefined; } & CoMap>
madeAt: Date
madeAt); }
Best Practices
When to Use CoFeeds
-
Use CoFeeds when:
- You need to track per-user/per-session data
- Time-based information matters (activity logs, presence)
-
Consider alternatives when:
- Data needs to be collaboratively edited (use CoMaps or CoLists)
- You need structured relationships (use CoMaps/CoLists with references)