arrowbase 0.1.1

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/MIGRATING.md ADDED
@@ -0,0 +1,238 @@
1
+ # MIGRATING.md — from @tanstack/db to ArrowBase
2
+
3
+ ArrowBase targets the same public API shape as `@tanstack/db`, but stores rows in
4
+ Arrow-style column buffers. Most app code can switch imports first, then opt into
5
+ columnar-specific persistence, IPC, and indexing features later.
6
+
7
+ ## Quick migration checklist
8
+
9
+ 1. Change imports from `@tanstack/db` to `arrowbase`.
10
+ 2. Add an ArrowBase schema and `capacity` for every root collection.
11
+ 3. Keep `getKey`, mutation handlers, transactions, optimistic actions, live query
12
+ builders, local-only helpers, and local-storage helpers the same shape.
13
+ 4. Run the parity gates: `pnpm typecheck`, `pnpm test`, `pnpm test:differential`,
14
+ `pnpm test:golden`, and `pnpm bench:vs-tanstack`.
15
+ 5. Check [COMPATIBILITY.md](./COMPATIBILITY.md) if an import touches a less common
16
+ helper or type alias.
17
+
18
+ ## Side-by-side snippets
19
+
20
+ ### 1. Local-only collection
21
+
22
+ TanStack DB:
23
+
24
+ ```ts
25
+ import { createCollection, localOnlyCollectionOptions } from '@tanstack/db';
26
+
27
+ type Todo = {
28
+ id: number;
29
+ title: string;
30
+ done: boolean;
31
+ };
32
+
33
+ const todos = createCollection(
34
+ localOnlyCollectionOptions<Todo, number>({
35
+ id: 'todos',
36
+ getKey: (todo) => todo.id,
37
+ initialData: [{ id: 1, title: 'ship', done: false }],
38
+ }),
39
+ );
40
+
41
+ await todos.preload();
42
+ ```
43
+
44
+ ArrowBase:
45
+
46
+ ```ts
47
+ import { createCollection, defineSchema, localOnlyCollectionOptions } from 'arrowbase';
48
+
49
+ type Todo = {
50
+ __id: number;
51
+ title: string;
52
+ done: boolean;
53
+ };
54
+
55
+ const todoSchema = defineSchema({
56
+ name: 'todos',
57
+ columns: {
58
+ __id: { type: 'uint32' },
59
+ title: { type: 'utf8' },
60
+ done: { type: 'bool' },
61
+ },
62
+ });
63
+
64
+ const todos = createCollection(
65
+ localOnlyCollectionOptions<Todo, number>({
66
+ id: 'todos',
67
+ schema: todoSchema,
68
+ capacity: 10_000,
69
+ getKey: (todo) => todo.__id,
70
+ initialData: [{ __id: 1, title: 'ship', done: false }],
71
+ }),
72
+ );
73
+
74
+ await todos.preload();
75
+ ```
76
+
77
+ Key difference: ArrowBase needs a compiled column schema and fixed `capacity`.
78
+ Use `__id` when you want the native primary-key fast path; custom keys still work
79
+ through `getKey` for TanStack-shaped APIs.
80
+
81
+ ### 2. Mutations and transactions
82
+
83
+ TanStack DB:
84
+
85
+ ```ts
86
+ import { createTransaction } from '@tanstack/db';
87
+
88
+ const tx = createTransaction({
89
+ mutationFn: async ({ transaction }) => {
90
+ await api.save(transaction.mutations);
91
+ },
92
+ });
93
+
94
+ tx.mutate(() => {
95
+ todos.insert({ id: 2, title: 'docs', done: false });
96
+ todos.update(1, (draft) => {
97
+ draft.done = true;
98
+ });
99
+ });
100
+
101
+ await tx.isPersisted.promise;
102
+ ```
103
+
104
+ ArrowBase:
105
+
106
+ ```ts
107
+ import { createTransaction } from 'arrowbase';
108
+
109
+ const tx = createTransaction({
110
+ mutationFn: async ({ transaction }) => {
111
+ await api.save(transaction.mutations);
112
+ },
113
+ });
114
+
115
+ tx.mutate(() => {
116
+ todos.insert({ __id: 2, title: 'docs', done: false });
117
+ todos.update(1, (draft) => {
118
+ draft.done = true;
119
+ });
120
+ });
121
+
122
+ await tx.isPersisted.promise;
123
+ ```
124
+
125
+ `ChangeMessage`, `PendingMutation`, rollback, optimistic mutation, and ambient
126
+ transaction shapes match the reference implementation. ArrowBase keeps the same
127
+ callback contracts but writes into column buffers.
128
+
129
+ ### 3. Query builder and aggregates
130
+
131
+ TanStack DB:
132
+
133
+ ```ts
134
+ import { Query, count, gt, sum } from '@tanstack/db';
135
+
136
+ const byDone = new Query()
137
+ .from({ todos })
138
+ .select(({ todos }) => ({
139
+ done: todos.done,
140
+ n: count(todos.id),
141
+ total: sum(todos.id),
142
+ }))
143
+ .where(({ todos }) => gt(todos.id, 0))
144
+ .groupBy(({ todos }) => todos.done);
145
+ ```
146
+
147
+ ArrowBase:
148
+
149
+ ```ts
150
+ import { Query, count, gt, sum } from 'arrowbase';
151
+
152
+ const byDone = new Query()
153
+ .from({ todos })
154
+ .select(({ todos }) => ({
155
+ done: todos.done,
156
+ n: count(todos.__id),
157
+ total: sum(todos.__id),
158
+ }))
159
+ .where(({ todos }) => gt(todos.__id, 0))
160
+ .groupBy(({ todos }) => todos.done);
161
+ ```
162
+
163
+ The builder surface is compatible. ArrowBase also keeps its native `query()` /
164
+ `run()` API and vectorized `filter()` DSL for hot columnar paths.
165
+
166
+ ### 4. Local storage
167
+
168
+ TanStack DB:
169
+
170
+ ```ts
171
+ import { createCollection, localStorageCollectionOptions } from '@tanstack/db';
172
+
173
+ const prefs = createCollection(
174
+ localStorageCollectionOptions({
175
+ id: 'prefs',
176
+ storageKey: 'app:prefs',
177
+ getKey: (row) => row.id,
178
+ }),
179
+ );
180
+ ```
181
+
182
+ ArrowBase:
183
+
184
+ ```ts
185
+ import { createCollection, defineSchema, localStorageCollectionOptions } from 'arrowbase';
186
+
187
+ const prefsSchema = defineSchema({
188
+ name: 'prefs',
189
+ columns: {
190
+ __id: { type: 'uint32' },
191
+ name: { type: 'utf8' },
192
+ value: { type: 'utf8' },
193
+ },
194
+ });
195
+
196
+ const prefs = createCollection(
197
+ localStorageCollectionOptions({
198
+ id: 'prefs',
199
+ schema: prefsSchema,
200
+ capacity: 1_000,
201
+ storageKey: 'app:prefs',
202
+ getKey: (row) => row.__id,
203
+ }),
204
+ );
205
+ ```
206
+
207
+ ArrowBase local storage persists the same logical collection state and exposes
208
+ `clearStorage`, `getStorageSize`, and `acceptMutations` utilities. The storage
209
+ record is columnar snapshot data rather than plain row JSON unless you provide a
210
+ custom parser.
211
+
212
+ ## Common pitfalls
213
+
214
+ - **Capacity is explicit.** ArrowBase collections allocate typed column buffers
215
+ up front. Pick a headroom value and add app-level rollover/compaction if the
216
+ collection can exceed it.
217
+ - **Schema first.** You must map row fields to ArrowBase column types. `utf8`,
218
+ `dict_utf8`, `binary`, `list`, and `struct` are available for richer rows.
219
+ - **Primary-key naming.** Native examples use `__id`. If an existing app uses
220
+ `id`, either rename during migration or keep `getKey: (row) => row.id` and add
221
+ a numeric `__id` for columnar PK storage.
222
+ - **BigInt ↔ Number.** Safe-range numeric join keys are normalized so `int64` and
223
+ `uint32` keys can match. Outside the safe integer range, keep both sides as
224
+ `bigint` to avoid precision loss.
225
+ - **floating-point aggregate tolerance.** ArrowBase uses stable summation for
226
+ `sum`/`avg`. Results can differ from the reference in the last few bits; compare
227
+ with a tolerance rather than strict stringified floats.
228
+ - **Soft deletes.** ArrowBase can preserve tombstones internally and omit them
229
+ from public rows. Use `includeSoftDeleted` only when the app intentionally
230
+ renders tombstones.
231
+ - **Browser SharedArrayBuffer.** Browser use needs COOP/COEP headers. Node and
232
+ worker-thread usage do not need extra headers.
233
+
234
+ ## Compatibility source of truth
235
+
236
+ [COMPATIBILITY.md](./COMPATIBILITY.md) is generated from the enumerated
237
+ `@tanstack/db@0.6.5` export list. For this parity release it is all green:
238
+ 289/289 exports reviewed and accepted under the tolerances above.