forked from joe-trellick/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
snippets.json
265 lines (265 loc) · 82.8 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
{
"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();\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\": 0}))\n .unwrap();\n\ncollection\n .find_by_id(doc_id)\n .update(|x| {\n if let Some(doc) = x {\n doc.set(\"owned_cars\", DittoCounter::new()).unwrap();\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\": 0}))\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.set(\"owned_cars\", DittoCounter::new()).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.collection(\"cars\")?.find(\"color == \\'red\\'\").observe(\n 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 let _ = tx.send(doc).unwrap();\n }\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 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 .with_minimum_log_level(CLogLevel::Info)\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 .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",
"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\": [NSNumber numberWithInt:0],\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\"] set:DITCounter.new];\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\";\n\nDITIdentity *identity = [[DITIdentity alloc] initSharedKeyWithAppID:@\"app\" sharedKey:p256_der_b64 persistenceDirectory:dittoPersistenceDir];\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": "// Replace the all-zero app ID with your own app ID\nDITIdentity *identity = [[DITIdentity alloc] initOnlinePlaygroundWithAppID:@\"00000000-0000-4000-0000-000000000000\"\n token:@\"REPLACE_ME_WITH_A_SHARED_TOKEN\"\n enableDittoCloudSync:YES\n persistenceDirectory:dittoPersistenceDir];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity persistenceDirectory: dittoPersistenceDir];\nNSError *error = nil;\n[ditto startSync:&error];\n\n",
"offline-playground": "// Replace the all-zero app ID with your own app ID\nDITIdentity *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",
"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",
"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, persistenceDirectory: dittoPersistenceDir)\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\"])\n try cars.upsert([\"make\": \"Ford\", \"color\": \"red\", \"owner\": docId])\n try cars.upsert([\"make\": \"Toyota\", \"color\": \"black\", \"owner\": docId])\n } catch (let err) {\n print(err.localizedDescription)\n }\n people.findByID(docId).evict()\n}\n\n",
"online-playground": "let ditto = Ditto(identity: DittoIdentity.onlinePlayground(\n // Replace the all-zero app ID with your own app ID\n appID: \"00000000-0000-4000-0000-000000000000\",\n token: \"REPLACE_ME_WITH_A_SHARED_TOKEN\"\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 // Replace the all-zero app ID with your own app ID\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 //hanlde 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 break\n default:\n print(\"Unable to fetch attachment\")\n break\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\": 0 // here 0 is a number\n ])\n \n ditto.store[\"people\"].findByID(docId).update({ mutableDoc in\n mutableDoc?[\"ownedCars\"].set(DittoCounter())\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\": 0\n ])\n\n ditto.store[\"people\"].findByID(docID).update { mutableDoc in\n mutableDoc?[\"age\"] = 32\n mutableDoc?[\"ownedCars\"].set(DittoCounter())\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 var names = doc[\"friends\"].arrayValue\n var dict = Dictionary<String, Any>()\n \n names.map { name in\n var 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 XCTAssertNotNil(docID)\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 ])\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": "let config = DittoTransportConfig()\n// Connect explicitly to a remote devices\nconfig.connect.tcpServers.add(\"135.1.5.5:12345\")\nconfig.connect.tcpServers.add(\"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.observePeersV2 { json in\n let peers = DittoPeerV2Parser.parseJson(json: json)!\n if !peers.isEmpty {\n // render peers\n }\n}\n\ndo {\n try ditto.startSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n",
"network-listen": "let 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",
"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.add(\"135.1.5.5:12345\")\nconfig.connect.tcpServers.add(\"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",
"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\", 0}});\n\nditto.get_store().collection(\"people\").find_by_id(docID).update(\n [](MutableDocument &doc) {\n doc[\"ownedCars\"].set(Counter());\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\", 0}});\n\nditto.get_store().collection(\"people\").find_by_id(doc_id).update(\n [](MutableDocument &doc) {\n doc[\"age\"].set(32);\n doc[\"ownedCars\"].set(Counter());\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": "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([&](std::vector<Document> docs, LiveQueryEvent event) {\n // do something\n });\n\n",
"online-playground": "Ditto ditto;\nauto identity = Identity::OnlinePlayground(\n \"00000000-0000-4000-0000-000000000000\",\n \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\", true, dir);\ntry {\n ditto = Ditto(identity, dir);\n ditto.start_sync();\n} catch (const DittoError &err) {\n}\n\n",
"offline-playground": "Ditto ditto;\nauto identity = Identity::OfflinePlayground(\n \"00000000-0000-4000-0000-000000000000\", 1234, dir);\ntry {\n 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",
"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/v2/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 \"value\": {\n \"_id\": { \n \"user_id\": \"456abc\",\n \"work_id\": 789\n },\n \"name\": \"Susan\", \n \"age\": 31\n }\n }]\n }'\n\n",
"upsert": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v2/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 \"value\": {\n \"name\": \"Susan\", \"age\": 31\n }\n }]\n }'\n\n",
"upsert-id": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v2/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 \"value\": {\n \"_id\": \"456abc\",\n \"name\": \"Susan\", \n \"age\": 31\n }\n }]\n }'\n\n",
"upsert-datatypes": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v2/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 \"value\": {\n \"_id\": \"456abc\",\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/v2/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 \"value\": {\n \"_id\": \"123abc\",\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/v2/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/v2/store/find' \\\n--header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n \"collection\": \"people\",\n \"query\": \"name == $args.name && age <= $args.age\",\n \"args\": {\n \"name\": \"max\",\n \"age\": 32\n }\n }'\n\n",
"query-limit": "curl -X POST 'https://<CLOUD_ENDPOINT>/api/v2/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 -X DELETE 'https://<CLOUD_ENDPOINT>/api/v1/collections/people/documents/<doc_id>' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \n\n"
},
"javascript": {
"online-playground": "import { init, Ditto } 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",
"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",
"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",
"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",
"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": "try\n{\n var ditto = new Ditto(DittoIdentity.OnlinePlayground(\"00000000-0000-4000-0000-000000000000\", \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\", true, path), 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), 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'\")\n .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",
"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"
},
"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 docID = 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",
"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}\ncatch (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(androidDependencies, appID = \"00000000-0000-4000-0000-000000000000\", token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\")\n val 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 = AndroidDittoDependencies(context)\n val identity = DittoIdentity.OfflinePlayground(androidDependencies, appID = \"00000000-0000-4000-0000-000000000000\")\n val 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",
"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.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.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.startSync()\n\n",
"network-monitor-conditions": "// ... Setting up inside an Activity\nval androidDependencies = DefaultAndroidDittoDependencies(applicationContext)\nval ditto = Ditto(androidDependencies, DittoIdentity.OnlinePlayground(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\n",
"update": "ditto.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 .observe((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",
"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",
"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);\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",
"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"
}
}