@taladb/react-native 0.10.2 → 0.11.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-MIT +21 -0
- package/android/src/main/jniLibs/arm64-v8a/libtaladb_ffi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libtaladb_ffi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libtaladb_ffi.so +0 -0
- package/cpp/TalaDBHostObject.cpp +2 -129
- package/cpp/taladb.h +2 -75
- package/ios/TalaDBFfi.xcframework/Info.plist +9 -9
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/TalaDBHostObject.cpp +2 -129
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/taladb.h +2 -75
- package/ios/TalaDBFfi.xcframework/ios-arm64/libtaladb_ffi.a +0 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/TalaDBHostObject.cpp +2 -129
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/taladb.h +2 -75
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/libtaladb_ffi_sim.a +0 -0
- package/package.json +7 -2
- package/src/NativeTalaDB.ts +3 -27
- package/src/index.tsx +122 -92
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- /package/{LICENSE → LICENSE-APACHE} +0 -0
package/src/index.tsx
CHANGED
|
@@ -1,71 +1,32 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* await TalaDBModule.initialize('myapp.db');
|
|
10
|
-
*
|
|
11
|
-
* // Anywhere in the app — same API as browser
|
|
12
|
-
* const db = openDB('myapp.db');
|
|
13
|
-
* const users = db.collection<User>('users');
|
|
14
|
-
* const id = users.insert({ name: 'Alice', age: 30 });
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* All operations are **synchronous** via JSI — no async/await needed
|
|
18
|
-
* after initialization.
|
|
19
|
-
*/
|
|
1
|
+
/** TalaDB React Native public API. CRUD is synchronous through the JSI host. */
|
|
2
|
+
import {
|
|
3
|
+
createWebhookDispatcher,
|
|
4
|
+
type WebhookConfig,
|
|
5
|
+
type WebhookDispatcher,
|
|
6
|
+
type WebhookEvent,
|
|
7
|
+
type WebhookStats,
|
|
8
|
+
} from 'taladb';
|
|
20
9
|
import NativeTalaDB from './NativeTalaDB';
|
|
21
10
|
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Module-level helpers
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
|
|
26
11
|
export const TalaDBModule = {
|
|
27
|
-
/**
|
|
28
|
-
* Open (or create) the database. Call once at app startup.
|
|
29
|
-
*
|
|
30
|
-
* @param configJson Optional JSON-serialised `TalaDbConfig` for HTTP push
|
|
31
|
-
* sync. Example: `JSON.stringify({ sync: { enabled: true,
|
|
32
|
-
* endpoint: 'https://api.example.com/events' } })`.
|
|
33
|
-
*/
|
|
12
|
+
/** Open the native database. The config controls durability/encryption only. */
|
|
34
13
|
initialize: (dbName: string, configJson?: string) =>
|
|
35
14
|
NativeTalaDB.initialize(dbName, configJson),
|
|
36
|
-
/** Close the database gracefully. */
|
|
37
15
|
close: () => NativeTalaDB.close(),
|
|
38
|
-
/** HTTP push events dropped by backpressure or failed after retries. */
|
|
39
|
-
syncStatus: () => native().syncStatus(),
|
|
40
|
-
/** Wait for HTTP push work accepted before this call. */
|
|
41
|
-
flushSync: (timeoutMs = 5000) => native().flushSync(timeoutMs),
|
|
42
16
|
};
|
|
43
17
|
|
|
44
|
-
// ---------------------------------------------------------------------------
|
|
45
|
-
// Collection handle
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
|
|
48
18
|
export interface Document {
|
|
49
19
|
_id?: string;
|
|
50
20
|
[key: string]: unknown;
|
|
51
21
|
}
|
|
52
22
|
|
|
23
|
+
export type InsertDocument<T extends Document> = Omit<T, '_id'> & { _id?: string };
|
|
53
24
|
export type Filter = Record<string, unknown>;
|
|
54
25
|
export type Update = Record<string, unknown>;
|
|
55
26
|
|
|
56
27
|
export interface Collection<T extends Document = Document> {
|
|
57
|
-
insert(doc:
|
|
58
|
-
insertMany(docs:
|
|
59
|
-
/**
|
|
60
|
-
* Upsert many documents **by `_id`**, in one commit. Requires an `_id` on every
|
|
61
|
-
* document — for replicated rows that comes from `deriveDocId(collection, key)`.
|
|
62
|
-
*
|
|
63
|
-
* `origin: 'remote'` marks rows as replicated in from an authoritative origin so
|
|
64
|
-
* they are never replicated back out; it defaults to `'local'`.
|
|
65
|
-
*/
|
|
66
|
-
replaceManyWithIds(docs: T[], origin?: 'local' | 'remote'): string[];
|
|
67
|
-
/** Delete many documents by id, in one commit. Returns the number removed. */
|
|
68
|
-
deleteManyWithIds(ids: string[], origin?: 'local' | 'remote'): number;
|
|
28
|
+
insert(doc: InsertDocument<T>): string;
|
|
29
|
+
insertMany(docs: InsertDocument<T>[]): string[];
|
|
69
30
|
find(filter?: Filter): T[];
|
|
70
31
|
findOne(filter: Filter): T | null;
|
|
71
32
|
updateOne(filter: Filter, update: Update): boolean;
|
|
@@ -79,26 +40,21 @@ export interface Collection<T extends Document = Document> {
|
|
|
79
40
|
dropFtsIndex(field: string): void;
|
|
80
41
|
}
|
|
81
42
|
|
|
43
|
+
export interface OpenDBOptions {
|
|
44
|
+
/** Runtime-agnostic outbound change webhook, delivered with global `fetch`. */
|
|
45
|
+
webhook?: WebhookConfig;
|
|
46
|
+
}
|
|
47
|
+
|
|
82
48
|
export interface DB {
|
|
83
49
|
collection<T extends Document = Document>(name: string): Collection<T>;
|
|
84
|
-
|
|
85
|
-
|
|
50
|
+
webhookStats(): WebhookStats;
|
|
51
|
+
flushWebhook(timeoutMs?: number): Promise<boolean>;
|
|
86
52
|
close(): Promise<void>;
|
|
87
53
|
}
|
|
88
54
|
|
|
89
55
|
interface JsiTalaDB {
|
|
90
56
|
insert(collection: string, doc: Object): string;
|
|
91
57
|
insertMany(collection: string, docs: Object[]): string[];
|
|
92
|
-
replaceManyWithIds(
|
|
93
|
-
collection: string,
|
|
94
|
-
docs: Object[],
|
|
95
|
-
origin: 'local' | 'remote',
|
|
96
|
-
): string[];
|
|
97
|
-
deleteManyWithIds(
|
|
98
|
-
collection: string,
|
|
99
|
-
ids: string[],
|
|
100
|
-
origin: 'local' | 'remote',
|
|
101
|
-
): number;
|
|
102
58
|
find(collection: string, filter: Object | null): Object[];
|
|
103
59
|
findOne(collection: string, filter: Object | null): Object | null;
|
|
104
60
|
updateOne(collection: string, filter: Object, update: Object): boolean;
|
|
@@ -110,8 +66,6 @@ interface JsiTalaDB {
|
|
|
110
66
|
dropIndex(collection: string, field: string): void;
|
|
111
67
|
createFtsIndex(collection: string, field: string): void;
|
|
112
68
|
dropFtsIndex(collection: string, field: string): void;
|
|
113
|
-
syncStatus(): { dropped: number; failed: number };
|
|
114
|
-
flushSync(timeoutMs?: number): boolean;
|
|
115
69
|
}
|
|
116
70
|
|
|
117
71
|
function native(): JsiTalaDB {
|
|
@@ -120,31 +74,102 @@ function native(): JsiTalaDB {
|
|
|
120
74
|
return host;
|
|
121
75
|
}
|
|
122
76
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
77
|
+
const EMPTY_STATS: WebhookStats = { pending: 0, delivered: 0, failed: 0, dropped: 0 };
|
|
78
|
+
|
|
79
|
+
function emitPostImages<T extends Document>(
|
|
80
|
+
webhook: WebhookDispatcher | null,
|
|
81
|
+
collection: string,
|
|
82
|
+
ids: string[],
|
|
83
|
+
op: 'insert' | 'update',
|
|
84
|
+
committedAt: number,
|
|
85
|
+
): void {
|
|
86
|
+
if (!webhook?.reports(collection) || ids.length === 0) return;
|
|
87
|
+
const docs = native().find(collection, { _id: { $in: ids } }) as T[];
|
|
88
|
+
const byId = new Map(docs.map((doc) => [doc._id, doc]));
|
|
89
|
+
for (const id of ids) {
|
|
90
|
+
const document = byId.get(id);
|
|
91
|
+
if (document) webhook.emit({ op, collection, id, document, committedAt } as WebhookEvent);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function emitDeletes<T extends Document>(
|
|
96
|
+
webhook: WebhookDispatcher | null,
|
|
97
|
+
collection: string,
|
|
98
|
+
docs: T[],
|
|
99
|
+
committedAt: number,
|
|
100
|
+
): void {
|
|
101
|
+
if (!webhook?.reports(collection)) return;
|
|
102
|
+
for (const document of docs) {
|
|
103
|
+
if (typeof document._id !== 'string') continue;
|
|
104
|
+
// DELETE carries the pre-image: after commit there is no post-image to read.
|
|
105
|
+
webhook.emit({
|
|
106
|
+
op: 'delete',
|
|
107
|
+
collection,
|
|
108
|
+
id: document._id,
|
|
109
|
+
document,
|
|
110
|
+
committedAt,
|
|
111
|
+
} as WebhookEvent);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
126
114
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
* this function.
|
|
132
|
-
*/
|
|
133
|
-
function collection<T extends Document>(colName: string): Collection<T> {
|
|
115
|
+
function collection<T extends Document>(
|
|
116
|
+
colName: string,
|
|
117
|
+
webhook: WebhookDispatcher | null,
|
|
118
|
+
): Collection<T> {
|
|
134
119
|
return {
|
|
135
|
-
insert
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
120
|
+
insert(doc) {
|
|
121
|
+
const id = native().insert(colName, doc as Object);
|
|
122
|
+
const committedAt = Date.now();
|
|
123
|
+
emitPostImages<T>(webhook, colName, [id], 'insert', committedAt);
|
|
124
|
+
return id;
|
|
125
|
+
},
|
|
126
|
+
insertMany(docs) {
|
|
127
|
+
const ids = native().insertMany(colName, docs as Object[]);
|
|
128
|
+
const committedAt = Date.now();
|
|
129
|
+
emitPostImages<T>(webhook, colName, ids, 'insert', committedAt);
|
|
130
|
+
return ids;
|
|
131
|
+
},
|
|
132
|
+
find: (filter) => native().find(colName, filter ?? null) as T[],
|
|
142
133
|
findOne: (filter) => native().findOne(colName, filter) as T | null,
|
|
143
|
-
updateOne
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
134
|
+
updateOne(filter, update) {
|
|
135
|
+
const before = native().findOne(colName, filter) as T | null;
|
|
136
|
+
const changed = native().updateOne(colName, filter, update);
|
|
137
|
+
const committedAt = Date.now();
|
|
138
|
+
if (changed && typeof before?._id === 'string') {
|
|
139
|
+
emitPostImages<T>(webhook, colName, [before._id], 'update', committedAt);
|
|
140
|
+
}
|
|
141
|
+
return changed;
|
|
142
|
+
},
|
|
143
|
+
updateMany(filter, update) {
|
|
144
|
+
const before = native().find(colName, filter) as T[];
|
|
145
|
+
const changed = native().updateMany(colName, filter, update);
|
|
146
|
+
const committedAt = Date.now();
|
|
147
|
+
if (changed > 0) {
|
|
148
|
+
emitPostImages<T>(
|
|
149
|
+
webhook,
|
|
150
|
+
colName,
|
|
151
|
+
before.map((doc) => doc._id).filter((id): id is string => typeof id === 'string'),
|
|
152
|
+
'update',
|
|
153
|
+
committedAt,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return changed;
|
|
157
|
+
},
|
|
158
|
+
deleteOne(filter) {
|
|
159
|
+
const before = native().findOne(colName, filter) as T | null;
|
|
160
|
+
const deleted = native().deleteOne(colName, filter);
|
|
161
|
+
const committedAt = Date.now();
|
|
162
|
+
if (deleted && before) emitDeletes(webhook, colName, [before], committedAt);
|
|
163
|
+
return deleted;
|
|
164
|
+
},
|
|
165
|
+
deleteMany(filter) {
|
|
166
|
+
const before = native().find(colName, filter) as T[];
|
|
167
|
+
const deleted = native().deleteMany(colName, filter);
|
|
168
|
+
const committedAt = Date.now();
|
|
169
|
+
if (deleted > 0) emitDeletes(webhook, colName, before, committedAt);
|
|
170
|
+
return deleted;
|
|
171
|
+
},
|
|
172
|
+
count: (filter) => native().count(colName, filter ?? null),
|
|
148
173
|
createIndex: (field) => native().createIndex(colName, field),
|
|
149
174
|
dropIndex: (field) => native().dropIndex(colName, field),
|
|
150
175
|
createFtsIndex: (field) => native().createFtsIndex(colName, field),
|
|
@@ -152,11 +177,16 @@ function collection<T extends Document>(colName: string): Collection<T> {
|
|
|
152
177
|
};
|
|
153
178
|
}
|
|
154
179
|
|
|
155
|
-
|
|
180
|
+
/** Get a synchronous DB handle after `TalaDBModule.initialize(dbName)`. */
|
|
181
|
+
export function openDB(_dbName: string, options?: OpenDBOptions): DB {
|
|
182
|
+
const webhook = createWebhookDispatcher(options?.webhook);
|
|
156
183
|
return {
|
|
157
|
-
collection,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
close: () =>
|
|
184
|
+
collection: <T extends Document>(name: string) => collection<T>(name, webhook),
|
|
185
|
+
webhookStats: () => webhook?.stats() ?? { ...EMPTY_STATS },
|
|
186
|
+
flushWebhook: (timeoutMs) => webhook?.flush(timeoutMs) ?? Promise.resolve(true),
|
|
187
|
+
close: async () => {
|
|
188
|
+
await webhook?.flush();
|
|
189
|
+
await NativeTalaDB.close();
|
|
190
|
+
},
|
|
161
191
|
};
|
|
162
192
|
}
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
File without changes
|
|
File without changes
|