@book.dev/sdk 1.60.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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/account.d.ts +57 -0
  4. package/dist/account.js +104 -0
  5. package/dist/account.js.map +1 -0
  6. package/dist/ai.d.ts +264 -0
  7. package/dist/ai.js +36 -0
  8. package/dist/ai.js.map +1 -0
  9. package/dist/backup.d.ts +52 -0
  10. package/dist/backup.js +35 -0
  11. package/dist/backup.js.map +1 -0
  12. package/dist/bookFolder.d.ts +44 -0
  13. package/dist/bookFolder.js +98 -0
  14. package/dist/bookFolder.js.map +1 -0
  15. package/dist/bookfile.d.ts +42 -0
  16. package/dist/bookfile.js +159 -0
  17. package/dist/bookfile.js.map +1 -0
  18. package/dist/client.d.ts +279 -0
  19. package/dist/client.js +502 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/connection.d.ts +20 -0
  22. package/dist/connection.js +77 -0
  23. package/dist/connection.js.map +1 -0
  24. package/dist/content.d.ts +38 -0
  25. package/dist/content.js +107 -0
  26. package/dist/content.js.map +1 -0
  27. package/dist/database.d.ts +687 -0
  28. package/dist/database.js +1082 -0
  29. package/dist/database.js.map +1 -0
  30. package/dist/formula.d.ts +41 -0
  31. package/dist/formula.js +469 -0
  32. package/dist/formula.js.map +1 -0
  33. package/dist/forwarding/challenge.d.ts +35 -0
  34. package/dist/forwarding/challenge.js +45 -0
  35. package/dist/forwarding/challenge.js.map +1 -0
  36. package/dist/forwarding/encoding.d.ts +14 -0
  37. package/dist/forwarding/encoding.js +54 -0
  38. package/dist/forwarding/encoding.js.map +1 -0
  39. package/dist/forwarding/forwardingClient.d.ts +76 -0
  40. package/dist/forwarding/forwardingClient.js +128 -0
  41. package/dist/forwarding/forwardingClient.js.map +1 -0
  42. package/dist/forwarding/index.d.ts +5 -0
  43. package/dist/forwarding/index.js +14 -0
  44. package/dist/forwarding/index.js.map +1 -0
  45. package/dist/forwarding/siteKey.d.ts +12 -0
  46. package/dist/forwarding/siteKey.js +36 -0
  47. package/dist/forwarding/siteKey.js.map +1 -0
  48. package/dist/forwarding/tunnelClient.d.ts +56 -0
  49. package/dist/forwarding/tunnelClient.js +206 -0
  50. package/dist/forwarding/tunnelClient.js.map +1 -0
  51. package/dist/forwarding/tunnelProtocol.d.ts +45 -0
  52. package/dist/forwarding/tunnelProtocol.js +29 -0
  53. package/dist/forwarding/tunnelProtocol.js.map +1 -0
  54. package/dist/index.d.ts +23 -0
  55. package/dist/index.js +19 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/mtime.d.ts +51 -0
  58. package/dist/mtime.js +84 -0
  59. package/dist/mtime.js.map +1 -0
  60. package/dist/pageProperties.d.ts +80 -0
  61. package/dist/pageProperties.js +97 -0
  62. package/dist/pageProperties.js.map +1 -0
  63. package/dist/plugins.d.ts +110 -0
  64. package/dist/plugins.js +113 -0
  65. package/dist/plugins.js.map +1 -0
  66. package/dist/routes.d.ts +89 -0
  67. package/dist/routes.js +89 -0
  68. package/dist/routes.js.map +1 -0
  69. package/dist/sampleDocument.d.ts +25 -0
  70. package/dist/sampleDocument.js +67 -0
  71. package/dist/sampleDocument.js.map +1 -0
  72. package/dist/suggestions.d.ts +126 -0
  73. package/dist/suggestions.js +21 -0
  74. package/dist/suggestions.js.map +1 -0
  75. package/dist/templates.d.ts +35 -0
  76. package/dist/templates.js +555 -0
  77. package/dist/templates.js.map +1 -0
  78. package/dist/types.d.ts +146 -0
  79. package/dist/types.js +16 -0
  80. package/dist/types.js.map +1 -0
  81. package/package.json +33 -0
@@ -0,0 +1,687 @@
1
+ /**
2
+ * Full-featured databases — the second unit of storage layered over {@link
3
+ * StoredPage}. A **database** is a collection of pages (its *rows*) managed by
4
+ * typed *properties* and presented through one or more configurable *views*
5
+ * (table, board, gallery, calendar, list, or a bar/pie chart).
6
+ *
7
+ * Three ideas make OpenBook databases different from a plain spreadsheet:
8
+ *
9
+ * 1. **Rows are real pages.** Each row is an ordinary page in the `pages`
10
+ * table with its own editable document — so a row can itself contain text,
11
+ * reactive sliders, charts, even another database. Opening a row in the
12
+ * split pane edits that page directly.
13
+ *
14
+ * 2. **Columns can be reactive.** A property of type `expr` reads a *named
15
+ * exported cell* from the row page's reactive store (the `names`/`values`
16
+ * pairs in its {@link PageSnapshot}). A "Total" column can therefore show
17
+ * the live result of an expression block inside each row, and the table can
18
+ * filter and sort on it.
19
+ *
20
+ * 3. **Columns can compute.** A property of type `formula` evaluates a small
21
+ * expression over the row's *other* properties (`prop("Price") * prop("Qty")`)
22
+ * via the pure evaluator in {@link ./formula}. Filters/sorts/charts read the
23
+ * computed value just like any stored one.
24
+ *
25
+ * The host page (the page that *contains* the database) is itself a regular
26
+ * page with its own content; it merely points at the database. The database
27
+ * record — properties, views, filters — lives in its own `databases` table.
28
+ */
29
+ import type { PageSnapshot } from './types';
30
+ /**
31
+ * The value kinds a property can hold. The manual kinds
32
+ * (`text`/`number`/`select`/`status`/`checkbox`/`date`/`person`/`verification`)
33
+ * store their value per row in `page.properties[id]`. `expr` projects a named
34
+ * reactive cell from the row page's document; `formula` computes from the row's
35
+ * *other* properties (`prop("Price") * prop("Qty")`); `rollup` folds a target
36
+ * property across the rows a `relation`/`dependency` points to; `backlinks` is
37
+ * computed from the link graph (never stored). The last three
38
+ * (`person`/`verification`/`backlinks`) double as the built-in page properties —
39
+ * see {@link ./pageProperties}.
40
+ */
41
+ export type DatabasePropertyType = 'text' | 'number' | 'rating' | 'select' | 'multi_select' | 'status' | 'checkbox' | 'date' | 'url' | 'email' | 'phone' | 'location' | 'files' | 'relation' | 'dependency' | 'rollup' | 'created_time' | 'last_edited_time' | 'unique_id' | 'expr' | 'formula' | 'person' | 'verification' | 'backlinks';
42
+ /** Display formatting for `number`/`formula`/`expr` numeric values. */
43
+ export type NumberFormat = 'plain' | 'integer' | 'decimal' | 'percent' | 'dollar' | 'euro' | 'pound' | 'yen' | 'rupee';
44
+ /** How a number cell is visualised: as text, a horizontal bar, or a ring. */
45
+ export type NumberDisplay = 'number' | 'bar' | 'ring';
46
+ /** The lifecycle bucket a `status` option belongs to. */
47
+ export type StatusGroup = 'todo' | 'in_progress' | 'complete';
48
+ /** One choice in a `select` / `multi_select` / `status` property. */
49
+ export interface DatabaseSelectOption {
50
+ id: string;
51
+ label: string;
52
+ /** A token from the shared swatch palette (see `SELECT_COLORS`). */
53
+ color?: string;
54
+ /** For `status` options: which lifecycle bucket the option sits in. */
55
+ group?: StatusGroup;
56
+ }
57
+ /** How a {@link DatabaseProperty.rollup} folds the related rows' target values. */
58
+ export type RollupFunction = 'show_original' | 'count' | 'count_values' | 'count_unique' | 'sum' | 'avg' | 'min' | 'max' | 'range' | 'median' | 'checked' | 'percent_checked';
59
+ /** Rollup configuration: aggregate a related set's target property. */
60
+ export interface RollupConfig {
61
+ /** A `relation` / `dependency` property on this row holding the related ids. */
62
+ relationPropertyId: string;
63
+ /** The property on the related rows to fold ({@link TITLE_PROPERTY_ID} for the title). */
64
+ targetPropertyId: string;
65
+ function: RollupFunction;
66
+ }
67
+ /**
68
+ * A column definition. Manual types (`text`/`number`/`select`/`checkbox`/
69
+ * `date`) store their value per row in `page.properties[id]`. The `expr` type
70
+ * stores nothing on the row — its value is projected live from the row page's
71
+ * exported cell named {@link cellName}.
72
+ */
73
+ export interface DatabaseProperty {
74
+ id: string;
75
+ name: string;
76
+ type: DatabasePropertyType;
77
+ /** Choices, for `select` / `multi_select` properties. */
78
+ options?: DatabaseSelectOption[];
79
+ /** Name of the exported reactive cell to read, for `expr` properties. */
80
+ cellName?: string;
81
+ /** Expression source, for `formula` properties (references other props by name). */
82
+ formula?: string;
83
+ /** Numeric display format, for `number` / `formula` / `expr` properties. */
84
+ numberFormat?: NumberFormat;
85
+ /** How a `number` cell is visualised: plain text (default), a `bar`, or a `ring`. */
86
+ numberDisplay?: NumberDisplay;
87
+ /** The 100%-of-the-bar value for `bar`/`ring` display (defaults to 100). */
88
+ numberTarget?: number;
89
+ /** Optional prefix for a `unique_id` property, e.g. `TASK` → `TASK-1`. */
90
+ idPrefix?: string;
91
+ /**
92
+ * `date` only: when true the cell holds a `{start, end}` range (a `DateRange`)
93
+ * instead of a single `YYYY-MM-DD` string. Drives the timeline's bar length.
94
+ */
95
+ dateRange?: boolean;
96
+ /** `date` only: when true the cell stores a time too (`YYYY-MM-DDTHH:mm`). */
97
+ includeTime?: boolean;
98
+ /** `date` only: show dates relative to today ("Today", "In 3 days") near the present,
99
+ * falling back to an absolute date further out. Defaults to absolute. */
100
+ dateDisplay?: 'absolute' | 'relative';
101
+ /** A short helper description, shown beneath the field in the page-view panel. */
102
+ description?: string;
103
+ /** The {@link PropertyGroup} this property belongs to (page-view organisation). */
104
+ groupId?: string;
105
+ /** Hidden in the page-view properties panel (still available as a table column). */
106
+ pageHidden?: boolean;
107
+ /** Rollup configuration, for `rollup` properties. */
108
+ rollup?: RollupConfig;
109
+ /**
110
+ * For a two-way `dependency`: the id of the paired inverse `dependency` property
111
+ * (same database). Linking A→B via this property also lists A on B's inverse.
112
+ */
113
+ syncedPropertyId?: string;
114
+ /**
115
+ * `relation` only: the id of the **target database** whose rows this column
116
+ * links to. A relation is database↔database — the cell picks rows from this
117
+ * database. (A legacy relation without it links arbitrary pages.)
118
+ */
119
+ relationDatabaseId?: string;
120
+ /**
121
+ * `relation` only: cap the cell at a single linked row (the "one" side of a
122
+ * 1:1 or 1:n relation). Many (the default) is the "n" side. Read by the cell
123
+ * editor on every relation property (forward and reverse).
124
+ */
125
+ relationSingle?: boolean;
126
+ /**
127
+ * `relation` (forward side) only: the chosen cardinality, kept for display and
128
+ * to derive the reverse property's multiplicity when pairing a two-way link.
129
+ */
130
+ relationCardinality?: RelationCardinality;
131
+ /**
132
+ * `relation` only: the id of the paired reverse `relation` property on the
133
+ * {@link relationDatabaseId target database} (a two-way link). Mirrors
134
+ * {@link syncedPropertyId} but across databases — setting A→B also lists A on
135
+ * B's reverse column.
136
+ */
137
+ reversePropertyId?: string;
138
+ }
139
+ /** Relation cardinality, from the perspective of the forward property: how many
140
+ * rows this side links, and how many the reverse side links back. */
141
+ export type RelationCardinality = '1:1' | '1:n' | 'n:n';
142
+ /** Whether each side of a relation cardinality holds a single row. `1:1` is
143
+ * single both ways; `1:n` links many but each target points back to one; `n:n`
144
+ * is many both ways. */
145
+ export declare function relationSides(card: RelationCardinality): {
146
+ forwardSingle: boolean;
147
+ reverseSingle: boolean;
148
+ };
149
+ /** The stored value of a `date` property configured as a range. */
150
+ export interface DateRange {
151
+ start: string | null;
152
+ end?: string | null;
153
+ }
154
+ /**
155
+ * The stored value of a `location` property: a geographic point with optional
156
+ * human label and source address. The shape mirrors the `location` **kit
157
+ * input** (see `blockeditor/kit/scope.ts`) so the two are interchangeable —
158
+ * `address` is added here for the database's geocoding round-trip (a text/address
159
+ * property geocoded into coords keeps the source string for re-display).
160
+ */
161
+ export interface LocationValue {
162
+ lat: number;
163
+ lng: number;
164
+ label?: string;
165
+ address?: string;
166
+ }
167
+ /** Read a `{lat, lng, …}` location value from a cell, or null when unresolvable. */
168
+ export declare function asLocation(value: unknown): LocationValue | null;
169
+ /**
170
+ * A named, collapsible/toggleable cluster of properties in the **page-view
171
+ * properties panel** (open a database row → its fields, organised). Hiding a
172
+ * group hides all its properties at once; collapsing just folds them away.
173
+ */
174
+ export interface PropertyGroup {
175
+ id: string;
176
+ name: string;
177
+ /** When true, the group's properties are hidden from the page-view panel. */
178
+ hidden?: boolean;
179
+ /** When true, the group renders folded (a header you can expand). */
180
+ collapsed?: boolean;
181
+ }
182
+ /**
183
+ * A reusable new-row preset: a named set of property values applied when a row
184
+ * is created "from template". Captured from an existing row and stored on the
185
+ * schema so every view can offer it from the New-row control.
186
+ */
187
+ export interface RowTemplate {
188
+ id: string;
189
+ name: string;
190
+ /** Property values to seed onto the new row (keyed by property id). */
191
+ properties: Record<string, unknown>;
192
+ }
193
+ /**
194
+ * The presentations the database screen supports. `table`/`list` are the
195
+ * row-oriented layouts; `gallery` shows cards; `board` is a kanban grouped by a
196
+ * select property; `calendar` lays rows out on a month grid by a date property;
197
+ * `bar`/`pie` are charts that aggregate rows by a category property.
198
+ */
199
+ export type DatabaseViewType = 'table' | 'list' | 'gallery' | 'board' | 'calendar' | 'timeline' | 'map' | 'graph' | 'bar' | 'pie';
200
+ /** How a chart (or a board column footer) aggregates a group of rows. */
201
+ export interface ChartAggregate {
202
+ /** `count` tallies rows; the others fold a numeric `propertyId`. */
203
+ type: 'count' | 'sum' | 'avg' | 'min' | 'max';
204
+ /** Property to fold (ignored for `count`). */
205
+ propertyId?: string;
206
+ }
207
+ /** A per-column footer calculation (table summary aggregations). */
208
+ export type SummaryType = 'none' | 'count_all' | 'count_values' | 'count_empty' | 'count_filled' | 'count_unique' | 'percent_empty' | 'percent_filled' | 'sum' | 'avg' | 'min' | 'max' | 'range' | 'median';
209
+ /** Comparison used by a {@link DatabaseFilter}. */
210
+ export type FilterOperator = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with' | 'gt' | 'lt' | 'gte' | 'lte' | 'before' | 'after' | 'on_or_before' | 'on_or_after' | 'is_today' | 'is_this_week' | 'is_past_week' | 'is_next_week' | 'is_this_month' | 'is_empty' | 'is_not_empty' | 'is_checked' | 'is_unchecked';
211
+ /** The value-less, relative-to-today date operators. */
212
+ export declare const RELATIVE_DATE_OPS: FilterOperator[];
213
+ export interface DatabaseFilter {
214
+ id: string;
215
+ /** Property to test. The reserved id {@link TITLE_PROPERTY_ID} targets the page name. */
216
+ propertyId: string;
217
+ operator: FilterOperator;
218
+ value?: unknown;
219
+ }
220
+ /** How a {@link DatabaseFilterGroup}'s children combine. */
221
+ export type FilterConjunction = 'and' | 'or';
222
+ /**
223
+ * A nested filter group: a set of conditions and/or sub-groups combined with a
224
+ * single conjunction (all `and`, or any `or`). This is the nested filter
225
+ * tree — `view.filterRoot` is the root group; an empty group matches everything.
226
+ */
227
+ export interface DatabaseFilterGroup {
228
+ id: string;
229
+ conjunction: FilterConjunction;
230
+ filters: Array<DatabaseFilter | DatabaseFilterGroup>;
231
+ }
232
+ /** A filter node is either a leaf condition or a nested group. */
233
+ export type FilterNode = DatabaseFilter | DatabaseFilterGroup;
234
+ /** True when a filter node is a group (vs. a leaf condition). */
235
+ export declare function isFilterGroup(node: FilterNode): node is DatabaseFilterGroup;
236
+ export type SortDirection = 'asc' | 'desc';
237
+ export interface DatabaseSort {
238
+ propertyId: string;
239
+ direction: SortDirection;
240
+ }
241
+ /** A conditional-formatting rule: when its condition holds for a row, the row's
242
+ * edge is tinted `color`. The first matching rule wins. */
243
+ export interface ColorRule {
244
+ id: string;
245
+ propertyId: string;
246
+ operator: FilterOperator;
247
+ value?: unknown;
248
+ /** A swatch palette token (see `SELECT_COLORS`). */
249
+ color: string;
250
+ }
251
+ /** A dashboard metric card: a single aggregate over the view's filtered rows. */
252
+ export interface DatabaseMetric {
253
+ id: string;
254
+ /** Property to summarise; the reserved {@link TITLE_PROPERTY_ID} counts rows. */
255
+ propertyId: string;
256
+ type: SummaryType;
257
+ /** Optional custom label (defaults to "<property> · <summary>"). */
258
+ label?: string;
259
+ /** Optional goal — when set, the card shows a progress bar of value/target. */
260
+ target?: number;
261
+ }
262
+ /** A saved presentation of the database: a layout plus its filters and sorts. */
263
+ export interface DatabaseView {
264
+ id: string;
265
+ name: string;
266
+ type: DatabaseViewType;
267
+ /** Legacy flat (all-AND) filters. Superseded by {@link filterRoot} when present. */
268
+ filters: DatabaseFilter[];
269
+ /** The nested filter tree (and/or groups). Falls back to ANDing {@link filters}. */
270
+ filterRoot?: DatabaseFilterGroup;
271
+ sorts: DatabaseSort[];
272
+ /**
273
+ * Property ids to show, in order. Empty/undefined shows every property. The
274
+ * title is always shown and is not listed here.
275
+ */
276
+ visiblePropertyIds?: string[];
277
+ /**
278
+ * Property to group rows by. Drives the kanban columns (`board`) and the
279
+ * category axis of a chart (`bar`/`pie`). Best paired with a `select`
280
+ * property, but any property works (rows group by their displayed value).
281
+ */
282
+ groupByPropertyId?: string;
283
+ /** Chart aggregation (`bar`/`pie`). Defaults to counting rows per group. */
284
+ aggregate?: ChartAggregate;
285
+ /**
286
+ * Chart second-level group (`bar`/`pie`). Splits each `groupByPropertyId`
287
+ * category into stacked bar segments (or a breakdown ring on the pie). Ignored
288
+ * when unset or equal to `groupByPropertyId`.
289
+ */
290
+ breakdownPropertyId?: string;
291
+ /** Bar chart with a breakdown: stretch every bar to 100% and show each segment
292
+ * as its share of the group total (proportions rather than absolute lengths). */
293
+ chartStacked100?: boolean;
294
+ /** Date property positioning rows on the month grid (`calendar`) or the bar
295
+ * start on the `timeline`. A `dateRange` property supplies both ends at once. */
296
+ datePropertyId?: string;
297
+ /** Timeline only: the property giving each bar's end (when not a range date). */
298
+ endDatePropertyId?: string;
299
+ /** Timeline only: the `dependency` property whose links draw arrows between bars. */
300
+ dependencyPropertyId?: string;
301
+ /** Gallery only: a `files`/`url` property whose first image is the card cover. */
302
+ coverPropertyId?: string;
303
+ /** Gallery only: card preview size. Defaults to `medium`. */
304
+ cardSize?: 'small' | 'medium' | 'large';
305
+ /** Gallery/board: a `select`/`status` property whose option colour tints each card's edge. */
306
+ cardColorPropertyId?: string;
307
+ /** Conditional formatting: rules that tint a row/card edge when their condition holds. */
308
+ colorRules?: ColorRule[];
309
+ /** Per-column footer summaries (table), keyed by property id (or {@link TITLE_PROPERTY_ID}). */
310
+ summaries?: Record<string, SummaryType>;
311
+ /** Dashboard metric cards shown above the view (count/sum/avg/… over the filtered rows). */
312
+ metrics?: DatabaseMetric[];
313
+ /** Board only: the per-column footer calculation (a property + summary). Defaults
314
+ * to summing the first numeric property, or counting rows. */
315
+ boardSummary?: {
316
+ propertyId: string;
317
+ type: SummaryType;
318
+ };
319
+ /** When grouped, collapse (fold) groups/columns/bands that currently have no rows
320
+ * rather than removing them — they stay visible but folded. On unless set false. */
321
+ collapseEmptyGroups?: boolean;
322
+ /**
323
+ * Board/timeline only: a **second** grouping dimension. The board renders one
324
+ * horizontal swimlane per value of this property (columns stay the primary
325
+ * {@link groupByPropertyId}, the Notion model); the timeline already groups by
326
+ * {@link groupByPropertyId}. Distinct from the chart {@link breakdownPropertyId}
327
+ * (different semantics — keep the menus unambiguous).
328
+ */
329
+ subGroupByPropertyId?: string;
330
+ /** Map only: the `location` property whose coords place each row's marker. */
331
+ geoPropertyId?: string;
332
+ /** Map only: an optional text/address property the user can opt to geocode into
333
+ * the {@link geoPropertyId} coords (no silent network calls — explicit action). */
334
+ addressPropertyId?: string;
335
+ /** Map only: cluster nearby markers at low zoom (default on for dense data). */
336
+ mapClustered?: boolean;
337
+ }
338
+ /** The full editable definition of a database: its columns, views, and the
339
+ * page-view property groups. */
340
+ export interface DatabaseSchema {
341
+ properties: DatabaseProperty[];
342
+ views: DatabaseView[];
343
+ /** Named groups organising the properties in the page-view panel. */
344
+ propertyGroups?: PropertyGroup[];
345
+ /** Reusable new-row presets offered by the New-row control. */
346
+ templates?: RowTemplate[];
347
+ }
348
+ /** A database as returned by the store. */
349
+ export interface StoredDatabase {
350
+ id: string;
351
+ /** The host page that contains this database. */
352
+ pageId: string;
353
+ name: string | null;
354
+ schema: DatabaseSchema;
355
+ createdAt: string;
356
+ updatedAt: string;
357
+ }
358
+ /** Payload for creating a database (always tied to an existing host page). */
359
+ export interface DatabaseInput {
360
+ id?: string;
361
+ pageId: string;
362
+ name?: string | null;
363
+ schema?: DatabaseSchema;
364
+ }
365
+ /** Payload for editing a database's name and/or schema in place. */
366
+ export interface DatabaseUpdate {
367
+ name?: string | null;
368
+ schema?: DatabaseSchema;
369
+ }
370
+ /**
371
+ * A single row, projected for list/table rendering. Lightweight on purpose: it
372
+ * carries the manual `properties` and the projected `exports` (named reactive
373
+ * values) but not the row page's full document — that is fetched only when the
374
+ * row is opened in the split pane.
375
+ */
376
+ export interface DatabaseRow {
377
+ /** The row's page id. */
378
+ id: string;
379
+ /** The row's page title. */
380
+ name: string | null;
381
+ /** Manual property values, keyed by property id. */
382
+ properties: Record<string, unknown>;
383
+ /** Exported reactive cell values, keyed by cell name. */
384
+ exports: Record<string, unknown>;
385
+ /** The row this row is a *sub-item* of (another row of the same database), or null. */
386
+ parentId: string | null;
387
+ createdAt: string;
388
+ updatedAt: string;
389
+ }
390
+ /** Payload for creating a row (a new page inside the database). */
391
+ export interface RowInput {
392
+ name?: string | null;
393
+ properties?: Record<string, unknown>;
394
+ data?: PageSnapshot;
395
+ /** Nest the new row under this row as a sub-item (same database). */
396
+ parentId?: string | null;
397
+ }
398
+ /**
399
+ * Arrange a flat row list into a parent→children forest by `parentId` (rows
400
+ * whose parent isn't in the set become roots), preserving the input order within
401
+ * each sibling group. Used to render sub-items as an expandable tree.
402
+ */
403
+ export interface RowTreeNode {
404
+ row: DatabaseRow;
405
+ depth: number;
406
+ children: RowTreeNode[];
407
+ }
408
+ export declare function buildRowTree(rows: DatabaseRow[]): RowTreeNode[];
409
+ /** Flatten a row tree to a list (depth-first), dropping the children of collapsed rows. */
410
+ export declare function flattenRowTree(nodes: RowTreeNode[], collapsed: Set<string>): RowTreeNode[];
411
+ /** Payload for editing a row's title and/or manual property values. */
412
+ export interface RowUpdate {
413
+ name?: string | null;
414
+ properties?: Record<string, unknown>;
415
+ }
416
+ /** Reserved property id addressing the row's page title in filters/sorts/views. */
417
+ export declare const TITLE_PROPERTY_ID = "title";
418
+ /** Swatch tokens for `select` options; resolved to colors by the UI. */
419
+ export declare const SELECT_COLORS: readonly ["gray", "brown", "orange", "yellow", "green", "blue", "purple", "pink", "red"];
420
+ /**
421
+ * Project a page snapshot's reactive store into a `{name: value}` map. This is
422
+ * how `expr` columns get their values without shipping the whole document: the
423
+ * `names` index maps each exported name to a cellId, and `values` holds the
424
+ * cellId → value pairs.
425
+ */
426
+ export declare function projectExports(snapshot: Pick<PageSnapshot, 'values' | 'names'>): Record<string, unknown>;
427
+ /** True when a URL looks like an image (by extension), for thumbnail rendering. */
428
+ export declare function isImageUrl(url: string): boolean;
429
+ /** The first image URL in a `files`/`url` cell value (a string or string[]), or null. */
430
+ export declare function firstImageUrl(value: unknown): string | null;
431
+ /**
432
+ * The URL a gallery cover should try: the first extension-detected image, else
433
+ * the first http(s) URL — CDN/signed image URLs often carry no extension, and
434
+ * the property was explicitly chosen as the cover, so any URL in it is worth
435
+ * attempting (the UI falls back to the placeholder if it fails to load).
436
+ */
437
+ export declare function coverImageUrl(value: unknown): string | null;
438
+ /**
439
+ * Resolve the value a row holds for a given property (title / manual / derived).
440
+ * `properties` is needed only to evaluate `formula` columns (which read other
441
+ * properties); pass it from any caller that has the schema (filters, sorts,
442
+ * cells). Without it, a formula resolves to `undefined`.
443
+ */
444
+ export declare function rowValue(row: DatabaseRow, property: DatabaseProperty | typeof TITLE_PROPERTY_ID, properties?: DatabaseProperty[], rows?: DatabaseRow[]): unknown;
445
+ /** The `start` day of a date value (a plain `YYYY-MM-DD` string or a {@link DateRange}). */
446
+ export declare function dateStart(value: unknown): string | null;
447
+ /** The `end` day of a {@link DateRange} value (null for a single-day date). */
448
+ export declare function dateEnd(value: unknown): string | null;
449
+ /** Parse a `YYYY-MM-DD` (or any Date-parseable) string to a *local* midnight Date. */
450
+ export declare function parseDay(value: string | null | undefined): Date | null;
451
+ /** An inclusive day span for a timeline bar. */
452
+ export interface DateSpan {
453
+ start: Date;
454
+ end: Date;
455
+ }
456
+ /**
457
+ * The timeline bar span for a row: `[start, end]` resolved from the view's date
458
+ * configuration — a `dateRange` property (start+end in one), or a start date
459
+ * property plus an optional `endDatePropertyId`. Returns `null` when the row has
460
+ * no start date. A missing/earlier end collapses to a single-day bar.
461
+ */
462
+ export declare function rowDateSpan(row: DatabaseRow, view: DatabaseView, properties: DatabaseProperty[]): DateSpan | null;
463
+ /**
464
+ * The map marker location for a row: the resolved coords of the view's
465
+ * `geoPropertyId` location cell, or null when the row has no usable coords (an
466
+ * empty cell, or an address that hasn't been geocoded). Pure — drives the map
467
+ * view's placed/unplaced split and is unit-testable.
468
+ */
469
+ export declare function rowLocation(row: DatabaseRow, view: DatabaseView, properties: DatabaseProperty[]): LocationValue | null;
470
+ /** A node in the dependency graph, placed in a layer (column) at an order (row). */
471
+ export interface GraphNode {
472
+ id: string;
473
+ /** Longest-path depth from a root (a row with no predecessors). */
474
+ layer: number;
475
+ /** Position within the layer (stable: source-row order). */
476
+ order: number;
477
+ }
478
+ /** A directed edge `from` a predecessor `to` the row that depends on it. */
479
+ export interface GraphEdge {
480
+ from: string;
481
+ to: string;
482
+ }
483
+ export interface DependencyGraph {
484
+ nodes: GraphNode[];
485
+ edges: GraphEdge[];
486
+ /** Number of layers (the graph's depth); at least 1. */
487
+ layerCount: number;
488
+ /** The most nodes in any one layer (the graph's height). */
489
+ maxLayerSize: number;
490
+ }
491
+ /**
492
+ * Lay a database's rows out as a dependency DAG: each row is a node, and its
493
+ * `dependency` property lists the predecessors it points back to (edge
494
+ * predecessor → dependent). Nodes are assigned a **layer** by longest path from a
495
+ * root (a row with no predecessors) so dependents always sit to the right of
496
+ * everything they depend on, and an **order** within the layer (stable, by row
497
+ * order). Pure and cycle-safe — a back-edge simply doesn't deepen the layer — so
498
+ * it can drive the graph view and be unit-tested directly.
499
+ */
500
+ export declare function dependencyGraph(rows: DatabaseRow[], dependencyPropertyId: string | undefined): DependencyGraph;
501
+ /** A related row's inverse-property value to write when syncing a two-way link. */
502
+ export interface InverseUpdate {
503
+ rowId: string;
504
+ value: string[];
505
+ }
506
+ /**
507
+ * Compute the inverse-property writes for a two-way `dependency` change: when
508
+ * `rowId`'s links go from `oldIds` to `newIds`, each newly-added related row gains
509
+ * `rowId` in its `inversePropertyId`, and each removed one loses it. Pure — the
510
+ * hook applies the returned updates — so the sync logic is unit-tested directly.
511
+ */
512
+ export declare function syncInverseUpdates(rowId: string, oldIds: string[], newIds: string[], relatedRows: DatabaseRow[], inversePropertyId: string): InverseUpdate[];
513
+ /**
514
+ * Evaluate a single filter against a resolved value. The optional `now`
515
+ * (defaulting to the current date) anchors the relative date operators
516
+ * (`is_today`, `is_this_week`, …) — pass it explicitly to keep tests deterministic.
517
+ */
518
+ export declare function matchesFilter(operator: FilterOperator, cell: unknown, target: unknown, now?: Date): boolean;
519
+ /**
520
+ * The effective filter tree for a view: its `filterRoot`, or a synthesised
521
+ * all-`and` group wrapping the legacy flat `filters`. Lets the UI always edit a
522
+ * single tree while old views keep working.
523
+ */
524
+ export declare function viewFilterRoot(view: DatabaseView): DatabaseFilterGroup;
525
+ /**
526
+ * Apply a view's filters and sorts to a row set, returning a new array. Filters
527
+ * are evaluated as a nested and/or tree ({@link viewFilterRoot}); sorts are
528
+ * applied in order (first sort is primary). Pure and side-effect free so it can
529
+ * run identically on the server or in the table UI.
530
+ */
531
+ /**
532
+ * True when a single leaf condition holds for a row — the same per-row test
533
+ * {@link applyView} uses for filtering, exposed for conditional formatting
534
+ * (color rules). Returns false when the condition's property no longer exists.
535
+ */
536
+ export declare function rowMatchesCondition(row: DatabaseRow, condition: {
537
+ propertyId: string;
538
+ operator: FilterOperator;
539
+ value?: unknown;
540
+ }, properties: DatabaseProperty[], rows?: DatabaseRow[]): boolean;
541
+ export declare function applyView(rows: DatabaseRow[], view: DatabaseView, properties: DatabaseProperty[]): DatabaseRow[];
542
+ /** Short non-cryptographic id for properties/views/options/filters. */
543
+ export declare const shortId: (prefix: string) => string;
544
+ /**
545
+ * A sensible starting schema for a brand-new database: a couple of manual
546
+ * properties and both a table and a list view, so the view switcher has
547
+ * something to switch between out of the box.
548
+ */
549
+ export declare function defaultDatabaseSchema(): DatabaseSchema;
550
+ /** A fresh view of a given type with sensible defaults for its layout. */
551
+ export declare function defaultView(type: DatabaseViewType, name: string, properties: DatabaseProperty[]): DatabaseView;
552
+ /** The starting options for a `status` property: one per lifecycle bucket. */
553
+ export declare function defaultStatusOptions(): DatabaseSelectOption[];
554
+ /** The lifecycle buckets a `status` property groups its options under, in order. */
555
+ export declare const STATUS_GROUPS: {
556
+ id: StatusGroup;
557
+ label: string;
558
+ }[];
559
+ /**
560
+ * Remove a property from a schema and scrub **every** dangling reference to it:
561
+ * each view's filters (flat list *and* the nested {@link filterRoot} tree),
562
+ * sorts, visible columns, summaries, and the group-by / date / cover config; plus
563
+ * any `rollup` on another property that aggregated through or over it. Pure —
564
+ * returns a fresh schema — so it can be unit-tested and shared by the delete
565
+ * action. (Renders already tolerate stale refs; this keeps the schema clean.)
566
+ */
567
+ export declare function removeProperty(schema: DatabaseSchema, propertyId: string): DatabaseSchema;
568
+ /** Format a numeric value for display per a {@link NumberFormat}. Non-numbers pass through as text. */
569
+ export declare function formatNumber(value: unknown, format: NumberFormat | undefined): string;
570
+ /**
571
+ * Format a `unique_id` value for display: an integer, optionally prefixed
572
+ * (`TASK` → `TASK-3`). Empty for unassigned (non-numeric) values. Pure.
573
+ */
574
+ export declare function formatUniqueId(value: unknown, prefix?: string): string;
575
+ /**
576
+ * The clamped 0..1 fraction of a number cell relative to its `target` (the
577
+ * value that fills a `bar`/`ring`). Non-numbers and a non-positive target read
578
+ * as 0; the target defaults to 100. Pure — drives the bar/ring cell and tests.
579
+ */
580
+ export declare function numberProgress(value: unknown, target?: number): number;
581
+ /** The label shown for rows that have no value for the grouping property. */
582
+ export declare const NO_VALUE_GROUP = "No value";
583
+ /** One group of rows sharing a value of the grouping property. */
584
+ export interface RowGroup {
585
+ /** Stable key for the group (option id, or the displayed string). */
586
+ key: string;
587
+ /** Human label (option label, or the value itself). */
588
+ label: string;
589
+ /** Swatch color, when the group corresponds to a select option. */
590
+ color?: string;
591
+ rows: DatabaseRow[];
592
+ }
593
+ /**
594
+ * Group rows by a property for the board (kanban) layout. When the property is a
595
+ * `select`, columns follow the option order (including empty ones) so the board
596
+ * is stable as rows move; otherwise columns are the distinct displayed values.
597
+ * Rows with no value collect into a trailing {@link NO_VALUE_GROUP} column.
598
+ */
599
+ export declare function groupRows(rows: DatabaseRow[], property: DatabaseProperty | undefined, properties: DatabaseProperty[]): RowGroup[];
600
+ /**
601
+ * Sentinel `groupByPropertyId` meaning "group by parent item" (sub-items).
602
+ * Not a real property id — {@link groupRowsBy} dispatches on it.
603
+ */
604
+ export declare const PARENT_GROUP_ID = "__parent__";
605
+ /** The label of the trailing group for rows that are nobody's sub-item. */
606
+ export declare const NO_PARENT_GROUP = "No parent";
607
+ /**
608
+ * Group rows by their parent row (sub-items): one group per row with at least
609
+ * one direct child in the set (key = the parent's row id, in row order), plus a
610
+ * trailing {@link NO_PARENT_GROUP} group for loose rows — rows that neither
611
+ * have a parent in the set nor children of their own. A row that is both a
612
+ * parent and a sub-item appears in its parent's group *and* heads its own.
613
+ * Parents outside the set (filtered out, or the host page) don't count.
614
+ */
615
+ export declare function groupRowsByParent(rows: DatabaseRow[]): RowGroup[];
616
+ /**
617
+ * Group rows by a view's `groupByPropertyId`: the {@link PARENT_GROUP_ID}
618
+ * sentinel groups by parent item ({@link groupRowsByParent}); anything else
619
+ * resolves to a property and falls through to {@link groupRows} (an unset or
620
+ * unknown id yields the single "All" group). The one dispatch shared by the
621
+ * board, table, list, gallery, and the chart aggregations.
622
+ */
623
+ export declare function groupRowsBy(rows: DatabaseRow[], groupByPropertyId: string | undefined, properties: DatabaseProperty[]): RowGroup[];
624
+ /** One category of a chart: a label, its aggregated value, and an optional color. */
625
+ export interface ChartDatum {
626
+ key: string;
627
+ label: string;
628
+ value: number;
629
+ color?: string;
630
+ }
631
+ /**
632
+ * Aggregate rows into chart data: one datum per group of the view's
633
+ * `groupByPropertyId`, with the bar/slice height computed by the view's
634
+ * `aggregate` (count by default, else sum/avg/min/max of a numeric property).
635
+ */
636
+ export declare function aggregateRows(rows: DatabaseRow[], view: DatabaseView, properties: DatabaseProperty[]): ChartDatum[];
637
+ /** Synthetic series used when a chart has no breakdown (a single full-height bar). */
638
+ export declare const CHART_TOTAL_SERIES = "__total__";
639
+ /** A breakdown series — the second-level group shared across every chart group. */
640
+ export interface ChartSeries {
641
+ /** Stable key (breakdown option id, or its displayed value). */
642
+ key: string;
643
+ label: string;
644
+ /** Swatch color when the series is a select option. */
645
+ color?: string;
646
+ }
647
+ /** One series' slice of a {@link ChartGroup}: its rows and aggregated value. */
648
+ export interface ChartSegment {
649
+ seriesKey: string;
650
+ value: number;
651
+ /** The rows behind this segment (powers click-to-drill). */
652
+ rows: DatabaseRow[];
653
+ }
654
+ /** One primary chart category, split across the shared {@link ChartMatrix.series}. */
655
+ export interface ChartGroup {
656
+ key: string;
657
+ label: string;
658
+ color?: string;
659
+ /** The group's bar height / slice size (sum of its segment values). */
660
+ total: number;
661
+ /** Per-series contributions, in {@link ChartMatrix.series} order (zero-filled). */
662
+ segments: ChartSegment[];
663
+ rows: DatabaseRow[];
664
+ }
665
+ /** A chart's full data: primary groups, each split across a shared series set. */
666
+ export interface ChartMatrix {
667
+ groups: ChartGroup[];
668
+ series: ChartSeries[];
669
+ }
670
+ /**
671
+ * Aggregate rows into a {@link ChartMatrix}: one group per value of the view's
672
+ * `groupByPropertyId`, each split into segments by `breakdownPropertyId` (the
673
+ * second-level group). The series are derived once across all rows so every group
674
+ * shares the same ordered, coloured set — a group with no rows for a series gets a
675
+ * zero segment, keeping stacked bars aligned. Without a breakdown each group has a
676
+ * single {@link CHART_TOTAL_SERIES} segment equal to its total. Pure — drives the
677
+ * bar and pie charts and their drill-downs.
678
+ */
679
+ export declare function aggregateMatrix(rows: DatabaseRow[], view: DatabaseView, properties: DatabaseProperty[]): ChartMatrix;
680
+ /**
681
+ * Compute a column footer summary over a row set: counts (all / values / empty /
682
+ * filled / unique), percentages, or numeric folds (sum / avg / min / max / range
683
+ * / median). Returns a display string ('' for `none`). `property` is
684
+ * {@link TITLE_PROPERTY_ID} for the title column; numeric folds honour a
685
+ * property's `numberFormat`. Pure — shared by the table footer UI and tests.
686
+ */
687
+ export declare function summarizeColumn(rows: DatabaseRow[], property: DatabaseProperty | typeof TITLE_PROPERTY_ID, type: SummaryType, properties: DatabaseProperty[]): string;