forked from joe-trellick/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
snippets.json
297 lines (297 loc) · 98.2 KB
/
snippets.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
{
"rust": {
"remove-query": "let removed_ids = col_tx\n .find_with_args(\"color == $args.color\", json!({\"color\": \"yellow\"}))\n .remove()\n .unwrap();\n\n",
"evict": "let evicted_ids = collection\n .find_with_args(\"$args.color == color\", json!({\"color\": \"red\"}))\n .sort(vec![sort_param])\n .evict()\n .unwrap();\n\n",
"sync-basic": "ditto.start_sync()?;\n\n",
"datamodel": "let store = ditto.store();\nlet collection = store.collection(\"people\").unwrap();\n\n",
"upsert-id": "let doc_id = DocumentId::new(&\"123abc\".to_string()).unwrap();\nlet person = json!({ // Person implements serde::Serialize\n \"_id\": doc_id,\n \"name\": \"Susan\".to_string(),\n \"age\": 31,\n});\ncollection.upsert(person).unwrap();\n\n",
"array-to-map": "collection\n .find_by_id(doc_id)\n .update(|opt_doc| {\n if let Some(doc) = opt_doc {\n let friends: DittoRegister = doc.get(\"friends\").unwrap();\n let mut map = HashMap::new();\n let array = friends.value.as_array().unwrap();\n\n for name in array {\n let id = Uuid::new_v4().to_string();\n let friend = json!({\n \"name\": name,\n \"id\": id\n });\n map.insert(id, friend);\n }\n\n doc.set(\"friendsMap\", map).unwrap();\n }\n })\n .unwrap();\n\n",
"upsert": "let person = json!({\n \"name\": \"Susan\".to_string(),\n \"age\": 31,\n});\nlet collection = ditto.store().collection(\"people\").unwrap();\nlet id = collection.upsert(person).unwrap();\n\n",
"remove-id": "collection.find_by_id(id).remove().unwrap();\n\n",
"upsert-composite-primary-key": "let collection = ditto.store().collection(\"people\").unwrap();\nlet complex_id = PersonId {\n user_id: \"456abc\".to_string(),\n work_id: 789,\n};\nlet doc_id = DocumentId::new(&serde_json::json!(complex_id)).unwrap();\nlet doc = json!({\n \"_id\": doc_id,\n \"name\": \"Susan\".to_string(),\n \"age\": 31,\n});\ncollection.upsert(doc).unwrap();\n\n",
"upsert-datatypes": "collection\n .upsert(json!({\n \"boolean\": true,\n \"string\": \"Hello World\",\n \"number\": 10,\n \"map\": {\n \"key\": \"value\"\n },\n \"array\": [1,2,3],\n \"null\": null,\n }))\n .unwrap();\n\n",
"upsert-default-data": "let default_id = DocumentId::new(&\"123abc\".to_string()).unwrap();\nlet data = json!({ // Person implements serde::Serialize\n \"_id\": default_id,\n \"name\": \"Susan\".to_string(),\n \"age\": 31,\n});\ncollection\n .upsert_with_strategy(data, WriteStrategy::InsertDefaultIfAbsent)\n .unwrap();\n\n",
"attachment": "let store = ditto.store();\nlet collection = store.collection(\"foo\")?;\nlet attachment_file_path = images_dir.join(\"image.png\");\nlet mut metadata = HashMap::new();\nmetadata.insert(\"some\".to_owned(), \"string\".to_owned());\nlet attachment =\n collection.new_attachment(attachment_file_path.to_str().unwrap(), metadata)?;\nlet doc_id = DocumentId::new(&\"123abc\".to_string())?;\nlet content = json!({\"_id\": doc_id, \"some\": \"string\", \"my_attachment\": attachment});\nlet _ = collection.upsert(content)?;\n// Later or on another peer ...\nlet doc = collection.find_by_id(doc_id).exec()?;\nlet attachment_token = doc.get::<DittoAttachmentToken>(\"my_attachment\")?;\nlet (tx, rx) = channel();\nlet m_tx = std::sync::Mutex::new(tx);\nlet fetcher = collection.fetch_attachment(attachment_token, move |event| {\n // completion handler\n if let DittoAttachmentFetchEvent::Completed { attachment } = event {\n let tx = m_tx.lock().unwrap();\n tx.send(attachment).unwrap();\n }\n})?;\nlet fetched_attachment = rx.recv().unwrap(); // may also use an async version or other sync strategy\nlet attachment_file_path = fetched_attachment.path();\nstd::fs::read(attachment_file_path)?;\n\n",
"counter": "let collection = ditto.store().collection(\"people\").unwrap();\nlet doc_id = collection\n .upsert(json!({\"name\": \"Frank\", \"owned_cars\": DittoCounter::new()}))\n .unwrap();\n\ncollection\n .find_by_id(doc_id)\n .update(|x| {\n if let Some(doc) = x {\n doc.increment(\"owned_cars\", 1.0).unwrap();\n }\n })\n .unwrap();\n\n",
"update": "let collection = ditto.store().collection(\"people\").unwrap();\nlet doc_id = collection\n .upsert(json!({\"name\": \"Frank\", \"owned_cars\": DittoCounter::new()}))\n .unwrap();\n\ncollection\n .find_by_id(doc_id)\n .update(|opt_doc| {\n if let Some(doc) = opt_doc {\n doc.set(\"age\", 32).unwrap();\n doc.increment(\"owned_cars\", 1.0).unwrap();\n }\n })\n .unwrap();\n\n",
"query-basic": "collection\n .find(\"favoriteBook.title == \\'The Great Gatsby\\'\")\n .exec()?;\n\n",
"query-args": "let args = json!({\"name\": \"Susan\", \"age\": 32});\ncollection\n .find_with_args(\"name == $args.name && age <= $args.age\", args)\n .exec()?;\n\n",
"query-sort": "let sort_param = ffi_sdk::COrderByParam {\n query_c_str: c!(\"miles\"),\n direction: ffi_sdk::QuerySortDirection::Ascending,\n};\ncollection\n .find(\"color == \\'red\\'\")\n .sort(vec![sort_param])\n .exec()?;\n\n",
"query-limit": "let sort_param = ffi_sdk::COrderByParam {\n query_c_str: c!(\"rank\"),\n direction: ffi_sdk::QuerySortDirection::Ascending,\n};\ncollection\n .find(\"color == \\'red\\'\")\n .sort(vec![sort_param])\n .limit(100)\n .exec()?;\n\n",
"subscribe": "let store = ditto.store(); // Ditto must have a longer lifetime than all live queries\nlet live_query = store\n .collection(\"cars\")?\n .find(\"color == \\'red\\'\")\n .subscribe();\n\n",
"sync-observe": "let store = ditto.store(); // Ditto must have a longer lifetime than all live queries\nlet (tx, rx) = channel();\n{\n let live_query = store\n .collection(\"cars\")?\n .find(\"color == \\'red\\'\")\n .observe_local(move |mut docs: Vec<BoxedDocument>, event| {\n match event {\n LiveQueryEvent::Initial { .. } => { /* handle if appropriate */ }\n LiveQueryEvent::Update { mut insertions, .. } => {\n insertions.sort_by(|a, b| b.cmp(a));\n for idx in insertions.iter() {\n let doc = docs.remove(*idx);\n tx.send(doc).unwrap();\n }\n }\n }\n })?;\n store\n .collection(\"cars\")?\n .upsert(json!({\"color\": \"red\"}))\n .unwrap();\n for doc in rx.iter() {\n println!(\"New doc {:?}\", doc);\n }\n} // IMPORTANT: LiveQuery goes out of scope and is Dropped and terminated here.\n\n",
"sync-observe-local": "// Some action in your app ...\nlet store = ditto.store();\nstore.collection(\"cars\")?.upsert(json!({\"color\": \"red\"}))?;\n// Elsewhere register handlers for data changes\n{\n let live_query = store\n .collection(\"cars\")?\n .find(\"color == \\'red\\'\")\n .observe_local(move |cars, event| {\n println!(\"cars {:?}, event {:?}\", cars, event);\n // do something when data changes\n // BUT this closure must be permitted to take ownership\n })?;\n // stash your live query in something with a long lifetime\n // or it will be dropped\n}\n\n",
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every\n// application.\nlet p256_der_b64: &str = \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\";\nlet app_id = AppId::from_env(\"app\")?;\nlet ditto = Ditto::builder()\n .with_root(Arc::new(PersistentRoot::from_current_exe()?))\n .with_identity(|ditto_root| identity::SharedKey::new(ditto_root, app_id, p256_der_b64))?\n .build()?;\nlet res = ditto.set_offline_only_license_token(&license_token);\nditto.start_sync()?;\n\n",
"online-playground": "let ditto = Ditto::builder()\n // creates a `ditto_data` folder in the directory containing the executing process\n .with_root(Arc::new(PersistentRoot::from_current_exe()?))\n .with_identity(|ditto_root| {\n // Provided as an env var, may also be provided as hardcoded string\n let app_id = AppId::from_env(\"00000000-0000-4000-0000-000000000000\")?;\n let shared_token = std::env::var(\"REPLACE_ME_WITH_A_SHARED_TOKEN\").unwrap();\n let enable_cloud_sync = true;\n let custom_auth_url = None;\n OnlinePlayground::new(\n ditto_root,\n app_id,\n shared_token,\n enable_cloud_sync,\n custom_auth_url,\n )\n })?\n .with_minimum_log_level(LogLevel::Debug)\n .build()?;\n\nditto.start_sync()?;\n\n",
"offline-playground": "let ditto = Ditto::builder()\n // creates a `ditto_data` folder in the directory containing the executing process\n .with_root(Arc::new(PersistentRoot::from_current_exe()?))\n .with_identity(|ditto_root| {\n // Provided as an env var, may also be provided as hardcoded string\n let app_id = AppId::from_env(\"00000000-0000-4000-0000-000000000000\")?;\n OfflinePlayground::new(ditto_root, app_id)\n })?\n .build()?;\n\nditto.start_sync()?;\nlet res = ditto.set_offline_only_license_token(&license_token);\n\n",
"network-remote-ditto": "let mut config = TransportConfig::new(); // empty\n\nconfig\n .connect\n .tcp_servers\n .insert(\"135.1.5.5:12345\".to_string()); // Custom TCP Listener\nconfig\n .connect\n .tcp_servers\n .insert(\"185.1.5.5:12345\".to_string()); // Custom TCP Listener\nconfig\n .connect\n .websocket_urls\n .insert(\"wss://example.com\".to_string()); // Custom WS endpoint\n\nditto.set_transport_config(config);\nditto.start_sync()?;\n\n",
"network-listen": "let mut config = TransportConfig::new(); // empty\n\nconfig.listen.tcp.enabled = true;\nconfig.listen.tcp.interface_ip = \"0.0.0.0\".to_string();\nconfig.listen.tcp.port = 4000;\nconfig.listen.http.enabled = false;\n\nditto.set_transport_config(config);\nditto.start_sync()?;\n\n",
"transport-sync-groups": "let mut config = TransportConfig::new(); // empty\n\nconfig.enable_all_peer_to_peer();\nconfig.global.sync_group = 1234;\n\nditto.set_transport_config(config);\nditto.start_sync()?;\n\n",
"network-multiple-transports": "let mut config = TransportConfig::new(); // empty\n\n// 1. Enable auto-discovery of peer to peer connections\nconfig.enable_all_peer_to_peer(); // Auto-connect via lan and bluetooth\n\n// 2. Configure TCP Listener\nconfig.listen.tcp.enabled = true;\nconfig.listen.tcp.interface_ip = \"0.0.0.0\".to_string();\nconfig.listen.tcp.port = 4000;\nconfig.listen.http.enabled = false;\n\n// 3. Configure explicit, hard coded connections\nconfig\n .connect\n .tcp_servers\n .insert(\"135.1.5.5:12345\".to_string()); // Custom TCP Listener\nconfig\n .connect\n .websocket_urls\n .insert(\"wss://example.com\".to_string()); // Custom WS endpoint\n\nditto.set_transport_config(config);\nditto.start_sync()?;\n\n"
},
"objc": {
"attachment": "NSBundle *testBundle = [NSBundle bundleForClass:self.class];\nNSURL *attachmentTestImage = [testBundle URLForResource:@\"attachment_test\" withExtension:@\"png\"];\nNSData *attachmentData = [NSData dataWithContentsOfURL:attachmentTestImage];\n\nNSDictionary<NSString *, NSString *> *metadata = @{@\"name\": @\"my_image.png\"};\nDITAttachment *attachment = [collection newAttachment:attachmentTestImage.path metadata:metadata];\n\nDITDocumentID *docID = [collection upsert:@{@\"some\": @\"string\", @\"my_attachment\": attachment} error:nil];\nDITDocument *doc = [[collection findByID:docID] exec];\nDITAttachmentToken *attachmentToken = doc[@\"my_attachment\"].attachmentToken;\n\nDITAttachmentFetcher *fetcher = [collection fetchAttachment:attachmentToken onFetchEvent:^(DITAttachmentFetchEvent *event) {\n switch (event.type) {\n case DITAttachmentFetchEventTypeCompleted: {\n DITAttachmentFetchEventCompleted *completed = [event asCompleted];\n DITAttachment *fetchedAttachment = completed.attachment;\n NSData *fetchedAttachmentData = [fetchedAttachment getData:nil];\n [attachmentRoundtripExpectation fulfill];\n break;\n }\n case DITAttachmentFetchEventTypeProgress:\n break;\n default:\n break;\n }\n}];\n\n\n",
"counter": "[[collection find:@\"make == 'Honda'\"] updateWithBlock:^(NSArray<DITMutableDocument *> *docs) {\n for (DITMutableDocument *doc in docs) {\n [doc[@\"mileage\"] set:DITCounter.new];\n [doc[@\"mileage\"].counter incrementBy:1];\n }\n}];\n\n",
"datamodel": "DITCollection *collection = [store collection:@\"people\"];\n\n",
"upsert-id": "DITDocumentID *docId = [collection upsert:@{@\"_id\": @\"123abc\", @\"name\": @\"Susan\", @\"age\": @32 } error:nil];\nNSLog(@\"%@\", docId); // => \"123abc\"\n\n",
"upsert": "DITDocumentID *docID = [[ditto.store collection:@\"people\"]\n upsert:@{ @\"name\": @\"Susan\", @\"age\": @31 }\n error:nil];\n\n",
"upsert-composite-primary-key": "DITDocumentID *docID = [[ditto.store collection:@\"people\"]\n upsert:@{\n @\"_id\": @{ @\"userId\": @\"456abc\", @\"workId\": @789 },\n @\"name\": @\"John\",\n @\"age\": @31 }\n error:nil];\nNSLog(@\"%@\", docID); // => \"NSDictionary @{ @\"userId\": \"456abc\": @\"workId\": @789 }\"\n\n",
"upsert-datatypes": "[[ditto.store collection:@\"foo\"]\n upsert:@{\n @\"boolean\": @true,\n @\"string\": @\"Hello World\",\n @\"number\": @10,\n @\"map\": @{ @\"key\": @\"value\" },\n @\"array\": @[ @1, @2, @3 ],\n @\"null\": [NSNull null]\n }\n error:nil\n];\n\n",
"upsert-default-data": "DITDocumentID *defaultDocID = [[ditto.store collection:@\"people\"]\n upsert:@{ @\"name\": @\"Susan\", @\"age\": @31 }\n writeStrategy: DITWriteStrategyInsertDefaultIfAbsent\n error:nil];\n\n",
"query-basic": "NSArray *docs = [[[ditto.store collection:@\"people\"]\n find:@\"favoriteBook.title == 'The Great Gatsby'\"] exec];\n\n",
"query-args": "NSArray *documents = [[[ditto.store collection:@\"people\"] find:@\"name == $args.name && age <= $args.age\" withArgs:@{@\"age\": @32, @\"name\": @\"Max\"}] exec];\n\n",
"remove-query": "NSArray<DITDocumentID *> *removedIDs = [[[ditto.store collection:@\"people\"]\n find:@\"name == 'Susan'\"] remove];\n\n",
"remove-id": "[[[ditto.store collection:@\"test\"] findByID:docID] remove];\n\n",
"update": "DITDocumentID *docID = [[ditto.store collection:@\"people\"] upsert:@{\n @\"name\": @\"Frank\",\n @\"age\": [NSNumber numberWithInt:31],\n @\"ownedCars\": DITCounter.new\n} error:nil];\n\n\nDITCollection *collection = [ditto.store collection:@\"people\"];\n[[collection findByID:docID] updateWithBlock:^(DITMutableDocument *doc) {\n [doc[@\"age\"] set:[NSNumber numberWithInt:32]];\n [doc[@\"ownedCars\"].counter incrementBy:1];\n}];\n\n",
"array-to-map": "[[collection findByID:docID] updateWithBlock:^(DITMutableDocument *doc) {\n NSMutableDictionary *map = [NSMutableDictionary new];\n NSArray *names = doc[@\"friends\"].arrayValue;\n for (id name in names) {\n NSString *uuid = [[NSUUID UUID] UUIDString];\n map[uuid] = @{\n @\"id\": uuid,\n @\"name\": name\n };\n }\n [doc[@\"friendsMap\"] set:map];\n}];\n\n",
"query-sort": "NSArray *sortedRedCars = [[[[ditto.store collection:@\"cars\"]\n find:@\"color == 'red'\"]\n sort:@\"miles\" direction:DITSortDirectionAscending] exec];\n\n",
"query-limit": "NSArray *sortedAndLimitedRedCars = [[[[[ditto.store collection:@\"cars\"]\n find:@\"color == 'red'\"]\n sort:@\"miles\" direction:DITSortDirectionAscending]\n limit:100] exec];\n\n",
"sync-basic": "NSError *error = nil;\n[ditto startSync:&error];\n\n",
"write-transaction": "NSArray *results = [store write:^(DITWriteTransaction *tx) {\n DITScopedWriteTransaction *cars = tx[@\"cars\"];\n DITScopedWriteTransaction *people = tx[@\"people\"];\n DITDocumentID *docID = [[DITDocumentID alloc] initWithValue: @\"abc123\"];\n [people upsert:@{@\"_id\": docID, @\"name\": @\"Susan\"} error:nil];\n [cars upsert:@{@\"make\": @\"Ford\", @\"color\": @\"black\", @\"owner\": docID} error:nil];\n [cars upsert:@{@\"make\": @\"Toyota\", @\"color\": @\"red\", @\"owner\": docID} error:nil];\n}];\n\n",
"sync-observe": "// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\nDITLiveQuery *liveQuery = [[collection find:@\"color == 'red'\"]\n observeLocal:^(NSArray<DITDocument *> *docs, DITLiveQueryEvent *event) {\n\n}];\n\n",
"subscribe": "// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\nDITSubscription *subscription = [[collection find:@\"color == 'red'\"] subscribe];\n\n",
"sync-observe-local": "// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\n\nDITLiveQuery *liveQuery = [[collection find:@\"color == 'red'\"]\n observeLocal:^(NSArray<DITDocument *> *docs, DITLiveQueryEvent *event) {\n\n}];\n\n",
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every application.\nNSString *p256_der_b64 = @\"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\";\nDITIdentity *identity = [[DITIdentity alloc] initSharedKeyWithAppID:@\"app\" sharedKey:p256_der_b64];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\n\nNSError *error = nil;\nif (![ditto setOfflineOnlyLicenseToken:validLicense error:&error]) {\n NSLog(@\"Error setting license: %@\", error);\n}\n\n",
"online-playground-cloudSync": "DITIdentity *identity = [[DITIdentity alloc] initOnlinePlaygroundWithAppID:@\"00000000-0000-4000-0000-000000000000\"\n token:@\"REPLACE_ME_WITH_A_SHARED_TOKEN\"\n // Set to false to disable syncing with the cloud\n enableDittoCloudSync:YES];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity persistenceDirectory: dittoPersistenceDir];\nNSError *error = nil;\n[ditto startSync:&error];\n\n",
"online-playground": "DITIdentity *identity = [[DITIdentity alloc] initOnlinePlaygroundWithAppID:@\"00000000-0000-4000-0000-000000000000\"\n token:@\"REPLACE_ME_WITH_A_SHARED_TOKEN\"\n enableDittoCloudSync:YES];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity persistenceDirectory: dittoPersistenceDir];\nNSError *error = nil;\n[ditto startSync:&error];\n\n",
"offline-playground": "DITIdentity *identity = [[DITIdentity alloc] initOfflinePlaygroundWithAppID:@\"00000000-0000-4000-0000-000000000000\"];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\nNSError *error = nil;\nif (![ditto setOfflineOnlyLicenseToken:validLicense error:&error]) {\n NSLog(@\"Error setting license: %@\", error);\n}\nif (![ditto startSync:&error]) {\n NSLog(@\"Error starting sync: %@\", error);\n}\n[ditto startSync:&error];\n\n",
"network-remote-ditto": "DITMutableTransportConfig *transportConfig = [[DITMutableTransportConfig alloc] init];\n[transportConfig.connect.tcpServers addObject:@\"135.1.5.5:12345\"];\n[transportConfig.connect.tcpServers addObject:@\"185.1.5.5:12345\"];\n[ditto setTransportConfig:transportConfig];\nNSError *err = nil;\n[ditto startSync:&err];\n\n",
"network-listen": "DITMutableTransportConfig *transportConfig = [[DITMutableTransportConfig alloc] init];\n[transportConfig.listen.tcp setEnabled:true];\n[transportConfig.listen.tcp setInterfaceIp:@\"0.0.0.0\"];\n[transportConfig.listen.tcp setPort:4000];\n[ditto setTransportConfig:transportConfig];\nNSError *err = nil;\n[ditto startSync:&err];\n\n",
"network-multiple-transports": "DITMutableTransportConfig *transportConfig = [[DITMutableTransportConfig alloc] init];\n// 1. Enable Local Area Network Connections\n[transportConfig enableAllPeerToPeer];\n// 2. Listen for incoming connections on port 4000\n[transportConfig.listen.tcp setEnabled:true];\n[transportConfig.listen.tcp setInterfaceIp:@\"0.0.0.0\"];\n[transportConfig.listen.tcp setPort:4000];\n// 3. Connect explicitly to remote devices\n[transportConfig.connect.tcpServers addObject:@\"135.1.5.5:12345\"];\n[transportConfig.connect.tcpServers addObject:@\"185.1.5.5:12345\"];\n\n[ditto setTransportConfig:transportConfig];\nNSError *err = nil;\n[ditto startSync:&err];\n\n",
"websocket-connect": "DITMutableTransportConfig *transportConfig = [[DITMutableTransportConfig alloc] init];\n\n[transportConfig enableAllPeerToPeer];\n\n[transportConfig.connect.websocketURLs addObject:@\"ws://127.0.0.1\"];\n\n[ditto setTransportConfig:transportConfig];\nNSError *err = nil;\n[ditto startSync:&err];\n\n",
"transport-configurations": "DITMutableTransportConfig *transportConfig = [[DITMutableTransportConfig alloc] init];\n\n//Enable all peer to peer transports\n[transportConfig enableAllPeerToPeer];\n\n//Or enable/disable each transport separately\n//BluetoothLe\n[transportConfig.peerToPeer.bluetoothLe setEnabled:true];\n//Local Area Network\n[transportConfig.peerToPeer.lan setEnabled:true];\n//Awdl\n[transportConfig.peerToPeer.awdl setEnabled:true];\n\n[ditto setTransportConfig:transportConfig];\nNSError *err = nil;\n[ditto startSync:&err];\n\n",
"network-monitor-conditions": "// Setting up inside a ViewController\nDITIdentity *identity = [[DITIdentity alloc] initOnlinePlaygroundWithAppID:@\"REPLACE_WITH_APP_ID\" token:@\"REPLACE_WITH_PLAYGROUND_TOKEN\"];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\nditto.delegate = self;\n[ditto startSync:nil];\n\n// Now you can observe real time changes to the transport conditions:\n@interface ViewController () <DITDittoDelegate>\n\n@end\n\n@implementation ViewController\n\n- (void)transportConditionChanged:(enum DITTransportCondition)condition forSubsystem:(enum DITConditionSource)source {\n if (condition == DITTransportConditionBleDisabled) {\n NSLog(@\"BLE disabled\");\n } else if (condition == DITTransportConditionNoBleCentralPermission) {\n NSLog(@\"Permission missing for BLE\");\n } else if (condition == DITTransportConditionNoBlePeripheralPermission) {\n NSLog(@\"Permission missing for BLE\");\n }\n}\n\n@end\n\n",
"network-query-overlap-group": "NSString *const orders = @\"orders\";\n\n// The passenger only observes orders that they created\n[[[passenger.store collection:orders] find:@\"user_id==abc123\"] observeLocal:^(NSArray<DITDocument *> *docs, DITLiveQueryEvent *event) {\n // render my orders in a list UI\n}];\n\n// Crew member devices observe all orders that everyone created\n[[[crewA.store collection:orders] find:@\"status == 'OPEN'\"] observeLocal:^(NSArray<DITDocument *> *docs, DITLiveQueryEvent *event) {\n // render all orders in a list UI\n}];\n\n[[[crewB.store collection:orders] find:@\"status == 'OPEN'\"] observeLocal:^(NSArray<DITDocument *> *docs, DITLiveQueryEvent *event) {\n // render all orders\n}];\n\n// Set up our query overlap group and priorities such that the crew members\n// will construct multihop connections with each other.\n[DITExperimental setQueryOverlapGroup:2 ditto:crewA];\n[DITExperimental setQueryOverlapGroup:2 ditto:crewB];\n\n// Query overlap groups should be set before startSync\n[crewA startSync:nil];\n[crewB startSync:nil];\n[passenger startSync:nil];\n\n",
"network-set-priority": "[DITExperimental setPriority:DITConnectionPriorityHigh\n forQueryOverlapGroup:2 ditto:crewA];\n[DITExperimental setPriority:DITConnectionPriorityHigh\n forQueryOverlapGroup:2 ditto:crewB];\n\n",
"transport-sync-groups": "DITMutableTransportConfig *transportConfig = [[DITMutableTransportConfig alloc] init];\n// 1. Enable All Peer to Peer Connection\n[transportConfig enableAllPeerToPeer];\n// 2. Set sync group to an integer between 0 and 2^32\ntransportConfig.global.syncGroup = 12312;\n\n[ditto setTransportConfig:transportConfig];\nNSError *error = nil;\n[ditto startSync:&error];\n\n",
"evict": "NSArray<DITDocumentID *> *evictedIDs = [[collection find:@\"make == 'Honda'\"] evict];\n\n"
},
"swift": {
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every application.\nlet p256DerB64 = \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\"\n\nlet identity = DittoIdentity.sharedKey(appID: \"app\", sharedKey: p256DerB64)\nlet ditto = Ditto(identity: identity, persistenceDirectory: dittoPersistenceDir)\ndo {\n try ditto.setOfflineOnlyLicenseToken(validLicense);\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"write-transaction": "ditto.store.write { transaction in\n let cars = transaction.scoped(toCollectionNamed: \"cars\")\n let people = transaction.scoped(toCollectionNamed: \"people\")\n let docId = \"abc123\"\n do {\n try people.upsert([\"_id\": docId, \"name\": \"Susan\"] as [String: Any?])\n try cars.upsert([\"make\": \"Ford\", \"color\": \"red\", \"owner\": docId] as [String: Any?])\n try cars.upsert([\"make\": \"Toyota\", \"color\": \"black\", \"owner\": docId] as [String: Any?])\n } catch (let err) {\n print(err.localizedDescription)\n }\n people.findByID(docId).evict()\n}\n\n",
"online-playground": "DittoLogger.minimumLogLevel = .debug\nlet ditto = Ditto(identity: .onlinePlayground(\n appID: \"00000000-0000-4000-0000-000000000000\",\n token: \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"\n))\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"online-playground-cloudSync": "let ditto = Ditto(identity: .onlinePlayground(\n appID: \"00000000-0000-4000-0000-000000000000\",\n token: \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\",\n // Set to false to disable syncing with the cloud\n enableDittoCloudSync: true\n))\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"offline-playground": "var ditto = Ditto(identity: DittoIdentity.offlinePlayground(\n appID: \"00000000-0000-4000-0000-000000000000\"\n))\ntry! ditto.setOfflineOnlyLicenseToken(validLicense);\ntry! ditto.startSync()\n\n",
"datamodel": "let carsCollection = ditto.store[\"cars\"]\n// or\nlet carsCollection = ditto.store.collection(\"cars\")\n\n",
"attachment": "let collection = ditto.store[\"foo\"]\n\nlet myImageURL = bundle.url(forResource: \"image\", withExtension: \"png\")!\n\nlet metadata = [\"name\": \"my_image.png\"]\nlet attachment = collection.newAttachment(\n path: myImageURL.path,\n metadata: metadata\n)!\n\nguard let docID = try? collection.upsert([\"some\": \"string\", \"my_attachment\": attachment]) else {\n // handle error\n return\n}\n\n// Later, find the document and the fetch the attachment\n\nlet doc = collection.findByID(docID).exec()\nlet attachmentToken = doc![\"my_attachment\"].attachmentToken!\n\nlet fetcher = collection.fetchAttachment(token: attachmentToken) { status in\n switch status {\n case .completed(let fetchedAttachment):\n // Do something with attachment\n default:\n print(\"Unable to fetch attachment\")\n }\n}\n\n",
"upsert-default-data": "do {\n let docID = try ditto.store[\"people\"].upsert([\n \"name\": \"Susan\",\n \"age\": 31\n ], writeStrategy: .insertDefaultIfAbsent)\n} catch {\n //handle error\n print(error)\n}\n\n",
"upsert-composite-primary-key": "do {\n let docID = try ditto.store[\"people\"].upsert([\n \"_id\": [ \"userId\": \"456abc\", \"workId\": 789 ],\n \"name\": \"Susan\",\n \"age\": 31\n ])\n print(docID) // \"[ \"userId\": \"456abc\", \"workId\": 789 ]\"\n} catch {\n //handle error\n print(error)\n}\n\n",
"upsert-datatypes": "do {\n // Insert JSON-compatible data into Ditto\n try ditto.store[\"foo\"].upsert([\n \"boolean\": true,\n \"string\": \"Hello World\",\n \"number\": 10,\n \"map\": [\"key\": \"value\"],\n \"array\": [1,2,3],\n \"null\": nil\n ])\n}\ncatch {\n //handle error\n print(error)\n}\n\n",
"counter": "do {\n let docId = try ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"ownedCars\": DittoCounter() // here 0 is a number\n ])\n\n ditto.store[\"people\"].findByID(docId).update({ mutableDoc in\n mutableDoc?[\"ownedCars\"].counter?.increment(by: 1)\n })\n} catch {\n //handle error\n print(error)\n}\n\n",
"update": "do {\n let docID = try ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"age\": 31,\n \"ownedCars\": DittoCounter()\n ])\n\n ditto.store[\"people\"].findByID(docID).update { mutableDoc in\n mutableDoc?[\"age\"] = 32\n mutableDoc?[\"ownedCars\"].counter?.increment(by: 1)\n }\n} catch {\n //handle error\n print(error)\n}\n\n",
"array-to-map": "collection.findByID(docID).update { doc in\n guard let doc = doc else {\n print(\"Document with id=\\(docID) not found\")\n return\n }\n\n let names = doc[\"friends\"].arrayValue\n var dict = Dictionary<String, Any>()\n\n _ = names.map { name in\n let friend: NSMutableDictionary = [:]\n let id = UUID().uuidString\n friend[\"id\"] = id\n friend[\"name\"] = name\n dict.updateValue(friend, forKey: id)\n }\n doc[\"friendsMap\"].set(dict)\n}\n\n",
"upsert": "do {\n // upsert JSON-compatible data into Ditto\n let docID = try ditto.store[\"people\"].upsert([\n \"name\": \"Susan\",\n \"age\": 31\n ])\n} catch {\n //handle error\n print(error)\n}\n\n",
"upsert-id": "do {\n // upsert JSON-compatible data into Ditto\n let docID = try ditto.store[\"people\"].upsert([\n \"_id\": \"abc123\",\n \"name\": \"Susan\",\n \"age\": 31\n ])\n XCTAssertEqual(docID, \"abc123\")\n} catch {\n //handle error\n print(error)\n}\n\n",
"query-basic": "let collection = ditto.store[\"people\"]\n .find(\"favoriteBook.title == 'The Great Gatsby'\")\n .exec()\n\n",
"query-args": "let documents = ditto.store[\"users\"].find(\"name == $args.name && age <= $args.age\", args: [\n \"age\": 32,\n \"name\": \"Max\"\n]).exec()\n\n",
"query-sort": "let sortedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", direction: .ascending)\n .exec()\n\n",
"query-limit": "let sortedAndLimitedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", direction: .ascending)\n .limit(100)\n .exec()\n\n",
"sync-observe-local": "// --- Action somewhere in your application\nfunc userDidInsertCar() {\n _ = try? ditto.store.collection(\"cars\").upsert([\n \"model\": \"Ford\",\n \"color\": \"black\"\n ] as [String: Any?])\n}\n\n// Register live query to update UI\nlet liveQuery = ditto.store.collection(\"cars\").find(\"color == 'red'\")\n .observeLocal { cars, event in\n // do something\n }\n\n",
"sync-observe": "// Register live query to update UI\nlet example = ditto.store.collection(\"cars\").find(\"color == 'red'\")\n .observeLocal { cars, event in\n // do something\n}\n\n",
"subscribe": "// Register live query to update UI\nlet subscription = ditto.store.collection(\"cars\").find(\"color == 'red'\").subscribe()\n\n",
"network-remote-ditto": "var config = DittoTransportConfig()\n// Connect explicitly to a remote devices\nconfig.connect.tcpServers.insert(\"135.1.5.5:12345\")\nconfig.connect.tcpServers.insert(\"185.1.5.5:12345\")\n\nditto.transportConfig = config\n\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"device-name": "ditto.deviceName = \"Susan B.\"\nlet observer = ditto.presence.observe { presence in\n if !presence.remotePeers.isEmpty {\n // render peers\n }\n}\n\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"transport-sync-groups": "struct User {\n var id: String\n var restaurantID: UInt32\n}\nlet authenticatedUser = User(id: \"abc123\", restaurantID: 323234)\n\nvar config = DittoTransportConfig()\n// 1. Enable All Peer to Peer Connections \nconfig.enableAllPeerToPeer()\n// 2. Set sync group to an integer between 0 and 2^32\nconfig.global.syncGroup = authenticatedUser.restaurantID\nditto.transportConfig = config\n\ndo {\n try ditto.startSync()\n} catch (let error) {\n print(error.localizedDescription)\n}\n\n",
"network-listen": "var config = DittoTransportConfig()\n\n// Listen for incoming connections on port 4000\nconfig.listen.tcp.isEnabled = true\nconfig.listen.tcp.interfaceIP = \"0.0.0.0\"\nconfig.listen.tcp.port = 4000\n\nditto.transportConfig = config\n\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"transport-configurations": "// Create a new DittoTransportConfig()\nvar config = DittoTransportConfig()\n\n//Enable all peer to peer transports\nconfig.enableAllPeerToPeer()\n\n//Or enable/disable each transport separately\n//BluetoothLe\nconfig.peerToPeer.bluetoothLE.isEnabled = true\n//Local Area Network\nconfig.peerToPeer.lan.isEnabled = true\n//Awdl\nconfig.peerToPeer.awdl.isEnabled = true\n\nditto.transportConfig = config\n\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"network-multiple-transports": "var config = DittoTransportConfig()\n// 1. Enable All Peer to Peer Connections\nconfig.enableAllPeerToPeer()\n\n// 2. Listen for incoming connections on port 4000\nconfig.listen.tcp.isEnabled = true\nconfig.listen.tcp.interfaceIP = \"0.0.0.0\"\nconfig.listen.tcp.port = 4000\n\n// 3. Connect explicitly to remote devices\nconfig.connect.tcpServers.insert(\"135.1.5.5:12345\")\nconfig.connect.tcpServers.insert(\"185.1.5.5:12345\")\n\nditto.transportConfig = config\n\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"network-monitor-conditions": "// Setting up inside a ViewController\nlet ditto = Ditto(identity: DittoIdentity.onlinePlayground(appID: \"00000000-0000-4000-0000-000000000000\", token: \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"))\nditto.delegate = self\ntry! ditto.startSync()\n\n// Now you can observe real time changes to the transport conditions:\nextension ViewController: DittoDelegate {\n func transportConditionDidChange(transportID: Int64, condition: TransportCondition) {\n if condition == .BleDisabled {\n print(\"BLE disabled\")\n } else if condition == .NoBleCentralPermission {\n print(\"Permission missing for BLE\")\n } else if condition == .NoBlePeripheralPermission {\n print(\"Permission missing for BLE\")\n }\n }\n\n\n",
"bus-peers-first-user": "// Get the DittoAddress from the first user in the peer object\nlet observer = ditto.presence.observe { presence in\n if !presence.remotePeers.isEmpty {\n let user2PeerAddress = presence.remotePeers[0].address\n }\n}\nobserver.stop()\n\n",
"bus-single-message-receive": "// User2 sets up a delegate to handle inbound requests\nlet delegate = SingleMessageReceivedDelegate()\nditto.bus?.delegate = delegate\n\nclass SingleMessageReceivedDelegate: DittoBusDelegate {\n var receivedMessage: Data?\n\n func dittoBus(_ bus: DittoBus, didReceiveSingleMessage message: DittoBusMessage) {\n self.receivedMessage = message.data\n }\n\n func dittoBus(_ bus: DittoBus, didReceiveIncomingStream busStream: DittoBusStream, fromPeer peer: DittoAddress) {\n // not implemented\n }\n}\n\n",
"bus-reliable-single-message-send": "// User1 sends data to User2. Success provides guarantee of data delivery.\nlet data = Data([1, 2, 3, 4, 5])\nditto.bus?.sendSingleReliableMessage(data, to: user2PeerAddress, completion: { error in\n if let error {\n // success\n }\n})\n\n",
"bus-unreliable-single-message-send": "// User1 sends data to User2. Success provides guarantee of data sent.\nlet data = Data([1, 2, 3, 4, 5])\nditto.bus?.sendSingleUnreliableMessage(data, to: user2PeerAddress, completion: { error in\n if let error {\n // success\n }\n})\n\n",
"bus-bidirectional-stream-common": "// Common Classes\n\n// Handles new stream requests\nclass IncomingStreamReceivedDelegate: DittoBusDelegate {\n var connectedStream: DittoBusStream?\n var streamDelegate: DittoBusStreamDelegate?\n\n func dittoBus(_ bus: DittoBus, didReceiveSingleMessage message: DittoBusMessage) {\n // Not implemented\n }\n\n func dittoBus(_ bus: DittoBus, didReceiveIncomingStream busStream: DittoBusStream, fromPeer peer: DittoAddress) {\n self.connectedStream = busStream\n busStream.delegate = self.streamDelegate\n }\n}\n\n/// Handles operations/messages on a connected stream\nclass StreamDelegate: DittoBusStreamDelegate {\n /// A new message has been received from the specified stream.\n func dittoBusStream(_ busStream: DittoBusStream, didReceiveMessage message: Data) {\n // handle message received\n }\n\n /// The stream has closed. This can be triggered by calling close() or by the remote peer doing the same.\n func dittoBusStream(_ busStream: DittoBusStream, didClose error: DittoSwiftError) {\n // handle connection closed\n }\n\n // The operation to enqueue outgoing data on a stream has completed. More data may now be enqueued.\n // The message sequence number may be used to track when the remote side has fully acknowledged receipt.\n // `error` will be non-nil if the operation failed.\n func dittoBusStream(_ busStream: DittoBusStream, didEnqueueDataWithMessageSequence messageSequence: UInt64, error: DittoSwiftError?) {\n // handle did enqueue data\n }\n\n // The remote peer has acknowledged receipt of all messages up to the given sequence number.\n func dittoBusStream(_ busStream: DittoBusStream, didAcknowledgeReceipt messageSequence: UInt64) {\n // handle did data was received\n }\n}\n\n",
"bus-bidirectional-stream-handler": "// User2 - Create a delegate to handle inbound stream requests\nlet incomingDelegate = IncomingStreamReceivedDelegate()\n// Attach a StreamDelegate to handle messages once a connection is established\nincomingDelegate.streamDelegate = StreamDelegate()\nditto.bus?.delegate = incomingDelegate\n\n// Send a message\nlet data = Data([1, 2, 3, 4, 5])\nincomingDelegate.connectedStream?.enqueueMessage(data: data)\n\n// Close the stream\nincomingDelegate.connectedStream?.close()\n\n",
"bus-reliable-bidirectional-stream-sender": "// User1 - Reliable Bidirectional Stream\n\nlet incomingDelegate = IncomingStreamReceivedDelegate()\nditto.bus?.delegate = incomingDelegate\n\nlet streamDelegate = StreamDelegate()\nvar user1Stream: DittoBusStream?\nditto1.bus?.openStream(toAddress: user2PeerAddress, reliability: .reliable) { stream, err in\n user1Stream = stream\n stream?.delegate = streamDelegate\n}\n\n// Send Message\nlet data = Data([1, 2, 3, 4, 5])\nuser1Stream?.enqueueMessage(data: data)\n\n// An ID unique to the local device that can be used to track this individual stream.\n_ = user1Stream?.id\n\n// close\nuser1Stream?.close()\n\n",
"bus-unreliable-bidirectional-stream-sender": "// User1 - Unreliable Bidirectional Stream\nlet incomingDelegate = IncomingStreamReceivedDelegate()\nditto.bus?.delegate = incomingDelegate\n\nlet streamDelegate = StreamDelegate()\nvar user1Stream: DittoBusStream?\nditto1.bus?.openStream(toAddress: user2PeerAddress, reliability: .unreliable) { stream, err in\n user1Stream = stream\n stream?.delegate = streamDelegate\n}\n\n// Send Message\nlet data = Data([1, 2, 3, 4, 5])\nuser1Stream?.enqueueMessage(data: data)\n\n// An ID unique to the local device that can be used to track this individual stream.\n_ = user1Stream?.id\n\n// close\nuser1Stream?.close()\n\n",
"network-query-overlap-group": "// The passenger only observes orders that they created\nlet passengerQuery = passenger.store.collection(\"orders\").find(\"user_id==abc123\")\nlet passengerSubscription = passengerQuery.subscribe()\nlet passengerLiveQuery = passengerQuery.observeLocal { docs, event in\n // render passenger orders in a list UI\n}\n\n// Crew member devices observe all orders that everyone created\nlet crewAQuery = crewA.store.collection(\"orders\").findAll()\nlet crewASubscription = crewAQuery.subscribe()\nlet crewALiveQuery = crewAQuery.observeLocal { docs, event in\n // render all orders in a list UI\n}\nlet crewBQuery = crewB.store.collection(\"orders\").findAll()\nlet crewBSubscription = crewBQuery.subscribe()\nlet crewBLiveQuery = crewBQuery.observeLocal { docs, event in\n // render all orders in a list UI\n}\n\n// Set up our query overlap group and priorities such that the crew members\n// will construct multihop connections with each other.\nDittoExperimental.setQueryOverlapGroup(queryOverlapGroup: 2, ditto: crewA)\nDittoExperimental.setQueryOverlapGroup(queryOverlapGroup: 2, ditto: crewB)\n\n// Query overlap groups should be set before startSync\ntry! passenger.startSync()\ntry! crewA.startSync()\ntry! crewB.startSync()\n\n",
"network-set-priority": "DittoExperimental.setPriority(DittoConnectionPriority.high, forQueryOverlapGroup: 2, ditto: crewA)\nDittoExperimental.setPriority(DittoConnectionPriority.high, forQueryOverlapGroup: 2, ditto: crewB)\n\n",
"evict": "collection.find(\"owner == 'Bob'\").evict()\n\n",
"remove-query": "collection.find(\"owner == 'Bob'\").remove()\n\n",
"remove-id": "collection.findByID(docID).remove()\n\n",
"sync-basic": "try! ditto.startSync()\n\n"
},
"cpp": {
"sync-observe-local": "// --- Register live query to update UI\nstd::shared_ptr<LiveQuery> query =\n collection.find(\"color == 'red'\")\n .observe_local([&](std::vector<Document> docs, LiveQueryEvent event) {\n\n });\n\n",
"datamodel": "Collection cars_collection = ditto.get_store().collection(\"cars\");\n\n",
"upsert-id": "json person = json({{\"_id\", \"123abc\"}, {\"name\", \"Susan\"}, {\"age\", 31}});\nDocumentId doc_id = ditto.get_store().collection(\"people\").upsert(person);\n\n",
"upsert": "json person = json({{\"name\", \"Susan\"}, {\"age\", 31}});\nDocumentId doc_id = ditto.get_store().collection(\"people\").upsert(person);\n\n",
"upsert-composite-primary-key": "json content = json({{\"_id\", {{\"userId\", \"456abc\"}, {\"workId\", 789}}},\n {\"name\", \"Susan\"},\n {\"age\", 31}});\nDocumentId doc_ID = ditto.get_store().collection(\"people\").upsert(content);\n\n",
"upsert-datatypes": "// Insert JSON-compatible data into Ditto\nditto.get_store().collection(\"foo\").upsert(json({{\"boolean\", true},\n {\"string\", \"Hello World\"},\n {\"number\", 10},\n {\"map\", {{\"key\", \"value\"}}},\n {\"array\", {1, 2, 3}},\n {\"null\", NULL}}));\n\n",
"write-transaction": "auto results = ditto.get_store().write([&](WriteTransaction &write_txn) {\n ScopedWriteTransaction people = write_txn.scoped(\"people\");\n ScopedWriteTransaction cars = write_txn.scoped(\"cars\");\n auto docId = \"abc123\";\n people.upsert({{\"name\", \"Susan\"}, {\"_id\", DocumentId(docId)}});\n cars.upsert({{\"make\", \"Hyundai\"}, {\"owner\", DocumentId(docId)}});\n cars.upsert({{\"make\", \"Toyota\"}, {\"owner\", DocumentId(docId)}});\n});\n\n",
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared\n// key for every application.\nconst std::string p256_der_b64 =\n \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4\"\n \"hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlq\"\n \"nfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\";\nDitto ditto = ditto::Ditto(Identity::SharedKey(\"\", p256_der_b64), path);\nditto.set_offline_only_license_token(valid_license);\n\n",
"attachment": "auto attachment_file_path = fs::path(images_path.string() + \"/image.png\");\nstd::map<std::string, std::string> metadata = {{\"some\", \"string\"}};\n\nAttachment attachment =\n collection.new_attachment(attachment_file_path.string(), metadata);\n\nauto doc_id =\n collection.upsert({{\"some\", \"string\"}, {\"my_attachment\", attachment}});\n\n// Later, find the document and the fetch the attachment\nauto doc = collection.find_by_id(doc_id).exec();\nauto att_token = (*doc)[\"my_attachment\"].get_attachment_token();\n\nauto fetcher = collection.fetch_attachment(\n att_token,\n AttachmentFetcherEventHandler{\n [&](std::unique_ptr<AttachmentFetchEvent> event) {\n switch (event->type) {\n case AttachmentFetchEventType::Completed: {\n AttachmentFetchEventCompleted *completed_event =\n static_cast<AttachmentFetchEventCompleted *>(event.get());\n Attachment fetched_attachment = completed_event->attachment;\n // Do something with attachment\n break;\n }\n default:\n std::cout << \"Unable to fetch attachment\" << std::endl;\n }\n }});\n\n",
"array-to-map": "ditto.get_store().collection(\"people\").find_by_id(docID).update(\n [](MutableDocument &doc) {\n auto friendsMap = json::object();\n auto array = doc[\"friends\"].get_json();\n for (size_t i = 0; i < array.size(); i++) {\n auto name = array[i];\n friendsMap[\"my_id\"] = json({{\"name\", name}, {\"id\", \"my_id\"}});\n };\n doc[\"friendsMap\"].set(friendsMap);\n });\n\n",
"counter": "DocumentId docID = ditto.get_store().collection(\"people\").upsert(\n {{\"name\", \"Frank\"}, {\"ownedCars\", Counter()}});\n\nditto.get_store().collection(\"people\").find_by_id(docID).update(\n [](MutableDocument &doc) {\n auto counter = doc[\"ownedCars\"].get_counter();\n counter->increment(1);\n });\n\n",
"update": "DocumentId doc_id = ditto.get_store().collection(\"people\").upsert(\n {{\"name\", \"Frank\"}, {\"age\", 31}, {\"ownedCars\", Counter()}});\n\nditto.get_store().collection(\"people\").find_by_id(doc_id).update(\n [](MutableDocument &doc) {\n doc[\"age\"].set(32);\n auto counter = doc[\"ownedCars\"].get_counter();\n counter->increment(1);\n });\n\n",
"remove-id": "ditto.get_store().collection(\"people\").find_by_id(doc_id).remove();\n\n",
"remove-query": "ditto.get_store().collection(\"people\").find(\"age <= 32\").remove();\n\n",
"evict": "ditto.get_store().collection(\"people\").find(\"age <= 32\").evict();\n\n",
"upsert-default-data": "DocumentId doc_id = ditto.get_store().collection(\"people\").upsert(\n content, WriteStrategy::insertDefaultIfAbsent);\n\n",
"query-basic": "std::vector<Document> results =\n ditto.get_store()\n .collection(\"people\")\n .find(\"favoriteBook.title == 'The Great Gatsby'\")\n .exec();\n\n",
"query-args": "json args = json({{\"age\", 32}, {\"name\", \"max\"}});\nstd::vector<Document> big_c_values =\n ditto.get_store()\n .collection(\"people\")\n .find(\"name == $args.name && age <= $args.age\", args)\n .exec();\n\n",
"query-sort": "std::vector<Document> sorted_red_cars =\n ditto.get_store()\n .collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", SortDirection::ascending)\n .exec();\n\n",
"query-limit": "std::vector<Document> sorted_and_limited_red_cars =\n ditto.get_store()\n .collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", SortDirection::ascending)\n .limit(100)\n .exec();\n\n",
"sync-basic": "try {\n ditto.start_sync();\n} catch (const DittoError &err) {\n std::cerr << err.what();\n}\n\n",
"subscribe": "std::shared_ptr<ditto::Subscription> subscription =\n collection.find(\"color == 'red'\").subscribe();\n\n",
"sync-observe": "std::shared_ptr<LiveQuery> liveQuery =\n collection.find(\"color == 'red'\")\n .observe_local([&](std::vector<Document> docs, LiveQueryEvent event) {\n // do something\n });\n\n",
"online-playground": "auto identity =\n Identity::OnlinePlayground(\"00000000-0000-4000-0000-000000000000\",\n \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\", true);\ntry {\n Ditto ditto = Ditto(identity, dir);\n ditto.set_minimum_log_level(LogLevel::debug);\n ditto.start_sync();\n} catch (const DittoError &err) {\n}\n\n",
"offline-playground": "auto identity =\n Identity::OfflinePlayground(\"00000000-0000-4000-0000-000000000000\", 1234);\ntry {\n Ditto ditto = Ditto(identity, dir);\n\n ditto.set_offline_only_license_token(valid_license);\n ditto.start_sync();\n} catch (const DittoError &err) {\n}\n\n",
"network-remote-ditto": "auto config = ditto::TransportConfig();\n// Connect explicitly to remote devices\nconfig.connect.tcp_servers.insert(\"135.1.5.5:12345\");\nconfig.connect.tcp_servers.insert(\"185.1.5.5:12345\");\n\n// set the transport config\nditto.set_transport_config(config);\n// now you can start ditto's sync\nditto.start_sync();\n\n",
"transport-sync-groups": "auto config = ditto::TransportConfig();\n\nconfig.enable_all_peer_to_peer();\nconfig.global.sync_group = 1234;\n\n// set the transport config\nditto.set_transport_config(config);\n// now you can start ditto's sync\nditto.start_sync();\n\n",
"network-listen": "auto config = ditto::TransportConfig();\n\nconfig.listen.tcp.enabled = true;\nconfig.listen.http.enabled = false;\nconfig.listen.tcp.interface_ip = \"0.0.0.0\";\nconfig.listen.tcp.port = 4000;\n\nditto.set_transport_config(config);\nditto.start_sync();\n\n",
"network-multiple-transports": "auto config = ditto::TransportConfig();\n// 1. Enable All Peer to Peer Connections\nconfig.enable_all_peer_to_peer();\n\n// 2. Listen for incoming connections on port 4000\nconfig.listen.tcp.enabled = true;\nconfig.listen.http.enabled = false;\nconfig.listen.tcp.interface_ip = \"0.0.0.0\";\nconfig.listen.tcp.port = 4000;\n\n// 3. Connect explicitly to remote devices\nconfig.connect.tcp_servers.insert(\"135.1.5.5:12345\");\nconfig.connect.tcp_servers.insert(\"185.1.5.5:12345\");\n\nditto.set_transport_config(config);\nditto.start_sync();\n\n"
},
"http": {
"upsert-composite-primary-key": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/write' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n [{\n \"method\": \"upsert\",\n \"collection\": \"people\",\n \"id\": { \n \"user_id\": \"456abc\",\n \"work_id\": 789\n },\n \"value\": {\n \"name\": \"Susan\", \n \"age\": 31\n }\n }]\n }'\n\n",
"upsert": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/write' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n \"commands\": [{\n \"method\": \"upsert\",\n \"collection\": \"people\",\n \"id\": \"abc123\",\n \"value\": {\n \"name\": \"Susan\", \"age\": 31\n }\n }]\n }'\n\n",
"upsert-id": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/write' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n \"commands\": [{\n \"method\": \"upsert\",\n \"collection\": \"people\",\n \"id\": \"456abc\",\n \"value\": {\n \"name\": \"Susan\", \n \"age\": 31\n }\n }]\n }'\n\n",
"upsert-datatypes": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/write' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n \"commands\": [{\n \"method\": \"upsert\",\n \"collection\": \"people\",\n \"id\": \"456abc\",\n \"value\": {\n \"boolean\": true, \n \"string\": \"Hello World\",\n \"number\": 10,\n \"map\": {\n \"key\": \"value\",\n },\n \"array\": [1,2,3],\n \"null\": null\n }\n }]\n }'\n\n",
"update": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/write' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n \"commands\": [{\n \"method\": \"upsert\",\n \"collection\": \"people\",\n \"id\": \"123abc\",\n \"value\": {\n \"name\": \"Frank\", \n \"age\": 32,\n \"friends\": [\"Susan\"],\n \"owned_cars\": 0\n }\n }]\n }'\n\n",
"query-basic": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/find' \\\n--header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n \"collection\": \"people\",\n \"query\": \"favoriteBook.title == 'The Great Gatsby'\"\n }'\n\n",
"query-args": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/find' \\\n--header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n \"args\": {\n \"name\": \"max\",\n \"age\": 32\n },\n \"collection\": \"people\",\n \"query\": \"name == $args.name && age <= $args.age\"\n }'\n\n",
"query-limit": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v3/store/find' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n \"collection\": \"people\",\n \"query\": \"color == 'red'\",\n \"limit\": 100\n }'\n\n",
"remove-id": "curl --location --request POST 'https://<CLOUD_ENDPOINT>/api/v3/store/write' \\\n--header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n \"commands\": [{\n \"method\": \"remove\",\n \"collection\": \"orders\",\n \"query\": \"_id == '<ID>'\"\n }]\n }'\n\n"
},
"javascript": {
"online-playground": "import { init, Ditto, Logger } from \"@dittolive/ditto\"\nconst identity: Identity = { type: 'onlinePlayground', appID: '00000000-0000-4000-0000-000000000000', token: 'REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN' }\nconst ditto = new Ditto(identity, path)\nditto.startSync()\n\n",
"online-playground-cloudSync": "const identity: Identity = {\n type: 'onlinePlayground',\n appID: '00000000-0000-4000-0000-000000000000',\n token: 'REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN',\n // Set to false to disable syncing with the cloud\n enableDittoCloudSync: true,\n}\nconst ditto = new Ditto(identity, path)\nditto.startSync()\n\n",
"offline-playground": "const identity: Identity = { type: 'offlinePlayground', appID: '00000000-0000-4000-0000-000000000000' }\nconst ditto = new Ditto(identity, path)\nditto.setOfflineOnlyLicenseToken(validLicense)\nditto.startSync()\n\n",
"datamodel": "const carsCollection = ditto.store.collection('cars')\n\n",
"upsert-id": "const docID = await ditto.store.collection('people').upsert({\n _id: '123abc',\n name: 'Susan',\n age: 31,\n})\n\nconsole.log(docID) // \"123abc\"\n\n",
"write-transaction": "const results = await ditto.store.write(async (transaction) => {\n // Use the `WriteTransaction` object that is available in the\n // transaction closure to acquire a handle to any collection, which\n // allows modifying and accessing its documents in the transaction\n // context.\n const cars = transaction.scoped('cars')\n const people = transaction.scoped('people')\n\n // In this example a new person and car document are created, and\n // finally the person document that was just created is evicted.\n // If any of these operations fail, all others are not applied.\n const susanId = await people.upsert({\n name: 'Susan',\n })\n await cars.upsert({\n make: 'Hyundai',\n color: 'red',\n owner: susanId,\n })\n await people.findByID(susanId).evict()\n})\n\n// The return value of a transaction is a list that contains a\n// summary of all operations in the transaction and the document IDs\n// that were affected:\n\n// results == [\n// {\n// type: 'inserted',\n// docID: DocumentID { ... },\n// collectionName: 'people'\n// },\n// {\n// type: 'inserted',\n// docID: DocumentID { ... },\n// collectionName: 'cars'\n// },\n// {\n// type: 'evicted',\n// docID: DocumentID { ... },\n// collectionName: 'people'\n// }\n// ]\n\n",
"upsert": "const docID = await ditto.store.collection('people').upsert({\n name: 'Susan',\n age: 31,\n})\nconsole.log(docID) // \"507f191e810c19729de860ea\"\n\n",
"upsert-datatypes": "// Insert JSON-compatible data into Ditto\nawait ditto.store.collection('people').upsert({\n boolean: true,\n string: 'Hello World',\n number: 10,\n map: { key: 'value' },\n array: [],\n null: null,\n})\n\n",
"counter": "const frankId = await ditto.store.collection('people').upsert({\n name: 'Frank',\n ownedCars: 0, // here 0 is a number\n})\n\nawait ditto.store\n .collection('people')\n .findByID(frankId)\n .update((mutableDoc) => {\n mutableDoc.at('ownedCars').set(new Counter())\n mutableDoc.at('ownedCars').counter.increment(1)\n })\n\n",
"upsert-default-data": "const docID = await ditto.store.collection('people').upsert(\n {\n name: 'Susan',\n age: 31,\n },\n { writeStrategy: 'insertDefaultIfAbsent' },\n)\n\n",
"upsert-composite-primary-key": "const docID = await ditto.store.collection('people').upsert({\n _id: { userID: '456abc', workID: 789 },\n name: 'Susan',\n age: 31,\n})\nconsole.log(docID) // \"{ \"userID\": \"456abc\", \"workID\": 789 }\"\n\n",
"update": "const docID = await ditto.store.collection('people').upsert({\n name: 'Frank',\n age: 31,\n ownedCars: 0,\n})\n\nawait ditto.store\n .collection('people')\n .findByID(docID)\n .update((mutableDoc) => {\n mutableDoc.at('age').set(32)\n\n mutableDoc.at('ownedCars').set(new Counter())\n mutableDoc.at('ownedCars').counter.increment(1)\n })\n\n",
"array-to-map": "await collection.findByID(docID).update((mutableDoc) => {\n const map = {}\n const array = mutableDoc.at('friends').value\n array.forEach((name) => {\n const id = getUUID()\n map[id] = { id, name }\n })\n mutableDoc.at('friendsMap').set(map)\n})\n\n",
"query-basic": "const collection = await ditto.store.collection('people').find(\"favoriteBook.title == 'The Great Gatsby'\")\n\n",
"remove-id": "await ditto.store.collection('people').findByID(docID).remove()\n\n",
"query-args": "const query = 'name == $args.name && age <= $args.age'\nconst documents = await ditto.store.collection('people').find(query, {\n age: 32,\n name: 'Max',\n})\n\n",
"remove-query": "await ditto.store.collection('people').find('age <= 32').remove()\n\n",
"query-sort": "const sortedRedCars = await ditto.store.collection('cars').find(\"color == 'red'\").sort('miles', 'ascending')\n\n",
"query-limit": "const sortedAndLimitedRedCars = await ditto.store.collection('cars').find(\"color == 'red'\").sort('miles', 'ascending').limit(100)\n\n",
"evict": "await ditto.store.collection('people').find('age <= 32').evict()\n\n",
"sync-basic": "try {\n ditto.startSync()\n} catch (err) {\n console.error(err)\n}\n\n",
"sync-observe": "const liveQuery = ditto.store\n .collection('cars')\n .find(\"color == 'red'\")\n .observeLocal((cars, event) => {\n // do something\n })\n\n",
"subscribe": "const subscription = ditto.store.collection('cars').find(\"color == 'red'\").subscribe()\n\n",
"sync-observe-local": "const liveQuery = ditto.store\n .collection('cars')\n .find(\"color == 'red'\")\n .observeLocal((cars, event) => {\n // do something\n })\n\n",
"attachment": "const collection = ditto.store.collection('foo')\n\nconst myImageBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAAA1BMVEW10NBjBBbqAAAAH0lEQVRoge3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAvg0hAAABmmDh1QAAAABJRU5ErkJggg=='\nconst myImageBytes = Uint8Array.from(myImageBase64, (character) => character.charCodeAt(0))\nconst metadata = { name: 'image.png' }\n\n// On Node, you can also pass a file path (string) instead of image data\n// and the attachment will be created from that file.\nconst attachment = await collection.newAttachment(myImageBytes, metadata)\n\nconst docID = await collection.upsert({ some: 'string', my_attachment: attachment })\n\n// Later, find the document and then fetch the attachment\n\nconst doc = await collection.findByID(docID)\nconst attachmentToken = doc.at('my_attachment').attachmentToken\n\nconst attachmentFetcher = collection.fetchAttachment(attachmentToken, async (attachmentFetchEvent) => {\n switch (attachmentFetchEvent.type) {\n case 'Completed':\n const fetchedAttachment = attachmentFetchEvent.attachment\n // Do something with attachment\n break\n\n default:\n console.log('Unable to fetch attachment')\n break\n }\n})\n\n// There is also a more convenient way of fetching the attachment\n// (AttachmentFetcher implements the `PromiseLike` protocol):\nconst fetchedAttachment = await collection.fetchAttachment(attachmentToken)\n// Do something with attachment\n\n",
"network-remote-ditto": "import { TransportConfig } from '@dittolive/ditto'\n\nconst config = new TransportConfig()\nconfig.connect.websocketURLs.push('wss://135.1.5.5:12345')\nconfig.connect.websocketURLs.push('wss://185.1.5.5:12345')\nditto.setTransportConfig(config)\nditto.startSync()\n\n\n",
"network-monitor-conditions": "const transportConditionsObserver = ditto.observeTransportConditions((condition, source) => {\n if (condition === 'BLEDisabled') {\n console.log('BLE disabled')\n } else if (condition === 'NoBLECentralPermission') {\n console.log('Permission missing for BLE')\n } else if (condition === 'NoBLEPeripheralPermission') {\n console.log('Permissions missing for BLE')\n }\n})\n\n",
"transport-sync-groups": "import { TransportConfig } from '@dittolive/ditto'\n\nconst config = new TransportConfig()\n// 1. Enable All Peer to Peer Connections (not in a browser environment)\nconfig.setAllPeerToPeerEnabled(true)\n\n//2. Set sync group to an integer between 0 and 2^32\nconfig.global.syncGroup = 1234\n\n// 3. Connect explicitly to remote devices\nditto.setTransportConfig(config)\nditto.startSync()\n\n",
"network-multiple-transports": "import { TransportConfig } from '@dittolive/ditto'\n\nconst config = new TransportConfig()\n// 1. Enable All Peer to Peer Connections (not in a browser environment)\nconfig.setAllPeerToPeerEnabled(true)\n\n// 2. Listen for incoming connections on port 4000\nconfig.listen.tcp.isEnabled = true\nconfig.listen.tcp.interfaceIP = '0.0.0.0'\nconfig.listen.tcp.port = 4000\n\n// 3. Connect explicitly to remote devices\nditto.setTransportConfig(config)\nditto.startSync()\n\n",
"transport-configurations": "const config = new TransportConfig()\n\n/* eslint-disable */\n// Enable all peer to peer transports\nconfig.setAllPeerToPeerEnabled(true)\n\n// or enable/disable each transport separately\n// BluetoothLE\nconfig.peerToPeer.bluetoothLE.isEnabled = true\n\n// Local Area Network\nconfig.peerToPeer.lan.isEnabled = true\n\n// AWDL\nconfig.peerToPeer.awdl.isEnabled = true\n/* eslint-enable */\n\nditto.setTransportConfig(config)\nditto.startSync()\n\n",
"websocket-connect": "import { TransportConfig } from '@dittolive/ditto'\n\nconst config = new TransportConfig()\nconfig.connect.websocketURLs.push('ws://127.0.0.1')\nditto.setTransportConfig(config)\nditto.startSync()\n\n",
"network-listen": "import { TransportConfig } from '@dittolive/ditto'\n\nconst config = new TransportConfig()\nconfig.listen.tcp.isEnabled = true\nconfig.listen.tcp.interfaceIP = '0.0.0.0'\nconfig.listen.tcp.port = 4000\nditto.setTransportConfig(config)\nditto.startSync()\n\n"
},
"csharp": {
"sync-basic": "try\n{\n onlineDitto.StartSync();\n}\ncatch (DittoException ex)\n{\n // handle exception\n}\n\n",
"remove-query": "ditto.Store.Collection(\"people\").Find(\"age <= 32\").Remove();\n\n",
"remove-id": "var wasRemoved = coll.FindById(docId).Remove();\n\n",
"counter": "var counter = new DittoCounter();\n\nvar docId = coll.Upsert(new Dictionary<string, object> {\n { \"make\", \"Honda\" }, { \"mileage\", counter }\n});\n\n_ = coll.FindById(docId).Update(mutableDoc =>\n{\n mutableDoc[\"mileage\"].Counter.Increment(100);\n});\n\n",
"update": "var content = new Dictionary<string, object>\n{\n { \"name\", \"Bob\" },\n { \"age\", 40 },\n { \"ownedCars\", new DittoCounter() }\n};\n\nvar docId = Ditto.Store.Collection(\"people\").Upsert(content);\nDitto.Store.Collection(\"people\").FindById(docId).Update(mutableDoc =>\n{\n mutableDoc[\"age\"].Set(32);\n mutableDoc[\"ownedCars\"].Counter.Increment(1);\n});\n\n",
"evict": "Ditto.Store.Collection(\"people\").Find(\"age <= 32\").Evict();\n\n",
"array-to-map": "Ditto.Store.Collection(\"people\").FindById(docId).Update(mutableDoc =>\n{\n var friendsMap = new Dictionary<string, object>();\n\n foreach (string name in mutableDoc[\"friends\"].ListValue)\n {\n var friend = new Dictionary<string, object>();\n var id = \"myId\";\n friend[\"id\"] = id;\n friend[\"name\"] = name;\n mutableDoc[id].Set(friend);\n }\n mutableDoc[\"friendsMap\"].Set(friendsMap);\n});\n\n",
"attachment": "string attachmentImagePath = Path.Combine(Directory.GetCurrentDirectory(), \"attachment_test.png\");\n\nvar originalBytes = File.ReadAllBytes(attachmentImagePath);\n\nvar metadata = new Dictionary<string, string> { { \"name\", \"my_image.png\" } };\nvar attachment = coll.NewAttachment(attachmentImagePath, metadata);\n\nvar docId = coll.Upsert(new Dictionary<string, object> { { \"some\", \"string\" }, { \"my_attachment\", attachment } });\n\nvar doc = coll.FindById(docId).Exec();\nvar attachmentToken = doc[\"my_attachment\"].AttachmentToken;\nusing var fetcher = coll.FetchAttachment(attachmentToken, ev =>\n{\n switch (ev)\n {\n case DittoAttachmentFetchEvent.Completed e:\n // Do something with attachment\n break;\n default:\n Console.WriteLine(\"Unable to fetch attachment\");\n break;\n }\n});\n\n",
"upsert-composite-primary-key": "// Insert JSON-compatible data into Ditto\nvar content = new Dictionary<string, object> {\n { \"_id\", new Dictionary<string, object> {{ \"userId\", \"456abc\" }, { \"workId\", 789 }} },\n { \"name\", \"Susan\" },\n { \"age\", 31 }\n};\nvar docId = ditto.Store.Collection(\"people\").Upsert(content);\n\n",
"upsert-default-data": "// Immediately try and insert some new default data\nvar docId = coll.Upsert(\n new Dictionary<string, object> { { \"name\", \"Susan\" } },\n DittoWriteStrategy.InsertDefaultIfAbsent);\n\n",
"datamodel": "var coll = ditto.Store.Collection(\"people\");\n\n",
"upsert": "var docId = ditto.Store.Collection(\"people\").Upsert(\n new Dictionary<string, object> {\n { \"name\", \"Susan\" },\n { \"age\", 31 },\n }\n);\n\n",
"upsert-id": "var returnedId = ditto.Store.Collection(\"people\").Upsert(\n new Dictionary<string, object> {\n { \"_id\", \"123abc\" },\n { \"name\", \"Joe\" },\n { \"age\", 32 },\n { \"isOnline\", true }\n }\n);\n\n",
"upsert-datatypes": "// Insert JSON-compatible data into Ditto\nvar content = new Dictionary<string, object>\n{\n { \"boolean\", true },\n { \"string\", \"Hello World\" },\n { \"number\", 10 },\n { \"map\", new Dictionary<string, string>{{ \"key\", \"value\"}} },\n { \"array\", new[] {1, 2, 3} },\n { \"null\", null }\n};\nDitto.Store.Collection(\"foo\").Upsert(content);\n\n",
"online-playground-cloudSync": "try\n{\n var ditto = new Ditto(DittoIdentity.OnlinePlayground(\n appId: \"00000000-0000-4000-0000-000000000000\",\n token: \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\",\n // Set to false to disable syncing with the cloud\n enableDittoCloudSync: true), path);\n\n ditto.StartSync();\n}\ncatch (DittoException ex)\n{\n Console.WriteLine($\"Ditto Error {ex.Message}\");\n}\n\n",
"online-playground": "try\n{\n DittoLogger.SetMinimumLogLevel(DittoLogLevel.Debug);\n var ditto = new Ditto(DittoIdentity.OnlinePlayground(\"00000000-0000-4000-0000-000000000000\", \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\", true), path);\n ditto.StartSync();\n}\ncatch (DittoException ex)\n{\n Console.WriteLine($\"Ditto Error {ex.Message}\");\n}\n\n",
"offline-playground": "try\n{\n var ditto = new Ditto(DittoIdentity.OfflinePlayground(\"00000000-0000-4000-0000-000000000000\", 0), path);\n ditto.StartSync();\n ditto.SetOfflineOnlyLicenseToken(validLicense);\n}\ncatch (DittoException ex)\n{\n Console.WriteLine($\"Ditto Error {ex.Message}\");\n}\n\n",
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every application.\nstring p256DerB64 = \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\";\nvar identity = DittoIdentity.SharedKey(\"app\", p256DerB64);\nvar ditto = new Ditto(identity);\ntry\n{\n ditto.SetOfflineOnlyLicenseToken(validLicense);\n}\ncatch (DittoException ex)\n{\n Console.WriteLine($\"Ditto Error {ex.Message}\");\n}\n\n",
"query-basic": "var results = ditto.Store.Collection(\"people\")\n .Find(\"favoriteBook.title == 'The Great Gatsby'\")\n .Exec();\n\n",
"query-args": "var docs = ditto.Store\n .Collection(\"users\")\n .Find(\n \"name == $args.name && age <= $args.age\",\n new Dictionary<string, object> { { \"name\", \"max\" }, { \"age\", 32 } })\n .Exec();\n\n",
"query-sort": "var sortedCars = ditto.Store.Collection(\"cars\")\n .Find(\"color == 'red'\")\n .Sort(\"miles\", direction: DittoSortDirection.Ascending)\n .Exec();\n\n",
"query-limit": "var sortedAndLimitedRedCars = ditto.Store.Collection(\"cars\")\n .Find(\"color == 'red'\")\n .Sort(\"miles\", direction: DittoSortDirection.Ascending)\n .Limit(100).Exec();\n\n",
"subscribe": "// --- Register live query to update UI\nvar subscription = ditto.Store.Collection(\"cars\").Find(\"color == 'red'\")\n .Subscribe();\n\n",
"sync-observe": "// --- Register live query to update UI\nvar liveQuery = ditto.Store.Collection(\"cars\").Find(\"color == 'red'\").ObserveLocal((docs, dittoLiveQueryEvent) =>\n{\n // Do something...\n});\n\n// --- Register live query to update UI\nvar localLiveQuery = ditto.Store.Collection(\"cars\").Find(\"color == 'red'\").ObserveLocal((docs, dittoLiveQueryEvent) =>\n{\n // Do something...\n});\n\n",
"sync-observe-local": "// --- Register live query to update UI\nvar localLiveQuery = ditto.Store.Collection(\"cars\").Find(\"color == 'red'\")\n .ObserveLocal((docs, dittoLiveQueryEvent) =>\n{\n // Do something...\n});\n\n",
"transport-configurations": "DittoTransportConfig config = new DittoTransportConfig();\n\n//Enable all peer to peer transports\nconfig.EnableAllPeerToPeer();\n\n//Or enable/disable each transport separately\n//BluetoothLe\nconfig.PeerToPeer.BluetoothLE.Enabled = true;\nconfig.PeerToPeer.BluetoothLE.Enabled = true;\n//Local Area Network\nconfig.PeerToPeer.Lan.Enabled = true;\n//Awdl\nconfig.PeerToPeer.Awdl.Enabled = true;\n\nDitto.TransportConfig = config;\n\nDitto.StartSync();\n\n",
"websocket-connect": "DittoTransportConfig config = new DittoTransportConfig();\n\nconfig.Connect.WebsocketUrls.Add(\"ws://127.0.0.1\");\n\nDitto.TransportConfig = config;\n\nDitto.StartSync();\n\n",
"network-remote-ditto": "DittoTransportConfig transportConfig = new DittoTransportConfig();\n// Connect explicitly to a remote device on\ntransportConfig.Connect.TcpServers.Add(\"135.1.5.5:12345\");\n// you can add as many TcpServers as you would like.\ntransportConfig.Connect.TcpServers.Add(\"185.1.5.5:4567\");\n// set the transport config\nDitto.TransportConfig = transportConfig;\n// now you can start ditto's sync\nDitto.StartSync();\n\n",
"network-listen": "DittoTransportConfig transportConfig = new DittoTransportConfig();\ntransportConfig.Listen.Tcp = new DittoTcpListenConfig();\n// By default Listen.Tcp.Enabled is false, be sure to set it to true.\ntransportConfig.Listen.Tcp.Enabled = true;\n// if you want to listen on localhost, most likely you will use 0.0.0.0\n// do not use \"localhost\" as a string\ntransportConfig.Listen.Tcp.InterfaceIp = \"0.0.0.0\";\n// specify your port.\ntransportConfig.Listen.Tcp.Port = 4000;\nDitto.TransportConfig = transportConfig;\n\n// now you can call `ditto.StartSync()`\nDitto.StartSync();\n\n",
"network-multiple-transports": "DittoTransportConfig transportConfig = new DittoTransportConfig();\n\n// 1. Enable Local Area Network Connections\ntransportConfig.EnableAllPeerToPeer();\n\n// 2. Listen for incoming connections on port 4000\ntransportConfig.Listen.Tcp.Enabled = true;\ntransportConfig.Listen.Tcp.InterfaceIp = \"0.0.0.0\";\ntransportConfig.Listen.Tcp.Port = 4000;\n\n// 3. Connect explicitly to remote devices\ntransportConfig.Connect.TcpServers.Add(\"135.1.5.5:12345\");\ntransportConfig.Connect.TcpServers.Add(\"185.1.5.5:12345\");\n\nditto.TransportConfig = transportConfig;\n\nditto.StartSync();\n\n",
"network-set-priority": "DittoExperimental.SetPriorityForQueryOverlapGroup(DittoConnectionPriority.High, 2, crewB);\nDittoExperimental.SetPriorityForQueryOverlapGroup(DittoConnectionPriority.High, 2, crewA);\n\n",
"transport-sync-groups": "DittoTransportConfig transportConfig = new DittoTransportConfig();\n// 1. Enable All Peer to Peer Connections \ntransportConfig.EnableAllPeerToPeer();\n// 2. Set sync group to an integer between 0 and 2^32\ntransportConfig.Global.SyncGroup = 12345;\nditto.TransportConfig = transportConfig;\n\nditto.StartSync();\n\n"
},
"kotlin": {
"attachment": "val testContext = InstrumentationRegistry.getInstrumentation().context\nval attachmentStream = testContext.assets.open(\"attachment_test.png\")\n\nval bitmapStream = testContext.assets.open(\"attachment_test.png\")\nval attachmentBitmap = BitmapFactory.decodeStream(bitmapStream)\nbitmapStream.close()\n\nval metadata = mapOf(\"name\" to \"my_image.png\")\nval attachment = coll.newAttachment(attachmentStream, metadata)\n\nval docId = coll.upsert(mapOf(\"some\" to \"string\", \"my_attachment\" to attachment))\nval doc = coll.findById(docId).exec()\nval attachmentToken = doc!![\"my_attachment\"].attachmentToken\n\nval fetcher = coll.fetchAttachment(attachmentToken!!) {\n when (it) {\n is Completed -> {\n val attBitmap: Bitmap = BitmapFactory.decodeStream(it.attachment.getInputStream())\n }\n is Progress -> {}\n }\n}\n\n",
"datamodel": "val carsCollection = ditto.store[\"cars\"]\n// or\nval carsCollection = ditto.store.collection(\"cars\")\n\n",
"upsert-id": "val docId = ditto.store[\"people\"].upsert(\n mapOf(\n \"_id\" to \"123abc\",\n \"name\" to \"Susan\",\n \"age\" to 31\n )\n)\n\n",
"upsert": "val docId2 = ditto.store[\"people\"].upsert(\n mapOf(\n \"name\" to \"Susan\",\n \"age\" to 31\n )\n)\n\n",
"upsert-composite-primary-key": "val docId = ditto.store[\"people\"].upsert(\n mapOf(\n \"_id\" to mapOf( \"userId\" to \"456abc\", \"workId\" to 789),\n \"name\" to \"Susan\",\n \"age\" to 31\n )\n)\n\n",
"upsert-datatypes": "ditto.store[\"foo\"].upsert(mapOf(\n \"boolean\" to true,\n \"string\" to \"Hello World\",\n \"number\" to 10,\n \"map\" to mapOf(\"key\" to \"value\"),\n \"array\" to listOf(1,2,3),\n \"null\" to null\n))\n\n",
"write-transaction": "val results = ditto.store.write { transaction ->\n val cars = transaction.scoped(\"cars\")\n val people = transaction.scoped(\"people\")\n val docId = \"abc123\"\n people.upsert(mapOf(\"_id\" to docId, \"name\" to \"Susan\"))\n cars.upsert(mapOf(\"make\" to \"Hyundai\", \"color\" to \"red\", \"owner\" to docId))\n cars.upsert(mapOf(\"make\" to \"Jeep\", \"color\" to \"pink\", \"owner\" to docId))\n people.findById(DittoDocumentId(docId)).evict()\n}\n\n",
"counter": "val docId = ditto.store[\"people\"].upsert(mapOf(\n \"name\" to \"Frank\",\n \"ownedCars\" to DittoCounter()\n))\n\nditto.store.collection(\"people\").findById(docId).update { mutableDoc ->\n mutableDoc!![\"ownedCars\"].counter!!.increment(amount = 1.0)\n}\n\n",
"counter-upsert": "val frankId = ditto.store[\"people\"].upsert(mapOf(\n \"name\" to \"Frank\",\n \"age\" to 31,\n \"ownedCars\" to DittoCounter()\n))\n\n",
"update": "ditto.store.collection(\"people\").findById(frankId).update { mutableDoc ->\n mutableDoc?.let {\n it[\"age\"].set(32)\n it[\"ownedCars\"].counter!!.increment(amount = 1.0)\n }\n}\n\n",
"evict": "ditto.store[\"people\"].find(\"age <= 32\").evict()\n\n",
"upsert-default-data": "val docId = ditto.store.collection(\"people\").upsert(mapOf(\n \"name\" to \"Susan\",\n \"age\" to 31\n), DittoWriteStrategy.InsertDefaultIfAbsent)\n\n",
"array-to-map": "collection.findById(docId).update { mutableDoc ->\n val map = mutableMapOf<String, Any>()\n val names = mutableDoc!![\"friends\"].listValue\n names.forEach { name ->\n val id = UUID.randomUUID().toString()\n map[id] = mapOf(\n \"id\" to id,\n \"name\" to name\n )\n }\n\n mutableDoc[\"friendsMap\"].set(map)\n}\n\n",
"device-name": "ditto.deviceName = \"Susan B.\"\nditto.startSync()\nditto.observePeersV2 { peers ->\n // render peer list\n}\n\n",
"online-playground-cloudSync": "val identity = DittoIdentity.OnlinePlayground(androidDependencies,\n appId = \"00000000-0000-4000-0000-000000000000\",\n token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\",\n // Set to false to disable syncing with the cloud\n enableDittoCloudSync = true\n )\nditto = Ditto(androidDependencies, identity)\nditto.startSync()\n\n",
"query-basic": "val results = ditto.store.collection(\"people\")\n .find(\"favoriteBook.title == 'The Great Gatsby'\")\n .exec()\n\n",
"query-args": "val foundDocs = ditto.store.collection(\"people\")\n .find(\"name == \\$args.name && age <= \\$args.age\", mapOf(\"name\" to \"max\", \"age\" to 32))\n\n",
"query-sort": "val sortedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", DittoSortDirection.Ascending)\n .exec()\n\n",
"query-limit": "val sortedAndLimitedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", DittoSortDirection.Ascending)\n .limit(100)\n .exec()\n\n",
"sync-basic": "try {\n ditto.startSync()\n} catch (e: DittoError) {\n // handle error\n}\n\n",
"sync-observe": "// --- DittoRegister live query to update UI\nval liveQuery = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .observeLocal { docs, event ->\n // Do something...\n }\n\n",
"sync-observe-local": "// --- Action somewhere in your application\nfun userDidInsertCar() {\n ditto.store.collection(\"cars\").upsert(mapOf(\n \"model\" to \"Ford\",\n \"color\" to \"black\"\n ))\n}\n\n// --- DittoRegister live query to update UI\nval observeLocalQuery = ditto.store.collection(\"cars\")\n .find(\"isSold == false\")\n .observeLocal { docs, event ->\n // Do something...\n}\n\n",
"subscribe": "// --- DittoRegister live query to update UI\nval subscription = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .subscribe()\n\n",
"online-playground": "try {\n val androidDependencies = DefaultAndroidDittoDependencies(context)\n val identity = DittoIdentity.OnlinePlayground(\n androidDependencies,\n appId = \"00000000-0000-4000-0000-000000000000\",\n token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"\n )\n DittoLogger.minimumLogLevel = DittoLogLevel.DEBUG\n ditto = Ditto(androidDependencies, identity)\n ditto.startSync()\n} catch (e: DittoError) {\n Log.e(\"Ditto error\", e.message!!)\n}\n\n",
"offline-playground": "try {\n val androidDependencies = DefaultAndroidDittoDependencies(context)\n val identity = DittoIdentity.OfflinePlayground(androidDependencies, appId =\n \"00000000-0000-4000-0000-000000000000\")\n ditto = Ditto(androidDependencies, identity)\n ditto.setOfflineOnlyLicenseToken(validLicense)\n ditto.startSync()\n} catch(e: DittoError) {\n Log.e(\"Ditto error\", e.message!!)\n}\n\n",
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every application.\nval p256DerB64 = \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\"\nval androidDependencies = DefaultAndroidDittoDependencies(context)\nval identity = DittoIdentity.SharedKey(\"app\", p256DerB64, null)\nval ditto = Ditto(androidDependencies, identity)\nditto.setOfflineOnlyLicenseToken(validLicense)\n\n",
"transport-configurations": "val config = DittoTransportConfig()\n\n//Enable all peer to peer transports\nconfig.enableAllPeerToPeer()\n\n//Or enable/disable each transport separately\n//BluetoothLe\nconfig.peerToPeer.bluetoothLe.enabled = true\n//Local Area Network\nconfig.peerToPeer.lan.enabled = true\n//Wifi Aware\nconfig.peerToPeer.wifiAware.enabled = true\n\nditto.transportConfig = config\n\nditto.startSync()\n\n",
"transport-sync-groups": "val config = DittoTransportConfig()\n\n//Enable all peer to peer transports\nconfig.enableAllPeerToPeer()\nconfig.global.syncGroup = 1234U\n\nditto.transportConfig = config\n\nditto.startSync()\n\n",
"websocket-connect": "val config = DittoTransportConfig()\n\nconfig.connect.websocketUrls.add(\"ws://127.0.0.1\")\n\nditto.transportConfig = config\n\nditto.startSync()\n\n",
"network-remote-ditto": "val transportConfig = DittoTransportConfig()\n\ntransportConfig.connect.tcpServers.add(\"135.1.5.5:12345\")\ntransportConfig.connect.tcpServers.add(\"185.1.5.5:12345\")\n\nditto.transportConfig = transportConfig\nditto.startSync()\n\n",
"network-listen": "val transportConfig = DittoTransportConfig()\ntransportConfig.connect.tcpServers.add(\"135.1.5.5:12345\")\ntransportConfig.connect.tcpServers.add(\"185.1.5.5:12345\")\nditto.transportConfig = transportConfig\nditto.startSync()\n\n",
"network-multiple-transports": "val transportConfig = DittoTransportConfig()\n// 1. Enable All Peer to Peer Connections\ntransportConfig.enableAllPeerToPeer()\n// 2. Listen for incoming connections on port 4000\ntransportConfig.listen.tcp.enabled = true\ntransportConfig.listen.http.enabled = false\ntransportConfig.listen.tcp.interfaceIp = \"0.0.0.0\"\ntransportConfig.listen.tcp.port = 4000\n// 3. Connect explicitly to remote devices\ntransportConfig.connect.tcpServers.add(\"135.1.5.5:12345\")\ntransportConfig.connect.tcpServers.add(\"185.1.5.5:12345\")\n\nditto.transportConfig = transportConfig\nditto.startSync()\n\n",
"network-monitor-conditions": "// ... Setting up inside an Activity\nval androidDependencies = DefaultAndroidDittoDependencies(applicationContext)\nval ditto = Ditto(androidDependencies, DittoIdentity.OnlinePlayground\n(androidDependencies, appId = \"REPLACE_WITH_APP_ID\", token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"))\nditto.callback = this\nditto.startSync()\n\n// Now you can observe real time changes to the transport conditions:\n\nclass MainActivity : AppCompatActivity(), DittoCallback {\n\n override fun transportConditionDidChange(transportId: Long, condition: TransportCondition) {\n var toastText: String? = null\n if (condition == TransportCondition.TRANSPORT_CONDITION_BLE_DISABLED) {\n toastText = \"BLE disabled\"\n } else if (condition == TransportCondition.TRANSPORT_CONDITION_NO_BLE_CENTRAL_PERMISSION) {\n toastText = \"Permission missing for BLE\"\n } else if (condition == TransportCondition.TRANSPORT_CONDITION_NO_BLE_PERIPHERAL_PERMISSION) {\n toastText = \"Permission missing for BLE\"\n }\n toastText?.let {\n Handler(mainLooper).post {\n Toast.makeText(this, it, Toast.LENGTH_LONG).show()\n }\n }\n }\n}\n\n",
"network-query-overlap-group": "// The passenger only observes orders that they created\npassenger.store.collection(\"orders\")\n .find(\"user_id==abc123\")\n .observeLocal { docs, event ->\n // render passenger orders in a list UI\n}\n\n// Crew member devices observe all orders that everyone created\ncrewA.store.collection(\"orders\")\n .find(\"status == 'OPEN'\")\n .observeLocal { docs, event ->\n // render all orders in a list UI\n}\ncrewB.store.collection(\"orders\")\n .find(\"status == 'OPEN'\")\n .observeLocal { docs, event ->\n // render all orders in a list UI\n}\n\nDittoExperimental.setQueryOverlapGroup(2u, crewA)\nDittoExperimental.setQueryOverlapGroup(2u, crewB)\n\ncrewA.startSync()\ncrewB.startSync()\npassenger.startSync()\n\n",
"network-set-priority": "DittoExperimental.setPriorityForQueryOverlapGroup(DittoConnectionPriority.High, 2u, crewA)\nDittoExperimental.setPriorityForQueryOverlapGroup(DittoConnectionPriority.High, 2u, crewB)\n\n",
"remove-id": "coll.findById(docId).remove()\n\n",
"remove-query": "val removedDocIds = coll.find(\"make == 'Honda'\").remove()\n\n"
},
"java": {
"attachment": "String attachmentPath = tempFile.getPath();\nMap<String, String> metadata = new HashMap<>();\nmetadata.put(\"name\", \"my_image.png\");\nDittoAttachment attachment = coll.newAttachment(attachmentPath, metadata);\ntempFile.delete();\n\nMap<String, Object> content = new HashMap<>();\ncontent.put(\"some\", \"string\");\ncontent.put(\"my_attachment\", attachment);\nDittoDocumentId docID = coll.upsert(content);\n\nDittoDocument doc = coll.findById(docID).exec();\nDittoAttachmentToken attachmentToken = doc.get(\"my_attachment\").getAttachmentToken();\n\nDittoAttachmentFetcher fetcher = coll.fetchAttachment(attachmentToken, event -> {\n if (event.getType() == DittoAttachmentFetchEventType.Completed) {\n DittoAttachment att = event.asCompleted().getAttachment();\n BufferedImage attachmentImage;\n try {\n attachmentImage = ImageIO.read(att.getInputStream());\n } catch (IOException e) {\n e.printStackTrace();\n }\n } else if (event.getType() == DittoAttachmentFetchEventType.Progress) {\n // do nothing - wait for `Completed` or `Deleted`\n } else {\n }\n});\n\n\n",
"datamodel": "DittoCollection carsCollection = ditto.store.collection(\"cars\");\n\n",
"upsert-id": "Map<String, Object> content = new HashMap<>();\ncontent.put(\"_id\", \"123abc\");\ncontent.put(\"name\", \"Susan\");\ncontent.put(\"age\", 31);\nDittoDocumentId docId = ditto.store.collection(\"people\").upsert(content);\n// docId => 123abc\n\n",
"upsert": "Map<String, Object> content = new HashMap<>();\ncontent.put(\"name\", \"Susan\");\ncontent.put(\"age\", 31);\nDittoDocumentId docId = ditto.store.collection(\"people\").upsert(content);\n// docId => 507f191e810c19729de860ea\n\n",
"upsert-composite-primary-key": "Map<String, Object> _id = new HashMap<>();\n_id.put(\"userId\", \"456abc\");\n_id.put(\"workId\", 789);\n\nMap<String, Object> value = new HashMap<>();\nvalue.put(\"_id\", _id);\nvalue.put(\"name\", \"Susan\");\nvalue.put(\"age\", 31);\nDittoDocumentId docID = ditto.store.collection(\"people\").upsert(value);\n// docId=> \"_id.put(\"userId\", \"456abc\"); _id.put(\"workId\", 789);\"\n\n",
"remove-id": "ditto.store.collection(\"people\").findById(docId).remove();\n\n",
"remove-query": "ditto.store.collection(\"people\").find(\"age <= 32\").remove();\n\n",
"evict": "ditto.store.collection(\"people\").find(\"age <= 32\").evict();\n\n",
"upsert-datatypes": "// Insert JSON-compatible data into Ditto\nMap<String, Object> content = new HashMap<>();\ncontent.put(\"boolean\", true);\ncontent.put(\"string\", \"Hello World\");\ncontent.put(\"number\", 10);\nMap<String, String> innerMap = new HashMap<>();\ninnerMap.put(\"key\", \"value\");\ncontent.put(\"map\", innerMap);\ncontent.put(\"array\", Arrays.asList(1, 2, 3));\ncontent.put(\"null\", null);\nditto.store.collection(\"foo\").upsert(content);\n\n",
"counter": "Map<String, Object> content = new HashMap<>();\ncontent.put(\"name\", \"Frank\");\ncontent.put(\"ownedCars\", new DittoCounter());\nDittoDocumentId docId = ditto.store.collection(\"people\").upsert(content);\n\nditto.store.collection(\"people\").findById(docId).update(mutDoc -> {\n assertThat(mutDoc).isNotNull();\n DittoMutableCounter counter = mutDoc.get(\"ownedCars\").getCounter();\n assertThat(counter).isNotNull();\n counter.increment(1);\n});\n\n",
"array-to-map": "collection.findById(docId).update(dittoMutableDocument -> {\n Map<String, Object> friendsMap = new HashMap<>();\n List<Object> names = dittoMutableDocument.get(\"friends\").getListValue();\n names.forEach(name -> {\n Map<String, Object> friend = new HashMap<>();\n String id = UUID.randomUUID().toString();\n friend.put(\"id\", id);\n friend.put(\"name\", name);\n friendsMap.put(id, friend);\n });\n});\n\n",
"counter-upsert": "Map<String, Object> content = new HashMap<>();\ncontent.put(\"name\", \"Frank\");\ncontent.put(\"age\", 31);\ncontent.put(\"ownedCars\", new DittoCounter());\nDittoDocumentId docId = ditto.store.collection(\"people\").upsert(content);\n\nditto.store.collection(\"people\").findById(docId).update(doc -> {\n try {\n doc.get(\"age\").set(32);\n doc.get(\"ownedCars\").getCounter().increment(1);\n } catch (DittoError err) {\n // Do something with error\n }\n});\n\n",
"device-name": "ditto.deviceName = \"Susan B.\";\ntry {\n ditto.startSync();\n} catch(DittoError e) {\n // handle error\n}\nditto.observePeersV2(peers -> {\n // render peers\n});\n\n",
"upsert-default-data": "Map<String, Object> content = new HashMap<>();\ncontent.put(\"name\", \"Susan\");\ncontent.put(\"age\", 31);\nDittoDocumentId docId = ditto.store\n .collection(\"people\")\n .upsert(content, DittoWriteStrategy.InsertDefaultIfAbsent);\n\n",
"query-basic": "List<DittoDocument> results = ditto.store.collection(\"people\")\n .find(\"favoriteBook.title == 'The Great Gatsby'\")\n .exec();\n\n",
"query-args": "Map<String, Object> queryArgs = new HashMap<>();\nqueryArgs.put(\"name\", \"max\");\nqueryArgs.put(\"age\", 32);\n\nList<DittoDocument> foundDocs = ditto.store.collection(\"users\")\n .find(\"name == $args.name && age <= $args.age\", queryArgs)\n .exec();\n\n",
"query-sort": "List<DittoDocument> sortedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", DittoSortDirection.Ascending)\n .exec();\n\n",
"query-limit": "List<DittoDocument> sortedAndLimitedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", DittoSortDirection.Ascending)\n .limit(100)\n .exec();\n\n",
"sync-basic": "try {\n ditto.startSync();\n} catch(DittoError e) {\n // handle error\n}\n\n",
"sync-observe": "// --- Register live query to update UI\nDittoLiveQuery liveQuery = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .observeLocal((docs, event) -> {\n // Do something...\n });\n\n",
"sync-observe-local": "// --- Action somewhere in your application\nMap<String, Object> content = new HashMap<>();\ncontent.put(\"model\", \"Ford\");\ncontent.put(\"color\", \"black\");\nditto.store.collection(\"cars\").upsert(content);\n\n// --- Register live query to update UI\nDittoLiveQuery liveQueryLocal = ditto.store.collection(\"cars\")\n .find(\"owner == 'Susan'\")\n .observeLocal((docs, event) -> {\n // Do something...\n });\n\n",
"subscribe": "// --- Register live query to update UI\nDittoSubscription subscription = ditto.store.collection(\"cars\")\n .find(\"!isSold\")\n .subscribe();\n\n",
"shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every application.\nString p256DerB64 = \"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\";\nDefaultAndroidDittoDependencies androidDependencies = new DefaultAndroidDittoDependencies(this.context);\nDittoIdentity identity = new DittoIdentity.SharedKey(androidDependencies, \"app\", p256DerB64);\nDitto ditto = new Ditto(androidDependencies, identity);\ntry {\n ditto.setOfflineOnlyLicenseToken(validLicense);\n} catch(DittoError e) {\n //handle error\n}\n\n",
"online-playground": "DittoDependencies androidDependencies = new DefaultAndroidDittoDependencies(this.context);\nDittoLogger.setMinimumLogLevel(DittoLogLevel.DEBUG);\nDittoIdentity identity = new DittoIdentity.OnlinePlayground(androidDependencies, \"00000000-0000-4000-0000-000000000000\", \"YOUR_PLAYGROUND_TOKEN_HERE\");\nDitto ditto = new Ditto(androidDependencies, identity);\n\ntry {\n ditto.startSync();\n} catch(DittoError e) {\n //handle error\n}\n\n",
"offline-playground": "DittoIdentity identity = new DittoIdentity.OfflinePlayground(androidDependencies, \"00000000-0000-4000-0000-000000000000\");\nDitto ditto = new Ditto(androidDependencies, identity);\ntry {\n ditto.setOfflineOnlyLicenseToken(validLicense);\n} catch(DittoError e) {\n //handle error\n}\ntry {\n ditto.startSync();\n} catch(DittoError e) {\n //handle error\n}\n\n",
"online-playground-cloudSync": "DittoIdentity identity = new DittoIdentity.OnlinePlayground(androidDependencies,\n \"00000000-0000-4000-0000-000000000000\",\n \"YOUR_PLAYGROUND_TOKEN_HERE\",\n // Set to false to disable syncing with the cloud\n true);\n\nDitto ditto = new Ditto(androidDependencies, identity);\n\ntry {\n ditto.startSync();\n} catch(DittoError e) {\n //handle error\n}\n\n",
"transport-configurations": "DittoTransportConfig config = new DittoTransportConfig();\n\n//Enable all peer to peer transports\nconfig.enableAllPeerToPeer();\n\n//Or enable/disable each transport separately\n//BluetoothLe\nconfig.getPeerToPeer().getBluetoothLe().setEnabled(true);\n//Local Area Network\nconfig.getPeerToPeer().getLan().setEnabled(true);\n//Awdl\nconfig.getPeerToPeer().getWifiAware().setEnabled(true);\n\nditto.setTransportConfig(config);\n\ntry {\n ditto.startSync();\n} catch(DittoError error) {\n // handle error\n}\n\n",
"websocket-connect": "DittoTransportConfig config = new DittoTransportConfig();\n\nDittoConnect connect = new DittoConnect();\nconnect.setWebsocketUrls(Collections.singleton(\"ws://127.0.0.1\"));\nconfig.setConnect(connect);\n\ntry {\n ditto.startSync();\n} catch(DittoError error) {\n // handle error\n}\n\n",
"network-remote-ditto": "DittoTransportConfig config = new DittoTransportConfig();\nDittoConnect connect = new DittoConnect();\nconnect.setTcpServers(Sets.newHashSet(\"135.1.5.5:12345\", \"185.1.5.5:12345\"));\nconfig.setConnect(connect);\n\ntry {\n ditto.startSync();\n} catch(DittoError error) {\n // handle error\n}\n\n",
"network-listen": "DittoTransportConfig config = new DittoTransportConfig();\nconfig.enableAllPeerToPeer();\n\nDittoListen listen = new DittoListen();\nDittoTcpListenConfig tcpListenConfig = new DittoTcpListenConfig();\ntcpListenConfig.setEnabled(true);\ntcpListenConfig.setInterfaceIp(\"0.0.0.0\");\ntcpListenConfig.setPort(4000);\nlisten.setTcp(tcpListenConfig);\nconfig.setListen(listen);\n\ntry {\n ditto.startSync();\n} catch(DittoError error) {\n // handle error\n}\n\n",
"network-multiple-transports": "DittoTransportConfig config = new DittoTransportConfig();\n\n// 1. Enable Peer to Peer Connections\nconfig.enableAllPeerToPeer();\n\n// 2. Listen for incoming connections on port 4000\nDittoListen listen = new DittoListen();\nDittoTcpListenConfig tcpListenConfig = new DittoTcpListenConfig();\ntcpListenConfig.setEnabled(true);\ntcpListenConfig.setInterfaceIp(\"0.0.0.0\");\ntcpListenConfig.setPort(4000);\nlisten.setTcp(tcpListenConfig);\nconfig.setListen(listen);\n// 3. Connect explicitly to remote devices\nDittoConnect connect = new DittoConnect();\nconnect.setTcpServers(Sets.newHashSet(\"135.1.5.5:12345\", \"185.1.5.5:12345\"));\nconfig.setConnect(connect);\n\ntry {\n ditto.startSync();\n} catch(DittoError error) {\n // handle error\n}\n\n",
"network-monitor-conditions": "// Setting up inside an Activity\nDefaultAndroidDittoDependencies androidDependencies = new DefaultAndroidDittoDependencies(getApplicationContext());\nDitto ditto = new Ditto(androidDependencies, new DittoIdentity.OnlinePlayground(androidDependenciesOne, \"REPLACE_WITH_APP_ID\"));\nditto.callback = this;\nditto.startSync();\n\n// Now you can observe real time changes to the transport conditions:\npublic class MainActivity extends AppCompatActivity implements DittoCallback {\n @Override\n public void transportConditionDidChange(@NotNull DittoTransportCondition condition, @NotNull DittoConditionSource transportId) {\n String toastText = null;\n if (condition == DittoTransportCondition.BleDisabled) {\n toastText = \"BLE disabled\";\n } else if (condition == DittoTransportCondition.NoBleCentralPermission) {\n toastText = \"Permission missing for BLE\";\n } else if (condition == DittoTransportCondition.NoBlePeripheralPermission) {\n toastText = \"Permission missing for BLE\";\n }\n\n if (toastText != null) {\n String finalToastText = toastText;\n runOnUiThread(new Runnable() {\n @Override\n public void run() {\n Toast.makeText(MainActivity.this, finalToastText, Toast.LENGTH_LONG).show();\n }\n });\n }\n }\n}\n\n"
}
}