Skip to content

Instantly share code, notes, and snippets.

@habdelra
Last active September 23, 2019 21:06
Show Gist options
  • Save habdelra/d26a39f18ad699c60c649b2280ec3ed7 to your computer and use it in GitHub Desktop.
Save habdelra/d26a39f18ad699c60c649b2280ec3ed7 to your computer and use it in GitHub Desktop.
Card Data Service brainstorming
import Service from '@ember/service';
export default class DataService extends Service {
cache = new Map();
async getCard(id /*: string */, format /*: string*/) {
// if the card already exists in the cache, just return cached card
// return Card instance
}
async createCard() {
// return Card instance, and create cache entry for Card
}
async deleteCard(id /*: string */) {
// also make sure to remove cached Card
}
}
class Card {
isDirty = false;
id; // string
format; // could be either 'embedded' or 'isolated'
embeddedData; // ResourceObject
isolatedData; // SingleResourceDocument
constructor(id /*: string */, format /*: string */, embeddedData /* ResourceObject*/) {
// this can be instantiated with an optional embeddedData object, which will be the embedded form of this card
// that was included as an embedded relationship from another card. This gives us the ability to
// render embedded cards without having to pay a lookup cost if this card's was included from a
// 'needed-when-embedded' field of another card.
this.id = id;
this.format = format;
this.embeddedData = embeddedData;
}
async setField(field /*: string */, value /* any (including another Card) */) {
// this.format needs to be 'isolated' in order to update the card. If this.format is not isolated,
// then let's fetch the isolated form of the card first.
}
async getField(field /*: string */) {
// if this.isDirty, should we should save() first? as computed/metadata fields could be impacted
// or maybe we should throw if you try to getField but this.isDirty is true
// if this.embeddedData or this.isolatedData has the field, then return it.
// Do note that we need to respect the format of the card when getting a field.
// getting an isolated-only field when the card is in the embedded format should probably
// throw an error.
// if the field value is another Card then instantiate a new Card instance and return that
// this should only expose card metadata and not internal card fields
}
async addField(fieldDefinition /*: SingleResourceDocument*/) {
// the fieldDefinition is the fields JSONAPI document for the new field.
// If the field has a relationship (e.g. a relationship to a constraint), the additional
// resources necessary should be in the included for the field.
// this.format needs to be 'isolated' in order to update the card. If this.format is not isolated,
// then let's fetch the isolated form of the card first.
}
async removeField(field /*: string*/) {
// this removes the field and the field's data from the Card.
// this.format needs to be 'isolated' in order to update the card. If this.format is not isolated,
// then let's fetch the isolated form of the card first.
}
async allFields() {
// this returns all the Card's metadata fields in the correct order and the field types so we know how to render them. Perhaps, we just return
// the JSON:API ResourceObjects for each field to make it simple for now?
// We also need to think about how to invoke with for an embedded card. it would be nice to not have to make an extra
// trip over the wire for each embedded card in order to render it--which I think means that the embedded form of a card
// needs to have enough schema information about it's fields to be able to communicate to the client how to render the field.
}
async save() {
// perform a post or patch (depending on if this card already exists)
// update this.isolatedData with the response of the post/patch (those always return the isolated card format)
// set this.isDirty to false
// return this (which will have metadata fields set, and computeds resolved)
}
async reload(format /*: string */) {
// get the lastest version of the card from the hub, and update the data service cache. load the requested card format
// this is analogous to the card polling that we've done in other projects like cardfolio and tally
// in the case where there is an indexer that is feeding the card new field data
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment