Overview
The @brainbox/core package provides shared types, utilities, node models, and business logic used across all Brainbox packages. It defines the core data structures for workspaces, nodes, documents, and synchronization.
Installation
npm install @brainbox/core
Exports
import * as Core from '@brainbox/core';
// Or import specific modules
import { generateId, IdType, NodeModel } from '@brainbox/core';
ID Generation
Utilities for generating type-safe unique identifiers using ULID.
generateId
Generates a new unique identifier for a specific type.
The type of ID to generate (Account, Workspace, User, Node, etc.)
A unique ID string with the type suffix
import { generateId, IdType } from '@brainbox/core';
const workspaceId = generateId(IdType.Workspace); // '01j1234567890abcdefghwc'
const nodeId = generateId(IdType.Node); // '01j1234567890abcdefghnd'
isIdOfType
Checks if an ID belongs to a specific type.
True if the ID matches the type
import { isIdOfType, IdType } from '@brainbox/core';
const isWorkspace = isIdOfType('01j1234567890abcdefghwc', IdType.Workspace); // true
getIdType
Extracts the type from an ID.
The ID to extract type from
import { getIdType, IdType } from '@brainbox/core';
const type = getIdType('01j1234567890abcdefghwc'); // IdType.Workspace
IdType Enum
enum IdType {
Account = 'ac',
Workspace = 'wc',
User = 'us',
Space = 'sp',
Page = 'pg',
Channel = 'ch',
Chat = 'ct',
Node = 'nd',
Message = 'ms',
Database = 'db',
Record = 'rc',
Folder = 'fl',
DatabaseView = 'dv',
Field = 'fd',
File = 'fi',
// ... and more
}
Node Models
Node models define the schema, permissions, and behavior for each node type.
Node Types
Top-level workspace container
Organizes pages and other nodes
Rich text document with CRDT support
Structured data collection with fields and records
Filtered/sorted view of a database
Column definition in a database
Public discussion channel
Private chat conversation
Message in a channel or chat
NodeModel Interface
interface NodeModel {
type: string;
attributesSchema: z.ZodType;
documentSchema?: z.ZodType;
canCreate: (context: CanCreateNodeContext) => boolean;
canUpdateAttributes: (context: CanUpdateAttributesContext) => boolean;
canUpdateDocument: (context: CanUpdateDocumentContext) => boolean;
canDelete: (context: CanDeleteNodeContext) => boolean;
canReact: (context: CanReactNodeContext) => boolean;
extractText: (id: string, attributes: NodeAttributes) => NodeText | null;
extractMentions: (id: string, attributes: NodeAttributes) => Mention[];
}
getNodeModel
Retrieve the model for a specific node type.
Node type (space, page, database, etc.)
The node model with schema and permissions
import { getNodeModel } from '@brainbox/core';
const pageModel = getNodeModel('page');
const canCreate = pageModel.canCreate(context);
Node Structure
type Node = {
id: string;
type: NodeType;
parentId: string;
rootId: string;
attributes: NodeAttributes;
createdAt: string;
createdBy: string;
updatedAt: string | null;
updatedBy: string | null;
};
Node Utilities
Extracts collaborators and their roles from node attributes.
attributes
NodeAttributes | NodeAttributes[]
required
Node attributes
import { extractNodeCollaborators } from '@brainbox/core';
const collaborators = extractNodeCollaborators(node.attributes);
// { 'user123': 'admin', 'user456': 'member' }
Extracts the display name from node attributes.
import { extractNodeName } from '@brainbox/core';
const name = extractNodeName(node.attributes); // 'My Page'
Determines the effective role for a collaborator on a node.
User’s workspace-level role
The effective role (admin, member, viewer)
import { extractNodeRole } from '@brainbox/core';
const role = extractNodeRole(tree, userId, workspaceRole);
if (role === 'admin') {
// User can edit
}
generateFractionalIndex
Generates a fractional index for positioning between two items.
import { generateFractionalIndex } from '@brainbox/core';
const newIndex = generateFractionalIndex(prevIndex, nextIndex);
Mutations
Mutation types for sync operations.
Mutation Types
type Mutation =
| CreateNodeMutation
| UpdateNodeMutation
| DeleteNodeMutation
| CreateNodeReactionMutation
| DeleteNodeReactionMutation
| NodeInteractionSeenMutation
| NodeInteractionOpenedMutation
| UpdateDocumentMutation;
CreateNodeMutation
type CreateNodeMutation = {
id: string;
type: 'node.create';
createdAt: string;
data: {
nodeId: string;
updateId: string;
createdAt: string;
data: string; // Encoded CRDT update
};
};
UpdateNodeMutation
type UpdateNodeMutation = {
id: string;
type: 'node.update';
createdAt: string;
data: {
nodeId: string;
updateId: string;
createdAt: string;
data: string; // Encoded CRDT update
};
};
UpdateDocumentMutation
type UpdateDocumentMutation = {
id: string;
type: 'document.update';
createdAt: string;
data: {
documentId: string;
updateId: string;
createdAt: string;
data: string; // Encoded CRDT update
};
};
Synchronizers
Synchronizer definitions for real-time sync.
SynchronizerMap Interface
interface SynchronizerMap {
'nodes.updates': {
input: NodesUpdatesSyncInput;
data: NodesUpdatesData;
};
'document.updates': {
input: DocumentUpdatesSyncInput;
data: DocumentUpdatesData;
};
'users': {
input: UsersSyncInput;
data: UsersData;
};
'node.reactions': {
input: NodeReactionsSyncInput;
data: NodeReactionsData;
};
'node.interactions': {
input: NodeInteractionsSyncInput;
data: NodeInteractionsData;
};
'node.tombstones': {
input: NodeTombstonesSyncInput;
data: NodeTombstonesData;
};
'collaborations': {
input: CollaborationsSyncInput;
data: CollaborationsData;
};
}
type SynchronizerInput = SynchronizerMap[keyof SynchronizerMap]['input'];
Type Definitions
WorkspaceRole
type WorkspaceRole = 'owner' | 'admin' | 'member' | 'viewer';
NodeRole
type NodeRole = 'admin' | 'member' | 'viewer';
MutationStatus
enum MutationStatus {
OK = 200,
CREATED = 201,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
FORBIDDEN = 403,
NOT_FOUND = 404,
CONFLICT = 409,
METHOD_NOT_ALLOWED = 405,
INTERNAL_SERVER_ERROR = 500,
}
Constants
// Export from lib/constants
export const MAX_FILE_SIZE: number;
export const SUPPORTED_FILE_TYPES: string[];
export const DEFAULT_PAGE_SIZE: number;
Utilities
// Export from lib/utils
export function debounce<T>(fn: T, delay: number): T;
export function throttle<T>(fn: T, delay: number): T;
export function clamp(value: number, min: number, max: number): number;