Storage
The Storage Class
serves as an interface to external storages, such as the
Async Storage or
Local Storage.
It creates the foundation to easily persist()
Agile Sub Instances
(like States or Collections) in nearly any external storage.
All you need to instantiate a Storage Interface,
is to call createStorage()
and specify some configurations.
const myStorage = createStorage(/* storage config */);
After a successful instantiation of the Storage Interface,
we must register the Storage at the shared Storage Manager
.
Otherwise, AgileTs doesn't know the Storage and therefore cannot store Instances in it.
The shared Storage Manager manages all Storages for AgileTs
and isn't instantiated by default due to tree shaking.
Thus, we need to instantiate a Storage Manager manually
and specify it as shared Storage Manager.
const storageManager = createStorageManager({ localStorage: false });
assignSharedStorageManager(storageManager);
After we have successfully created a shared Storage Manager we can register
our just creation Storage at it using the registerStorage()
method.
storageManager.registerStorage(myStorage, {default: true});
Here we set the property default
to true
,
in order to use myStorage
as the default Storage.
Each persisted Instance will then be stored in myStorage
by default,
if no further configurations have been made.
// Is stored in 'myStorage'
MY_STATE.persist();
// Is stored in 'myStorage2'
MY_STATE.persist({storageKeys: ['myStorage2']});
When setting the property localStorage
to true
,
the Local Storage
will be registered as default
Storage by AgileTs
and can be used out of the box.
const storageManager = createStorageManager({ localStorage: true });
assignSharedStorageManager(storageManager);
// Is stored in the Local Storage
MY_STATE.persist();
💾 Example
Async Storage
In a react-native environment it is common to use the Async Storage
.
The Async Storage
isn't registered by default, so we have to do it ourselves.
// Create Storage Interface representing the Async Storage
const asyncStorage = createStorage({
key: "AsyncStorage",
async: true,
methods: {
get: AsyncStorage.getItem,
set: AsyncStorage.setItem,
remove: AsyncStorage.removeItem,
},
});
// Register the Async Storage Interface to AgileTs as default Storage
storageManager.registerStorage(asyncStorage, {default: true});
If we now persist()
, for example, a State,
the State value will be stored in the Async Storage
.
MY_STATE.persist();
Object Storage
The Object Storage
isn't an actual useful Storage,
however it demonstrates the use of the Storage Class
pretty good.
// Object Storage
const myStorage = {};
// Create Storage Interface representing the Object Storage
const objectStorage = createStorage({
key: "ObjectStorage",
async: false,
methods: {
get: (key) => {
return myStorage[key];
},
set: (key, value) => {
myStorage[key] = value;
},
remove: (key) => {
delete myStorage[key];
},
},
});
// Register the Object Storage Interface to AgileTs as the default Storage
storageManager.registerStorage(objectStorage, {default: true});
📭 Props
createStorage(config);
config
A Storage
takes a required configuration object as its only parameter.
createStorage( {
key: "myStorage",
methods: {
get: () => {},
set: () => {},
remove: () => {},
}
});
Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.
export interface CreateStorageConfigInterface extends StorageConfigInterface {
key: string;
methods: StorageMethodsInterface;
}
// or without extending
export interface CreateStorageConfigInterface {
key: string;
async?: boolean;
prefix?: string;
methods: {
get: (key: string) => any;
set: (key: string, value: any) => void;
remove: (key: string) => void;
}
}
key
The required property key/name
should be a unique string/number
to identify the Storage later.
createStorage({
key: "myStorage"
// ..
});
This is especially important if we have several Storages in use and want to decide which value is stored in which Storage.
// Store MY_STATE in 'myStorage'
MY_STATE.persist({storageKeys: ['myStorage']});
// Store MY_STATE_2 in 'myStorage2'
MY_STATE_2.persist({storageKeys: ['myStorage2']});
Type | Default | Required |
---|---|---|
string \| number | undefined | Yes |
async
Defines whether the Storage Interface has to work with an async storage and should handle it accordingly.
createStorage({
key: "asyncStorage",
async: true
});
It is often not necessary to define the async
property,
since the Storage Interface is in the most cases able to find out with which kind of Storage it has to deal.
Type | Default | Required |
---|---|---|
boolean | false | No |
prefix
The prefix will be added before each Storage Key
and is intended to highlight the items stored by AgileTs.
A Storage Key
identifies the stored value in the corresponding Storage.
MY_STATE.persist({key: 'myState'});
// Storage Key: '_prefix_myState'
MY_COLLECTION.persist({key: 'myCollection'});
// Storage Keys:
// Collection Indicator: '_prefix_myCollection'
// Default Group: '_prefix__myCollection_group_default'
// Item with id '1': '_prefix__myCollection_item_1'
// Item with id '2': '_prefix__myCollection_item_2'
In the below image you can see a simple Todo Collection stored in the Local Storage
with the prefix 'agile'.
Type | Default | Required |
---|---|---|
string | 'agile' | No |
methods.get
Method used to get a specific value at storageKey
from the external Storage.
createStorage({
// ..
methods: {
get: (key) => {
console.log(`GET '${key}'`);
return myStorage[key];
},
// ..
}
});
myStorage.get("item1"); // console log: "GET 'item1'"
Type | Default | Required |
---|---|---|
(key: string) => any | undefined | Yes |
methods.set
Method used to set a specific value at storageKey
into the external Storage.
createStorage({
// ..
methods: {
set: (key, value) => {
console.log(`SET '${key}'`, value);
myStorage[key] = value;
},
// ..
}
});
myStorage.set("item1", {my: "value"}); // console log: "SET 'item1'" {my: "value"}
Type | Default | Required |
---|---|---|
(key: string, value: any) => void | undefined | Yes |
methods.remove
Method used to remove a specific value at storageKey
from the external Storage.
createStorage({
// ..
methods: {
remove: (key) => {
console.log(`REMOVE '${key}'`);
delete myStorage[key];
},
// ..
}
});
myStorage.remove("item1"); // console log: "REMOVE 'item1'"
Type | Default | Required |
---|---|---|
(key: string) => void | undefined | Yes |
🟦 Typescript
The Storage Class
is almost 100% typesafe.