@alexmitchell/melondb 0.0.0-stage → 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alzen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,486 @@
1
- # Temporary Holding Version
1
+ # 🍈 MelonDB
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Typed helpers for [WatermelonDB](https://github.com/Nozbe/WatermelonDB).
4
+
5
+ MelonDB is WatermelonDB but more DRY. WatermelonDB is excellent for building offline-first React Native apps. **MelonDB** improves the developer experience by wrapping common operations in a small, typed API you configure once per app, reducing boilerplate and making simple mistakes easier to catch.
6
+
7
+ ---
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @alexmitchell/melondb @nozbe/watermelondb
13
+ ```
14
+
15
+ ```bash
16
+ yarn add @alexmitchell/melondb @nozbe/watermelondb
17
+ ```
18
+
19
+ `@nozbe/watermelondb` (>= 0.27) and `react` (>= 18) are **peer dependencies**: MelonDB uses your app's copy rather than bundling its own. If you've already set up WatermelonDB you have both.
20
+
21
+ ---
22
+
23
+ ## Quick start
24
+
25
+ Suppose you have some note data to insert:
26
+
27
+ ```ts
28
+ const draft = {
29
+ title: "Hello",
30
+ body: "World",
31
+ // ...
32
+ };
33
+ ```
34
+
35
+ With **WatermelonDB**, creating the row looks like this:
36
+
37
+ ```ts
38
+ const noteId = await database.write(async () => {
39
+ const note = await database.get<NoteModel>("notes").create((record) => {
40
+ record.title = draft.title;
41
+ record.body = draft.body;
42
+ // ...
43
+ });
44
+ return note.id;
45
+ });
46
+ ```
47
+
48
+ Once [configured](#setup), **MelonDB** reduces the same operation to:
49
+
50
+ ```ts
51
+ const noteId = await melon.insert("notes", draft);
52
+ ```
53
+
54
+ WatermelonDB requires each field to be assigned manually. TypeScript can catch a wrong type when it is assigned to a typed model property, but it does not check `draft` as a complete `notes` payload at the database call. A missing assignment is easy to overlook, and the `"notes"` string is not tied to the `NoteModel` type argument.
55
+
56
+ MelonDB uses `"notes"` to infer `TableData["notes"]`, then checks `draft` against it. A missing required property or a value with the wrong type—such as `body: 123`—causes a TypeScript error at the `insert` call. An unknown table name is rejected too.
57
+
58
+ ---
59
+
60
+ ## Setup
61
+
62
+ ### Define your tables
63
+
64
+ You still define each model and schema the WatermelonDB way. MelonDB only replaces the repetitive database access layer.
65
+
66
+ ```ts
67
+ import { Model, tableSchema } from "@nozbe/watermelondb";
68
+ import { text, readonly, date } from "@nozbe/watermelondb/decorators";
69
+
70
+ class NoteModel extends Model {
71
+ static table = "notes";
72
+
73
+ @text("title") title!: string;
74
+ @text("body") body!: string;
75
+ @readonly @date("created_at") createdAt!: Date;
76
+ }
77
+
78
+ type Note = Omit<NoteModel, keyof Model>;
79
+
80
+ const noteSchema = tableSchema({
81
+ name: "notes",
82
+ columns: [
83
+ { name: "title", type: "string" },
84
+ { name: "body", type: "string" },
85
+ { name: "created_at", type: "number" },
86
+ ],
87
+ });
88
+ ```
89
+
90
+ ### Initialize MelonDB
91
+
92
+ Then register your tables once in the app-wide configuration:
93
+
94
+ ```ts
95
+ import { createMelon } from "@alexmitchell/melondb";
96
+
97
+ // Register every table in these app-wide definitions.
98
+
99
+ type TableModels = {
100
+ notes: NoteModel;
101
+ // ...
102
+ };
103
+
104
+ type TableData = {
105
+ notes: Note;
106
+ // ...
107
+ };
108
+
109
+ const tables = [
110
+ noteSchema,
111
+ // ...
112
+ ];
113
+
114
+ const modelClasses = [
115
+ NoteModel,
116
+ // ...
117
+ ];
118
+
119
+ export const melon = createMelon<TableModels, TableData>({
120
+ version: 1,
121
+ tables,
122
+ modelClasses,
123
+ migrations: [],
124
+ });
125
+ ```
126
+
127
+ That gives you a typed `melon` instance plus the underlying `melon.db` if you need raw WatermelonDB APIs.
128
+
129
+ ---
130
+
131
+ ## More examples
132
+
133
+ ### Batch create
134
+
135
+ Suppose you have several notes to insert:
136
+
137
+ ```ts
138
+ const rows = [
139
+ { title: "One", body: "..." },
140
+ { title: "Two", body: "..." },
141
+ // ...
142
+ ];
143
+ ```
144
+
145
+ **WatermelonDB**
146
+
147
+ ```ts
148
+ await database.write(async () => {
149
+ const collection = database.get<NoteModel>("notes");
150
+ const prepared = rows.map((row) =>
151
+ collection.prepareCreate((record) => {
152
+ record.title = row.title;
153
+ record.body = row.body;
154
+ }),
155
+ );
156
+ await database.batch(prepared);
157
+ });
158
+ ```
159
+
160
+ **MelonDB**
161
+
162
+ ```ts
163
+ await melon.insertBatch("notes", rows);
164
+ ```
165
+
166
+ ---
167
+
168
+ ### Fetch one row by id
169
+
170
+ WatermelonDB's `find` rejects if the row does not exist, so returning `null` instead requires handling that error yourself.
171
+
172
+ **WatermelonDB**
173
+
174
+ ```ts
175
+ let note: NoteModel | null = null;
176
+ try {
177
+ note = await database.get<NoteModel>("notes").find(id);
178
+ } catch {
179
+ note = null;
180
+ }
181
+ ```
182
+
183
+ **MelonDB**
184
+
185
+ ```ts
186
+ const note = await melon.getRowById("notes", id); // NoteModel | null
187
+ ```
188
+
189
+ MelonDB handles the missing-row case and returns `null`. It also infers `NoteModel` from the `"notes"` table name, so the string and model type cannot drift apart.
190
+
191
+ ---
192
+
193
+ ### Update one field
194
+
195
+ Updating a single column on a single row is a common operation. Suppose you want to rename a note:
196
+
197
+ ```ts
198
+ const newTitle = "Renamed";
199
+ ```
200
+
201
+ **WatermelonDB**
202
+
203
+ ```ts
204
+ await database.write(async () => {
205
+ await note.update((row) => {
206
+ row.title = newTitle;
207
+ // easy to forget a convention like updatedDate
208
+ });
209
+ });
210
+ ```
211
+
212
+ **MelonDB**
213
+
214
+ ```ts
215
+ await melon.updateColumn(note, "title", newTitle);
216
+ ```
217
+
218
+ `updateColumn` ties the property name to that property's value type. Because `title` is a string, TypeScript would flag `newTitle` if it were a number. If the model has an `updatedDate` property, MelonDB also sets it to `new Date().toISOString()` automatically.
219
+
220
+ For several fields:
221
+
222
+ ```ts
223
+ await melon.updateColumns(note, [
224
+ { property: "title", value: "Renamed" },
225
+ { property: "body", value: "New body" },
226
+ ]);
227
+ ```
228
+
229
+ Or a full updater when you need custom logic:
230
+
231
+ ```ts
232
+ await melon.updateRow(note, (row) => {
233
+ row.title = row.title.trim();
234
+ });
235
+ ```
236
+
237
+ ---
238
+
239
+ ### Soft-delete
240
+
241
+ WatermelonDB deletes model instances rather than IDs. If all you have is `noteId`, you must fetch the row before you can delete it:
242
+
243
+ **WatermelonDB**
244
+
245
+ ```ts
246
+ const note = await database.get<NoteModel>("notes").find(noteId);
247
+
248
+ await database.write(async () => {
249
+ await note.markAsDeleted();
250
+ });
251
+ ```
252
+
253
+ **MelonDB**
254
+
255
+ ```ts
256
+ await melon.deleteRowById("notes", noteId);
257
+ ```
258
+
259
+ `deleteRowById` performs the lookup and soft-delete for you. If you already have the model instance, use `melon.deleteRow(note)` instead.
260
+
261
+ ---
262
+
263
+ ### Typed collections
264
+
265
+ **WatermelonDB**
266
+
267
+ ```ts
268
+ const notes = database.get<NoteModel>("notes");
269
+ // table name is a free string; generics are easy to drift
270
+ ```
271
+
272
+ **MelonDB**
273
+
274
+ ```ts
275
+ const notes = melon.get("notes");
276
+ // Collection<NoteModel> — table name is keyed by TableModels
277
+ ```
278
+
279
+ ---
280
+
281
+ ### Observable components (`withObservables`)
282
+
283
+ WatermelonDB's `withObservables` HOC is powerful but awkward to type when you also have query props and extra component props.
284
+
285
+ **WatermelonDB** (common pattern: cast and hope)
286
+
287
+ ```ts
288
+ export default withObservables(["noteId"], ({ noteId }) => ({
289
+ note: database.get("notes").findAndObserve(noteId),
290
+ }))(NoteBody) as React.ComponentType<{ noteId: string }>;
291
+ ```
292
+
293
+ **MelonDB**
294
+
295
+ ```ts
296
+ type Injected = { note: NoteModel };
297
+ type Query = { noteId: string };
298
+ type Props = { showTimestamp: boolean };
299
+
300
+ const enhancer = withObservables(["noteId"], ({ noteId }: Query) => ({
301
+ note: melon.get("notes").findAndObserve(noteId),
302
+ }));
303
+
304
+ export default melon.enhance<Injected, Query, Props>(enhancer, NoteBody);
305
+ // ComponentType<{ noteId: string; showTimestamp: boolean }>
306
+ ```
307
+
308
+ `enhance` is a thin typing helper: it wires `Injected` (from the HOC), `Query` (inputs that drive observables), and optional extra `Props` without fighting the HOC generics by hand.
309
+
310
+ ---
311
+
312
+ ### Safe database reset
313
+
314
+ Calling `unsafeResetDatabase` while React components still observe the DB can crash (see [WatermelonDB #102](https://github.com/Nozbe/WatermelonDB/issues/102)).
315
+
316
+ **WatermelonDB**
317
+
318
+ ```ts
319
+ // You must coordinate unmounting observers yourself, then:
320
+ await database.write(async () => {
321
+ await database.unsafeResetDatabase();
322
+ });
323
+ ```
324
+
325
+ **MelonDB**
326
+
327
+ ```ts
328
+ // Gate UI on availability:
329
+ const available = useSyncExternalStore(
330
+ melon.subscribeDatabaseAvailable,
331
+ melon.getDatabaseAvailable,
332
+ melon.getDatabaseAvailable,
333
+ );
334
+
335
+ if (!available) return null;
336
+
337
+ // Later, after a schema bump or logout:
338
+ await melon.resetDatabase();
339
+ ```
340
+
341
+ `resetDatabase` sets availability to `false`, waits for React to unmount gated observers, resets, then sets availability back to `true`.
342
+
343
+ ---
344
+
345
+ ## Platform adapters
346
+
347
+ `createMelon` / `createWatermelon` pick an adapter automatically:
348
+
349
+ | Platform | Adapter |
350
+ | ------------- | ------------------------------------------- |
351
+ | iOS / Android | SQLite (`createAdapter.ts`) |
352
+ | Web | LokiJS + IndexedDB (`createAdapter.web.ts`) |
353
+
354
+ Metro and webpack resolve the `.web.ts` file on web. You do not need to branch this yourself.
355
+
356
+ ---
357
+
358
+ ## IDs
359
+
360
+ By default, MelonDB leaves WatermelonDB's own random id generator in place. Pass `idGenerator` to replace it globally:
361
+
362
+ ```ts
363
+ createMelon({
364
+ // ...schema
365
+ idGenerator: () => myCustomId(),
366
+ });
367
+ ```
368
+
369
+ See [Tips → UUID v7 ids](#uuid-v7-ids) for a common choice.
370
+
371
+ ---
372
+
373
+ ## Logging
374
+
375
+ On by default. MelonDB logs to the console (prefixed `[🍈 MelonDB]`) when `getRowById` fails and when `resetDatabase` completes. To turn that off:
376
+
377
+ ```ts
378
+ createMelon({
379
+ // ...schema
380
+ logging: false,
381
+ });
382
+ ```
383
+
384
+ `logRowCount` and `logAllRows` always print, since calling them is an explicit request for output.
385
+
386
+ ---
387
+
388
+ ## Exporting plain rows
389
+
390
+ When you need JSON without WatermelonDB meta (`_status`, `_changed`):
391
+
392
+ ```ts
393
+ import { cleanRow } from "@alexmitchell/melondb";
394
+
395
+ const plain = cleanRow()(note);
396
+ // or merge extra fields:
397
+ const withUser = cleanRow({ user_id: userId })(note);
398
+ ```
399
+
400
+ For debug logging of model instances (circular refs):
401
+
402
+ ```ts
403
+ import { sanitizeCircular } from "@alexmitchell/melondb";
404
+
405
+ console.log(JSON.stringify(sanitizeCircular(note)));
406
+ ```
407
+
408
+ ---
409
+
410
+ ## API summary
411
+
412
+ | Method | Purpose |
413
+ | --------------------------------------- | --------------------------- |
414
+ | `melon.db` | Raw WatermelonDB `Database` |
415
+ | `melon.get(table)` | Typed `Collection` |
416
+ | `melon.getRowById(table, id)` | Fetch one or `null` |
417
+ | `melon.insert(table, data)` | Create, return id |
418
+ | `melon.insertBatch(table, rows)` | Batch create |
419
+ | `melon.updateRow(model, fn)` | Update with updater |
420
+ | `melon.updateColumn(model, key, value)` | Single-field update |
421
+ | `melon.updateColumns(model, cols)` | Multi-field update |
422
+ | `melon.deleteRow(model)` | Soft-delete |
423
+ | `melon.deleteRowById(table, id)` | Soft-delete by id |
424
+ | `melon.deleteBatch(models)` | Soft-delete many |
425
+ | `melon.deleteTable(table)` | Soft-delete all rows |
426
+ | `melon.emptyTable(table)` | Permanent destroy all |
427
+ | `melon.getRowCount(table)` | Count |
428
+ | `melon.logRowCount` / `logAllRows` | Debug helpers |
429
+ | `melon.enhance(hoc, Component)` | Typed `withObservables` |
430
+ | `melon.resetDatabase()` | Safe reset |
431
+ | `melon.getDatabaseAvailable()` | Current availability flag |
432
+ | `melon.subscribeDatabaseAvailable(fn)` | Subscribe to that flag |
433
+
434
+ Also exported: `createWatermelon`, `createAdapter`, `cleanRow`, `sanitizeCircular`.
435
+
436
+ ---
437
+
438
+ ## Type parameters
439
+
440
+ ```ts
441
+ createMelon<TableModels, TableData>({ ... })
442
+ ```
443
+
444
+ - `**TableModels**`: map table name → Model class instance type
445
+ - `**TableData**`: map table name → plain object shape for `insert` / `insertBatch`
446
+
447
+ Keep those two maps in sync with your schema and you get end-to-end typing for table names and insert payloads.
448
+
449
+ ---
450
+
451
+ ## What this is not
452
+
453
+ - Not a sync engine. No pull/push, no backend protocol.
454
+ - Not a replacement for WatermelonDB models, schemas, migrations, or queries.
455
+ - Not a full ORM. Prefer `melon.get(table).query(...)` when you need WatermelonDB's query API.
456
+
457
+ ---
458
+
459
+ ## Tips
460
+
461
+ ### UUID v7 ids
462
+
463
+ WatermelonDB's default ids are short random strings. If you sync with a backend that uses UUID primary keys, time-ordered UUID v7 ids are a good fit: they sort by creation time and index well in Postgres.
464
+
465
+ ```bash
466
+ npm install uuid react-native-get-random-values
467
+ ```
468
+
469
+ ```ts
470
+ import "react-native-get-random-values"; // must run before uuid, polyfills crypto.getRandomValues on React Native
471
+ import { v7 as uuidv7 } from "uuid";
472
+ import { createMelon } from "@alexmitchell/melondb";
473
+
474
+ export const melon = createMelon<TableModels, TableData>({
475
+ // ...schema
476
+ idGenerator: () => uuidv7(),
477
+ });
478
+ ```
479
+
480
+ On web you can skip `react-native-get-random-values`, because browsers already provide `crypto.getRandomValues`.
481
+
482
+ ---
483
+
484
+ ## License
485
+
486
+ MIT
@@ -0,0 +1,11 @@
1
+ export type DirtyRaw = {
2
+ [key: string]: any;
3
+ };
4
+ /**
5
+ * Build a mapper that strips WatermelonDB meta fields (`_status`, `_changed`)
6
+ * from a model's `_raw` and optionally merges extra fields.
7
+ *
8
+ * Useful when exporting rows to JSON, PDF, or a remote API.
9
+ */
10
+ export declare const cleanRow: (changes?: DirtyRaw) => (row?: DirtyRaw) => DirtyRaw | undefined;
11
+ //# sourceMappingURL=cleanRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanRow.d.ts","sourceRoot":"","sources":["../src/cleanRow.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IAErB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,QAAa,MACrC,MAAM,QAAQ,KAAG,QAAQ,GAAG,SASrC,CAAA"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanRow = void 0;
4
+ /**
5
+ * Build a mapper that strips WatermelonDB meta fields (`_status`, `_changed`)
6
+ * from a model's `_raw` and optionally merges extra fields.
7
+ *
8
+ * Useful when exporting rows to JSON, PDF, or a remote API.
9
+ */
10
+ const cleanRow = (changes = {}) => {
11
+ return (row) => {
12
+ if (!row) {
13
+ return undefined;
14
+ }
15
+ const { _status, _changed, ...rest } = row._raw;
16
+ return { ...rest, ...changes };
17
+ };
18
+ };
19
+ exports.cleanRow = cleanRow;
20
+ //# sourceMappingURL=cleanRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanRow.js","sourceRoot":"","sources":["../src/cleanRow.ts"],"names":[],"mappings":";;;AAKA;;;;;GAKG;AACI,MAAM,QAAQ,GAAG,CAAC,UAAoB,EAAE,EAAE,EAAE;IACjD,OAAO,CAAC,GAAc,EAAwB,EAAE;QAC9C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;QAE/C,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,EAAE,CAAA;IAChC,CAAC,CAAA;AACH,CAAC,CAAA;AAVY,QAAA,QAAQ,YAUpB"}
@@ -0,0 +1,5 @@
1
+ import SQLiteAdapter from "@nozbe/watermelondb/adapters/sqlite";
2
+ import { SQLiteAdapterOptions } from "@nozbe/watermelondb/adapters/sqlite/type";
3
+ /** Native (iOS / Android) SQLite adapter. */
4
+ export declare const createAdapter: (options: SQLiteAdapterOptions) => SQLiteAdapter;
5
+ //# sourceMappingURL=createAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAdapter.d.ts","sourceRoot":"","sources":["../src/createAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAEhF,6CAA6C;AAC7C,eAAO,MAAM,aAAa,GAAI,SAAS,oBAAoB,kBAE1D,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createAdapter = void 0;
7
+ const sqlite_1 = __importDefault(require("@nozbe/watermelondb/adapters/sqlite"));
8
+ /** Native (iOS / Android) SQLite adapter. */
9
+ const createAdapter = (options) => {
10
+ return new sqlite_1.default(options);
11
+ };
12
+ exports.createAdapter = createAdapter;
13
+ //# sourceMappingURL=createAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAdapter.js","sourceRoot":"","sources":["../src/createAdapter.ts"],"names":[],"mappings":";;;;;;AAAA,iFAAgE;AAGhE,6CAA6C;AACtC,MAAM,aAAa,GAAG,CAAC,OAA6B,EAAE,EAAE;IAC7D,OAAO,IAAI,gBAAa,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC,CAAC;AAFW,QAAA,aAAa,iBAExB"}
@@ -0,0 +1,4 @@
1
+ import LokiJSAdapter, { LokiAdapterOptions } from '@nozbe/watermelondb/adapters/lokijs';
2
+ /** Web adapter (LokiJS + IndexedDB). Metro/webpack resolve this via `.web.ts`. */
3
+ export declare const createAdapter: (options: LokiAdapterOptions) => LokiJSAdapter;
4
+ //# sourceMappingURL=createAdapter.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAdapter.web.d.ts","sourceRoot":"","sources":["../src/createAdapter.web.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,EAAE,EACpB,kBAAkB,EACnB,MAAM,qCAAqC,CAAA;AAE5C,kFAAkF;AAClF,eAAO,MAAM,aAAa,GAAI,SAAS,kBAAkB,kBAMxD,CAAA"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createAdapter = void 0;
7
+ const lokijs_1 = __importDefault(require("@nozbe/watermelondb/adapters/lokijs"));
8
+ /** Web adapter (LokiJS + IndexedDB). Metro/webpack resolve this via `.web.ts`. */
9
+ const createAdapter = (options) => {
10
+ return new lokijs_1.default({
11
+ useWebWorker: false,
12
+ useIncrementalIndexedDB: true,
13
+ ...options,
14
+ });
15
+ };
16
+ exports.createAdapter = createAdapter;
17
+ //# sourceMappingURL=createAdapter.web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAdapter.web.js","sourceRoot":"","sources":["../src/createAdapter.web.ts"],"names":[],"mappings":";;;;;;AAAA,iFAE4C;AAE5C,kFAAkF;AAC3E,MAAM,aAAa,GAAG,CAAC,OAA2B,EAAE,EAAE;IAC3D,OAAO,IAAI,gBAAa,CAAC;QACvB,YAAY,EAAE,KAAK;QACnB,uBAAuB,EAAE,IAAI;QAC7B,GAAG,OAAO;KACX,CAAC,CAAA;AACJ,CAAC,CAAA;AANY,QAAA,aAAa,iBAMzB"}
@@ -0,0 +1,37 @@
1
+ import { ComponentType } from "react";
2
+ import { Collection, Model } from "@nozbe/watermelondb";
3
+ import { WatermelonParams } from "./createWatermelon";
4
+ export type Melon = ReturnType<typeof createMelon>;
5
+ export type MelonParams = WatermelonParams & {
6
+ /** Console logging for failed lookups and database resets. Defaults to `true`. */
7
+ logging?: boolean;
8
+ /** Replaces WatermelonDB's global id generator. Defaults to WatermelonDB's own generator. */
9
+ idGenerator?: () => string;
10
+ };
11
+ export declare const createMelon: <TableModels extends Record<string, Model>, TableData extends Record<keyof TableModels, unknown>>(params: MelonParams) => {
12
+ /** Underlying WatermelonDB `Database` instance. */
13
+ db: import("@nozbe/watermelondb").Database;
14
+ enhance: <Injected, Query = unknown, Props = unknown>(enhancer: (Component: ComponentType<Injected & Props>) => ComponentType<Query & Props>, Component: ComponentType<Injected & Props>) => ComponentType<Query & Props>;
15
+ get: <T extends Extract<keyof TableModels, string>>(tableName: T) => Collection<TableModels[T]>;
16
+ getRowById: <T extends Extract<keyof TableModels, string>>(tableName: T, id: string) => Promise<TableModels[T] | null>;
17
+ insert: <T extends Extract<keyof TableModels, string>>(tableName: T, data: TableData[T]) => Promise<string>;
18
+ insertBatch: <T extends Extract<keyof TableModels, string>>(tableName: T, data: TableData[T][]) => Promise<void>;
19
+ updateRow: <T extends Extract<keyof TableModels, string>>(model: TableModels[T], updater: (row: TableModels[T]) => void) => Promise<TableModels[T]>;
20
+ updateColumn: <M extends Model, P extends keyof M, V extends M[P]>(model: M, property: P, value: V) => Promise<M>;
21
+ updateColumns: <M extends Model, P_1 extends keyof M, V_1 extends M[P_1]>(model: M, columns: {
22
+ property: P_1;
23
+ value: V_1;
24
+ }[]) => Promise<M>;
25
+ deleteRow: <T extends Model>(row: T) => Promise<void>;
26
+ deleteRowById: <T extends Extract<keyof TableModels, string>>(tableName: T, id: string | undefined) => Promise<void>;
27
+ deleteBatch: <T extends Model>(rows: T[]) => Promise<void>;
28
+ deleteTable: <T extends Extract<keyof TableModels, string>>(tableName: T) => Promise<void>;
29
+ emptyTable: <T extends Extract<keyof TableModels, string>>(tableName: T, batchSize?: number) => Promise<void>;
30
+ getRowCount: (tableName: Extract<keyof TableModels, string>) => Promise<number>;
31
+ logRowCount: (tableName: Extract<keyof TableModels, string>) => Promise<void>;
32
+ logAllRows: (tableName: Extract<keyof TableModels, string>) => Promise<void>;
33
+ resetDatabase: () => Promise<void>;
34
+ getDatabaseAvailable: () => boolean;
35
+ subscribeDatabaseAvailable: (listener: (available: boolean) => void) => () => void;
36
+ };
37
+ //# sourceMappingURL=createMelon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMelon.d.ts","sourceRoot":"","sources":["../src/createMelon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAK,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAoB,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGxE,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG;IAC3C,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,WAAW,GACtB,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACzC,SAAS,SAAS,MAAM,CAAC,MAAM,WAAW,EAAE,OAAO,CAAC,EAEpD,QAAQ,WAAW;IAgQjB,mDAAmD;;cA9OpC,QAAQ,EAAE,KAAK,YAAY,KAAK,sBACrC,CACR,SAAS,EAAE,aAAa,CAAC,QAAQ,GAAG,KAAK,CAAC,KACvC,aAAa,CAAC,KAAK,GAAG,KAAK,CAAC,aACtB,aAAa,CAAC,QAAQ,GAAG,KAAK,CAAC,KACzC,aAAa,CAAC,KAAK,GAAG,KAAK,CAAC;UAIlB,CAAC,wDAAgC,CAAC,KACE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;iBAGjD,CAAC,wDAAgC,CAAC,MAAM,MAAM;aAYlD,CAAC,wDACV,CAAC,QACN,SAAS,CAAC,CAAC,CAAC,KACjB,OAAO,CAAC,MAAM,CAAC;kBAUS,CAAC,wDACf,CAAC,QACN,SAAS,CAAC,CAAC,CAAC,EAAE;gBAaG,CAAC,oDACjB,WAAW,CAAC,CAAC,CAAC,WACZ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI;mBASlB,CAAC,SAAS,KAAK,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAC/D,CAAC,YACE,CAAC,SACJ,CAAC;oBAgBa,CAAC,SAAS,KAAK,cAAY,MAAM,CAAC,cAAY,CAAC,CAAC,GAAC,CAAC,SAChE,CAAC,WACC;QAAE,QAAQ,EAAE,GAAC,CAAC;QAAC,KAAK,EAAE,GAAC,CAAA;KAAE,EAAE;gBAcb,CAAC,SAAS,KAAK,OAAO,CAAC;oBAMnB,CAAC,wDACjB,CAAC,MACR,MAAM,GAAG,SAAS;kBAYG,CAAC,SAAS,KAAK,QAAQ,CAAC,EAAE;kBAe1B,CAAC,wDAAgC,CAAC;iBAkBnC,CAAC,wDACd,CAAC;;;;;;2CA0CF,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;CAiEzC,CAAC"}