Learn how to build a Store supporting queries and mutations.
Model
InterfaceStore
, we’ll start by defining a generalized Model
interface. This interface represents any data type we wish to store and forms the foundation of our data model.
Model
interfaces uses type parameters K
, P
, and E
to represent the Key
, Properties
, and Edges
of the model, respectively. This design allows us to define models with varying structures while maintaining type safety.
Model
Interface in Post
Model
interface in place, we can now refactor our Post
class to implement this interface. This enables us to define operations on different aspects of a Post
, such as its key, properties, and edges.
Model
interface in Post
allows us to define operations on various Post
models. For instance:Post
, we have only the Properties
(no Key
or Edges
).Post
, we have both the Key
and the Properties
.Post
s, we have a list of Post.Node
.Post
, we have a Post.Composite
.Post
class now aligns with the Model
interface, allowing us to leverage the type hierarchy for different operations.
Operation
Sealed ClassOperation
sealed class. This class serves as the base for all specific operation types in our Store
.
Operation
class is parameterized with the types K
, P
, E
, and N
, corresponding to the Model
components. The Operation
class has two subclasses, Query
and Mutation
. Query
represents read operations, while Mutation
represents write operations.
Create
OperationsMutation
class, we can define the Create
operations that allow us to insert new data into the Store
.
Create
operations, we have InsertOne
and InsertMany
, which accept Properties
or a list of Properties
as input. Notice that we use Nothing
for types we don’t have yet, such as the Key
for new entries.
Read
OperationsDataSources
sealed class to represent the different sources of data we may want to query.
DataSources
class allows us to specify whether to fetch data from memory, disk, or remote sources.
Query
operations within the Operation
class. Each query
operation specifies the DataSources
to use.
Query
operations include:
FindOne
and FindMany
for fetching specific items by key(s).FindAll
for fetching all items.ObserveOne
and ObserveMany
for observing changes to specific items.Update
OperationsMutation
class, we can define the Update
operations for modifying existing data.
Update
operations include:
UpdateOne
and UpdateMany
for updating existing items.UpsertOne
and UpsertMany
for inserting or updating an item.Delete
OperationsDelete
operations under the Mutation
class.
Delete
operations include:
DeleteOne
and DeleteMany
for deleting specific items by key(s).DeleteAll
for deleting all items.Key
of the items to be deleted.
Model
or a collection of Model
s, we need to define an output type that can represent both cases.
We’ll define an Output
sealed class to represent the results of our operations.
Output
class has two subclasses:
Single
, which wraps a single Model
item.Collection
, which wraps a list of Model
items.Store
to handle both single-item and multiple-item results in a type-safe manner.
PostStore
to use the new Operation
and Output
types.
PostOperation
, Output
, and PostStore
simplifies our code and improves readability.Fetcher
, SourceOfTruth
, Updater
, and Bookkeeper
to support these operations.