@simple-persist/core
v0.1.5
Published
Typescript decorator for persisting data in browser applications
Downloads
8
Maintainers
Readme
SimplePersist Core
TypeScript property decorator for easy client-side persistance
Table of Contents
Installation
npm install @simple-persist/core
Quick start
Add @Persist()
decorator to any class property:
import { Persist } from '@simple-persist/core';
class Foo {
@Persist() public bar;
}
Note: For more features (like persisting Angular forms or RxJS Subjects) check out our extensions!
Caveats
Multi-instance use
SimplePersist is best fit for singleton use. Class instances are not observed, meaning multiple instances of the same class can cause unexpected behavior:
const foo1 = new Foo();
foo1.bar = 'baz';
const foo2 = new Foo();
console.log(foo2.bar); // Displays 'baz'.
You can overcome this by writing your own keygen.
Types
By default SimplePersist can only persist scalars, as well as objects and arrays containing scalars. (Basically stuff that survives JSON.parse(JSON.stringify(value))
.) You can overcome this by writing your own middleware to serialize & rehydrate your objects.
Storage
SimplePersist uses localStorage
by default. You can switch to sessionStorage
or use cookieStorage
from cookie‑storage like so:
import { CookieStorage } from 'cookie-storage';
class Foo {
@Persist({ storage: sessionStorage }) public bar;
// or
@Persist({ storage: new CookieStorage() }) public baz;
}
You can write your own storage too!
Advanced use
Imperative syntax
For imperative programming use the Persistor
class:
import { Persistor, JsonMiddleware } from '@simple-persist/core';
const persistor = new Persistor<string>({
keygens: [() => 'foo'],
middlewares: [new JsonMiddleware()],
storage: localStorage,
});
persistor.set('bar'); // Saves 'bar' as the value of 'foo' to storage.
persistor.get(); // Loads the value of 'foo' from storage.
persistor.delete(); // Deletes 'foo' from storage.
Note: All configuration options of
Persistor
are optionally available for@Persist()
as well. Use the same syntax to define custom keygens, middlewares or storage for your decorator!
Keygens
By default @Persist()
uses property names as key. This can easily become an issue:
class FooA {
@Persist()
public bar; // Persists as 'bar'.
}
class FooB {
@Persist()
public bar; // Persists as 'bar' too, which creates conflict. :(
}
You can use a custom keygen to overcome this issue. Keygens are functions that modify the default key:
class FooA {
@Persist({ keygens: [() => 'FooA.bar'] })
public bar; // Persists as 'FooA.bar'.
}
class FooB {
@Persist({ keygens: [() => 'FooB.bar'] })
public bar; // Persists as 'FooB.bar'.
}
Alternatively:
class FooA {
@Persist({ keygens: [(key) => `FooA.${key}`] })
public bar; // Persists as 'FooA.bar'.
}
class FooB {
@Persist({ keygens: [(key) => `FooB.${key}`] })
public bar; // Persists as 'FooB.bar'.
}
Note: If you set up multiple keygens, they will be chained by SimplePersist.
You can write your own keygen by implementing the Keygen
interface.
Middlewares
SimplePersist can encode values before saving them to storage. This happens by utilizing a middleware. Middlewares consist of two methods: encode
and decode
.
As an example, take a look at the built-in JsonMiddleware
. (This is the default middleware when using @Persist()
.)
import { Middleware } from '@simple-persist/core';
export class JsonMiddleware implements Middleware<any, string> {
public encode(value: any): string {
return JSON.stringify(value);
}
public decode(value: string | null | undefined): any | null | undefined {
return value && JSON.parse(value);
}
}
These methods are run automatically by SimplePersist. encode()
will be called before saving to storage, decode()
will be called after loading from storage.
Note: If you set up multiple middlewares, encoders will be chained in the defined order, decoders in reverse order.
Write your own middleware by implementing the Middleware
interface or use an extension!
Storages
The native localStorage
and sessionStorage
(from the global scope) are compatible with SimplePersist by design:
class Foo {
@Persist({ storage: sessionStorage }) public bar;
}
You can also write your own storage wrapper by implementing the native Storage
interface or use an extension.
Extensions
We have you covered for some of the common use cases. Check out these extensions and let me know if you miss anything!
| NamePackage | Description |
|:---|:---|
| @PersistControl()@simple‑persist/angular | Decorator for handling Angular forms. |
| @PersistSubject()@simple‑persist/rxjs | Decorator for handling RxJS Subjects & BehaviorSubjects. |
| ConsoleMiddleware@simple‑persist/core | Middleware for displaying values on the console. (Useful for debuging.) |
| CookieStoragecookie‑storage | Storage interface for cookies. |
| DateMiddleware@simple‑persist/core | Middleware for handling JavaScript Date objects. |
| JsonMiddleware@simple‑persist/core | Middleware for encoding to & from JSON. (Default when using @Persist()
.) |
Read more
Check out my article about the reasoning behind this package: Do we need state management in Angular?
Collaboration
Feel free to suggest features, open issues, or contribute! Also let me know about your extensions, so I can link them in this document.