SDK Guides
...
Tutorials in JavaScript
Task App: Node.js
to get started right away without having to build an app from scratch, explore with the ditto ready to use demo task app this article provides a quickstart on building and interacting with a basic task app for managing and tracking task items code overview with comments following is an overview of the installation, setup, and build process with comments for a step by step walkthrough for the full source code, see getditto > samples > nodejs > https //github com/getditto/samples/blob/main/tasks/nodejs/index ts repository in github /#installing and setting up ditto /#building and running the app /#creating new task documents /#editing task documents /#replicating data import { init, ditto } from '@dittolive/ditto' import as readline from 'readline/promises' import { stdin as input, stdout as output } from 'node\ process'; let ditto let livequery let tasks = \[] let subscription async function main () { await init() ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) ditto startsync() //// // data replication section //// // subscribe to changes from other peers subscription = ditto store collection("tasks") find("isdeleted == false") subscribe() //// // live query section //// const livequerycallback = (docs, event) => { tasks = docs; } livequery = ditto store collection("tasks") find("isdeleted == false") observelocal(livequerycallback) tasks = await ditto store collection("tasks") find("isdeleted == false") //// // command line interface section //// console log(" commands ") console log(" create \<task name>"); console log(" creates a task"); console log(" example \\" insert my new task\\""); console log(" toggle \<task id>"); console log(" toggles the iscompleted field"); console log(" example \\" toggle 1234abc\\""); console log(" delete \<task id>"); console log(" deletes a task"); console log(" example \\" delete 1234abc\\""); console log(" list"); console log(" list the current tasks"); console log(" exit"); console log(" exits the program"); console log(" commands ") const rl = readline createinterface({ input, output }) while (true) { let answer = await rl question('your command ') if (answer startswith(" create")) { // upsert a new document into tasks let body = answer replace(" create ", "") ditto store collection("tasks") upsert({ body, isdeleted false, iscompleted false }) } else if (answer startswith(" toggle")) { // find the document based on the id an toggle the // 'iscompleted' field to true using the update api const id = answer replace(" toggle ", "") const togglecompleted = (doc) => { const iscompleted = doc value iscompleted doc at("iscompleted") set(!iscompleted) } ditto store collection("tasks") findbyid(id) update(togglecompleted) } else if (answer startswith(" list")) { console log(tasks map((task) => task value)) } else if (answer startswith(" delete")) { // find the document based on the id an set the // 'isdeleted' field to true using the update api const id = answer replace(" delete ", "") const setdeleted = (doc) => { doc at("isdeleted") set(true) } ditto store collection("tasks") findbyid(id) update(setdeleted) } else if (answer startswith(" exit")) { ditto stopsync() process exit() } } } main() installing and setting up ditto create a new directory, navigate to it, and then initialize npm bash mkdir ditto example cd ditto example npm init install the @dittolive/ditto and readline package bash npm i @dittolive/ditto readline open the current directory in your ide for example, if using https //code visualstudio com/ bash code import and initialize ditto create an index js file, and then import, initialize, instantiate, and start ditto by adding the following to it replace 'your app id' and 'your token' with your access credentials to get your access credentials, you must create an account and register an app in the portal for instructions, see docid\ hk2s3ld8sj ti5snxwkq1 import { init, ditto } from '@dittolive/ditto' let ditto async function main () { // initialize the ditto module await init() // create a ditto instance ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) // start synchronization ditto startsync() } main() setting up the app once you've installed and set up your environment with ditto, create a command line interface (cli) along with the various placeholder logic, or stubs , for the methods you'll use to perform various operations import { init, ditto } from '@dittolive/ditto' // add new import modules import as readline from 'readline/promises' import { stdin as input, stdout as output } from 'node\ process'; let ditto ditto | undefined async function main () { // initialize the ditto module await init() // create a ditto instance ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) // start synchronization ditto startsync() //// // data replication section //// // //// // live query section //// // //// // command line interface section //// console log(" commands ") console log(" create \<task name>"); console log(" creates a task"); console log(" example \\" insert my new task\\""); console log(" toggle \<task id>"); console log(" toggles the iscomplete field"); console log(" example \\" toggle 1234abc\\""); console log(" delete \<task id>"); console log(" deletes a task"); console log(" example \\" delete 1234abc\\""); console log(" list"); console log(" list the current tasks"); console log(" exit"); console log(" exits the program"); console log(" commands ") // create a new readline interface const rl = readline createinterface({ input, output }) while (true) { let answer = await rl question('your command ') if (answer startswith(" create")) { // create logic stub } else if (answer startswith(" toggle")) { // toggle logic stub } else if (answer startswith(" list")) { // list logic stub } else if (answer startswith(" delete")) { // delete logic stub } else if (answer startswith(" exit")) { ditto stopsync() process exit() } } } main() building and running the app now that you have the app's cli implemented, build and run the task app bash js node index js the following output cli indicates that the demo task app is running output commands \ create \<task name> inserts a task example " create my new task" \ toggle \<task id> toggles the iscomplete field example " toggle 1234abc" \ delete \<task id> deletes a task example " delete 1234abc" \ list list the current tasks \ exit exits the program commands your command performing reads now that the setup is complete, create a live query a live query is a mechanism that allows you to track specific changes stored within the local environment, referred to as the ditto store relevant documents are stored in a local tasks object; as these documents change, the tasks object automatically updates to reflect their most current state that automatically updates to reflect the latest state as data changes occur, the tasks object updates to reflect the latest state once you've installed and set up the ditto sdk, create a live query that will allow us to see when changes we care about happen to our local store we store any relevant documents in a local tasks object and update the tasks object as changes happen using the live query we'll also implement our list command to return known documents implement live query logic and list command import { init, ditto } from '@dittolive/ditto' import as readline from 'readline/promises' import { stdin as input, stdout as output } from 'node\ process'; let ditto // add a livequery variable to store the livequery object // the livequery must be kept in a location where it will not be // cleaned up by the garbage collector let livequery // create a new tasks object to store known task documents let tasks = \[] async function main () { await init() ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) ditto startsync() //// // data replication section //// // //// // live query section //// // callback that will be triggered const livequerycallback = (docs, event) => { // store documents that match our query in the local tasks object tasks = docs; } // create a live query that will trigger or callback livequery = ditto store collection("tasks") find("isdeleted == false") observelocal(livequerycallback) // get an initial set of data from the store after setting the // live query this ensures we don't have any stale initial data tasks = await ditto store collection("tasks") find("isdeleted == false") //// // command line interface section //// console log(" commands ") console log(" create \<task name>"); console log(" creates a task"); console log(" example \\" insert my new task\\""); console log(" toggle \<task id>"); console log(" toggles the iscomplete field"); console log(" example \\" toggle 1234abc\\""); console log(" delete \<task id>"); console log(" deletes a task"); console log(" example \\" delete 1234abc\\""); console log(" list"); console log(" list the current tasks"); console log(" exit"); console log(" exits the program"); console log(" commands ") const rl = readline createinterface({ input, output }) while (true) { let answer = await rl question('your command ') if (answer startswith(" create")) { // create logic stub } else if (answer startswith(" toggle")) { // toggle logic stub } else if (answer startswith(" list")) { // console log known tasks console log(tasks map((task) => task value)) } else if (answer startswith(" delete")) { // delete logic stub } else if (answer startswith(" exit")) { ditto stopsync() process exit() } } } main() run the list command in the console the output should be an empty array bash your command list output \[] creating new task documents we'll now extend our application with the ability to create new task documents in the ditto store using the upsert method we'll do this by implementing the create command in our application implement create command logic import { init, ditto } from '@dittolive/ditto' import as readline from 'readline/promises' import { stdin as input, stdout as output } from 'node\ process'; let ditto let livequery let tasks = \[] async function main () { await init() ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) ditto startsync() //// // data replication section //// // //// // live query section //// const livequerycallback = (docs, event) => { tasks = docs; } livequery = ditto store collection("tasks") find("isdeleted == false") observelocal(livequerycallback) tasks = await ditto store collection("tasks") find("isdeleted == false") //// // command line interface section //// console log(" commands ") console log(" create \<task name>"); console log(" creates a task"); console log(" example \\" insert my new task\\""); console log(" toggle \<task id>"); console log(" toggles the iscomplete field"); console log(" example \\" toggle 1234abc\\""); console log(" delete \<task id>"); console log(" deletes a task"); console log(" example \\" delete 1234abc\\""); console log(" list"); console log(" list the current tasks"); console log(" exit"); console log(" exits the program"); console log(" commands ") const rl = readline createinterface({ input, output }) while (true) { let answer = await rl question('your command ') if (answer startswith(" create")) { // upsert a new document into tasks let body = answer replace(" create ", "") ditto store collection("tasks") upsert({ body, isdeleted false, iscompleted false }) } else if (answer startswith(" toggle")) { // toggle logic stub } else if (answer startswith(" list")) { console log(tasks map((task) => task value)) } else if (answer startswith(" delete")) { // delete logic stub } else if (answer startswith(" exit")) { ditto stopsync() process exit() } } } main() run the create my first task command run the list command by default, the document id is automatically generated output \[ { id '64c9b6480049a0c400c95c51', body 'my first task', iscompleted false, isdeleted false } ] you can now open the data browser in the ditto portal to see the changes in the big peer ( https //portal ditto live ) editing task documents we'll now extend our application to support editing documents to do this we'll introduce the ability to mark a file as deleted by setting the isdeleted field to true the ability to chage the complteted state by being able to toggle the iscomplete field add logic for toggle and deleted input import { init, ditto } from '@dittolive/ditto' import as readline from 'readline/promises' import { stdin as input, stdout as output } from 'node\ process'; let ditto let livequery let tasks = \[] async function main () { await init() ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) ditto startsync() //// // data replication section //// // //// // live query section //// const livequerycallback = (docs, event) => { tasks = docs; } livequery = ditto store collection("tasks") find("isdeleted == false") observelocal(livequerycallback) tasks = await ditto store collection("tasks") find("isdeleted == false") //// // command line interface section //// console log(" commands ") console log(" create \<task name>"); console log(" creates a task"); console log(" example \\" insert my new task\\""); console log(" toggle \<task id>"); console log(" toggles the iscompleted field"); console log(" example \\" toggle 1234abc\\""); console log(" delete \<task id>"); console log(" deletes a task"); console log(" example \\" delete 1234abc\\""); console log(" list"); console log(" list the current tasks"); console log(" exit"); console log(" exits the program"); console log(" commands ") const rl = readline createinterface({ input, output }) while (true) { let answer = await rl question('your command ') if (answer startswith(" create")) { // upsert a new document into tasks let body = answer replace(" create ", "") ditto store collection("tasks") upsert({ body, isdeleted false, iscompleted false }) } else if (answer startswith(" toggle")) { // find the document based on the id an toggle the // 'iscompleted' field to true using the update api const id = answer replace(" toggle ", "") const togglecompleted = (doc) => { const iscompleted = doc value iscompleted doc at("iscompleted") set(!iscompleted) } ditto store collection("tasks") findbyid(id) update(togglecompleted) } else if (answer startswith(" list")) { console log(tasks map((task) => task value)) } else if (answer startswith(" delete")) { // find the document based on the id an set the // 'isdeleted' field to true using the update api const id = answer replace(" delete ", "") const setdeleted = (doc) => { doc at("isdeleted") set(true) } ditto store collection("tasks") findbyid(id) update(setdeleted) } else if (answer startswith(" exit")) { ditto stopsync() process exit() } } } main() run the list command to get known documents (note the id is generated and will be different) output \[ { id '64c9b6480049a0c400c95c51', body 'my first task', iscompleted false, isdeleted false } ] run the toggle command with the id of the document you want to change iscompleted state of in our case it's document 64c9b6480049a0c400c95c51 run the list command to see state update output \[ { id '64c9b6480049a0c400c95c51', body 'my first task', iscompleted true, isdeleted false } ] run the delete command with the id of the document you want to set to deleted in our case it's document 64c9b6480049a0c400c95c51 run the list command to see state update we now have an empty list because our live query is only subscribing to documents that have "isdeleted == false" output \[] replicating data finally, we'll extend our application to replicate data from other locally connected peers we'll do this by adding a subscription with a query that matches our live query add a subscription with a query that looks for documents in the tasks collection with "isdeleted == false" import { init, ditto } from '@dittolive/ditto' let ditto // add a subscription variable to store the subscription object // the subscription must be kept in a location where it will not be // cleaned up by the garbage collector let subscription async function main () { await init() ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) ditto startsync() // start a new subscription subscription = ditto store collection("tasks") find("isdeleted == false") subscribe() } main()import { init, ditto } from '@dittolive/ditto' import as readline from 'readline/promises' import { stdin as input, stdout as output } from 'node\ process'; let ditto let livequery let tasks = \[] // add a subscription object to store the subscription let subscription async function main () { await init() ditto = new ditto({ type 'onlineplayground', appid 'your app id', token 'your token here'}) ditto startsync() //// // data replication section //// // subscribe to changes from other peers subscription = ditto store collection("tasks") find("isdeleted == false") subscribe() //// // live query section //// const livequerycallback = (docs, event) => { tasks = docs; } livequery = ditto store collection("tasks") find("isdeleted == false") observelocal(livequerycallback) tasks = await ditto store collection("tasks") find("isdeleted == false") //// // command line interface section //// console log(" commands ") console log(" create \<task name>"); console log(" creates a task"); console log(" example \\" insert my new task\\""); console log(" toggle \<task id>"); console log(" toggles the iscompleted field"); console log(" example \\" toggle 1234abc\\""); console log(" delete \<task id>"); console log(" deletes a task"); console log(" example \\" delete 1234abc\\""); console log(" list"); console log(" list the current tasks"); console log(" exit"); console log(" exits the program"); console log(" commands ") const rl = readline createinterface({ input, output }) while (true) { let answer = await rl question('your command ') if (answer startswith(" create")) { // upsert a new document into tasks let body = answer replace(" create ", "") ditto store collection("tasks") upsert({ body, isdeleted false, iscompleted false }) } else if (answer startswith(" toggle")) { // find the document based on the id an toggle the // 'iscompleted' field to true using the update api const id = answer replace(" toggle ", "") const togglecompleted = (doc) => { const iscompleted = doc value iscompleted doc at("iscompleted") set(!iscompleted) } ditto store collection("tasks") findbyid(id) update(togglecompleted) } else if (answer startswith(" list")) { console log(tasks map((task) => task value)) } else if (answer startswith(" delete")) { // find the document based on the id an set the // 'isdeleted' field to true using the update api const id = answer replace(" delete ", "") const setdeleted = (doc) => { doc at("isdeleted") set(true) } ditto store collection("tasks") findbyid(id) update(setdeleted) } else if (answer startswith(" exit")) { ditto stopsync() process exit() } } } main()