@drakkar.software/octovault-sdk 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-RMN6N2PQ.js +1 -0
- package/dist/index.d.ts +1350 -0
- package/dist/index.js +2108 -0
- package/dist/platform/hash-wasm-shim.d.ts +1 -0
- package/dist/platform/hash-wasm-shim.js +1 -0
- package/dist/platform/index.d.ts +16 -0
- package/dist/platform/index.js +16 -0
- package/dist/platform/index.native.d.ts +17 -0
- package/dist/platform/index.native.js +16 -0
- package/package.json +77 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
import { PresenceStatus, VerificationLevel, ObjectBlobRef } from '@drakkar.software/dk-spaces-sdk';
|
|
2
|
+
export { InvitePreview, MAX_OBJECT_BLOB_BYTES, MatchRange, OBJECT_COLLECTIONS, ObjectBlobRef, PresenceStatus, RankedResult, ReadValue, SubscribeChangesOptions, TitleMatch, VerificationLevel, attachmentKind, buildSignedEventsRequest, clearLiveSyncBus, clockTime, dispatchDocChange, emitSseStatus, fold, formatBytes, initialsFor, isMuteActive, isWordStart, keyringPull, keyringPush, matchTitle, objIndexPull, objIndexPush, objInvPull, objInvPush, objLogName, objPubPull, objPubPush, objectBlobName, objectDirName, onSseStatus, plural, previewInvite, rankResults, registerPull, relativeTime, relativeTimeShort, subscribeChanges, typesIndexName, typesIndexPull, typesIndexPush } from '@drakkar.software/dk-spaces-sdk';
|
|
3
|
+
import * as _drakkar_software_starfish_spaces from '@drakkar.software/starfish-spaces';
|
|
4
|
+
import { SealedBlob, Space as Space$1, ObjectContentKind, ObjectType, ObjectNode, MutePrefs, Session, ReadPrefs, LinkedIdentity, DeviceKeys, PersistedSession, PublicProfile, PairResult } from '@drakkar.software/starfish-spaces';
|
|
5
|
+
export { CapMap, DerivedIdentity, ID, LinkedIdentity, MutePrefs, MuteValue, NewObjectInput, NodeAccess, NodeInviteLinkToken, ObjectContentKind, ObjectDirectoryEntry, ObjectNode, ObjectTreeNode, ObjectType, ObjectsIndex, PairResult, PasskeyEnrollment, PersistedSession, PubAccessMap, ObjectDirectoryEntry as PublicObjectDirEntry, ReadPrefs, SealedBlob, SeedLock, Session, SpaceAccessEntry, SpaceAccessError, SpaceAccessMap, SpaceInviteLinkToken, SpaceMeta, SpaceMetaUpdate, UnlockMethod, Vault, VaultLoad, acceptSpaceInvite, activeAccountOf, addObject, ancestors, archiveObject, breadcrumbs, broadcastSpaceMeta, buildTree, capProviderFor, clearNodeAccessCache, clearSpaceAccessStore, createNode, createSpace, createSpaceInviteLink, fingerprintFromUserId, generateSeedWords, getNodeAccess, getNodeAccessEntry, getSpaceAccessEntry, getSpaceClient, hydrateSpaceAccessStore, inviteToNode, inviteToSpace, isValidSeed, joinNodeByLink, joinSpaceByLink, linkAccessFromStore, localSpaceAccessEntries, makeJoinRequest, memberCapsFromStore, nextOrder, onSpaceMeta, ownerEnsureKeyring, ownerTrustedAdders, parseObjectDirectoryDoc, patchObject, readObjectDirectory, readSpaceAccess, reconcileSpaceMeta, recoverSpaceAccess, removeSpaceAccessEntry, removeSpaceMember, reorderObjects, reorderSpaces, reparentObject, rootIdentityOf, saveNodeAccessEntry, saveSpaceAccessEntry, sealToRecipient, sealToSelf, subtreeIds, unsealFromRecipient, unsealFromSelf, updateSpacesDoc, writeSpaceAccess } from '@drakkar.software/starfish-spaces';
|
|
6
|
+
export { bytesToHex, randomId, slugify as roomSlug } from '@drakkar.software/starfish-protocol';
|
|
7
|
+
import { WalDocument } from '@drakkar.software/starfish-wal';
|
|
8
|
+
export { WalDocument } from '@drakkar.software/starfish-wal';
|
|
9
|
+
import * as _drakkar_software_starfish_client from '@drakkar.software/starfish-client';
|
|
10
|
+
import { StarfishClient, Encryptor, ByteSealer } from '@drakkar.software/starfish-client';
|
|
11
|
+
export { ByteSealer, FileTooLargeError } from '@drakkar.software/starfish-client';
|
|
12
|
+
export { parseSseFrames } from '@drakkar.software/starfish-client/events';
|
|
13
|
+
export { createWalDocument, noopEncryptor } from '@drakkar.software/starfish-wal/client';
|
|
14
|
+
|
|
15
|
+
interface OctoVaultConfig {
|
|
16
|
+
syncBase: string;
|
|
17
|
+
syncNamespace: string | undefined;
|
|
18
|
+
syncPrefix: string;
|
|
19
|
+
eventsUrl: string;
|
|
20
|
+
webBase: string;
|
|
21
|
+
/** Separate namespace for `user/{userId}/_spaces` reads/writes, enabling a
|
|
22
|
+
* shared joined-space list across OctoVault and OctoChat. When set, both apps
|
|
23
|
+
* must agree on the same value. Absent → uses `syncNamespace` (per-app silo). */
|
|
24
|
+
sharedSpacesNamespace?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Configure the SDK with the sync server's coordinates. Call once at app boot
|
|
28
|
+
* (before any other SDK function), passing the env-derived values.
|
|
29
|
+
*
|
|
30
|
+
* Also configures the shared octospaces-sdk so all re-exported modules work
|
|
31
|
+
* without requiring a separate `configureOctoSpaces` call at the app level,
|
|
32
|
+
* then installs the OctoVault SpaceLayout via `configureSpaces`.
|
|
33
|
+
*/
|
|
34
|
+
declare function configureOctoVault(config: Partial<OctoVaultConfig>): void;
|
|
35
|
+
/** Base URL of the Starfish sync server, e.g. `https://sync.example.com`. */
|
|
36
|
+
declare function getSyncBase(): string;
|
|
37
|
+
/** Starfish namespace name (undefined for a root-mounted local dev server). */
|
|
38
|
+
declare function getSyncNamespace(): string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Namespaced path prefix (`/v1/<namespace>`, or '') for raw requests that live
|
|
41
|
+
* outside the StarfishClient (SSE `GET /events`, raw profile GET).
|
|
42
|
+
*/
|
|
43
|
+
declare function getSyncPrefix(): string;
|
|
44
|
+
/** SSE event endpoint URL. */
|
|
45
|
+
declare function getEventsUrl(): string;
|
|
46
|
+
|
|
47
|
+
interface KvAdapter {
|
|
48
|
+
get: (key: string) => Promise<string | null>;
|
|
49
|
+
set: (key: string, value: string) => Promise<void>;
|
|
50
|
+
remove: (key: string) => Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Configure the KV store. Call at app boot before any SDK function that reads
|
|
54
|
+
* or writes persisted state (member caps, mutes, reads, AI settings, etc.).
|
|
55
|
+
*
|
|
56
|
+
* Also wires the shared dk-spaces-sdk so its pull-cache, profile-cache, and
|
|
57
|
+
* space-access-store all use the same platform adapter.
|
|
58
|
+
*/
|
|
59
|
+
declare function configureKv(adapter: KvAdapter): void;
|
|
60
|
+
declare function kvGet(key: string): Promise<string | null>;
|
|
61
|
+
declare function kvSet(key: string, value: string): Promise<void>;
|
|
62
|
+
declare function kvRemove(key: string): Promise<void>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* OctoVault curated icon name set — the single source of truth for the `IconName`
|
|
66
|
+
* union. App components import this from the SDK and derive their runtime mapping
|
|
67
|
+
* from it; nothing in the SDK renders icons, but several domain tables (blocks,
|
|
68
|
+
* object-types) carry icon names as data so they need the type.
|
|
69
|
+
*/
|
|
70
|
+
type IconName = 'hash' | 'stream' | 'lock' | 'unlock' | 'plus' | 'plus-circle' | 'search' | 'send' | 'paperclip' | 'smile' | 'reply' | 'thread' | 'dm' | 'pin' | 'mic' | 'image' | 'video' | 'file' | 'link' | 'qr' | 'qr-scan' | 'check' | 'check-circle' | 'chev' | 'chevron-down' | 'chevron-up' | 'gear' | 'bell' | 'volume' | 'volume-off' | 'menu' | 'x' | 'arrow-l' | 'arrow-r' | 'shield' | 'people' | 'user' | 'dots' | 'dots-v' | 'camera' | 'key' | 'devices' | 'copy' | 'eye' | 'eye-off' | 'alert' | 'info' | 'edit' | 'trash' | 'logout' | 'at' | 'clock' | 'refresh' | 'zap' | 'globe' | 'folder' | 'share' | 'chat' | 'agents' | 'work' | 'book' | 'target' | 'layers' | 'text' | 'heading' | 'subheading' | 'list' | 'list-numbered' | 'todo' | 'quote' | 'code' | 'minus' | 'callout' | 'palette' | 'grip' | 'expand' | 'h1' | 'h2' | 'quote-mark' | 'code-block' | 'list-bullet' | 'list-number' | 'toggle-chev' | 'page' | 'square' | 'square-check' | 'drag' | 'duplicate' | 'move-to' | 'restore' | 'sidebar' | 'external' | 'emoji' | 'chev-down' | 'chev-right' | 'arrow-up' | 'arrow-down' | 'enter' | 'command' | 'table' | 'filter';
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Text size-scale variant names — mirrors the keys of the `type` const in
|
|
74
|
+
* `apps/mobile/src/theme.ts`. Defined here so non-UI SDK modules (blocks,
|
|
75
|
+
* page-model) can carry the variant as data without importing @/theme.
|
|
76
|
+
*/
|
|
77
|
+
type TextVariant = 'pageTitle' | 'display' | 'title' | 'heading' | 'subhead' | 'body' | 'callout' | 'footnote' | 'caption' | 'micro';
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Domain model for OctoVault.
|
|
81
|
+
*
|
|
82
|
+
* Re-exports the shared octospaces-sdk types (Space, ObjectNode, NodeAccess, …)
|
|
83
|
+
* and adds vault-specific types (User, Profile, AutomationMeta, PropValue, etc.).
|
|
84
|
+
*
|
|
85
|
+
* ObjectNode.access / ObjectNode.enc (from octospaces) replace the old Space.type
|
|
86
|
+
* ('private'|'public') model. Space is now a neutral container (no `type`, `ownerId`,
|
|
87
|
+
* or `write` field). The per-node access:'public' model replaces public spaces.
|
|
88
|
+
*
|
|
89
|
+
* ObjectNode.automation and ObjectNode.props moved into ObjectNode.meta:
|
|
90
|
+
* node.meta?.automation → automationOf(node) (from objects-ext.ts)
|
|
91
|
+
* node.meta?.props → propsOf(node) (from objects-ext.ts)
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
interface Space extends Space$1 {
|
|
95
|
+
/** Two-letter monogram shown in compact rail tiles. Populated by onSpaceMeta. */
|
|
96
|
+
short?: string;
|
|
97
|
+
/** Avatar data-URI (same contract as profile avatars). Populated by onSpaceMeta. */
|
|
98
|
+
image?: string;
|
|
99
|
+
/** Live unread count, overlaid by `useSpaces` from the read-marks store. */
|
|
100
|
+
unread?: number;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** A vault user display record (enriched from the public profile). */
|
|
104
|
+
interface User {
|
|
105
|
+
id: string;
|
|
106
|
+
name: string;
|
|
107
|
+
handle: string;
|
|
108
|
+
initials: string;
|
|
109
|
+
presence?: PresenceStatus;
|
|
110
|
+
/** Uploaded avatar as a data URI; absent → render the monogram initials. */
|
|
111
|
+
avatar?: string;
|
|
112
|
+
}
|
|
113
|
+
interface SecurityItem {
|
|
114
|
+
id: string;
|
|
115
|
+
icon: 'shield' | 'devices' | 'key';
|
|
116
|
+
title: string;
|
|
117
|
+
detail: string;
|
|
118
|
+
level: VerificationLevel;
|
|
119
|
+
mono?: boolean;
|
|
120
|
+
}
|
|
121
|
+
interface Profile {
|
|
122
|
+
user: User;
|
|
123
|
+
pronouns: string;
|
|
124
|
+
description: string;
|
|
125
|
+
status: string;
|
|
126
|
+
fingerprint: string;
|
|
127
|
+
security: SecurityItem[];
|
|
128
|
+
}
|
|
129
|
+
/** Scalar value that can be stored in an ObjectNode's `meta.props` map. */
|
|
130
|
+
type PropValue = string | number | boolean | null;
|
|
131
|
+
/** Stored, synced config of an automation node (`type:'automation'`), kept in
|
|
132
|
+
* `node.meta.automation`. Use {@link automationOf} / `objects-ext.ts` to access. */
|
|
133
|
+
interface AutomationMeta {
|
|
134
|
+
/** FK into the built-in provider catalog (e.g. 'rss' / 'http'). */
|
|
135
|
+
providerId: string;
|
|
136
|
+
/** Non-secret provider params (URLs, locations, etc.). */
|
|
137
|
+
params: Record<string, unknown>;
|
|
138
|
+
/** Scheduled-fetch cadence in minutes; `0` = commands-only (no scheduled run). */
|
|
139
|
+
intervalMin: number;
|
|
140
|
+
/** When set, the automation fires on every room open / background check,
|
|
141
|
+
* bypassing the `intervalMin` time gate. */
|
|
142
|
+
onOpen?: boolean;
|
|
143
|
+
/** Off → ticker skips and `onCommand` ignores; the room itself still renders. */
|
|
144
|
+
enabled: boolean;
|
|
145
|
+
/** Bot write credential SEALED to the minting account key. */
|
|
146
|
+
credential: SealedBlob;
|
|
147
|
+
/** The deterministic id of the device elected to run this automation. */
|
|
148
|
+
runOnDeviceId: string | null;
|
|
149
|
+
/** Last successful tick (epoch ms). */
|
|
150
|
+
lastRunAt: number | null;
|
|
151
|
+
/** Hash of the last text a scheduled fetch posted. */
|
|
152
|
+
lastFetchHash?: string | null;
|
|
153
|
+
/** Last error message — set on throw, cleared on success. */
|
|
154
|
+
lastError: string | null;
|
|
155
|
+
}
|
|
156
|
+
/** The builtin object types shipped with OctoVault renderers. A custom type is
|
|
157
|
+
* any `string` beyond these (the ObjectType union is open-ended). */
|
|
158
|
+
type BuiltinObjectType = 'folder' | 'page' | 'board' | 'task' | 'file' | 'image' | 'automation' | 'note' | 'calendar' | 'form' | 'feedback';
|
|
159
|
+
/** Runtime set of builtin type strings — use to branch "do we ship a renderer?". */
|
|
160
|
+
declare const BUILTIN_OBJECT_TYPES: readonly BuiltinObjectType[];
|
|
161
|
+
|
|
162
|
+
type Capability = 'pages' | 'boards' | 'notes' | 'calendar' | 'forms' | 'feedback';
|
|
163
|
+
interface CapabilityMeta {
|
|
164
|
+
label: string;
|
|
165
|
+
description: string;
|
|
166
|
+
objectType?: string;
|
|
167
|
+
}
|
|
168
|
+
declare const CAPABILITY_META: Record<Capability, CapabilityMeta>;
|
|
169
|
+
|
|
170
|
+
type PropKind$1 = 'text' | 'number' | 'select' | 'date' | 'checkbox' | 'url' | 'relation';
|
|
171
|
+
type EditorKind$1 = 'page' | 'board' | 'file' | 'record' | 'calendar' | 'form' | 'feedback' | 'none';
|
|
172
|
+
type ContentKind = 'append' | 'merge' | 'none';
|
|
173
|
+
interface SelectOption {
|
|
174
|
+
id: string;
|
|
175
|
+
label: string;
|
|
176
|
+
}
|
|
177
|
+
interface FieldDef {
|
|
178
|
+
key: string;
|
|
179
|
+
label: string;
|
|
180
|
+
kind: PropKind$1;
|
|
181
|
+
required?: boolean;
|
|
182
|
+
options?: SelectOption[];
|
|
183
|
+
/** For `kind: 'relation'` — the target ObjectType id. */
|
|
184
|
+
targetType?: string;
|
|
185
|
+
}
|
|
186
|
+
interface TypeDef {
|
|
187
|
+
id: string;
|
|
188
|
+
label: string;
|
|
189
|
+
icon: string;
|
|
190
|
+
color?: string;
|
|
191
|
+
editorKind: EditorKind$1;
|
|
192
|
+
contentKind: ContentKind;
|
|
193
|
+
fields: FieldDef[];
|
|
194
|
+
creatable: boolean;
|
|
195
|
+
archived: boolean;
|
|
196
|
+
}
|
|
197
|
+
interface TypesDoc {
|
|
198
|
+
types: TypeDef[];
|
|
199
|
+
}
|
|
200
|
+
declare const EMPTY_TYPES_DOC: TypesDoc;
|
|
201
|
+
declare function addType(doc: TypesDoc, def: Omit<TypeDef, 'id'>): {
|
|
202
|
+
doc: TypesDoc;
|
|
203
|
+
id: string;
|
|
204
|
+
};
|
|
205
|
+
declare function patchType(doc: TypesDoc, id: string, patch: Partial<Omit<TypeDef, 'id' | 'fields'>>): TypesDoc;
|
|
206
|
+
declare function addField$1(doc: TypesDoc, typeId: string, field: FieldDef): TypesDoc;
|
|
207
|
+
declare function patchField$1(doc: TypesDoc, typeId: string, fieldKey: string, patch: Partial<FieldDef>): TypesDoc;
|
|
208
|
+
declare function removeField(doc: TypesDoc, typeId: string, fieldKey: string): TypesDoc;
|
|
209
|
+
declare function reorderFields(doc: TypesDoc, typeId: string, keys: string[]): TypesDoc;
|
|
210
|
+
declare function archiveType(doc: TypesDoc, id: string): TypesDoc;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Object type registry — the single place that maps an {@link ObjectType} (builtin OR
|
|
214
|
+
* user-defined) to how the app treats it: which content sync model it uses, which icon
|
|
215
|
+
* renders it, which editor opens it, and what structured props it supports. Keeping this
|
|
216
|
+
* open-ended is what lets a custom type drop in without a renderer rewrite — unknown types
|
|
217
|
+
* resolve to a generic descriptor (a merge-doc with a neutral glyph) instead of being
|
|
218
|
+
* special-cased away.
|
|
219
|
+
*
|
|
220
|
+
* Pure data/logic (no React) so any layer — hooks picking a collection, the tree
|
|
221
|
+
* picking a glyph — reads the same descriptors.
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
/** The fixed renderer a type reuses — a closed set of editors the app ships.
|
|
225
|
+
* Data can declare new types but cannot ship new renderers without a code change. */
|
|
226
|
+
type EditorKind = 'page' | 'board' | 'file' | 'record' | 'calendar' | 'form' | 'feedback' | 'none';
|
|
227
|
+
type PropKind = 'text' | 'number' | 'select' | 'date' | 'checkbox' | 'url' | 'relation';
|
|
228
|
+
interface PropOption {
|
|
229
|
+
id: string;
|
|
230
|
+
label: string;
|
|
231
|
+
color?: string;
|
|
232
|
+
}
|
|
233
|
+
interface PropField {
|
|
234
|
+
key: string;
|
|
235
|
+
label: string;
|
|
236
|
+
kind: PropKind;
|
|
237
|
+
options?: PropOption[];
|
|
238
|
+
required?: boolean;
|
|
239
|
+
}
|
|
240
|
+
interface TypeDescriptor {
|
|
241
|
+
/** Default content sync model for this type (a node's own `contentKind` overrides). */
|
|
242
|
+
contentKind: ObjectContentKind;
|
|
243
|
+
icon: IconName;
|
|
244
|
+
label: string;
|
|
245
|
+
/** The fixed renderer this type opens in. */
|
|
246
|
+
editor: EditorKind;
|
|
247
|
+
/** Declared structured property fields. */
|
|
248
|
+
props: PropField[];
|
|
249
|
+
/** Whether this type appears in the "create new" menus. */
|
|
250
|
+
creatable: boolean;
|
|
251
|
+
/** Whether this type appears in the workspace sidebar tree. Unknown types default to true. */
|
|
252
|
+
workTree: boolean;
|
|
253
|
+
/** Whether this type is searchable in quick-find / command palette. Unknown types default to true. */
|
|
254
|
+
findable: boolean;
|
|
255
|
+
/** Placeholder title for a newly created object. */
|
|
256
|
+
defaultTitle?: string;
|
|
257
|
+
/** Theme color swatch for the type pill (undefined = default accent). */
|
|
258
|
+
color?: string;
|
|
259
|
+
/** Which app capability this type belongs to. */
|
|
260
|
+
capability?: Capability;
|
|
261
|
+
/** Whether the editor owns its own internal ScrollView (outer StackScreen must not add one). */
|
|
262
|
+
ownsScroll?: boolean;
|
|
263
|
+
}
|
|
264
|
+
/** @deprecated Use {@link TypeDescriptor} — kept for legacy call sites reading only icon/label/contentKind. */
|
|
265
|
+
type ObjectDescriptor = TypeDescriptor;
|
|
266
|
+
/** Resolve a type's descriptor — a builtin, or the generic fallback for a custom type. */
|
|
267
|
+
declare function objectDescriptor(type: ObjectType): TypeDescriptor;
|
|
268
|
+
/** Resolve the display icon for a node from its type descriptor. */
|
|
269
|
+
declare function iconForNode(node: Pick<ObjectNode, 'type'>): IconName;
|
|
270
|
+
/** A container type holds children but has no content of its own (folder/category) —
|
|
271
|
+
* in the tree it toggles open/closed instead of opening a content route. */
|
|
272
|
+
declare function isContainerType(type: ObjectType): boolean;
|
|
273
|
+
/** Whether a node appears in the workspace sidebar tree. Unknown custom types default to shown. */
|
|
274
|
+
declare function showsInWorkTree(node: Pick<ObjectNode, 'type'>): boolean;
|
|
275
|
+
/** Whether a type can be opened in an editor (clicking navigates rather than toggling). */
|
|
276
|
+
declare function isOpenableObjectType(type: ObjectType): boolean;
|
|
277
|
+
/** Whether a type is surfaced in quick-find and search. Unknown custom types default to findable. */
|
|
278
|
+
declare function isFindableType(type: ObjectType): boolean;
|
|
279
|
+
/** The effective content sync model for a node: its explicit `contentKind` wins (a
|
|
280
|
+
* custom type declares its own), else the type descriptor's default. */
|
|
281
|
+
declare function contentKindOf(node: Pick<ObjectNode, 'type' | 'contentKind'>): ObjectContentKind;
|
|
282
|
+
interface CreatableTypeEntry extends TypeDescriptor {
|
|
283
|
+
type: ObjectType;
|
|
284
|
+
}
|
|
285
|
+
/** Types the user can explicitly create from the "new object" menus. */
|
|
286
|
+
declare function creatableTypes(): CreatableTypeEntry[];
|
|
287
|
+
/** Default `props` map for a newly created object of this type (all fields absent = empty map). */
|
|
288
|
+
declare function defaultProps(_type: ObjectType): Record<string, PropValue>;
|
|
289
|
+
interface TypeRegistry {
|
|
290
|
+
descriptor: (type: string) => TypeDescriptor;
|
|
291
|
+
creatableTypes: () => CreatableTypeEntry[];
|
|
292
|
+
showsInWorkTree: (node: Pick<ObjectNode, 'type'>) => boolean;
|
|
293
|
+
iconForNode: (node: Pick<ObjectNode, 'type'>) => IconName;
|
|
294
|
+
isFindableType: (type: string) => boolean;
|
|
295
|
+
isContainerType: (type: string) => boolean;
|
|
296
|
+
isOpenableType: (type: string) => boolean;
|
|
297
|
+
/** All types — built-in + custom (non-archived). */
|
|
298
|
+
allTypes: () => Array<CreatableTypeEntry & {
|
|
299
|
+
isCustom: boolean;
|
|
300
|
+
}>;
|
|
301
|
+
}
|
|
302
|
+
/** Build a merged TypeRegistry from built-ins + custom TypeDefs.
|
|
303
|
+
* Custom types with the same id as a built-in are IGNORED (built-ins win). */
|
|
304
|
+
declare function makeRegistry(customTypes: TypeDef[]): TypeRegistry;
|
|
305
|
+
/** A static registry containing only built-in types (no React context needed).
|
|
306
|
+
* Use this at non-React call sites; React components should use `useTypeRegistry()`. */
|
|
307
|
+
declare const BUILTIN_REGISTRY: TypeRegistry;
|
|
308
|
+
/** The detail route an object opens into — collapses to a single generic route now that
|
|
309
|
+
* every object type (page, board, task, file, image, custom) is handled by one screen. */
|
|
310
|
+
declare function routeForNode(_node: Pick<ObjectNode, 'type'>): '/work/object/[id]';
|
|
311
|
+
/**
|
|
312
|
+
* Absolute shareable URL for an object — the "Copy link" target. Web-only by
|
|
313
|
+
* construction (it needs a routable origin; a native deep-link scheme would not
|
|
314
|
+
* open for a collaborator), so it returns `null` off web and callers hide the
|
|
315
|
+
* affordance.
|
|
316
|
+
*/
|
|
317
|
+
declare function objectLink(spaceId: string, node: Pick<ObjectNode, 'id' | 'type'>): string | null;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Friendly error mapping for user-facing failure surfaces (onboarding, accounts,
|
|
321
|
+
* pairing, joining spaces). The sync/crypto stack throws developer-grade messages
|
|
322
|
+
* ("Failed to fetch", WebAuthn DOMExceptions, Argon2/WASM internals) that erode
|
|
323
|
+
* trust exactly where it matters most — the identity ceremony. Every screen that
|
|
324
|
+
* renders an error to a human routes it through {@link humanizeError} first.
|
|
325
|
+
*
|
|
326
|
+
* The mapping is deliberately heuristic, not a taxonomy: we only special-case the
|
|
327
|
+
* failure shapes users actually hit (network down, dismissed passkey prompt,
|
|
328
|
+
* permission/server errors) and otherwise pass through messages that already read
|
|
329
|
+
* like sentences — much of `src/lib/starfish/*` throws carefully-worded strings
|
|
330
|
+
* ("That is not a valid space invite.") that SHOULD reach the user verbatim.
|
|
331
|
+
*/
|
|
332
|
+
/**
|
|
333
|
+
* Map an unknown thrown value to a human string. Pass a `fallback` to tailor the
|
|
334
|
+
* generic case to the action ("Couldn't create your identity.").
|
|
335
|
+
*/
|
|
336
|
+
declare function humanizeError(e: unknown, fallback?: string): string;
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Curated emoji shortcode table (GitHub/Slack style). Powers the composer's
|
|
340
|
+
* `:shortcode:` autocomplete (type `:` + a name to insert the glyph) and the
|
|
341
|
+
* visual icon picker (`components/ui/EmojiPicker`), which renders the same
|
|
342
|
+
* table grouped by category.
|
|
343
|
+
*
|
|
344
|
+
* Deliberately a small, hand-picked set (no data dependency) — common smileys,
|
|
345
|
+
* gestures, hearts, symbols and a few marine/theme picks. Several codes may map
|
|
346
|
+
* to the same glyph as aliases (`+1`/`thumbsup`, `plus`/`heavy_plus_sign`), so
|
|
347
|
+
* familiar names from either ecosystem resolve; the picker collapses aliases
|
|
348
|
+
* into one cell while search still matches every name.
|
|
349
|
+
*/
|
|
350
|
+
/** A shortcode paired with the glyph it inserts. */
|
|
351
|
+
interface EmojiMatch {
|
|
352
|
+
/** The shortcode without surrounding colons (e.g. `octopus`). */
|
|
353
|
+
code: string;
|
|
354
|
+
/** The emoji glyph it expands to. */
|
|
355
|
+
glyph: string;
|
|
356
|
+
}
|
|
357
|
+
/** A named group of glyphs — section data for the picker grid. */
|
|
358
|
+
interface EmojiCategory {
|
|
359
|
+
id: string;
|
|
360
|
+
/** Section heading shown above the group in the picker. */
|
|
361
|
+
label: string;
|
|
362
|
+
/** Glyphs in curated order, aliases already collapsed (one cell per glyph). */
|
|
363
|
+
emoji: EmojiMatch[];
|
|
364
|
+
}
|
|
365
|
+
/** Flat shortcode → glyph lookup (every alias present) — the autocomplete table. */
|
|
366
|
+
declare const EMOJI: Record<string, string>;
|
|
367
|
+
/** Picker sections: curated categories with aliases collapsed. */
|
|
368
|
+
declare const EMOJI_CATEGORIES: EmojiCategory[];
|
|
369
|
+
/** Every distinct glyph in curated order — the picker's "all" grid. */
|
|
370
|
+
declare const EMOJI_LIST: EmojiMatch[];
|
|
371
|
+
/**
|
|
372
|
+
* Detect the active emoji shortcode token at the end of `textBeforeCaret`.
|
|
373
|
+
* Returns the partial `query` (no leading colon) and `start`, the index of the
|
|
374
|
+
* opening colon in the original text, or `null` when the caret isn't in a token.
|
|
375
|
+
*/
|
|
376
|
+
declare function activeEmojiQuery(textBeforeCaret: string): {
|
|
377
|
+
query: string;
|
|
378
|
+
start: number;
|
|
379
|
+
} | null;
|
|
380
|
+
/**
|
|
381
|
+
* Up to `limit` shortcodes matching `query` (case-insensitive). Prefix matches
|
|
382
|
+
* rank above interior substring matches; ties keep table order. An empty query
|
|
383
|
+
* yields nothing — we only suggest once the user commits to a name character.
|
|
384
|
+
*/
|
|
385
|
+
declare function matchEmoji(query: string, limit?: number): EmojiMatch[];
|
|
386
|
+
/**
|
|
387
|
+
* Glyph search for the picker grid: ranks like {@link matchEmoji} (prefix over
|
|
388
|
+
* interior substring, ties in table order) across EVERY alias, then collapses
|
|
389
|
+
* aliases so each glyph appears once. Empty query yields nothing — the picker
|
|
390
|
+
* shows the category sections instead.
|
|
391
|
+
*/
|
|
392
|
+
declare function searchEmoji(query: string, limit?: number): EmojiMatch[];
|
|
393
|
+
|
|
394
|
+
interface LegalSection {
|
|
395
|
+
title: string;
|
|
396
|
+
paragraphs: string[];
|
|
397
|
+
}
|
|
398
|
+
interface LegalDoc {
|
|
399
|
+
title: string;
|
|
400
|
+
subtitle: string;
|
|
401
|
+
updated: string;
|
|
402
|
+
sections: LegalSection[];
|
|
403
|
+
}
|
|
404
|
+
declare const privacy: LegalDoc;
|
|
405
|
+
declare const terms: LegalDoc;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* dk-spaces-sdk 0.31 stopped wrapping the mute store — `createMutesStore` is gone.
|
|
409
|
+
* Build the generic `createPrefsStore` directly with dk-spaces-sdk's mute config
|
|
410
|
+
* preset, and re-derive the old room/space-specific method names this module used
|
|
411
|
+
* to expose (the generic store only has `get`/`mutate`/`subscribe`/etc.).
|
|
412
|
+
*/
|
|
413
|
+
|
|
414
|
+
declare const getMutePrefs: () => MutePrefs;
|
|
415
|
+
declare const isRoomMuted: (roomId: string) => boolean;
|
|
416
|
+
declare const isSpaceMuted: (spaceId: string) => boolean;
|
|
417
|
+
declare const isMuted: (roomId: string, spaceId: string) => boolean;
|
|
418
|
+
declare const subscribeMutes: (listener: () => void) => () => void;
|
|
419
|
+
declare const hydrateMutes: (userId: string, serverPrefs: MutePrefs) => Promise<void>;
|
|
420
|
+
declare const resetMutes: () => void;
|
|
421
|
+
declare const loadMutesFromKv: (userId: string) => Promise<MutePrefs>;
|
|
422
|
+
declare const setRoomMute: (session: Session, roomId: string, muted: boolean) => Promise<void>;
|
|
423
|
+
declare const setSpaceMute: (session: Session, spaceId: string, muted: boolean) => Promise<void>;
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* dk-spaces-sdk 0.31 stopped wrapping the read-marks store — `createReadsStore` is
|
|
427
|
+
* gone. Build the generic `createPrefsStore` directly with dk-spaces-sdk's read
|
|
428
|
+
* config preset, and re-derive the old room-specific method names this module used
|
|
429
|
+
* to expose (the generic store only has `get`/`mutate`/`subscribe`/etc.).
|
|
430
|
+
*/
|
|
431
|
+
|
|
432
|
+
declare const getReadPrefs: () => ReadPrefs;
|
|
433
|
+
declare const getRoomReadAt: (roomId: string) => number;
|
|
434
|
+
declare const subscribeReads: (listener: () => void) => () => void;
|
|
435
|
+
declare const loadReadMarksFromKv: (userId: string) => Promise<ReadPrefs>;
|
|
436
|
+
declare const hydrateReads: (userId: string, serverPrefs: ReadPrefs) => Promise<void>;
|
|
437
|
+
declare const resetReads: () => void;
|
|
438
|
+
declare const flushReadsNow: () => Promise<void>;
|
|
439
|
+
declare const setRoomReadAt: (session: Session, roomId: string, ts: number) => Promise<void>;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Identity bootstrap — thin wrappers that keep the old 2-arg call ergonomics
|
|
443
|
+
* (`buildSession({userId,keys}, name?)`, `deriveSession(seedWords, name?)`,
|
|
444
|
+
* `buildLinkedSession(linked, name?)`, `sessionFromPersisted(persisted)`) while
|
|
445
|
+
* injecting the per-call `clientOpts` required by starfish-spaces.
|
|
446
|
+
*
|
|
447
|
+
* dk-spaces-sdk 0.31 dropped its `sessionFromPersisted` proxy — clients now call
|
|
448
|
+
* starfish-spaces directly and must pass `clientOpts` themselves (2nd positional
|
|
449
|
+
* arg). `activeAccountOf` / `rootIdentityOf` take no `clientOpts` and are
|
|
450
|
+
* re-exported unchanged.
|
|
451
|
+
*/
|
|
452
|
+
|
|
453
|
+
/** Derive a session from a BIP-39 seed phrase. Preserves old `(seedWords, name?)` signature. */
|
|
454
|
+
declare function deriveSession(seedWords: string[], name?: string): Promise<Session>;
|
|
455
|
+
/** Build a session from a pre-derived root identity. Preserves old `({userId,keys}, name?)` signature. */
|
|
456
|
+
declare function buildSession(opts: {
|
|
457
|
+
userId: string;
|
|
458
|
+
keys: DeviceKeys;
|
|
459
|
+
}, name?: string): Promise<Session>;
|
|
460
|
+
/** Build a session from a QR-paired linked identity. Preserves old `(linked, name?)` signature. */
|
|
461
|
+
declare function buildLinkedSession(linked: LinkedIdentity, name?: string): Promise<Session>;
|
|
462
|
+
/** Restore a session from a persisted account. Preserves old `(persisted)` signature. */
|
|
463
|
+
declare function sessionFromPersisted(persisted: PersistedSession): Promise<Session>;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Per-identity quick-reaction palette — the six emojis offered in the inline
|
|
467
|
+
* message reaction picker ({@link MessageActions}). Synced server-side: the durable
|
|
468
|
+
* source of truth is the user's own `_spaces` doc (a `quickReactions` key alongside
|
|
469
|
+
* `mutes`/`reads`, see `registry.ts`), which a fresh device re-hydrates from its seed
|
|
470
|
+
* so an edit on one device propagates cross-device. Held as a module-level snapshot —
|
|
471
|
+
* like `mutes.ts` / `notification-settings.ts` — so a non-React caller can read it
|
|
472
|
+
* synchronously; React consumers subscribe via {@link QuickReactionsProvider}.
|
|
473
|
+
*
|
|
474
|
+
* The snapshot seeds with the curated defaults so a picker opened before the session
|
|
475
|
+
* hydrates still shows something sane; the synced palette overwrites it on load. There
|
|
476
|
+
* is no local-kv cache (unlike `mutes`, which warms one for the headless push task) —
|
|
477
|
+
* the palette has no background consumer, so an offline cold-start shows the defaults
|
|
478
|
+
* until the next successful pull heals it.
|
|
479
|
+
*/
|
|
480
|
+
|
|
481
|
+
/** How many emojis the quick-reaction palette holds — a fixed six slots. */
|
|
482
|
+
declare const QUICK_REACTION_COUNT = 6;
|
|
483
|
+
/** The default palette, kept identical to the original hardcoded set. */
|
|
484
|
+
declare const DEFAULT_QUICK_REACTIONS: string[];
|
|
485
|
+
/** The live palette — synchronous read for any non-React caller. */
|
|
486
|
+
declare function getQuickReactions(): string[];
|
|
487
|
+
/** Subscribe to snapshot changes (drives `useSyncExternalStore`). */
|
|
488
|
+
declare function subscribeQuickReactions(listener: () => void): () => void;
|
|
489
|
+
/** Replace the live snapshot and notify React consumers. */
|
|
490
|
+
declare function setQuickReactions(next: string[]): void;
|
|
491
|
+
/** Reset to defaults on sign-out so a fresh session never inherits the prior one's.
|
|
492
|
+
* Wired into `resetAccountScopedState` (the twin of `resetMutes`). */
|
|
493
|
+
declare function resetQuickReactions(): void;
|
|
494
|
+
/**
|
|
495
|
+
* Load the active account's palette into the snapshot. `serverPalette` comes from the
|
|
496
|
+
* SAME `_spaces` read that hydrates caps/mutes (session-context), so the doc isn't
|
|
497
|
+
* pulled twice. SERVER-AUTHORITATIVE wholesale replace — that is what lets an edit on
|
|
498
|
+
* another device propagate here. A `pending` local write is left untouched (its own emit
|
|
499
|
+
* already reflects the change). The strict {@link coerce} runs here so a doc that
|
|
500
|
+
* predates the feature (reads back `[]`) hydrates to the defaults.
|
|
501
|
+
*/
|
|
502
|
+
declare function hydrateQuickReactions(serverPalette: string[]): void;
|
|
503
|
+
/** Optimistically update the snapshot and sync the palette to the durable `_spaces`
|
|
504
|
+
* doc. `pending` brackets the round-trip so a navigation re-hydrate can't revert the
|
|
505
|
+
* optimistic emit before the server reflects it (twin of `setMute`). */
|
|
506
|
+
declare function saveQuickReactions(session: Session, emojis: string[]): Promise<void>;
|
|
507
|
+
|
|
508
|
+
interface AiSettings {
|
|
509
|
+
/** Master switch for AI agents & suggestions. Off by default until the user
|
|
510
|
+
* explicitly opts in — respects that on-device model availability is unknown
|
|
511
|
+
* at first launch. */
|
|
512
|
+
enabled: boolean;
|
|
513
|
+
}
|
|
514
|
+
declare const DEFAULT_AI_SETTINGS: AiSettings;
|
|
515
|
+
/** The live settings — synchronous read. */
|
|
516
|
+
declare function getAiSettings(): AiSettings;
|
|
517
|
+
/** Subscribe to snapshot changes (drives `useSyncExternalStore`). */
|
|
518
|
+
declare function subscribeAiSettings(listener: () => void): () => void;
|
|
519
|
+
/** Replace the live snapshot and notify React consumers. */
|
|
520
|
+
declare function setAiSettings(next: AiSettings): void;
|
|
521
|
+
/** Reset to defaults on sign-out so a fresh session never inherits the prior one's. */
|
|
522
|
+
declare function resetAiSettings(): void;
|
|
523
|
+
/** Read this identity's persisted settings (does NOT mutate the snapshot). */
|
|
524
|
+
declare function loadAiSettings(userId: string): Promise<AiSettings>;
|
|
525
|
+
/** Merge a patch into the live snapshot and persist it for the identity. */
|
|
526
|
+
declare function saveAiSettings(userId: string, patch: Partial<AiSettings>): Promise<void>;
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* One-shot handoff of the `_spaces` doc from session setup to {@link SpacesProvider}.
|
|
530
|
+
*
|
|
531
|
+
* Session establishment already reads the user's `_spaces` doc once (it carries the
|
|
532
|
+
* durable member caps — see session-context `hydrateCapsFor`). That doc ALSO holds
|
|
533
|
+
* the space list, so we stash it here for SpacesProvider to adopt instead of pulling
|
|
534
|
+
* the very same doc again on first paint. Lives in its own tiny module so neither
|
|
535
|
+
* `session-context` nor `spaces-context` has to import the other (they already form
|
|
536
|
+
* a one-way edge via `useSession`).
|
|
537
|
+
*/
|
|
538
|
+
|
|
539
|
+
/** Stash the space list read during session setup, keyed by identity. */
|
|
540
|
+
declare function primeSpaces(userId: string, spaces: Space[]): void;
|
|
541
|
+
/**
|
|
542
|
+
* Adopt the primed spaces for `userId`, if a fresh stash exists (set in the last few
|
|
543
|
+
* seconds, for this identity). Returns null — so the caller reads the doc itself —
|
|
544
|
+
* when absent, stale, or for a different account. Consuming clears the stash.
|
|
545
|
+
*/
|
|
546
|
+
declare function consumePrimedSpaces(userId: string): Space[] | null;
|
|
547
|
+
/** Drop any stash (account switch / sign-out). */
|
|
548
|
+
declare function clearPrimedSpaces(): void;
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Page-as-blocks model on a {@link WalDocument} (the Notion-style core).
|
|
552
|
+
*
|
|
553
|
+
* One page = one WAL document holding:
|
|
554
|
+
* - an RGA list **`order`** of block ids (ordering + insert/delete; reorder via
|
|
555
|
+
* the reconcile `setList`, which keeps unchanged ids and only diffs the move);
|
|
556
|
+
* - per block, a char-RGA text list **`text:{id}`** so two people editing the
|
|
557
|
+
* same block converge per character (`setText`);
|
|
558
|
+
* - per block, LWW registers **`type:{id}`** and **`checked:{id}`** for the
|
|
559
|
+
* block kind and the to-do state, plus the structure registers
|
|
560
|
+
* **`indent:{id}`** (nesting depth under lists/toggles), **`collapsed:{id}`**
|
|
561
|
+
* (a toggle's disclosure state) and **`ref:{id}`** (the child Object id a
|
|
562
|
+
* `page` block links to). All follow the same `name:{id}` register pattern so
|
|
563
|
+
* a future register costs one line here and nothing in the transport.
|
|
564
|
+
*
|
|
565
|
+
* Pure functions over a WalDocument: no React, no network — unit-testable with a
|
|
566
|
+
* fake transport. The `use-page` hook owns commit/pull; these only build ops.
|
|
567
|
+
*/
|
|
568
|
+
|
|
569
|
+
type BlockType = 'paragraph' | 'heading' | 'subheading' | 'todo' | 'bulleted' | 'numbered' | 'toggle' | 'quote' | 'code' | 'divider' | 'page' | 'image' | 'file' | 'bookmark' | 'table';
|
|
570
|
+
/** Block types that reference a child Object by id (no inline text; clicking navigates). */
|
|
571
|
+
declare const REF_BLOCK_TYPES: ReadonlySet<BlockType>;
|
|
572
|
+
/** Cached OG metadata for a `bookmark` block (stored as a JSON LWW register). */
|
|
573
|
+
interface BookmarkMeta {
|
|
574
|
+
title: string;
|
|
575
|
+
description?: string;
|
|
576
|
+
image?: string;
|
|
577
|
+
favicon?: string;
|
|
578
|
+
/** The URL the metadata was fetched for — used to invalidate when `text` changes. */
|
|
579
|
+
fetchedFor: string;
|
|
580
|
+
}
|
|
581
|
+
interface Block {
|
|
582
|
+
id: string;
|
|
583
|
+
type: BlockType;
|
|
584
|
+
text: string;
|
|
585
|
+
/** Only meaningful for `type === 'todo'`. */
|
|
586
|
+
checked?: boolean;
|
|
587
|
+
/** Nesting depth (0 = root). Drives the per-level indent and which toggle governs visibility. */
|
|
588
|
+
indent?: number;
|
|
589
|
+
/** Only meaningful for `type === 'toggle'` — whether its deeper-indented run is hidden. */
|
|
590
|
+
collapsed?: boolean;
|
|
591
|
+
/** Only meaningful for `type === 'page'|'image'|'file'` — the linked child Object's index id. */
|
|
592
|
+
ref?: string;
|
|
593
|
+
/** Only meaningful for `type === 'bookmark'` — cached OG metadata from the unfurl server. */
|
|
594
|
+
bookmark?: BookmarkMeta;
|
|
595
|
+
}
|
|
596
|
+
interface NewBlock {
|
|
597
|
+
type?: BlockType;
|
|
598
|
+
text?: string;
|
|
599
|
+
checked?: boolean;
|
|
600
|
+
indent?: number;
|
|
601
|
+
ref?: string;
|
|
602
|
+
}
|
|
603
|
+
/** Project the WAL document into an ordered, de-duplicated list of blocks. */
|
|
604
|
+
declare function readBlocks(doc: WalDocument): Block[];
|
|
605
|
+
/**
|
|
606
|
+
* The render-visible subset: blocks governed by a COLLAPSED toggle are hidden.
|
|
607
|
+
* A block is "governed" by the nearest preceding block with a SHALLOWER indent;
|
|
608
|
+
* walking the list once with a hide-threshold covers arbitrarily nested toggles
|
|
609
|
+
* (a visible block at/above the threshold ends the hidden run; if it is itself a
|
|
610
|
+
* collapsed toggle it starts a new one). Pure — unit-tested without a renderer.
|
|
611
|
+
*/
|
|
612
|
+
declare function visibleBlocks(blocks: Block[]): Block[];
|
|
613
|
+
/** Insert a new block at `index` (clamped). Returns the new block id. */
|
|
614
|
+
declare function insertBlock(doc: WalDocument, index: number, init?: NewBlock): string;
|
|
615
|
+
/** Append a block to the end. Returns the new block id. */
|
|
616
|
+
declare function appendBlock(doc: WalDocument, init?: NewBlock): string;
|
|
617
|
+
/** Replace a block's body text (character-level CRDT merge). */
|
|
618
|
+
declare function setBlockText(doc: WalDocument, id: string, text: string): void;
|
|
619
|
+
declare function setBlockType(doc: WalDocument, id: string, type: BlockType): void;
|
|
620
|
+
declare function setBlockChecked(doc: WalDocument, id: string, checked: boolean): void;
|
|
621
|
+
/** Set a block's nesting depth (clamped to ≥ 0; 0 clears the register). */
|
|
622
|
+
declare function setBlockIndent(doc: WalDocument, id: string, indent: number): void;
|
|
623
|
+
declare function setBlockCollapsed(doc: WalDocument, id: string, collapsed: boolean): void;
|
|
624
|
+
/** Point a `page` block at the child Object it links to. */
|
|
625
|
+
declare function setBlockRef(doc: WalDocument, id: string, ref: string): void;
|
|
626
|
+
/** Remove a block: drop it from `order`, clear its text, tombstone its props. */
|
|
627
|
+
declare function removeBlock(doc: WalDocument, id: string): void;
|
|
628
|
+
/** Move a block to `toIndex` via a minimal reconcile of the order list. */
|
|
629
|
+
declare function moveBlock(doc: WalDocument, id: string, toIndex: number): void;
|
|
630
|
+
/**
|
|
631
|
+
* Enter-to-split: rewrite `id`'s text to `head` and insert a sibling holding the
|
|
632
|
+
* tail DIRECTLY after it, as ONE op batch (the hook's single `touch()` commits
|
|
633
|
+
* them together, so a concurrent fold never sees a half-split). The caller picks
|
|
634
|
+
* the tail's type (list continuation) and indent. Returns the new block id, or
|
|
635
|
+
* null when `id` is no longer in the order (concurrently removed).
|
|
636
|
+
*/
|
|
637
|
+
declare function splitBlock(doc: WalDocument, id: string, head: string, init?: NewBlock): string | null;
|
|
638
|
+
/**
|
|
639
|
+
* Backspace-at-start: append `id`'s text to the PREVIOUS block and remove `id`.
|
|
640
|
+
* `textOverride` lets the editor pass its live (not-yet-committed) field value so
|
|
641
|
+
* the merge never resurrects stale committed text. Returns the surviving block id
|
|
642
|
+
* and the seam offset (where the caret should land), or null at the top of the doc.
|
|
643
|
+
*/
|
|
644
|
+
declare function mergeBlockIntoPrevious(doc: WalDocument, id: string, textOverride?: string): {
|
|
645
|
+
prevId: string;
|
|
646
|
+
offset: number;
|
|
647
|
+
} | null;
|
|
648
|
+
/** Insert a copy of `id` (type/text/checked/indent/ref/bookmark) directly below it. */
|
|
649
|
+
declare function duplicateBlock(doc: WalDocument, id: string): string | null;
|
|
650
|
+
/**
|
|
651
|
+
* Undo for a structural delete: re-insert a previously {@link removeBlock}-ed
|
|
652
|
+
* block at `index` with its ORIGINAL id (so a concurrent device that still holds
|
|
653
|
+
* ops for it converges onto the same block). Re-setting the LWW registers and
|
|
654
|
+
* re-typing the text revives the tombstoned state.
|
|
655
|
+
*/
|
|
656
|
+
declare function restoreBlock(doc: WalDocument, index: number, block: Block): void;
|
|
657
|
+
/** Store (or update) the fetched OG metadata for a `bookmark` block. */
|
|
658
|
+
declare function setBlockBookmark(doc: WalDocument, id: string, meta: BookmarkMeta): void;
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Block-type presentation table — the single source of truth for how each
|
|
662
|
+
* {@link BlockType} renders, reads and is reached in the page editor (see
|
|
663
|
+
* {@link PageView}).
|
|
664
|
+
*
|
|
665
|
+
* Keeps the editor component declarative: instead of inline `switch`/`if` on the
|
|
666
|
+
* type for the label, slash-menu section, icon, text variant, mono-ness,
|
|
667
|
+
* multiline-ness and placeholder, components look these up here. Also carries
|
|
668
|
+
* the Markdown shortcut prefixes and the slash-menu search keywords, plus the
|
|
669
|
+
* pure typing-behaviour helpers (Enter continuation, slash filtering, numbered
|
|
670
|
+
* run counting) so the editor's "feel" logic is unit-testable without React.
|
|
671
|
+
*/
|
|
672
|
+
|
|
673
|
+
/** Slash/insert menu grouping (Notion-style sections, micro mono headers). */
|
|
674
|
+
type BlockSection = 'basic' | 'list' | 'other';
|
|
675
|
+
declare const BLOCK_SECTIONS: {
|
|
676
|
+
id: BlockSection;
|
|
677
|
+
label: string;
|
|
678
|
+
}[];
|
|
679
|
+
/** A {@link BlockType}'s presentation: how it reads and which editor it uses. */
|
|
680
|
+
interface BlockTypeDef {
|
|
681
|
+
type: BlockType;
|
|
682
|
+
/** Menu label. */
|
|
683
|
+
label: string;
|
|
684
|
+
/** Glyph in the block-type / slash menu and (where shown) the gutter. */
|
|
685
|
+
icon: IconName;
|
|
686
|
+
/** Slash/insert menu section. */
|
|
687
|
+
section: BlockSection;
|
|
688
|
+
/** Extra slash-filter aliases beyond the label ("/h1", "/ul", "/check"…). */
|
|
689
|
+
keywords: string[];
|
|
690
|
+
/** Type-scale step the block's text renders at (also the editor's `textVariant`). */
|
|
691
|
+
variant: TextVariant;
|
|
692
|
+
/** Render the text in JetBrains Mono (code blocks). */
|
|
693
|
+
mono: boolean;
|
|
694
|
+
/** Editor allows in-block newlines (web Shift+Enter; plain Enter still splits). */
|
|
695
|
+
multiline: boolean;
|
|
696
|
+
/** Placeholder shown ONLY in the focused empty editor (unfocused empties are blank). */
|
|
697
|
+
placeholder: string;
|
|
698
|
+
/** Start-of-line Markdown shortcuts that convert a block to this type. */
|
|
699
|
+
mdPrefixes?: string[];
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Every block type, in the order they appear in the block-type / slash menu.
|
|
703
|
+
* `divider` renders as a rule (no text editor); `page` renders as a child-page
|
|
704
|
+
* link row (its content lives in the linked Object, not in this doc).
|
|
705
|
+
*/
|
|
706
|
+
declare const BLOCK_TYPES: BlockTypeDef[];
|
|
707
|
+
/** The full presentation def for a block type. */
|
|
708
|
+
declare function blockDef(type: BlockType): BlockTypeDef;
|
|
709
|
+
declare const labelFor: (type: BlockType) => string;
|
|
710
|
+
declare const iconFor: (type: BlockType) => IconName;
|
|
711
|
+
declare const variantFor: (type: BlockType) => TextVariant;
|
|
712
|
+
declare const monoFor: (type: BlockType) => boolean;
|
|
713
|
+
declare const isMultiline: (type: BlockType) => boolean;
|
|
714
|
+
declare const placeholderFor: (type: BlockType) => string;
|
|
715
|
+
/**
|
|
716
|
+
* What Enter at the end of a `type` block creates next: lists/todos/toggles
|
|
717
|
+
* continue themselves; everything else (headings, quotes, paragraphs…) yields a
|
|
718
|
+
* fresh paragraph — the Notion continuation rule.
|
|
719
|
+
*/
|
|
720
|
+
declare function continuationType(type: BlockType): BlockType;
|
|
721
|
+
/** Whether Enter on an EMPTY block of this type should demote it to a paragraph
|
|
722
|
+
* (ending the list) instead of stacking another empty item. */
|
|
723
|
+
declare function endsListOnEmptyEnter(type: BlockType): boolean;
|
|
724
|
+
interface MdShortcutMatch {
|
|
725
|
+
type: BlockType;
|
|
726
|
+
/** Whatever the user typed after the prefix — kept as the block's text. */
|
|
727
|
+
rest: string;
|
|
728
|
+
/** `[x] ` starts a CHECKED to-do. */
|
|
729
|
+
checked?: boolean;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Resolve a start-of-line Markdown shortcut: if `text` STARTS WITH a known
|
|
733
|
+
* prefix (e.g. `"# "`, `"- "`, `"[x] "`, `"--- "`), return the {@link BlockType}
|
|
734
|
+
* it converts to plus the remainder to keep as the block's text — so pasting
|
|
735
|
+
* `"# Title"` converts AND keeps "Title". Prefix-based (not exact-match) so the
|
|
736
|
+
* shortcut also fires when typed before existing text.
|
|
737
|
+
*/
|
|
738
|
+
declare function mdShortcut(text: string): MdShortcutMatch | undefined;
|
|
739
|
+
/**
|
|
740
|
+
* Filter the slash menu by the text typed after "/" — case-insensitive substring
|
|
741
|
+
* over the label plus prefix match over the keyword aliases, preserving the
|
|
742
|
+
* canonical menu order (Notion keeps its sections stable rather than re-ranking).
|
|
743
|
+
*/
|
|
744
|
+
declare function filterBlockTypes(query: string): BlockTypeDef[];
|
|
745
|
+
/**
|
|
746
|
+
* Per-run numbering for `numbered` blocks: a run restarts after any
|
|
747
|
+
* non-numbered block at the SAME indent, while deeper-indented content nested
|
|
748
|
+
* under an item does NOT break its parent's run (each indent level keeps its
|
|
749
|
+
* own counter, reset when the level is interrupted). Render-side only — the
|
|
750
|
+
* model stores no ordinals, so concurrent inserts renumber for free.
|
|
751
|
+
*/
|
|
752
|
+
declare function listOrdinals(blocks: Pick<Block, 'id' | 'type' | 'indent'>[]): Map<string, number>;
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Generic schema-driven content model — the shared vocabulary between
|
|
756
|
+
* `page-content.ts`, `board-content.ts`, and the future WAL/merge content
|
|
757
|
+
* engines for custom types.
|
|
758
|
+
*
|
|
759
|
+
* A `ContentSchema` describes the WAL key layout for an object type:
|
|
760
|
+
* - `collections`: the named id-lists (RGAs) that hold item ids
|
|
761
|
+
* - For each item field: whether it is char-RGA text or a LWW register
|
|
762
|
+
*
|
|
763
|
+
* `PAGE_SCHEMA` and `BOARD_SCHEMA` express the existing page/board layouts as
|
|
764
|
+
* data. Consumers that need to open a generic WAL doc (e.g. a future record
|
|
765
|
+
* editor) read the schema instead of hard-coding key names.
|
|
766
|
+
*/
|
|
767
|
+
/** How a field's value is stored in the WAL doc. */
|
|
768
|
+
type FieldKind = 'charRga' | 'lww';
|
|
769
|
+
interface ContentField {
|
|
770
|
+
key: string;
|
|
771
|
+
kind: FieldKind;
|
|
772
|
+
}
|
|
773
|
+
/** One named id-list (RGA) in the WAL doc, plus the per-item fields. */
|
|
774
|
+
interface ContentCollection {
|
|
775
|
+
/** The WAL key for the id-list (e.g. `'order'`, `'columns'`, `'tasks'`). */
|
|
776
|
+
listKey: string;
|
|
777
|
+
/** Per-item field descriptors; keys are the base name (actual key = `${base}:${id}`). */
|
|
778
|
+
fields: ContentField[];
|
|
779
|
+
}
|
|
780
|
+
/** Full schema for an object type's WAL content doc. */
|
|
781
|
+
interface ContentSchema {
|
|
782
|
+
collections: ContentCollection[];
|
|
783
|
+
}
|
|
784
|
+
/** Page content schema: one `order` collection whose items have char-RGA text
|
|
785
|
+
* plus LWW registers for type/checked/indent/collapsed/ref. */
|
|
786
|
+
declare const PAGE_SCHEMA: ContentSchema;
|
|
787
|
+
/** Board content schema: `columns` collection (title/done per column) plus
|
|
788
|
+
* `tasks` collection (col/order/status/title/notes per task).
|
|
789
|
+
* NOTE: In Phase F, tasks will become first-class ObjectNodes and the `tasks`
|
|
790
|
+
* collection will be removed from this schema. */
|
|
791
|
+
declare const BOARD_SCHEMA: ContentSchema;
|
|
792
|
+
declare const CALENDAR_SCHEMA: ContentSchema;
|
|
793
|
+
declare const FORM_SCHEMA: ContentSchema;
|
|
794
|
+
declare const FEEDBACK_SCHEMA: ContentSchema;
|
|
795
|
+
/** Resolve the schema for an object's content kind.
|
|
796
|
+
* Returns null for `'none'` (no content doc). */
|
|
797
|
+
declare function schemaFor(editorKind: string): ContentSchema | null;
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Per-block discussions on a {@link WalDocument} — the Notion-style "floating
|
|
801
|
+
* comment" core. Lives in a page's **sibling** comments WAL doc (one per page,
|
|
802
|
+
* keyed `…__comments`), separate from the page content doc so the page snapshot
|
|
803
|
+
* stays lean and comments load in parallel.
|
|
804
|
+
*
|
|
805
|
+
* A **discussion** is the thread anchored to one block (by its stable block id):
|
|
806
|
+
* - a per-block RGA list **`comments:{blockId}`** of comment ids (append order);
|
|
807
|
+
* - per comment, the author **`author:{commentId}`** (LWW, the account userId —
|
|
808
|
+
* the device key only *signs* the op), the timestamp **`created:{commentId}`**
|
|
809
|
+
* (LWW) and a char-RGA body **`body:{commentId}`** so two people editing the
|
|
810
|
+
* same comment converge per character;
|
|
811
|
+
* - per block, a thread-level **`resolved:{blockId}`** flag (LWW);
|
|
812
|
+
* - per (comment, reactor), an emoji set **`react:{commentId}:{userId}`** (LWW
|
|
813
|
+
* JSON array). A **per-reactor** register — not one shared map — so two members
|
|
814
|
+
* reacting at once never clobber each other; the projection folds the
|
|
815
|
+
* `react:{commentId}:*` registers into `{ emoji → userIds[] }`.
|
|
816
|
+
*
|
|
817
|
+
* All registers follow the same `name:{id}` pattern as {@link page-content}, so a
|
|
818
|
+
* future field costs one line here and nothing in the transport. Pure functions
|
|
819
|
+
* over a WalDocument (no React, no network) — the `use-comments` hook owns
|
|
820
|
+
* commit/pull; these only build ops.
|
|
821
|
+
*/
|
|
822
|
+
|
|
823
|
+
/** One emoji and the members who reacted with it. */
|
|
824
|
+
interface CommentReaction {
|
|
825
|
+
emoji: string;
|
|
826
|
+
userIds: string[];
|
|
827
|
+
}
|
|
828
|
+
/** A single comment in a block's discussion. */
|
|
829
|
+
interface Comment {
|
|
830
|
+
id: string;
|
|
831
|
+
/** Account userId of the author (resolved to a name/avatar at the UI layer). */
|
|
832
|
+
author: string;
|
|
833
|
+
/** Creation timestamp (ms since epoch). */
|
|
834
|
+
createdAt: number;
|
|
835
|
+
/** Char-RGA body text. */
|
|
836
|
+
body: string;
|
|
837
|
+
/** Aggregated emoji reactions (empty when none). */
|
|
838
|
+
reactions: CommentReaction[];
|
|
839
|
+
}
|
|
840
|
+
/** The discussion anchored to one block. */
|
|
841
|
+
interface DiscussionThread {
|
|
842
|
+
blockId: string;
|
|
843
|
+
resolved: boolean;
|
|
844
|
+
comments: Comment[];
|
|
845
|
+
}
|
|
846
|
+
/** Project the discussion for a single block (empty thread when none exist). */
|
|
847
|
+
declare function readThread(doc: WalDocument, blockId: string): DiscussionThread;
|
|
848
|
+
/** Project every block's discussion that holds at least one comment, keyed by
|
|
849
|
+
* block id. The page editor reads this once and indexes per block. */
|
|
850
|
+
declare function readThreads(doc: WalDocument): Map<string, DiscussionThread>;
|
|
851
|
+
/** Most-recent comment timestamp in a thread (0 when empty) — the unread sort key. */
|
|
852
|
+
declare function threadLastActivity(thread: DiscussionThread): number;
|
|
853
|
+
/** Add a comment to a block's discussion. Returns the new comment id. */
|
|
854
|
+
declare function addComment(doc: WalDocument, blockId: string, authorUserId: string, text: string, createdAt?: number): string;
|
|
855
|
+
/** Replace a comment's body text (character-level CRDT merge). */
|
|
856
|
+
declare function setCommentBody(doc: WalDocument, commentId: string, text: string): void;
|
|
857
|
+
/** Remove a comment: drop it from the block's list, clear its body, and tombstone
|
|
858
|
+
* its author/timestamp registers plus every reactor's register for it. */
|
|
859
|
+
declare function removeComment(doc: WalDocument, blockId: string, commentId: string): void;
|
|
860
|
+
/** Mark a block's discussion resolved (or reopen it). Clears the register when
|
|
861
|
+
* reopening so a resolved-then-reopened thread leaves no snapshot residue. */
|
|
862
|
+
declare function resolveThread(doc: WalDocument, blockId: string, resolved: boolean): void;
|
|
863
|
+
/** Toggle one member's emoji reaction on a comment. Updates only that member's
|
|
864
|
+
* own `react:{commentId}:{userId}` register, so concurrent reactors never
|
|
865
|
+
* clobber each other; the register is cleared when their last emoji is removed. */
|
|
866
|
+
declare function toggleReaction(doc: WalDocument, commentId: string, userId: string, emoji: string): void;
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Kanban-board view definition on a {@link WalDocument} (the `board` object type).
|
|
870
|
+
*
|
|
871
|
+
* One board WAL doc holds ONLY the **column list** (title + done-flag). Tasks are
|
|
872
|
+
* now first-class {@link ObjectNode}s (`type === 'task'`, `parentId === boardId`);
|
|
873
|
+
* see {@link task-model} for the projection from nodes → board view.
|
|
874
|
+
*
|
|
875
|
+
* Every mutation is an idempotent CRDT op. Pure over a WalDocument (no React/network).
|
|
876
|
+
*/
|
|
877
|
+
|
|
878
|
+
interface Column {
|
|
879
|
+
id: string;
|
|
880
|
+
title: string;
|
|
881
|
+
/** This column is the board's "Done" group: tasks in it render checked/struck. */
|
|
882
|
+
done: boolean;
|
|
883
|
+
}
|
|
884
|
+
/** Project the WAL document into the board's column list. */
|
|
885
|
+
declare function readColumns(doc: WalDocument): Column[];
|
|
886
|
+
/**
|
|
887
|
+
* Sort key for a card landing between two siblings — fractional indexing over
|
|
888
|
+
* the plain-number `order` register, so ANY drop position is a single LWW write.
|
|
889
|
+
*/
|
|
890
|
+
declare function orderBetween(above: number | undefined, below: number | undefined): number;
|
|
891
|
+
declare function addColumn(doc: WalDocument, title: string): string;
|
|
892
|
+
declare function renameColumn(doc: WalDocument, id: string, title: string): void;
|
|
893
|
+
declare function setColumnDone(doc: WalDocument, id: string, done: boolean): void;
|
|
894
|
+
declare function moveColumn(doc: WalDocument, id: string, toIndex: number): void;
|
|
895
|
+
declare function deleteColumn(doc: WalDocument, id: string): void;
|
|
896
|
+
declare function seedDefaultColumns(doc: WalDocument): void;
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Inline table block model on a {@link WalDocument} — a page's WAL doc can hold
|
|
900
|
+
* one or more table blocks among its other blocks, each keyed by its block id `T`.
|
|
901
|
+
*
|
|
902
|
+
* CRDT design decisions
|
|
903
|
+
* - Columns: RGA list `tblcols:{T}` of column ids + per-column LWW registers.
|
|
904
|
+
* Mirrors board-content's column list exactly (`coltitle:{c}` pattern).
|
|
905
|
+
* - Rows: RGA list `tblrows:{T}` of row ids. Like page-content's `order`.
|
|
906
|
+
* - Cells: `tcell:{r}:{c}` — whole-value LWW scalar registers. Deliberate trade-off:
|
|
907
|
+
* concurrent edits to the SAME cell are last-writer-wins (simpler, no char-RGA).
|
|
908
|
+
* Concurrent edits to DIFFERENT cells / rows / columns converge freely.
|
|
909
|
+
* - Sort + filters: `tblsort:{T}` / `tblfilters:{T}` — LWW JSON objects shared
|
|
910
|
+
* across all collaborators. Sort/filter are render-time derivations: the stored
|
|
911
|
+
* `tblrows` order is NEVER mutated by sort.
|
|
912
|
+
*
|
|
913
|
+
* Pure functions over a WalDocument: no React, no network — unit-testable.
|
|
914
|
+
*/
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Swatch names available for `TableSelectOption` colors.
|
|
918
|
+
* Mirrors `SwatchName` from `theme.ts` (SDK copy avoids an app-layer dependency).
|
|
919
|
+
*/
|
|
920
|
+
type TableSwatchName = 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'purple' | 'pink';
|
|
921
|
+
type TableColType = 'text' | 'number' | 'select' | 'checkbox';
|
|
922
|
+
/** One option in a `select` column — id + display label + categorical swatch. */
|
|
923
|
+
interface TableSelectOption {
|
|
924
|
+
id: string;
|
|
925
|
+
label: string;
|
|
926
|
+
swatch: TableSwatchName;
|
|
927
|
+
}
|
|
928
|
+
interface TableColumn {
|
|
929
|
+
id: string;
|
|
930
|
+
title: string;
|
|
931
|
+
type: TableColType;
|
|
932
|
+
/** Options for `type === 'select'` columns. */
|
|
933
|
+
options?: TableSelectOption[];
|
|
934
|
+
/** Column width override in pixels; undefined uses the layout default. */
|
|
935
|
+
width?: number;
|
|
936
|
+
}
|
|
937
|
+
type CellValue = string | number | boolean | null;
|
|
938
|
+
type SortDir = 'asc' | 'desc';
|
|
939
|
+
interface TableSort {
|
|
940
|
+
colId: string;
|
|
941
|
+
dir: SortDir;
|
|
942
|
+
}
|
|
943
|
+
type TableFilter = {
|
|
944
|
+
kind: 'contains';
|
|
945
|
+
text: string;
|
|
946
|
+
} | {
|
|
947
|
+
kind: 'numRange';
|
|
948
|
+
min?: number;
|
|
949
|
+
max?: number;
|
|
950
|
+
} | {
|
|
951
|
+
kind: 'isOption';
|
|
952
|
+
optionIds: string[];
|
|
953
|
+
} | {
|
|
954
|
+
kind: 'checked';
|
|
955
|
+
value: boolean;
|
|
956
|
+
};
|
|
957
|
+
interface TableModel {
|
|
958
|
+
columns: TableColumn[];
|
|
959
|
+
/** Stored (insertion-ordered) row ids — NOT sorted/filtered. */
|
|
960
|
+
rowIds: string[];
|
|
961
|
+
/** Cell values keyed `${rowId}:${colId}`. Missing key = null / empty. */
|
|
962
|
+
cells: Record<string, CellValue>;
|
|
963
|
+
sort: TableSort | null;
|
|
964
|
+
filters: Record<string, TableFilter>;
|
|
965
|
+
}
|
|
966
|
+
/** Project the WAL document into the full {@link TableModel} for block `T`. */
|
|
967
|
+
declare function readTable(doc: WalDocument, T: string): TableModel;
|
|
968
|
+
/**
|
|
969
|
+
* Derive the visible (post-filter, post-sort) row id list from a {@link TableModel}.
|
|
970
|
+
* Pure — no WAL writes. The stored `rowIds` order is NEVER mutated by sort.
|
|
971
|
+
*/
|
|
972
|
+
declare function visibleTableRowIds(model: TableModel): string[];
|
|
973
|
+
/**
|
|
974
|
+
* Seed a newly-inserted table block: 3 columns (Name · Status · Notes) + 2 empty rows.
|
|
975
|
+
* Called from the page editor immediately after the block is created.
|
|
976
|
+
*/
|
|
977
|
+
declare function createTable(doc: WalDocument, T: string): void;
|
|
978
|
+
/** Add a new column and return its id. */
|
|
979
|
+
declare function addTableColumn(doc: WalDocument, T: string, type: TableColType, title: string): string;
|
|
980
|
+
declare function renameTableColumn(doc: WalDocument, id: string, title: string): void;
|
|
981
|
+
declare function setTableColumnType(doc: WalDocument, id: string, type: TableColType): void;
|
|
982
|
+
declare function setTableColumnOptions(doc: WalDocument, id: string, options: TableSelectOption[]): void;
|
|
983
|
+
declare function addTableSelectOption(doc: WalDocument, colId: string, label: string, swatch?: TableSwatchName): void;
|
|
984
|
+
declare function removeTableSelectOption(doc: WalDocument, colId: string, optionId: string): void;
|
|
985
|
+
declare function setTableColumnWidth(doc: WalDocument, colId: string, width: number): void;
|
|
986
|
+
declare function moveTableColumn(doc: WalDocument, T: string, id: string, toIndex: number): void;
|
|
987
|
+
/**
|
|
988
|
+
* Delete a column: remove it from the column list, tombstone its registers, and
|
|
989
|
+
* clear all cells in that column.
|
|
990
|
+
*/
|
|
991
|
+
declare function deleteTableColumn(doc: WalDocument, T: string, id: string): void;
|
|
992
|
+
/** Add a new row at `atIndex` (appends if omitted). Returns the new row id. */
|
|
993
|
+
declare function addTableRow(doc: WalDocument, T: string, atIndex?: number): string;
|
|
994
|
+
declare function moveTableRow(doc: WalDocument, T: string, id: string, toIndex: number): void;
|
|
995
|
+
/** Duplicate a row, placing the copy directly below the original. Returns the new row id. */
|
|
996
|
+
declare function duplicateTableRow(doc: WalDocument, T: string, id: string): string;
|
|
997
|
+
/**
|
|
998
|
+
* Delete a row: remove from the row list and tombstone all its cells.
|
|
999
|
+
*/
|
|
1000
|
+
declare function deleteTableRow(doc: WalDocument, T: string, id: string): void;
|
|
1001
|
+
/** Set or clear a single cell value (LWW). */
|
|
1002
|
+
declare function setTableCell(doc: WalDocument, r: string, c: string, value: CellValue): void;
|
|
1003
|
+
declare function setTableSort(doc: WalDocument, T: string, colId: string, dir: SortDir): void;
|
|
1004
|
+
declare function clearTableSort(doc: WalDocument, T: string): void;
|
|
1005
|
+
/** Set the filter for one column. Merges into the existing filters record (LWW on the whole record). */
|
|
1006
|
+
declare function setTableFilter(doc: WalDocument, T: string, colId: string, filter: TableFilter): void;
|
|
1007
|
+
declare function clearTableFilter(doc: WalDocument, T: string, colId: string): void;
|
|
1008
|
+
declare function clearAllTableFilters(doc: WalDocument, T: string): void;
|
|
1009
|
+
/**
|
|
1010
|
+
* Tombstone all WAL keys owned by table block `T` (call when the block is
|
|
1011
|
+
* permanently deleted and undo has expired). Reads current col/row ids
|
|
1012
|
+
* internally so the caller does not need to pass them.
|
|
1013
|
+
*/
|
|
1014
|
+
declare function clearTable(doc: WalDocument, T: string): void;
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Pure projection of task {@link ObjectNode}s into the kanban view.
|
|
1018
|
+
*
|
|
1019
|
+
* A task is an ObjectNode with `type === 'task'` and `parentId === boardId`.
|
|
1020
|
+
* Its positional state lives in `meta.props` (via `propsOf`): `columnId`,
|
|
1021
|
+
* `order` (fractional number), and the legacy `status` register (kept for boards
|
|
1022
|
+
* without a Done column).
|
|
1023
|
+
*/
|
|
1024
|
+
|
|
1025
|
+
type TaskStatus = 'todo' | 'doing' | 'done';
|
|
1026
|
+
interface Task {
|
|
1027
|
+
id: string;
|
|
1028
|
+
columnId: string;
|
|
1029
|
+
title: string;
|
|
1030
|
+
status: TaskStatus;
|
|
1031
|
+
order: number;
|
|
1032
|
+
/** Derived completion — column membership when the board has a Done column,
|
|
1033
|
+
* else the legacy `status` prop. Render from THIS, never from `status`. */
|
|
1034
|
+
done: boolean;
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Project task ObjectNodes into the board's view model.
|
|
1038
|
+
*
|
|
1039
|
+
* Orphaned tasks (unknown columnId) are re-homed to the first column.
|
|
1040
|
+
*/
|
|
1041
|
+
declare function tasksForBoard(nodes: ObjectNode[], boardId: string, columns: Column[]): {
|
|
1042
|
+
tasksByColumn: Record<string, Task[]>;
|
|
1043
|
+
done: number;
|
|
1044
|
+
total: number;
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
interface CalendarEvent {
|
|
1048
|
+
id: string;
|
|
1049
|
+
title: string;
|
|
1050
|
+
start: number;
|
|
1051
|
+
end: number;
|
|
1052
|
+
allDay: boolean;
|
|
1053
|
+
color: string | null;
|
|
1054
|
+
desc: string | null;
|
|
1055
|
+
}
|
|
1056
|
+
declare function readEvents(doc: WalDocument): CalendarEvent[];
|
|
1057
|
+
declare function addEvent(doc: WalDocument, init: {
|
|
1058
|
+
start: number;
|
|
1059
|
+
end?: number;
|
|
1060
|
+
title?: string;
|
|
1061
|
+
allDay?: boolean;
|
|
1062
|
+
color?: string;
|
|
1063
|
+
desc?: string;
|
|
1064
|
+
}): string;
|
|
1065
|
+
declare function deleteEvent(doc: WalDocument, id: string): void;
|
|
1066
|
+
declare function patchEvent(doc: WalDocument, id: string, patch: Partial<Omit<CalendarEvent, 'id'>>): void;
|
|
1067
|
+
|
|
1068
|
+
type FormFieldKind = 'text' | 'email' | 'number' | 'select' | 'checkbox';
|
|
1069
|
+
interface FormFieldOption {
|
|
1070
|
+
id: string;
|
|
1071
|
+
label: string;
|
|
1072
|
+
}
|
|
1073
|
+
interface FormField {
|
|
1074
|
+
id: string;
|
|
1075
|
+
label: string;
|
|
1076
|
+
kind: FormFieldKind;
|
|
1077
|
+
required: boolean;
|
|
1078
|
+
options: FormFieldOption[];
|
|
1079
|
+
}
|
|
1080
|
+
interface FormResponse {
|
|
1081
|
+
id: string;
|
|
1082
|
+
submittedAt: number;
|
|
1083
|
+
submitter: string;
|
|
1084
|
+
data: Record<string, unknown>;
|
|
1085
|
+
}
|
|
1086
|
+
declare function readFields(doc: WalDocument): FormField[];
|
|
1087
|
+
declare function readResponses(doc: WalDocument): FormResponse[];
|
|
1088
|
+
declare function addField(doc: WalDocument, init?: Partial<FormField>): string;
|
|
1089
|
+
declare function deleteField(doc: WalDocument, id: string): void;
|
|
1090
|
+
declare function moveField(doc: WalDocument, id: string, toIndex: number): void;
|
|
1091
|
+
declare function patchField(doc: WalDocument, id: string, patch: Partial<Omit<FormField, 'id'>>): void;
|
|
1092
|
+
declare function addResponse(doc: WalDocument, submitter: string, data: Record<string, unknown>, now: number): string;
|
|
1093
|
+
|
|
1094
|
+
type FeedbackStatus = 'open' | 'planned' | 'in-progress' | 'done';
|
|
1095
|
+
interface FeedbackItem {
|
|
1096
|
+
id: string;
|
|
1097
|
+
title: string;
|
|
1098
|
+
status: FeedbackStatus;
|
|
1099
|
+
desc: string | null;
|
|
1100
|
+
voters: string[];
|
|
1101
|
+
}
|
|
1102
|
+
declare function readItems(doc: WalDocument): FeedbackItem[];
|
|
1103
|
+
declare function addItem(doc: WalDocument, title: string): string;
|
|
1104
|
+
declare function deleteItem(doc: WalDocument, id: string): void;
|
|
1105
|
+
declare function patchItem(doc: WalDocument, id: string, patch: Partial<Omit<FeedbackItem, 'id' | 'voters'>>): void;
|
|
1106
|
+
declare function vote(doc: WalDocument, id: string, userId: string): void;
|
|
1107
|
+
declare function unvote(doc: WalDocument, id: string, userId: string): void;
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Starfish client construction + space keyring / encryptor / profile helpers.
|
|
1111
|
+
*
|
|
1112
|
+
* Profile read/write functions are thin wrappers that inject the global
|
|
1113
|
+
* connection config (baseUrl, namespace via the octospaces-sdk residual
|
|
1114
|
+
* `getSyncBase()` / `getSyncNamespace()`) into the starfish-spaces API,
|
|
1115
|
+
* preserving the old single-argument call signature used throughout the app.
|
|
1116
|
+
*
|
|
1117
|
+
* openEncryptor / buildEncryptor are OctoVault-flavored wrappers: they take a
|
|
1118
|
+
* `spaceId` string and construct the keyring pull path internally.
|
|
1119
|
+
*
|
|
1120
|
+
* makeClient is re-exported as an alias for the renamed makeSpaceClient.
|
|
1121
|
+
*/
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Build cap-cert auth headers for a raw `fetch` outside the StarfishClient (e.g. `GET /events`).
|
|
1125
|
+
* Signing host is derived from `getSyncBase()` so the server-side verifier agrees — same pin as
|
|
1126
|
+
* the client's own REST requests (StarfishClient.signingHost).
|
|
1127
|
+
*
|
|
1128
|
+
* starfish-spaces re-exports its own `buildAuthHeaders` that hardcodes `host: ""`, which causes
|
|
1129
|
+
* `verifyRequestSignature` to fail on deployed servers that bind host. This local override
|
|
1130
|
+
* restores correct behavior: sign the REAL host.
|
|
1131
|
+
*/
|
|
1132
|
+
declare function buildAuthHeaders(cap: unknown, devEdPrivHex: string, method: string, pathAndQuery: string): Promise<Record<string, string>>;
|
|
1133
|
+
/**
|
|
1134
|
+
* Read a user's public profile (pseudo, avatar, public keys). Injects globals.
|
|
1135
|
+
*
|
|
1136
|
+
* Unlike readProfiles (routed through a namespace-aware client), starfish-spaces'
|
|
1137
|
+
* readProfile does a raw `${baseUrl}${pullPath}` concat with no namespace option —
|
|
1138
|
+
* so baseUrl must already carry the `/v1/{ns}` prefix (getSyncPrefix()).
|
|
1139
|
+
*/
|
|
1140
|
+
declare function readProfile(userId: string): Promise<PublicProfile>;
|
|
1141
|
+
/** Read multiple users' profiles in batched round-trips. Injects globals. */
|
|
1142
|
+
declare function readProfiles(ids: string[]): Promise<Map<string, PublicProfile>>;
|
|
1143
|
+
/** Merge a patch into the caller's own profile doc. Injects the layout. */
|
|
1144
|
+
declare function writeProfile(client: StarfishClient, userId: string, patch: {
|
|
1145
|
+
pseudo?: string;
|
|
1146
|
+
avatar?: string | null;
|
|
1147
|
+
edPub?: string;
|
|
1148
|
+
kemPub?: string;
|
|
1149
|
+
kemSig?: string;
|
|
1150
|
+
}): Promise<void>;
|
|
1151
|
+
/** Soft variant of {@link openEncryptor}: returns null instead of throwing. */
|
|
1152
|
+
declare function buildEncryptor(client: StarfishClient, keys: DeviceKeys, spaceId: string, trustedAdders: string[]): Promise<Encryptor | null>;
|
|
1153
|
+
|
|
1154
|
+
/**
|
|
1155
|
+
* Device pairing (one-way, PIN-sealed). The existing device provisions a new
|
|
1156
|
+
* device's keypair + cap bundle, seals it with the PIN (Argon2id → AES-GCM), and
|
|
1157
|
+
* drops it on the public `_pairing/<nonce>` rendezvous. The QR carries only the
|
|
1158
|
+
* nonce; the new device fetches the sealed blob, opens it with the PIN, and
|
|
1159
|
+
* validates the cap bundle. This proves the cryptographic handshake end-to-end.
|
|
1160
|
+
*
|
|
1161
|
+
* `startDevicePairing` / `completeDevicePairing` come directly from
|
|
1162
|
+
* starfish-spaces — dk-spaces-sdk 0.30 stopped wrapping device pairing.
|
|
1163
|
+
*
|
|
1164
|
+
* starfish alpha.63 made root-trust MANDATORY on pairing completion: the receiving
|
|
1165
|
+
* device must pass `expectedRootEdPub` (a pinned root key) or `confirmUnpinnedRoot`
|
|
1166
|
+
* (a callback), else `completeDevicePairing` throws. OctoVault has no prior-pinned
|
|
1167
|
+
* root to check against here (the new device is bootstrapping FROM this scan), so
|
|
1168
|
+
* `confirmUnpinnedRoot` always trusts — the actual security boundary is the
|
|
1169
|
+
* PIN-sealed bundle + physical QR proximity, same as before this change.
|
|
1170
|
+
*/
|
|
1171
|
+
|
|
1172
|
+
declare const PAIR_PREFIX = "octovault-pair:";
|
|
1173
|
+
|
|
1174
|
+
/** New device: open the sealed bundle at the rendezvous nonce and install it. */
|
|
1175
|
+
declare function completeDevicePairing(payload: string, pin: string): Promise<PairResult>;
|
|
1176
|
+
/** Existing device: provision + PIN-seal a new device, publish to rendezvous, return the QR payload. */
|
|
1177
|
+
declare function startDevicePairing(session: Session, pin: string): Promise<string>;
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Member-cap shims — thin compatibility layer over the starfish-spaces
|
|
1181
|
+
* space-access store. Exposes `getMemberCap` (vault convenience helper) and
|
|
1182
|
+
* the store operations that the vault actively consumes.
|
|
1183
|
+
*/
|
|
1184
|
+
|
|
1185
|
+
/** Returns the raw cap string for member-kind entries; null otherwise. */
|
|
1186
|
+
declare function getMemberCap(spaceId: string): string | null;
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Wraps starfish-spaces `readSpaces` to re-flatten OctoVault-specific extra fields:
|
|
1190
|
+
* - `mutes: MutePrefs` — from `doc.extra.mutes`
|
|
1191
|
+
* - `reads: ReadPrefs` — from `doc.extra.reads`
|
|
1192
|
+
*
|
|
1193
|
+
* Call-sites that destructure `{ spaces, caps, mutes, reads }` work without change.
|
|
1194
|
+
*/
|
|
1195
|
+
declare function readSpaces(client: StarfishClient, session: Session): Promise<{
|
|
1196
|
+
mutes: MutePrefs;
|
|
1197
|
+
reads: ReadPrefs;
|
|
1198
|
+
spaces: _drakkar_software_starfish_spaces.Space[];
|
|
1199
|
+
caps: _drakkar_software_starfish_spaces.CapMap;
|
|
1200
|
+
pubAccess: _drakkar_software_starfish_spaces.PubAccessMap;
|
|
1201
|
+
extra: Record<string, unknown>;
|
|
1202
|
+
hash: string | null;
|
|
1203
|
+
}>;
|
|
1204
|
+
/**
|
|
1205
|
+
* Member-side: leave a space — drop it from this identity's own `_spaces` doc (the
|
|
1206
|
+
* `spaces` list AND its `caps`/`pubAccess` entry) through the conflict-retrying
|
|
1207
|
+
* `updateSpacesDoc` funnel, then forget its member cap from the local store.
|
|
1208
|
+
*
|
|
1209
|
+
* This is a LOCAL leave (the user stops syncing/seeing the space) — it does NOT
|
|
1210
|
+
* remove the user from the owner's roster or rotate the keyring; that is the owner's
|
|
1211
|
+
* `removeSpaceMember`, and a true keyring revoke is out of scope.
|
|
1212
|
+
*/
|
|
1213
|
+
declare function leaveSpace(client: StarfishClient, session: Session, spaceId: string): Promise<void>;
|
|
1214
|
+
/** A user-facing category/space validation failure (empty/duplicate name).
|
|
1215
|
+
* The hook layer surfaces `message` verbatim, unlike an opaque network/HTTP error. */
|
|
1216
|
+
declare class CategoryError extends Error {
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* OctoVault-specific object-tree extensions.
|
|
1221
|
+
*
|
|
1222
|
+
* These helpers bridge the vault's `props`/`automation` concept (which used to be
|
|
1223
|
+
* top-level ObjectNode fields) onto the octospaces-sdk `node.meta` bag.
|
|
1224
|
+
*
|
|
1225
|
+
* Migration:
|
|
1226
|
+
* OLD: node.props?.[key] → NEW: propsOf(node)[key]
|
|
1227
|
+
* OLD: node.automation → NEW: automationOf(node)
|
|
1228
|
+
* OLD: addObject(nodes, { type, title, props, automation }, now)
|
|
1229
|
+
* → addVaultObject(nodes, { type, title, props, automation }, now)
|
|
1230
|
+
* OLD: setProps(nodes, id, patch, now) → same, from here
|
|
1231
|
+
* OLD: clearProp(nodes, id, key, now) → same, from here
|
|
1232
|
+
*/
|
|
1233
|
+
|
|
1234
|
+
/** Read the `props` map from a node's `meta` bag (typed for vault usage). */
|
|
1235
|
+
declare function propsOf(node: ObjectNode): Record<string, PropValue>;
|
|
1236
|
+
/** Read the `automation` config from a node's `meta` bag. Returns `null` when absent. */
|
|
1237
|
+
declare function automationOf(node: ObjectNode): AutomationMeta | null;
|
|
1238
|
+
/** Vault-specific new-node input (adds `props` and `automation` fields). */
|
|
1239
|
+
interface VaultNewObjectInput {
|
|
1240
|
+
type: string;
|
|
1241
|
+
parentId?: string | null;
|
|
1242
|
+
title: string;
|
|
1243
|
+
emoji?: string;
|
|
1244
|
+
id?: string;
|
|
1245
|
+
access?: ObjectNode['access'];
|
|
1246
|
+
enc?: boolean;
|
|
1247
|
+
/** Structured property values (stored under `meta.props`). */
|
|
1248
|
+
props?: Record<string, PropValue>;
|
|
1249
|
+
/** Automation config (stored under `meta.automation`). */
|
|
1250
|
+
automation?: AutomationMeta;
|
|
1251
|
+
/** Any additional meta fields (merged with props/automation). */
|
|
1252
|
+
meta?: Record<string, unknown>;
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Create a new vault object node, mapping vault-specific `props`/`automation`
|
|
1256
|
+
* into `meta.props`/`meta.automation` as required by the octospaces model.
|
|
1257
|
+
*/
|
|
1258
|
+
declare function addVaultObject(nodes: ObjectNode[], input: VaultNewObjectInput, now: number): {
|
|
1259
|
+
nodes: ObjectNode[];
|
|
1260
|
+
node: ObjectNode;
|
|
1261
|
+
};
|
|
1262
|
+
/** Merge a props patch into a node's `meta.props` (node-level LWW write; bumps `updatedAt`). */
|
|
1263
|
+
declare function setProps(nodes: ObjectNode[], id: string, patch: Record<string, PropValue>, now: number): ObjectNode[];
|
|
1264
|
+
/** Remove a single key from a node's `meta.props` (LWW write; bumps `updatedAt`). */
|
|
1265
|
+
declare function clearProp(nodes: ObjectNode[], id: string, key: string, now: number): ObjectNode[];
|
|
1266
|
+
/** Patch a node's `automation` field (stored as `meta.automation`), bumping `updatedAt`. */
|
|
1267
|
+
declare function patchAutomation(nodes: ObjectNode[], id: string, automation: AutomationMeta | null, now: number): ObjectNode[];
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Default object-blob store — a second, independent `createSealedBlobStore`
|
|
1271
|
+
* singleton, in-memory cache only (no KV persistence — matches the old
|
|
1272
|
+
* octospaces-sdk default singleton this replaces), previously exposed as bare
|
|
1273
|
+
* `uploadObjectBlob`/`loadObjectBlob` functions. Used directly by file/image
|
|
1274
|
+
* ObjectNode attachments (see apps/mobile's use-object-files.ts /
|
|
1275
|
+
* use-object-blob.ts) — kept separate from ./attachments' custom-prefixed,
|
|
1276
|
+
* KV-persisted store so neither store's cache behavior shifts.
|
|
1277
|
+
*/
|
|
1278
|
+
|
|
1279
|
+
declare function uploadObjectBlob(client: StarfishClient, enc: ByteSealer | null, spaceId: string, bytes: Uint8Array, name: string, mime: string): Promise<ObjectBlobRef>;
|
|
1280
|
+
declare function loadObjectBlob(client: StarfishClient, enc: ByteSealer | null, spaceId: string, blobId: string): Promise<Uint8Array>;
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* OctoVault attachment layer, backed by the `objblob` collection
|
|
1284
|
+
* (`spaces/{spaceId}/objects/blobs/{blobId}`) via starfish-client's
|
|
1285
|
+
* `createSealedBlobStore`, fed dk-spaces-sdk's `objectBlobPaths` path/AAD
|
|
1286
|
+
* strategy. Blobs are keyed by SPACE, sealed client-side before upload, and
|
|
1287
|
+
* cached in memory + KV for offline reads.
|
|
1288
|
+
*
|
|
1289
|
+
* Public API is kept stable (same names/types as the legacy attachment store)
|
|
1290
|
+
* so callers need no changes to imports. dk-spaces-sdk 0.30 stopped wrapping
|
|
1291
|
+
* the blob store — this module now builds it directly and re-attaches the
|
|
1292
|
+
* `name`/`mime`/`kind` metadata the new generic store no longer tracks (its
|
|
1293
|
+
* `upload`/`load` only take raw bytes + id).
|
|
1294
|
+
*/
|
|
1295
|
+
|
|
1296
|
+
interface AttachmentRef extends ObjectBlobRef {
|
|
1297
|
+
kind: 'image' | 'file';
|
|
1298
|
+
}
|
|
1299
|
+
declare function uploadAttachment(client: StarfishClient, enc: ByteSealer | null, spaceId: string, bytes: Uint8Array, name: string, mime: string): Promise<AttachmentRef>;
|
|
1300
|
+
declare function loadAttachment(client: StarfishClient, enc: ByteSealer | null, spaceId: string, ref: AttachmentRef): Promise<Uint8Array>;
|
|
1301
|
+
declare function clearAttachmentCache(): void;
|
|
1302
|
+
|
|
1303
|
+
/** OctoVault's connection timeout: 12 s (octospaces used 12 s; starfish default is 10 s). */
|
|
1304
|
+
declare const CONNECT_TIMEOUT_MS = 12000;
|
|
1305
|
+
/**
|
|
1306
|
+
* Returns a timeout-wrapped `fetch` function that aborts after `ms` milliseconds.
|
|
1307
|
+
* Drop-in for the global `fetch` — pass to StarfishClient, useSyncInit, etc.
|
|
1308
|
+
* Default timeout preserves OctoVault's historic 12 s.
|
|
1309
|
+
*/
|
|
1310
|
+
declare function fetchWithTimeout(ms?: number): typeof globalThis.fetch;
|
|
1311
|
+
|
|
1312
|
+
/** 30 days — mirrors the default from the old octospaces pullCache. */
|
|
1313
|
+
declare const PULL_CACHE_MAX_AGE_MS: number;
|
|
1314
|
+
/**
|
|
1315
|
+
* Returns the shared KV-backed pull-cache singleton. Pass it as `cache:` in every
|
|
1316
|
+
* `useSyncInit` / `useSharedSyncStore` / `useMergeDoc` call-site.
|
|
1317
|
+
*/
|
|
1318
|
+
declare function pullCache(): _drakkar_software_starfish_client.PullCache;
|
|
1319
|
+
|
|
1320
|
+
/**
|
|
1321
|
+
* Bot / integration write credentials for automation stream rooms.
|
|
1322
|
+
*
|
|
1323
|
+
* `openStreamBotCredential` opens a stored (sealed) bot credential from an
|
|
1324
|
+
* automation node's `meta.automation.credential` field.
|
|
1325
|
+
*
|
|
1326
|
+
* NOTE: `createStreamBotCredential` relied on the removed pubstream/public-link
|
|
1327
|
+
* model. New automation bots are enrolled as node members via `inviteToNode` and
|
|
1328
|
+
* receive a standard member cap; this module only provides the credential-open
|
|
1329
|
+
* helper needed at runtime.
|
|
1330
|
+
*/
|
|
1331
|
+
|
|
1332
|
+
interface StreamBotCredential {
|
|
1333
|
+
/** The public-link fragment (an audience cap) — the bot's `parsePublicLink` input.
|
|
1334
|
+
* Carries no private key; the bot signs with its own generated key. */
|
|
1335
|
+
token: string;
|
|
1336
|
+
/** Full append endpoint the bot POSTs to (already namespace-prefixed). */
|
|
1337
|
+
endpoint: string;
|
|
1338
|
+
/** The path+query the bot must sign (what `redeemPublicLink` binds the signature to). */
|
|
1339
|
+
signPath: string;
|
|
1340
|
+
/** Absolute expiry (unix seconds) of the credential, if a TTL was set. */
|
|
1341
|
+
expiresAt?: number;
|
|
1342
|
+
}
|
|
1343
|
+
/** Open a stored automation bot credential. Current rooms store it SEALED to the owner
|
|
1344
|
+
* key (`mintSealedCredential`) — unseal with the seed. A LEGACY room (created before
|
|
1345
|
+
* the seal) stored the credential in the clear; detect that by its `token` and return
|
|
1346
|
+
* it as-is so the automation keeps working until the owner rotates (which re-seals).
|
|
1347
|
+
* No new exposure: a legacy credential was already plaintext in the synced doc. */
|
|
1348
|
+
declare function openStreamBotCredential(session: Session, stored: SealedBlob | StreamBotCredential): Promise<StreamBotCredential>;
|
|
1349
|
+
|
|
1350
|
+
export { type AiSettings, type AttachmentRef, type AutomationMeta, BLOCK_SECTIONS, BLOCK_TYPES, BOARD_SCHEMA, BUILTIN_OBJECT_TYPES, BUILTIN_REGISTRY, type Block, type BlockSection, type BlockType, type BlockTypeDef, type BookmarkMeta, type BuiltinObjectType, CALENDAR_SCHEMA, CAPABILITY_META, CONNECT_TIMEOUT_MS, type CalendarEvent, type Capability, type CapabilityMeta, CategoryError, type CellValue, type Column, type Comment, type CommentReaction, type ContentCollection, type ContentField, type ContentKind, type ContentSchema, type CreatableTypeEntry, DEFAULT_AI_SETTINGS, DEFAULT_QUICK_REACTIONS, type DiscussionThread, EMOJI, EMOJI_CATEGORIES, EMOJI_LIST, EMPTY_TYPES_DOC, type EditorKind, type EmojiCategory, type EmojiMatch, FEEDBACK_SCHEMA, FORM_SCHEMA, type FeedbackItem, type FeedbackStatus, type FieldDef, type FieldKind, type FormField, type FormFieldKind, type FormFieldOption, type FormResponse, type IconName, type LegalDoc, type LegalSection, type MdShortcutMatch, type NewBlock, type ObjectDescriptor, PAGE_SCHEMA, PAIR_PREFIX, PULL_CACHE_MAX_AGE_MS, type Profile, type PropField, type PropKind, type PropOption, type PropValue, QUICK_REACTION_COUNT, REF_BLOCK_TYPES, type SecurityItem, type SelectOption, type SortDir, type Space, type EditorKind$1 as StoresEditorKind, type PropKind$1 as StoresPropKind, type StreamBotCredential, type TableColType, type TableColumn, type TableFilter, type TableModel, type TableSelectOption, type TableSort, type TableSwatchName, type Task, type TaskStatus, type TextVariant, type TypeDef, type TypeDescriptor, type TypeRegistry, type TypesDoc, type User, activeEmojiQuery, addColumn, addComment, addEvent, addField$1 as addField, addField as addFormField, addItem, addResponse, addTableColumn, addTableRow, addTableSelectOption, addType, addVaultObject, appendBlock, archiveType, automationOf, blockDef, buildAuthHeaders, buildEncryptor, buildLinkedSession, buildSession, clearAllTableFilters, clearAttachmentCache, clearPrimedSpaces, clearProp, clearTable, clearTableFilter, clearTableSort, completeDevicePairing, configureKv, configureOctoVault, consumePrimedSpaces, contentKindOf, continuationType, creatableTypes, createTable, defaultProps, deleteColumn, deleteEvent, deleteField as deleteFormField, deleteItem, deleteTableColumn, deleteTableRow, deriveSession, duplicateBlock, duplicateTableRow, endsListOnEmptyEnter, fetchWithTimeout, filterBlockTypes, flushReadsNow, getAiSettings, getEventsUrl, getMemberCap, getMutePrefs, getQuickReactions, getReadPrefs, getRoomReadAt, getSyncBase, getSyncNamespace, getSyncPrefix, humanizeError, hydrateMutes, hydrateQuickReactions, hydrateReads, iconFor, iconForNode, insertBlock, isContainerType, isFindableType, isMultiline, isMuted, isOpenableObjectType, isRoomMuted, isSpaceMuted, kvGet, kvRemove, kvSet, labelFor, leaveSpace, listOrdinals, loadAiSettings, loadAttachment, loadMutesFromKv, loadObjectBlob, loadReadMarksFromKv, makeRegistry, matchEmoji, mdShortcut, mergeBlockIntoPrevious, monoFor, moveBlock, moveColumn, moveField as moveFormField, moveTableColumn, moveTableRow, objectDescriptor, objectLink, openStreamBotCredential, orderBetween, patchAutomation, patchEvent, patchField$1 as patchField, patchField as patchFormField, patchItem, patchType, placeholderFor, primeSpaces, privacy, propsOf, pullCache, readBlocks, readColumns, readEvents, readFields, readItems, readProfile, readProfiles, readResponses, readSpaces, readTable, readThread, readThreads, removeBlock, removeComment, removeField, removeTableSelectOption, renameColumn, renameTableColumn, reorderFields, resetAiSettings, resetMutes, resetQuickReactions, resetReads, resolveThread, restoreBlock, routeForNode, saveAiSettings, saveQuickReactions, schemaFor, searchEmoji, seedDefaultColumns, sessionFromPersisted, setAiSettings, setBlockBookmark, setBlockChecked, setBlockCollapsed, setBlockIndent, setBlockRef, setBlockText, setBlockType, setColumnDone, setCommentBody, setProps, setQuickReactions, setRoomMute, setRoomReadAt, setSpaceMute, setTableCell, setTableColumnOptions, setTableColumnType, setTableColumnWidth, setTableFilter, setTableSort, showsInWorkTree, splitBlock, startDevicePairing, subscribeAiSettings, subscribeMutes, subscribeQuickReactions, subscribeReads, tasksForBoard, terms, threadLastActivity, toggleReaction, unvote, uploadAttachment, uploadObjectBlob, variantFor, visibleBlocks, visibleTableRowIds, vote, writeProfile };
|