summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md64
-rw-r--r--graffiti.js20
-rw-r--r--test.html97
3 files changed, 102 insertions, 79 deletions
diff --git a/README.md b/README.md
index 06812e5..cf97d02 100644
--- a/README.md
+++ b/README.md
@@ -3,66 +3,4 @@
This is the base Javascript library that interfaces with the [Graffiti server](https://github.com/graffiti-garden/server).
We recommend not using this vanilla library itself but instead using framework plugins that are built on top of it like the [Graffiti plugin for Vue.JS](https://github.com/graffiti-garden/graffiti-x-vue).
-Example usage:
-
-```javascript
-import Graffiti from "https://graffiti-garden.github.io/graffiti-x-js/graffiti.js"
-
-// You can initialize a connection to the graffiti server
-const graffiti = Graffiti()
-await graffiti.initialize()
-
-// You can subscribe to queries
-const queryID = await graffiti.subscribe({
- type: 'post',
- content: { $type: 'string' }
- }
- // With an arbitrary update callback
- (obj) => console.log(`An object has been created: {obj}`),
- // and remove callback
- (obj) => console.log(`An object with id {obj._id} by user {obj._by} has been removed.`)
-)
-
-// And then unsubscribe to those queries
-await graffiti.unsubscribe(queryID)
-
-// You can toggle logging in and out
-graffiti.toggleLogIn()
-
-// When you are logged in you can reference your user ID
-console.log(graffiti.myID)
-
-// And when you are logged in you can
-// create objects,
-const myCoolPost = {
- type: 'post',
- content: 'hello world'
-}
-// ("completing" an object annotates
-// it with your user ID and a random
-// object ID, required by the server)
-graffiti.complete(myCoolPost)
-await graffiti.update(myCoolPost, {})
-
-// replace objects,
-myCoolPost.content += '!!!'
-await graffiti.update(myCoolPost, {})
-
-// and remove objects.
-await graffiti.remove(myCoolPost)
-
-// The second argument in the update
-// function is a query. If the object you
-// try to add does not match the query
-// it will be rejected. This prevents
-// you from accidentally creating data
-// that gets "lost".
-const query = { type: 'post' }
-const myPost = { type: 'post' }
-const myNotPost = { type: 'notpost' }
-graffiti.complete(myNotPost)
-// This works
-await graffiti.update(myPost, query)
-// But this won't work!
-await graffiti.update(myNotPost, query)
-```
+If you create a [local Graffiti instance](https://github.com/graffiti-garden/server#local-usage) and a local webserver in this directory (*e.g.* `python3 -m http.server`) and navigate to `test.html` (*e.g.* [http://localhost:8000/test.html](http://localhost:8000/test.html)) you should be able to log in and test each of the Graffiti primitives: `subscribe`, `unsubscribe`, `update`, `remove`. These primitives will be robust to spamming and network interruptions.
diff --git a/graffiti.js b/graffiti.js
index 5db4eff..0314b85 100644
--- a/graffiti.js
+++ b/graffiti.js
@@ -126,18 +126,12 @@ export default class {
}
async update(object, query) {
- const data = await this.request({
- type: "update",
- object, query
- })
+ const data = await this.request({ object, query })
return data.objectID
}
async remove(objectID) {
- await this.request({
- type: "remove",
- objectID
- })
+ await this.request({ objectID })
}
async subscribe(
@@ -152,10 +146,7 @@ export default class {
if (!queryID) queryID = crypto.randomUUID()
// Send the request
- await this.request({
- type: "subscribe",
- queryID, query, since, ...flags
- })
+ await this.request({ queryID, query, since, ...flags })
// Store the subscription in case of disconnections
this.subscriptionData[queryID] = {
@@ -171,10 +162,7 @@ export default class {
delete this.subscriptionData[queryID]
// And unsubscribe
- const data = await this.request({
- type: "unsubscribe",
- queryID
- })
+ const data = await this.request({ queryID })
}
async onOpen() {
diff --git a/test.html b/test.html
new file mode 100644
index 0000000..3a0d853
--- /dev/null
+++ b/test.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<body>
+ <h1> Graffiti x JS </h1>
+
+ <p id="ID"></p>
+
+ <h2 id="status">Unsubscribed</h2>
+
+ <button onclick="Subscribe()">
+ Subscribe
+ </button>
+
+ <button onclick="Unsubscribe()">
+ Unsubscribe
+ </button>
+
+ <button onclick="Update()">
+ Update
+ </button>
+
+ <button onclick="Remove()">
+ Remove
+ </button>
+
+ <button onclick="LogOut()">
+ Log Out
+ </button>
+
+<script type="module">
+ import Graffiti from "./graffiti.js"
+
+ // Connect to a local Graffiti instance
+ // (see the server README for how to run locally)
+ const graffiti = new Graffiti("http://localhost:5001")
+ await graffiti.initialize()
+
+ // Log in automatically if not already
+ // and supply a log out button
+ if (!graffiti.myID) graffiti.toggleLogIn()
+ window.LogOut = ()=> graffiti.toggleLogIn()
+ document.getElementById('ID').innerHTML = `Your Graffiti ID is: ${graffiti.myID}`
+
+ // Create a display counter
+ let count = 0
+ function displayCount() {
+ document.getElementById('status').innerHTML = `Subscribed: ${count} Objects`
+ }
+
+ // From here to below we're going to
+ // define functions that can be activated
+ // with button presses, corresponding to
+ // each of the four Graffiti primitives.
+
+ // Create an object containing a special string
+ const special = crypto.randomUUID()
+ const usedIDs = []
+ window.Update = async function() {
+ usedIDs.unshift(crypto.randomUUID())
+ await graffiti.update({
+ _id: usedIDs[0],
+ _by: graffiti.myID,
+ special
+ }, {})
+ }
+
+ // Remove an existing object
+ window.Remove = async function() {
+ if ( usedIDs.length ) {
+ await graffiti.remove( usedIDs.pop() )
+ }
+ }
+
+ // Subscribe to objects containing the special string
+ let queryID = null
+ window.Subscribe = async function() {
+ if (queryID) return
+ count = 0
+ queryID = await graffiti.subscribe(
+ { special },
+ (obj)=> { count++; displayCount() },
+ (obj)=> { count--; displayCount() }
+ )
+ displayCount()
+ }
+
+ // Unsubscribe to the existing query
+ window.Unsubscribe = async function() {
+ if (queryID) {
+ await graffiti.unsubscribe(queryID)
+ queryID = null
+ document.getElementById('status').innerHTML = "Unsubscribed"
+ }
+ }
+</script>
+</body>
+</html>