diff --git a/snippets.json b/snippets.json index 3935d5b038..a881458fdf 100644 --- a/snippets.json +++ b/snippets.json @@ -2,8 +2,7 @@ "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", - "insert": "let id1 = collection\n .insert(json!({\"some\": \"value\"}), Some(&custom_id), false)\n .unwrap();\n\n", - "sync-basic": "let res = ditto.try_start_sync();\n\n", + "sync-basic": "let res = 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", "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", @@ -12,9 +11,9 @@ "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::(\"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.replace_with_counter(\"owned_cars\", false).unwrap();\n doc.increment(\"owned_cars\", 1.0).unwrap();\n }\n })\n .unwrap();\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", "array": "let people = ditto.store().collection(\"people\").unwrap();\nlet id = people\n .upsert(json!({\"name\": \"Frank\", \"friends\": []}))\n .unwrap();\n\npeople\n .find_by_id(id)\n .update(|opt_doc| {\n if let Some(doc) = opt_doc {\n doc.push(\"friends\", \"Susan\").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, \"friends\": []}))\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.replace_with_counter(\"owned_cars\", false).unwrap();\n doc.increment(\"owned_cars\", 1.0).unwrap();\n doc.push(\"friends\", \"Susan\").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, \"friends\": []}))\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 doc.push(\"friends\", \"Susan\").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 && arg <= $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", @@ -22,16 +21,16 @@ "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, 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.try_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 OnlinePlaygroundV2::new(\n ditto_root,\n app_id,\n shared_token,\n enable_cloud_sync,\n custom_auth_url,\n )\n })?\n .build()?;\n\nditto.try_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.try_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.try_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.try_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.try_start_sync()?;\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 *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 XCTAssertEqualObjects(fetchedAttachmentData, attachmentData);\n XCTAssertEqualObjects(fetchedAttachment.metadata, metadata);\n [attachmentRoundtripExpectation fulfill];\n break;\n }\n case DITAttachmentFetchEventTypeProgress:\n break;\n default:\n XCTFail(@\"Got an attachment fetch event of something other than completed or progress\");\n break;\n }\n}];\n\n\n", - "counter": "[[collection find:@\"make == 'Honda'\"] updateWithBlock:^(NSArray *docs) {\n for (DITMutableDocument *doc in docs) {\n [doc[@\"mileage\"] replaceWithCounter];\n [doc[@\"mileage\"] increment:1];\n }\n}];\n\n", + "attachment": "NSBundle *testBundle = [NSBundle bundleForClass:self.class];\nNSURL *attachmentTestImage = [testBundle URLForResource:@\"attachment_test\" withExtension:@\"png\"];\nNSData *attachmentData = [NSData dataWithContentsOfURL:attachmentTestImage];\n\nNSDictionary *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 *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", @@ -43,36 +42,36 @@ "remove-query": "NSArray *removedIDs = [[[ditto.store collection:@\"people\"]\n find:@\"name == 'Susan'\"] remove];\n\n", "remove-id": "[[[ditto.store collection:@\"test\"] findByID:docID] remove];\n\n", "array": "DITDocumentID *id = [[ditto.store collection:@\"people\"] upsert:@{\n @\"name\": @\"Frank\",\n @\"friends\": @[]\n} error:nil];\n\n\nDITCollection *people = [ditto.store collection:@\"people\"];\n[[people findByID:id] updateWithBlock:^(DITMutableDocument *doc) {\n [doc[@\"friends\"] push:@\"Susan\"];\n}];\n\n", - "update": "DITDocumentID *docID = [[ditto.store collection:@\"people\"] upsert:@{\n @\"name\": @\"Frank\",\n @\"age\": [NSNumber numberWithInt:31],\n @\"ownedCars\": [NSNumber numberWithInt:0],\n @\"friends\": @[]\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\"] replaceWithCounter];\n [doc[@\"ownedCars\"] increment:1];\n [doc[@\"friends\"] push:@\"Susan\"];\n}];\n\n", + "update": "DITDocumentID *docID = [[ditto.store collection:@\"people\"] upsert:@{\n @\"name\": @\"Frank\",\n @\"age\": [NSNumber numberWithInt:31],\n @\"ownedCars\": [NSNumber numberWithInt:0],\n @\"friends\": @[]\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 [doc[@\"friends\"] push:@\"Susan\"];\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": "\n DITDitto *ditto = [TestHelpers makeDitto];\n\n NSError *error = nil;\n [ditto tryStartSync:&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-basic": "\n DITDitto *ditto = [TestHelpers makeDitto];\n\n 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\nSuppressUnusedWarning(results);\n\n", "sync-observe": "\nDITDitto *ditto = [TestHelpers makeDitto];\n// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\nDITLiveQuery *liveQuery = [[collection find:@\"color == 'red'\"]\n observe:^(NSArray *docs, DITLiveQueryEvent *event) {\n\n}];\n\n", - "subscribe": "\nDITDitto *ditto = [TestHelpers makeDitto];\n// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\nDITLiveQuery *liveQuery = [[collection find:@\"color == 'red'\"] subscribe];\n\n", + "subscribe": "\nDITDitto *ditto = [TestHelpers makeDitto];\n// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\nDITSubscription *subscription = [[collection find:@\"color == 'red'\"] subscribe];\n\n", "sync-observe-local": "\nDITDitto *ditto = [TestHelpers makeDitto];\n// Register live query to update UI\nDITCollection *collection = [ditto.store collection:@\"cars\"];\n\nDITLiveQuery *liveQuery = [[collection find:@\"color == 'red'\"]\n observeLocal:^(NSArray *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.\n\nNSString *p256_der_b64 = @\"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgFUUrOkOH52QN+Rr6uDSDsk4hUTcD1eW4mT0UnGGptFehRANCAATJ3fG8TVLQcDwUV18BJJI8efK0hQAjzB3VJeYOVbfOlqnfukVId0V25r/abxwjD3HfHuPsCGEiefzzmkMbjPo9\";\nDITIdentity *identity = [[DITIdentity alloc] initSharedKeyWithAppID:@\"app\" sharedKey:p256_der_b64 siteID:nil];\nNSError *error = nil;\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\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] initOnlinePlaygroundV2WithAppID:@\"00000000-0000-4000-0000-000000000000\"\n token:@\"REPLACE_ME_WITH_A_SHARED_TOKEN\"];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\nNSError *error = nil;\n[ditto tryStartSync:&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 tryStartSync:&error]) {\n NSLog(@\"Error starting sync: %@\", error);\n}\n[ditto tryStartSync:&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 tryStartSync:&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 tryStartSync:&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 tryStartSync:&err];\n\n", - "network-monitor-conditions": "// Setting up inside a ViewController\nDITIdentity *identity = [[DITIdentity alloc] initOnlinePlaygroundV2WithAppID:@\"REPLACE_WITH_APP_ID\" token:@\"REPLACE_WITH_PLAYGROUND_TOKEN\"];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\nditto.delegate = self;\n[ditto tryStartSync:nil];\n \n// Now you can observe real time changes to the transport conditions:\n@interface ViewController () \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", + "shared-key": "// This is just an example. You should use OpenSSL to generate a unique shared key for every application.\n\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": "// 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\"];\nDITDitto *ditto = [[DITDitto alloc] initWithIdentity:identity];\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 () \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", "evict": "NSArray *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\"\nlet identity = DittoIdentity.sharedKey(appID: \"app\", sharedKey: p256DerB64)\nlet ditto = Ditto(identity: identity)\ntry! ditto.setOfflineOnlyLicenseToken(validLicense);\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 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 people.findByID(docId).evict()\n}\n\n", - "online-playground": "var ditto = Ditto(identity: DittoIdentity.onlinePlaygroundV2(\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))\ntry! ditto.tryStartSync()\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.tryStartSync()\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))\ntry! ditto.startSync()\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": "\nlet 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\nlet docID = try! collection.upsert([\"some\": \"string\", \"my_attachment\": attachment])\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", + "attachment": "\n let collection = ditto.store[\"foo\"]\n\n let myImageURL = bundle.url(forResource: \"image\", withExtension: \"png\")!\n\n let metadata = [\"name\": \"my_image.png\"]\n let attachment = collection.newAttachment(\n path: myImageURL.path,\n metadata: metadata\n )!\n\n let docID = try! collection.upsert([\"some\": \"string\", \"my_attachment\": attachment])\n\n // Later, find the document and the fetch the attachment\n\n let doc = collection.findByID(docID).exec()\n let attachmentToken = doc![\"my_attachment\"].attachmentToken!\n\n let 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": "let docID = try! ditto.store[\"people\"].upsert([\n \"name\": \"Susan\",\n \"age\": 31\n], writeStrategy: .insertDefaultIfAbsent)\n\n", "upsert-composite-primary-key": "let docID = try! ditto.store[\"people\"].upsert([\n \"_id\": [ \"userId\": \"456abc\", \"workId\": 789 ],\n \"name\": \"Susan\",\n \"age\": 31\n])\nprint(docID) // \"[ \"userId\": \"456abc\", \"workId\": 789 ]\"\n\n", "upsert-datatypes": "// Insert JSON-compatible data into Ditto\ntry! 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\n", - "counter": "let docId = try! ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"ownedCars\": 0 // here 0 is a number\n])\n\nditto.store[\"people\"].findByID(docId).update({ mutableDoc in\n mutableDoc?[\"ownedCars\"].replaceWithCounter()\n mutableDoc?[\"ownedCars\"].increment(amount: 1)\n})\n\n", + "counter": "let docId = try! ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"ownedCars\": 0 // here 0 is a number\n])\n\nditto.store[\"people\"].findByID(docId).update({ mutableDoc in\n mutableDoc?[\"ownedCars\"].set(DittoCounter())\n mutableDoc?[\"ownedCars\"].counter?.increment(by: 1)\n})\n\n", "array": "let id = try! ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"friends\": []\n])\n\nditto.store[\"people\"].findByID(id).update({ mutableDoc in\n mutableDoc?[\"friends\"].push(\"Susan\")\n})\n\n", - "update": "let docID = try! ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"age\": 31,\n \"ownedCars\": 0,\n \"friends\": []\n])\n\nditto.store[\"people\"].findByID(docID).update { mutableDoc in\n mutableDoc?[\"age\"] = 32\n mutableDoc?[\"ownedCars\"].replaceWithCounter()\n mutableDoc?[\"ownedCars\"].increment(amount: 1)\n mutableDoc?[\"friends\"].push(\"Susan\")\n}\n\n", + "update": "let docID = try! ditto.store[\"people\"].upsert([\n \"name\": \"Frank\",\n \"age\": 31,\n \"ownedCars\": 0,\n \"friends\": []\n])\n\nditto.store[\"people\"].findByID(docID).update { mutableDoc in\n mutableDoc?[\"age\"] = 32\n mutableDoc?[\"ownedCars\"].set(DittoCounter())\n mutableDoc?[\"ownedCars\"].counter?.increment(by: 1)\n mutableDoc?[\"friends\"].push(\"Susan\")\n}\n\n", "upsert": "// upsert JSON-compatible data into Ditto\nlet docID = try! ditto.store[\"people\"].upsert([\n \"name\": \"Susan\",\n \"age\": 31\n])\n\n", "upsert-id": "// upsert JSON-compatible data into Ditto\nlet docID = try! ditto.store[\"people\"].upsert([\n \"_id\": \"abc123\",\n \"name\": \"Susan\",\n \"age\": 31\n])\n\n", "query-basic": "let collection = ditto.store[\"people\"]\n .find(\"favoriteBook.title == 'The Great Gatsby'\")\n .exec()\n\n", @@ -82,15 +81,15 @@ "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 .observe { 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.setTransportConfig(config: config)\n\ndo {\n try ditto.tryStartSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n", - "device-name": "ditto.deviceName = \"Susan B.\"\nditto.observePeersV2 { json in\n let peers = DittoPeerV2Parser.parseJson(json: json)!\n if !peers.isEmpty {\n // render peers\n }\n}\n\ndo {\n try ditto.tryStartSync()\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.setTransportConfig(config: config)\n\ndo {\n try ditto.tryStartSync()\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.setTransportConfig(config: config)\n\ndo {\n try ditto.tryStartSync()\n} catch (let err) {\n print(err.localizedDescription)\n}\n\n", - "network-monitor-conditions": "// Setting up inside a ViewController\nlet ditto = Ditto(identity: DittoIdentity.onlinePlaygroundV2(appID: \"00000000-0000-4000-0000-000000000000\", token: \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"))\nditto.delegate = self\ntry! ditto.tryStartSync()\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-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", "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.tryStartSync()\n\n" + "sync-basic": "try! ditto.startSync()\n\n" }, "cpp": { "sync-observe-local": "// --- Register live query to update UI\nstd::shared_ptr query =\n collection.find(\"color == 'red'\")\n .observe_local([&](std::vector docs, LiveQueryEvent event) {\n\n });\n\n", @@ -101,9 +100,9 @@ "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", "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 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 event) {\n switch (event->type) {\n case AttachmentFetchEventType::Completed: {\n AttachmentFetchEventCompleted *completed_event =\n static_cast(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", - "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\"].replace_with_counter();\n doc[\"ownedCars\"].increment(1);\n });\n\n", - "update": "DocumentId doc_id = ditto.get_store().collection(\"people\").upsert(\n {{\"name\", \"Frank\"}, {\"age\", 31}, {\"ownedCars\", 0}, {\"friends\", {}}});\n\nditto.get_store().collection(\"people\").find_by_id(doc_id).update(\n [](MutableDocument &doc) {\n doc[\"age\"].set(32);\n doc[\"ownedCars\"].replace_with_counter();\n doc[\"ownedCars\"].increment(1);\n doc[\"friends\"].push(\"Susan\");\n });\n\n", - "array": "DocumentId id = ditto.get_store().collection(\"people\").upsert(\n {{\"name\", \"Frank\"}, {\"friends\", {}}});\n\nditto.get_store().collection(\"people\").find_by_id(id).update(\n [](MutableDocument &doc) { doc[\"friends\"].push(\"Susan\"); });\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}, {\"friends\", {}}});\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 doc[\"friends\"].set(Rga());\n });\n\n", + "array": "DocumentId id = ditto.get_store().collection(\"people\").upsert(\n {{\"name\", \"Frank\"}, {\"friends\", Rga()}});\n\nditto.get_store().collection(\"people\").find_by_id(id).update(\n [](MutableDocument &doc) { doc[\"friends\"].get_rga()->push(\"Susan\"); });\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", @@ -112,14 +111,14 @@ "query-args": "json args = json({{\"age\", 32}, {\"name\", \"max\"}});\nstd::vector 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 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 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.try_start_sync();\n} catch (const DittoError &err) {\n std::cerr << err.what();\n}\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 =\n collection.find(\"color == 'red'\")\n .observe([&](std::vector docs, LiveQueryEvent event) {\n // do something\n });\n\n", - "online-playground": "Ditto ditto;\nauto identity =\n Identity::OnlinePlaygroundV2(\"00000000-0000-4000-0000-000000000000\",\n \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\");\ntry {\n ditto = Ditto(identity, dir);\n ditto.try_start_sync();\n} catch (const DittoError &err) {\n}\n\n", - "offline-playground": "Ditto ditto;\nauto identity =\n Identity::OfflinePlayground(\"00000000-0000-4000-0000-000000000000\");\ntry {\n ditto = Ditto(identity, dir);\n\n ditto.set_offline_only_license_token(valid_license);\n ditto.try_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.try_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.try_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.try_start_sync();\n\n" + "online-playground": "Ditto ditto;\nauto identity =\n Identity::OnlinePlayground(\"00000000-0000-4000-0000-000000000000\",\n \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\");\ntry {\n ditto = Ditto(identity, dir);\n ditto.start_sync();\n} catch (const DittoError &err) {\n}\n\n", + "offline-playground": "Ditto ditto;\nauto identity =\n Identity::OfflinePlayground(\"00000000-0000-4000-0000-000000000000\");\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:///api/v1/store' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \\\n --data-raw '{\n \"method\": \"write\",\n \"parameters\": {\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\n", @@ -133,41 +132,41 @@ "remove-id": "curl -X DELETE 'https:///api/v1/collections/people/documents/' \\\n --header 'X-DITTO-CLIENT-ID: AAAAAAAAAAAAAAAAAAAABQ==' \\\n --header 'Content-Type: application/json' \n\n" }, "javascript": { - "online-playground": "import { init, Ditto } from \"@dittolive/ditto\"\n(async () => {\n await init() // you need to call this at least once before using any of the Ditto API\nconst identity: Identity = { type: 'onlinePlaygroundV2', appID: '00000000-0000-4000-0000-000000000000', token: 'REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN' }\nconst ditto = new Ditto(identity, path)\nditto.tryStartSync()\n})()\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.tryStartSync()\n\n", + "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-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._replaceWithCounterAt('ownedCars')\n mutableDoc._incrementCounterAt('ownedCars', 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", - "array": "const id = await ditto.store.collection('people').upsert({\n name: 'Frank',\n friends: [],\n})\n\nawait ditto.store\n .collection('people')\n .findByID(id)\n .update((mutableDoc) => {\n mutableDoc['friends'].push('Susan')\n })\n\n", - "update": "const docID = await ditto.store.collection('people').upsert({\n name: 'Frank',\n age: 31,\n ownedCars: 0,\n friends: [],\n})\n\nawait ditto.store\n .collection('people')\n .findByID(docID)\n .update((mutableDoc) => {\n mutableDoc['age'] = 32\n mutableDoc['friends'].push('Susan')\n\n mutableDoc._replaceWithCounterAt('ownedCars')\n mutableDoc._incrementCounterAt('ownedCars', 1)\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", + "array": "const id = await ditto.store.collection('people').upsert({\n name: 'Frank',\n friends: new RGA([]),\n})\n\nawait ditto.store\n .collection('people')\n .findByID(id)\n .update((mutableDoc) => {\n mutableDoc.at('friends').rga.push('Susan')\n })\n\n", + "update": "const docID = await ditto.store.collection('people').upsert({\n name: 'Frank',\n age: 31,\n ownedCars: 0,\n friends: new RGA([]),\n})\n\nawait ditto.store\n .collection('people')\n .findByID(docID)\n .update((mutableDoc) => {\n mutableDoc.at('age').set(32)\n mutableDoc.at('friends').rga.push('Susan')\n\n mutableDoc.at('ownedCars').set(new Counter())\n mutableDoc.at('ownedCars').counter.increment(1)\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", + "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.tryStartSync()\n} catch (err) {\n console.error(err)\n}\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 .observe((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.my_attachment\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": "\n import { TransportConfig } from '@dittolive/ditto'\n\n const config = new TransportConfig()\n config.connect.websocketURLs.push('wss://135.1.5.5:12345')\n config.connect.websocketURLs.push('wss://185.1.5.5:12345')\n ditto.setTransportConfig(config)\n ditto.tryStartSync()\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.tryStartSync()\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.tryStartSync()\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.TryStartSync();\n}\ncatch (DittoException ex)\n{\n // handle exception\n}\n\n", + "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 results = coll.FindById(docID).Update(mutableDoc =>\n{\n mutableDoc[\"color\"].Set(\"yellow\");\n mutableDoc[\"mileage\"].ReplaceWithCounter();\n mutableDoc[\"mileage\"].Increment(99);\n});\n\n", + "counter": "var results = coll.FindById(docID).Update(mutableDoc =>\n{\n mutableDoc[\"color\"].Set(\"yellow\");\n mutableDoc[\"mileage\"].Counter.Increment(99);\n});\n\n", "array": "var content = new Dictionary\n{\n { \"name\", \"Bob\" },\n { \"friends\", new List() }\n};\n\nvar docId = Ditto.Store.Collection(\"people\").Upsert(content);\nDitto.Store.Collection(\"people\").FindById(docId).Update(mutableDoc =>\n{\n mutableDoc[\"friends\"].Push(\"Susan\");\n});\n\n", - "update": "var content = new Dictionary\n{\n { \"name\", \"Bob\" },\n { \"age\", 40 },\n { \"ownedCars\", 0 },\n { \"friends\", new List() }\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\"].ReplaceWithCounter();\n mutableDoc[\"ownedCars\"].Increment(1);\n mutableDoc[\"friends\"].Push(\"Susan\");\n});\n\n", + "update": "var content = new Dictionary\n{\n { \"name\", \"Bob\" },\n { \"age\", 40 },\n { \"ownedCars\", new DittoCounter() },\n { \"friends\", new List() }\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 mutableDoc[\"friends\"].Push(\"Susan\");\n});\n\n", "evict": "Ditto.Store.Collection(\"people\").Find(\"age <= 32\").Evict();\n\n", "attachment": "string attachmentImagePath = Path.Combine(Directory.GetCurrentDirectory(), \"attachment_test.png\");\n\nvar originalBytes = File.ReadAllBytes(attachmentImagePath);\n\nvar metadata = new Dictionary { { \"name\", \"my_image.png\" } };\nvar attachment = coll.NewAttachment(attachmentImagePath, metadata);\n\nvar docId = coll.Upsert(new Dictionary { { \"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 {\n { \"_id\", new Dictionary {{ \"userId\", \"456abc\" }, { \"workId\", 789 }} },\n { \"name\", \"Susan\" },\n { \"age\", 31 }\n};\nvar docId = ditto.Store.Collection(\"people\").Upsert(content);\n\n", @@ -176,8 +175,8 @@ "upsert": "var docId = ditto.Store.Collection(\"people\").Upsert(\n new Dictionary {\n { \"name\", \"Susan\" },\n { \"age\", 31 },\n }\n);\n\n", "upsert-id": "var returnedId = ditto.Store.Collection(\"people\").Upsert(\n new Dictionary {\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\n{\n { \"boolean\", true },\n { \"string\", \"Hello World\" },\n { \"number\", 10 },\n { \"map\", new Dictionary{{ \"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.OnlinePlaygroundV2(\"00000000-0000-4000-0000-000000000000\", \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"), path);\n ditto.TryStartSync();\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\"), path);\n ditto.TryStartSync();\n ditto.SetOfflineOnlyLicenseToken(validLicense);\n}\ncatch (DittoException ex)\n{\n System.Console.WriteLine($\"Ditto Error {ex.Message}\");\n}\n\n", + "online-playground": "try\n{\n var ditto = new Ditto(DittoIdentity.OnlinePlayground(\"00000000-0000-4000-0000-000000000000\", \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"), 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\"), path);\n ditto.StartSync();\n ditto.SetOfflineOnlyLicenseToken(validLicense);\n}\ncatch (DittoException ex)\n{\n System.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 System.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 { { \"name\", \"max\" }, { \"age\", 32 } })\n .Exec();\n\n", @@ -186,39 +185,39 @@ "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 .Observe((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.SetTransportConfig(transportConfig);\n// now you can start ditto's sync\nDitto.TryStartSync();\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.SetTransportConfig(transportConfig);\n\n// now you can call `ditto.TryStartSync()`\nDitto.TryStartSync();\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.SetTransportConfig(transportConfig);\n\nDitto.TryStartSync();\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.SetTransportConfig(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.SetTransportConfig(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.SetTransportConfig(transportConfig);\n\nDitto.StartSync();\n\n" }, "kotlin": { - "attachment": "val image = ImageIO.read(imageFile)\n\nval metadata = mapOf(\"name\" to \"my_image.png\")\nval attachment = coll.newAttachment(attachmentStream, metadata)\nval docID = coll.upsert(mapOf(\n \"some\" to \"string\",\n \"my_attachment\" to attachment\n))\n\nvar attachmentImage: BufferedImage? = null\n\ncoll.findByID(docID).exec()?.let { doc ->\n doc[\"my_attachment\"].attachmentToken?.let { token ->\n runBlocking {\n attachmentImage = suspendCoroutine { continuation ->\n val fetcher = coll.fetchAttachment(token) { fetchEvent ->\n when (fetchEvent) {\n is Completed -> {\n val fetchedImage =\n ImageIO.read(fetchEvent.attachment.getInputStream())\n continuation.resume(fetchedImage)\n }\n is Progress -> {}\n else -> continuation.resume(null)\n }\n }\n fetcher.stop()\n }\n }\n }\n}\n\n", + "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 0\n))\n\nditto.store.collection(\"people\").findByID(docID).update { mutableDoc ->\n mutableDoc!![\"ownedCars\"].replaceWithCounter()\n mutableDoc[\"ownedCars\"].increment(1)\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(by = 1.0)\n}\n\n", "array": "val id = ditto.store[\"people\"].upsert(mapOf(\n \"name\" to \"Frank\",\n \"friends\" to emptyList()\n))\n\nval susanId = ditto.store[\"people\"].upsert(mapOf(\n \"name\" to \"Susan\",\n \"friends\" to emptyList()\n))\n\nditto.store.collection(\"people\").findByID(id).update { mutableDoc ->\n mutableDoc!![\"friends\"].push(susanId)\n}\n\n", - "update": "val frankId = ditto.store[\"people\"].upsert(mapOf(\n \"name\" to \"Frank\",\n \"age\" to 31,\n \"ownedCars\" to 0,\n \"friends\" to emptyList()\n))\n\nditto.store.collection(\"people\").findByID(frankId).update { mutableDoc ->\n mutableDoc?.let {\n it[\"age\"].set(32)\n it[\"ownedCars\"].replaceWithCounter()\n it[\"ownedCars\"].increment(1)\n it[\"friends\"].push(susanId)\n }\n}\n\n", + "update": "val frankId = ditto.store[\"people\"].upsert(mapOf(\n \"name\" to \"Frank\",\n \"age\" to 31,\n \"ownedCars\" to DittoCounter(),\n \"friends\" to emptyList()\n))\n\nditto.store.collection(\"people\").findByID(frankId).update { mutableDoc ->\n mutableDoc?.let {\n it[\"age\"].set(32)\n it[\"ownedCars\"].counter!!.increment(by = 1.0)\n it[\"friends\"].push(susanId)\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", - "device-name": "ditto.deviceName = \"Susan B.\"\nditto.tryStartSync()\nditto.observePeersV2 { peers ->\n // render peer list\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.tryStartSync()\n}\ncatch (e: DittoError) {\n // handle error\n}\n\n", - "sync-observe": "// --- Register live query to update UI\nval liveQuery = ditto.store.collection(\"cars\")\n.findAll()\n.observe { 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// --- Register live query to update UI\nval observeLocalQuery = ditto.store.collection(\"cars\")\n .findAll()\n .observeLocal { docs, event ->\n // Do something...\n}\n\n", - "subscribe": "// --- Register 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 = AndroidDittoDependencies(context)\n val identity = DittoIdentity.OnlinePlaygroundV2(androidDependencies, appID = \"00000000-0000-4000-0000-000000000000\", token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\")\n val ditto = Ditto(androidDependencies, identity)\n ditto.tryStartSync()\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.tryStartSync()\n} catch(e: DittoError) {\n Log.e(\"Ditto error\", e.message!!)\n}\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.findAll()\n.observe { 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 .findAll()\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 = AndroidDittoDependencies(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.tryStartSync()\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.tryStartSync()\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.tryStartSync()\n\n", - "network-monitor-conditions": "\n // ... Setting up inside an Activity\n val androidDependencies = DefaultAndroidDittoDependencies(applicationContext)\n val ditto = Ditto(androidDependencies, DittoIdentity.OnlinePlaygroundV2(androidDependencies, appID = \"REPLACE_WITH_APP_ID\", token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"))\n ditto.callback = this\n ditto.tryStartSync()\n\n // Now you can observe real time changes to the transport conditions:\n\n class 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-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": "\n // ... Setting up inside an Activity\n val androidDependencies = DefaultAndroidDittoDependencies(applicationContext)\n val ditto = Ditto(androidDependencies, DittoIdentity.OnlinePlayground(androidDependencies, appID = \"REPLACE_WITH_APP_ID\", token = \"REPLACE_ME_WITH_YOUR_PLAYGROUND_TOKEN\"))\n ditto.callback = this\n ditto.startSync()\n\n // Now you can observe real time changes to the transport conditions:\n\n class 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", "remove-id": "coll.findByID(docID).remove()\n\n", "remove-query": "val removedDocIDs = coll.find(\"make == 'Honda'\").remove()\n\n" }, @@ -232,25 +231,25 @@ "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 content = new HashMap<>();\ncontent.put(\"boolean\", true);\ncontent.put(\"string\", \"Hello World\");\ncontent.put(\"number\", 10);\nMap 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 content = new HashMap<>();\ncontent.put(\"name\", \"Frank\");\ncontent.put(\"ownedCars\", 0);\nDittoDocumentID docID = ditto.store.collection(\"people\").upsert(content);\n\nditto.store.collection(\"people\").findByID(docID).update(mutDoc -> {\n try {\n mutDoc.get(\"ownedCars\").replaceWithCounter();\n mutDoc.get(\"ownedCars\").increment(1);\n } catch (DittoError err) {\n // Do something with error\n }\n});\n\n", - "array": "Map frank = new HashMap<>();\nfrank.put(\"name\", \"Frank\");\nfrank.put(\"friends\", Arrays.asList());\nDittoDocumentID frankId = ditto.store.collection(\"people\").upsert(frank);\n\nditto.store.collection(\"people\").findByID(frankId).update(doc -> {\n try {\n doc.get(\"age\").set(32);\n doc.get(\"cars\").push(\"Ford\");\n } catch (DittoError err) {\n // Do something with error\n }\n});\n\n", - "update": "Map content = new HashMap<>();\ncontent.put(\"name\", \"Frank\");\ncontent.put(\"age\", 31);\ncontent.put(\"ownedCars\", 0);\ncontent.put(\"friends\", Arrays.asList());\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\").replaceWithCounter();\n doc.get(\"ownedCars\").increment(1);\n doc.get(\"friends\").push(\"Susan\");\n } catch (DittoError err) {\n // Do something with error\n }\n});\n\n", - "device-name": "ditto.deviceName = \"Susan B.\";\ntry {\n ditto.tryStartSync();\n} catch(DittoError e) {\n // handle error\n}\nditto.observePeersV2(peers -> {\n // render peers\n});\n\n", + "counter": "Map 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": "Map frank = new HashMap<>();\nfrank.put(\"name\", \"Frank\");\nfrank.put(\"friends\", Collections.emptyList());\nDittoDocumentID frankId = ditto.store.collection(\"people\").upsert(frank);\n\nditto.store.collection(\"people\").findByID(frankId).update(doc -> {\n try {\n assertThat(doc).isNotNull();\n doc.get(\"age\").set(32);\n doc.get(\"cars\").push(\"Ford\");\n } catch (DittoError err) {\n // Do something with error\n }\n});\n\n", + "update": "Map content = new HashMap<>();\ncontent.put(\"name\", \"Frank\");\ncontent.put(\"age\", 31);\ncontent.put(\"ownedCars\", new DittoCounter());\ncontent.put(\"friends\", Collections.emptyList());\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 doc.get(\"friends\").push(\"Susan\");\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 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 results = ditto.store.collection(\"people\")\n .find(\"favoriteBook.title == 'The Great Gatsby'\")\n .exec();\n\n", "query-args": "Map queryArgs = new HashMap<>();\nqueryArgs.put(\"name\", \"max\");\nqueryArgs.put(\"age\", 32);\n\nList foundDocs = ditto.store.collection(\"users\")\n .find(\"name == $args.name && age <= $args.age\", queryArgs)\n .exec();\n\n", "query-sort": "List sortedRedCars = ditto.store.collection(\"cars\")\n .find(\"color == 'red'\")\n .sort(\"miles\", DittoSortDirection.Ascending)\n .exec();\n\n", "query-limit": "List 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.tryStartSync();\n} catch(DittoError e) {\n // handle error\n}\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 .findAll()\n .observe((docs, event) -> {\n // Do something...\n });\n\n", "subscribe": "// --- Register live query to update UI\nDittoSubscription subscription = ditto.store.collection(\"cars\")\n .findAll()\n .subscribe();\n\n", "sync-observe-local": "// --- Action somewhere in your application\nMap 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 .findAll()\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.OnlinePlaygroundV2(androidDependencies, \"00000000-0000-4000-0000-000000000000\", \"YOUR_PLAYGROUND_TOKEN_HERE\");\nDitto ditto = new Ditto(androidDependencies, identity);\n\ntry {\n ditto.tryStartSync();\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.tryStartSync();\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.tryStartSync();\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.tryStartSync();\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.tryStartSync();\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.tryStartSync();\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" + "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" } }