A Twitter clone using Dgraph.io for back end data management and React for front end UI.
-
Clone the
GabeStah/dgraph-twitter-cloneGit repository to a local directory.$ git clone https://github.com/GabeStah/dgraph-twitter-clone.git $ cd dgraph-twitter-clone -
Make sure Dgraph Alpha is installed and running. By default the Dgraph Alpha server is available at
localhost:8080, but if you changed this endpoint during your installation, you'll need to update the configuration to match your setup. To do so open thepackages/dgraph-query-manager/src/config/development.tsfile and change thedgraph.adapter.addressto your Dgraph Alpha server endpoint.// File: packages/dgraph-query-manager/src/config/development.ts const development = { dgraph: { adapter: { address: 'http://localhost:8080' } } };
-
Now execute the
yarn run buildcommand from thedgraph-twitter-cloneroot directory.WARNING: This command will drop all existing data from your Dgraph database. If you prefer to keep your existing Dgraph data, please run the
yarn run build:safecommand instead, which will not drop data, and will only add additional schema and data.$ yarn run build
This command will install a few global Node packages (
gulp-cliandyalc), install all required local Node packages for the API and Client apps, transpile TypeScript source files into executable CommonJS, connect to Dgraph, add the new schema, and finally generate the initial dummy data used by thedgraph-twitter-cloneapp. This process will take a couple minutes and may appear to hang during thedb:generatestep, but the output should look something like the following.yarn run v1.13.0 $ yarn global add gulp-cli yalc && yarn install && gulp install [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages... success Installed "gulp-cli@2.1.0" with binaries: - gulp success Installed "yalc@1.0.0-pre.27" with binaries: - yalc [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.7: The platform "linux" is incompatible with this module. info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... [4/4] Building fresh packages... [16:54:29] Requiring external module @babel/register [16:54:30] Using gulpfile ~/projects/dgraph-twitter-clone/gulpfile.babel.js [16:33:13] Starting 'install'... [16:33:13] Starting 'api:yarn:install'... [16:33:19] Finished 'api:yarn:install' after 5.84 s [16:33:19] Starting 'client:yarn:install'... [16:33:29] Finished 'client:yarn:install' after 9.88 s [16:33:29] Starting 'packages:publish'... [16:33:29] Starting 'packages:remove:modules'... [16:33:29] Starting 'cleanupPackageDirectories'... [16:33:29] Finished 'cleanupPackageDirectories' after 5.92 ms [16:33:29] Finished 'packages:remove:modules' after 6.32 ms [16:33:29] Starting 'packages:install:modules'... [16:33:29] Starting 'installPackageModules'... [16:33:31] Finished 'installPackageModules' after 2.87 s [16:33:31] Finished 'packages:install:modules' after 2.87 s [16:33:31] Starting 'packages:build'... [16:33:31] Starting 'buildPackage'... [16:33:33] Finished 'buildPackage' after 1.76 s [16:33:33] Starting 'bumpVersion'... [16:33:33] Bumped 0.6.175 to 0.6.176 with type: patch [16:33:33] Finished 'bumpVersion' after 6.76 ms [16:33:33] Starting 'publishToYalc'... [16:33:33] Finished 'publishToYalc' after 251 ms [16:33:33] Finished 'packages:build' after 2.02 s [16:33:33] Starting 'packages:push'... [16:33:33] Starting 'pushPackagesToApi'... [16:33:34] Finished 'pushPackagesToApi' after 154 ms [16:33:34] Starting 'pushPackagesToClient'... [16:33:34] Finished 'pushPackagesToClient' after 192 ms [16:33:34] Finished 'packages:push' after 347 ms [16:33:34] Finished 'packages:publish' after 5.24 s [16:33:34] Starting 'api:transpile'... [16:33:38] Finished 'api:transpile' after 4.11 s [16:33:38] Starting 'db:regenerate'... [16:35:08] Finished 'db:regenerate' after 1.5 min [16:35:08] Finished 'install' after 1.92 min Done in 117.21s. -
With everything installed you can now run the Client and/or API apps with
yarn run start.$ yarn run start yarn run v1.13.0 $ gulp start [16:57:04] Requiring external module @babel/register [16:57:04] Using gulpfile ~/projects/dgraph-twitter-clone/gulpfile.babel.js [16:57:04] Starting 'start'... [16:57:04] Starting 'api:start'... [16:57:04] Starting 'client:start'...
The React client should open in a new browser tab automatically. If not, manually browse to the client app at
http://localhost:3000. -
You can now access the API at
localhost:5000, or via and endpoint such aslocalhost:5000/api/tweets/10:$ curl localhost:5000/api/tweets/10 | jq { "statusCode": 200, "success": true, "uri": "", "message": "tweets found.", "request": "query find($count: int) {\n data(func: has (tweet.text), first: $count) {\n uid\n expand(_all_) {\n uid\n expand(_all_)\n }\n }\n }", "response": [ { "uid": "0x6b950", "tweet.createdAt": "2019-04-01T00:16:24.519Z", "tweet.favorited": false, "tweet.text": "@Mossie_Russel61 Realigned homogeneous structure #real-time #front-end", "tweet.hashtag": [ { "uid": "0x6b94e", "hashtag.hashtag": "real", "hashtag.indices": [ 49, 54 ] }, { "uid": "0x6b94f", "hashtag.hashtag": "front", "hashtag.indices": [ 60, 66 ] } ], "tweet.retweeted": false, "tweet.retweetCount": 400, "tweet.isQuoteStatus": true, "tweet.inReplyToStatusId": { "uid": "0x6bcfc", "tweet.favorited": true, "tweet.retweetCount": 263, "tweet.createdAt": "2019-04-01T00:16:54.001Z", "tweet.isQuoteStatus": true, "tweet.text": "@David21 Cross-platform user-facing array #collaborative #frictionless", "tweet.favoriteCount": 209, "tweet.retweeted": false }, "tweet.user": { "uid": "0x6b946", "user.email": "Berniece_Klocko66@example.org", "user.friendsCount": 832, "user.name": "Selina Altenwerth", "user.url": "https://jamarcus.info", "user.createdAt": "2019-04-01T00:16:24.317Z", "user.followersCount": 238, "user.avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/nickfratter/128.jpg", "user.listedCount": 735, "user.description": "Quis a et rem optio. Sunt deserunt quia. Et sit quis enim eum corrupti at velit dolorem. Voluptas maiores natus voluptas beatae delectus.", "user.location": "New Brionna, Bahrain", "user.screenName": "Ezekiel81", "user.favouritesCount": 215 }, "tweet.favoriteCount": 500 }, ] }
-
You can also skip the API and access Dgraph directly. Running the following GraphQL+- query in Ratel (
http://localhost:8000) will return the same results as the API endpoint above.{ data(func: has (tweet.text), first: 10) { uid expand(_all_) { uid expand(_all_) } } }
Auto-generated documentation is available at the following locations.
The following Gulp commands can be issued from the root dgraph-twitter-clone directory.
install- Executes a full install ofapi,client, andpackagesby runningapi:yarn:install,client:yarn:install,packages:publish,api:transpile, anddb:regenerate.install:safe- Same asinstallcommand, but does not drop Dgraph data. Only perform additive operations.start- Starts bothapiandclientapps.default- Same aspackages:publish.
db:regenerate- Drops Dgraph database and regenerates starting data.db:schema:alter- Updates Dgraph schema fromapi/src/config.dgraph.schema.db:generate:data- Generates Dgraph data.
api:docs- Regenerate docs forapiproject.client:docs- Regenerate docs forclientproject.package:docs- Regenerate docs forpackages/dgraph-query-managerproject.docs:all- Regenerates all docs.
packages:remove:modules- Cleans uppackages/dgraph-query-manager/node_modulesdirectory by removing all packages,distdirectory, andyarn.lock.packages:install:modules- Installs node modules forpackages/dgraph-query-manager.packages:cleanup- Executes bothpackages:remove:modulesandpackages:install:modules.packages:build- Rebuildspackages/dgraph-query-managerby transpiling TypeScript src, creating source maps, and definition files. Also bumps version inpackage.jsonand publishes to localyalcrepo.packages:push- Pushes local package inyalcrepo toapiandclientprojects.packages:publish- Performs a full node package removal, reinstall, rebuild, and republish ofpackages/dgraph-query-manager.
api:yarn:install- Executes theyarn installcommand for theapiproject.api:transpile- Transpilesapiproject.api:start- Runs theapiapplication.
client:yarn:install- Executes theyarn installcommand for theclientproject.client:start- Runs theclientapplication.
The dgraph-twitter-clone/api app is an Express-based API that dynamically generates routes based on Query configurations found in the dgraph-query-manager package. As such, the API can accept requests to standard REST API endpoints (e.g. /api/tweets/user/:id), or JSON payloads to the /api/json endpoint for more complex API requests.
See Building the API Server for more details.
Transpile TypeScript into CommonJS, create source maps, and generate definition files by running the default Gulp task from the /api directory.
$ gulp defaultRun yarn test or manually execute jest to execute the test suite.
Start the API server with yarn start or a manual node command.
$ node -r ts-node/register dist/app.js --inspectOR
$ nodemon -r ts-node/register dist/app.js --inspectThe following Gulp commands can be issued from the dgraph-twitter-clone/api directory.
db:drop- Drop all Dgraph data and schema (i.e. a full reset).db:schema:alter- Set Dgraph schema to what's specified inconfig.dgraph.schemavalue.db:reset- Executesdb:dropanddb:schema:alter.db:generate:data- Generates a healthy set of pseudo-randomized Twitter-like data via theGenerator.generateInitialData()method. Currently generates25Users,500Tweets, and randomly assigns various values to integrate the data together (i.e. user tweet authorship, tweet replies, favorite/retweet counts, faked field data, etc).db:regenerate- Refreshes entire database with new data by executingdb:drop,db:schema:alter, anddb:generate:data.build:typescript- Transpiles all.tsfiles in/apiproject, including source maps and definition files.watch:typescript- Watchesapi/srcdirectory for changes, performing a transpile if needed.default- Executesbuild:typescript.
Routes are dynamically generated from Queries specified in the dgraph-query-manager package. Requsts can be either direct REST endpoints (e.g. api/tweet/:id), or complex JSON payloads to the api/json endpoint.
See Handling JSON API Payloads and Dynamically Generating Express Routes for more info.
The dgraph-twitter-clone/client app is a React-based single page application that mimics the core features of Twitter using the Dgraph back end for all queries, mutations, and data management. It can be configured to execute directly with Dgraph, via the API through REST endpoints, or via the API using JSON payloads, all of which tie back to Dgraph.
See The Client for more details.
The dgraph-query-manager package is not publicly published to NPM, so it is built and published locally for use in the /client and /api apps.
- Install any missing node packages via
yarn install. - Make local changes.
- Execute the default Gulp task from the root
dgraph-twitter-clonedirectory to rebuild thedgraph-query-managerpackage and redistribute it to the/clientand/apiapps:
$ gulp default
[19:34:45] Requiring external module @babel/register
[19:34:45] Using gulpfile D:\work\dgraph\projects\dgraph-twitter-clone\gulpfile.babel.js
[19:34:45] Starting 'default'...
[19:34:45] Starting 'packages:remove:modules'...
[19:34:45] Starting 'cleanupPackageDirectories'...
[19:34:47] Finished 'cleanupPackageDirectories' after 1.18 s
[19:34:47] Finished 'packages:remove:modules' after 1.18 s
[19:34:47] Starting 'packages:install:modules'...
[19:34:47] Starting 'installPackageModules'...
[19:34:51] Finished 'installPackageModules' after 4.32 s
[19:34:51] Finished 'packages:install:modules' after 4.33 s
[19:34:51] Starting 'packages:build'...
[19:34:51] Starting 'buildPackage'...
[19:34:53] Finished 'buildPackage' after 1.89 s
[19:34:53] Starting 'bumpVersion'...
[19:34:53] Bumped 0.6.54 to 0.6.55 with type: patch
[19:34:53] Finished 'bumpVersion' after 9.52 ms
[19:34:53] Starting 'publishToYalc'...
[19:34:53] Finished 'publishToYalc' after 270 ms
[19:34:53] Finished 'packages:build' after 2.17 s
[19:34:53] Starting 'packages:push'...
[19:34:53] Starting 'pushPackagesToApi'...
[19:34:54] Finished 'pushPackagesToApi' after 850 ms
[19:34:54] Starting 'pushPackagesToClient'...
[19:34:55] Finished 'pushPackagesToClient' after 734 ms
[19:34:55] Finished 'packages:push' after 1.59 s
[19:34:55] Finished 'default' after 9.27 sYou may need to change the location to your running Dgraph installation in the dgraph-query-manager/src/config files.
-
Open
packages/dgraph-query-manager/src/config/development.ts(orproduction.tsif applicable). -
Set the
dgraph.adapter.addressto the Dgraph server endpoint.const development = { // ... dgraph: { adapter: { address: 'http://localhost:8080' } } // ... };
-
Save your changes and redeploy the
dgraph-query-managerpackage.
Three types of integrations with Dgraph are supported, allowing the dgraph-twitter-clone app to perform data manipulation in whatever method is suitable to your needs.
DIRECT- Passes serialized request objects (i.e. JSON) to thedgraph-adapter-httpinstance, which in turn generates Dgraph transactions via thedgraph-js-httppackage. This connection type completely bypasses the/apiapplication and forms a direct connection to Dgraph (hence theDIRECTname). This is the default connection type.API- Posts the serialized request object to the API's/jsonendpoint. The request body is converted to an executable query, which is then passed along as a Dgraph transaction.REST_API- Uses an endpoint-based REST API from auto-generated Express routes, which are based on the set ofQueriesfound indgraph-query-manager.
The current connection DgraphConnectionTypes enum value is specified in the DgraphQueryManager's config file. Simply change this value then run gulp default from the dgraph-twitter-clone root directory to redistribute the latest package, then start the API then Client apps.
