Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

We require three new handles:

  • InsertHandler: binds to add.
  • DeleteHandler: binds to delete.
  • UpdateHandler (optional): binds to set and replace.

Getting random values

await user.friends.friends.random // returns a random friend

Addition

This requires a straightforward handler that intercepts the add and addAll functions that take one mandatory argument.

Adding a single value:

await user.friends.add('https://rubensworks.solid.community/profile/card#me')
await user.friends.add(await user.friends.friends) // Add a random friends friend.

SPARQL:

INSERT DATA
{ 
  <https://rubensworks.solid.community/profile/card#me> foaf:knows <https://rubensworks.solid.community/profile/card#me>.
}

Adding multiple values:

1. Adding friend of friends to as your friends
await user.friends.add(user.friends.friends)
INSERT
{
  <https://rubensworks.solid.community/profile/card#me> foaf:knows ?friendOfFriend.
}
WHERE
{
  <https://rubensworks.solid.community/profile/card#me> foaf:knows ?friend.
  ?friend foaf:knows ?friendOfFriend.
}
2. Adding yourself as friend to your friends friends
await user.friends.friends.add(user)
INSERT
{
  ?friendOfFriend foaf:knows <https://rubensworks.solid.community/profile/card#me>.
}
WHERE
{
  <https://rubensworks.solid.community/profile/card#me> foaf:knows ?friend.
  ?friend foaf:knows ?friendOfFriend.
}
3. Adding your mother as friend to your friends friends
await user.friends.friends.add(user.mother)
INSERT
{
  ?friendOfFriend foaf:knows ?mother.
}
WHERE
{
  <https://rubensworks.solid.community/profile/card#me> foaf:knows ?friend.
  ?friend foaf:knows ?friendOfFriend.

  <https://rubensworks.solid.community/profile/card#me> :hasMother ?mother.
}

Note: We can not trap = via the proxy (set), as this requires a synchronous operation, and you can not play around with return values.

Adding multiple raw values:

await user.friends.add('uri-a', 'uri-b')

Deletion

This requires a handler that intercepts the delete and deleteAll functions that take one optional argument.

Deleting a single value:

await user.friends.delete('https://rubensworks.solid.community/profile/card#me')
await user.friends.delete(await user.friends.friends) // Delete a random friends friend.
await user.friends.random.delete() // Delete a random friend
await user.friends.delete() // Delete all friends

SPARQL:

DELETE DATA
{ 
  <https://rubensworks.solid.community/profile/card#me> foaf:knows <https://rubensworks.solid.community/profile/card#me>.
}

Deleting multiple values:

await user.friends.delete(user.friends.friends)

SPARQL:

DELETE
{
  <https://rubensworks.solid.community/profile/card#me> foaf:knows ?friendOfFriend.
}
WHERE
{
  <https://rubensworks.solid.community/profile/card#me> foaf:knows ?friend.
  ?friend foaf:knows ?friendOfFriend.
}

Note: We can not trap the delete operator via the proxy (deleteProperty), as this requires a synchronous operation, and you can not play around with return values.

Deleting multiple raw values:

await user.friends.delete('uri-a', 'uri-b')

Update

This corresponds to a delete followed by an insert. This is merely convenience functionality that combines deletion and addition (optimizable with a combined SPARQL query: https://www.w3.org/TR/2013/REC-sparql11-update-20130321/#deleteInsert). This requires a handler for set and setAll that take one mandatory argument.

Updating a single value:

await user.name.set('Ruben')

Translation:

await user.name.delete() // Delete all existing values
await user.name.add('Ruben') // Add a single value

Updating with a random value:

await user.name.set(user.friends.name.random)

Translation:

await user.name.delete()
await user.name.add(user.friends.name.random)

Updating with multiple values:

await user.name.set(user.friends.name)

Translation:

await user.name.delete()
await user.name.add(user.friends.name)

Replacing values:

await user.name.replace('ruben', 'Ruben')

Translation:

await user.name.delete('ruben')
await user.name.add('Ruben')

Syntactical sugar

Some syntactical sugar for updates and deletes.

Update

data.user.name = 'Ruben';

Translation:

data.addPendingPromise(user.name.delete()) // This will have no effect if no previous value existed.
data.addPendingPromise(user.name.add('Ruben'))

data.pending is an awaitable over all pending promises.

Delete

delete data.user.daughter;

Translation:

data.addPendingPromise(data.user.daughter.delete())

Batching

Batching allows multiple operations to be grouped together in a single SPARQL query, for improved efficiency. (We probably don't need this in the first stage)

Option 1

// Do data things batched
data.batch((batch) -> {
  batch.user.name = 'Ruben';
  batch.user.brother.name = 'Niels';
  batch.user.sister.name = 'Muriel';
  delete batch.user.daughter;
});

Option 2

// Do data things batched
const batch = data.batch();
batch.user.name = 'Ruben';
batch.user.brother.name = 'Niels';
batch.user.sister.name = 'Muriel';
delete batch.user.daughter;

More complex to implement, but may be doable using WeakMap.

@RubenVerborgh

This comment has been minimized.

Copy link

RubenVerborgh commented Jan 8, 2019

Agree except for addPendingPromise. To be discussed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.