Skip to content

Commit

Permalink
Merge pull request #22 from MacFJA/update
Browse files Browse the repository at this point in the history
Storage creation name + encrypted storage + serializer
  • Loading branch information
MacFJA authored Aug 21, 2022
2 parents c6ad468 + d3dfda5 commit 5e643dc
Show file tree
Hide file tree
Showing 25 changed files with 6,352 additions and 4,494 deletions.
38 changes: 0 additions & 38 deletions .docs/03-Self-Update-Storage.md

This file was deleted.

20 changes: 12 additions & 8 deletions .docs/01-Basic.md → .docs/Examples/01-Basic.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
---
name: Basic examples
order: 1
---
# Basic examples

## Local Storage

```html
<script>
import { persist, localStorage } from "@macfja/svelte-persistent-store"
import { persistBrowserLocal } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
const theme = persist(writable('light'), localStorage(), 'myapp-theme')
const theme = persistBrowserLocal(writable('light'), 'myapp-theme')
</script>
<aside>
<label>
Expand All @@ -25,11 +29,11 @@

```html
<script>
import { persist, sessionStorage } from "@macfja/svelte-persistent-store"
import { persistBrowserSession } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
const currentDocumentTitle = persist(writable('Unsaved document'), sessionStorage(), 'myapp-new-document-title')
const currentDocumentContent = persist(writable('Lorem ipsum'), sessionStorage(), 'myapp-new-document-content')
const currentDocumentTitle = persistBrowserSession(writable('Unsaved document'), 'myapp-new-document-title')
const currentDocumentContent = persistBrowserSession(writable('Lorem ipsum'), 'myapp-new-document-content')
const save = () => {
// myApi.save({title: $currentDocumentTitle, content: $currentDocumentContent})
Expand Down Expand Up @@ -65,10 +69,10 @@

```html
<script>
import { persist, indexedDBStorage } from "@macfja/svelte-persistent-store"
import { persist, createIndexedDBStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
const layout = persist(writable('2column'), indexedDBStorage(), 'myapp-layout')
const layout = persist(writable('2column'), createIndexedDBStorage(), 'myapp-layout')
</script>

<aside>
Expand All @@ -82,4 +86,4 @@
</select>
</label>
</aside>
```
```
30 changes: 18 additions & 12 deletions .docs/02-Reuse-Store.md → .docs/Examples/02-Reuse-Store.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
---
name: Reuse a store across an application
order: 2
---
# Reuse a store across an application

There are, at least, 3 ways to have the same store between components.

1. Recreate the same code definition in the second component
Expand All @@ -16,15 +22,15 @@ Creating the component in a separate JS/TS file, the store is not _"attached"_ t

Here an example of those 3 implementations

### Duplication definition in every component
## Duplication definition in every component

```html
<!-- Component1.svelte -->
<script>
import { persist, localStorage } from "@macfja/svelte-persistent-store"
import { persist, createLocalStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
let name = persist(writable("John"), localStorage(), "name")
let name = persist(writable("John"), createLocalStorage(), "name")
$name = 'Jeanne Doe'
</script>
Expand All @@ -33,25 +39,25 @@ Here an example of those 3 implementations
```html
<!-- Component2.svelte -->
<script>
import { persist, localStorage } from "@macfja/svelte-persistent-store"
import { persist, createLocalStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
import { onMount } from "svelte"
let name = persist(writable("Foobar"), localStorage(), "name")
let name = persist(writable("Foobar"), createLocalStorage(), "name")
onMount(() => { alert($name) }) // If Component2 is loaded/mount after Component1 the alert will be "Jeanne Doe"
</script>
```

### Context module
## Context module

```html
<!-- Component1.svelte -->
<script context="module">
import { persist, localStorage } from "@macfja/svelte-persistent-store"
import { persist, createLocalStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
export let name = persist(writable("John"), localStorage(), "name")
export let name = persist(writable("John"), createLocalStorage(), "name")
</script>
<script>
$name = "Jeanne Doe"
Expand All @@ -67,14 +73,14 @@ Here an example of those 3 implementations
</script>
```

### External definition
## External definition

```js
// stores.js
import { persist, localStorage } from "@macfja/svelte-persistent-store"
import { persist, createLocalStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"

export let name = persist(writable("John"), localStorage(), "name")
export let name = persist(writable("John"), createLocalStorage(), "name")
```
&nbsp;
```html
Expand All @@ -93,4 +99,4 @@ export let name = persist(writable("John"), localStorage(), "name")
name.subscribe(value => alert(value)) // the alert will open when the store is change in any component
</script>
```
```
42 changes: 42 additions & 0 deletions .docs/Examples/03-Self-Update-Storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Storage that can update themselves
order: 3
---
# Storage that can update themselves

The **createSessionStorage** and **createLocalStorage** are able to listen changes made externally to the current Window.

_**NOTE:** Change that are made from another browser window (browser tab) from the same website domain and same browser **ONLY**.
Change made inside the same application instance (i.e. in another page of an SPA) are NOT considered as external changes!_

To activate this feature, just add `true` as the parameter of the `createLocalStorage` and `createSessionStorage`.

## Examples

### Local Storage

```html
<script>
import { persist, createLocalStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
const nickname = persist(writable('John'), createLocalStorage(true), 'myapp-nickname')
// ^^^^
</script>
```

If the another Window from the (same) browser change the value of the _createLocalStorage_ (from a Svelte application or not), the store will be updated.

### Session Storage

```html
<script>
import { persist, createSessionStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
const unreadCount = persist(writable(0), createSessionStorage(true), 'myapp-unread')
// ^^^^
</script>
```

If the another Window from the (same) browser change the value of the _createSessionStorage_ (from a Svelte application or not), the store will be updated._
22 changes: 22 additions & 0 deletions .docs/Examples/04-Encrypted-Storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: Encrypt persisted data
order: 4
---
# Encrypt persisted data

You can encrypt data that are persisted.
Both the key and the data are encrypted.

_**NOTE:** The encryption is not well adapted for cookie storage, as the data is encrypted, its size greatly increase, you will rapidly get to the allowed cookie size._

## Examples

```html
<script>
import { persist, createLocalStorage, createEncryptedStorage } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
const storage = createEncryptedStorage(createLocalStorage(), "5368566D597133743677397A24432646")
const nickname = persist(writable("John"), storage, "myapp-nickname")
</script>
```
6 changes: 5 additions & 1 deletion .docs/04-New-Storage.md → .docs/How-To/01-New-Storage.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
name: Create new storage
order: 1
---
# Create new storage

New storages can be added. They need to implement the interface `StorageInterface<T>`.
Expand All @@ -14,4 +18,4 @@ The only particularity in this interface, the method `StorageInterface.getValue`

The method `SelfUpdateStorageInterface.addListener` take as parameter a function that must be call every time the storage is updated (by an external source).
This function take one parameter, the key that have been changed.
The store will call the `StorageInterface.getValue` to get the new value
The store will call the `StorageInterface.getValue` to get the new value
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
name: Create a new asynchronous storage
order: 2
---
# Create a new asynchronous storage

There is a workaround (trickery) to work with asynchronous data storage.
Expand Down Expand Up @@ -25,4 +29,4 @@ function myStorage<T>(): SelfUpdateStorageInterface<T> {
// ... addListener, removeListener, setValue, deleteValue
}
}
```
```
10 changes: 7 additions & 3 deletions .docs/06-Store-Classes.md → .docs/How-To/03-Store-Classes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
name: Persist a JavaScript class
order: 3
---
# Persist a JavaScript class

The storage of classes is a bit more involving that simple object or array.
Expand All @@ -6,11 +10,11 @@ Class are complex object that contains functions and logic that do more than hol

To store classes we need to serialize them into a special form that we will be able to reverse, to do so we need to register the class, so we know that we have something to do with it.

# Example
## Example

```html
<script>
import { persist, localStorage, addSerializableClass } from "@macfja/svelte-persistent-store"
import { persist, createLocalStorage, addSerializableClass } from "@macfja/svelte-persistent-store"
import { writable } from "svelte/store"
export class NameHolder {
Expand All @@ -29,7 +33,7 @@ To store classes we need to serialize them into a special form that we will be a
// Register the class
addSerializableClass(NameHolder);
let classStore = persist(writable(new NameHolder()), localStorage(), 'user-name');
let classStore = persist(writable(new NameHolder()), createLocalStorage(), 'user-name');
function updateName() {
$classStore.setName('Jeanne');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
name: Disabling warning about missing storage
order: 4
---
# Disabling warning about missing storage

When using the library both on Client and Server side, you can have warnings messages about missing storage on the server.
Expand Down
28 changes: 28 additions & 0 deletions .docs/How-To/05-Missing-Encryption-Behavior.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: Change behavior with missing encryption
order: 5
---
# Change the behavior when the encryption is not possible

The encryption library use the browser native WebCrypto library to work (or NodeJS Crypto library on a server).

But there is case where the WebCrypto library may not be available, for example on a not secure URL.

By default, this library will raise an exception.

But you can change this with this code:

```js
import { noEncryptionBehavior, NO_ENCRYPTION_BEHAVIOR } from "@macfja/svelte-persistent-store";
noEncryptionBehavior(NO_ENCRYPTION_BEHAVIOR.NO_ENCRYPTION);
```

Put this function call before calling the persistent storage or in the init/boot script.

## List of behavior

| Name | Numeric value | Comment |
|-------------------------------------------|---------------|-------------------------------------------------------------------|
| [[NO_ENCRYPTION_BEHAVIOR.EXCEPTION]] | `0` | **(default)** Raise an exception |
| [[NO_ENCRYPTION_BEHAVIOR.NO_ENCRYPTION]] | `1` | Use the wrapped Storage as-is. Data will be saved not encrypted |
| [[NO_ENCRYPTION_BEHAVIOR.NO_STORAGE]] | `2` | Don't use any storage, so no not encrypted data will be persisted |
14 changes: 8 additions & 6 deletions .docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

## Examples

- [Basic](01-Basic.md)
- [Reuse a store](02-Reuse-Store.md)
- [Self updated Storage](03-Self-Update-Storage.md)
- [Basic](Examples/01-Basic.md)
- [Reuse a store](Examples/02-Reuse-Store.md)
- [Self updated Storage](Examples/03-Self-Update-Storage.md)
- [Encrypt persisted data](Examples/04-Encrypted-Storage.md)

## How to

- [Add new storage](04-New-Storage.md)
- [Add an asynchronous storage](05-New-Async-Storage.md)
- [Store a class](06-Store-Classes.md)
- [Add new storage](How-To/01-New-Storage.md)
- [Add an asynchronous storage](How-To/02-New-Async-Storage.md)
- [Store a class](How-To/03-Store-Classes.md)
- [Disable warnings](How-To/04-Disable-Warnings.md)
15 changes: 15 additions & 0 deletions .docs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",

"include": ["src/*"],
"exclude": ["docs/*", "dist/*"],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"declarationDir": "../types",
"sourceMap": false
},
"files": [
"../src/index.ts"
]
}
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ module.exports = {
"@typescript-eslint/no-explicit-any": ["off"]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".ts"]
},
},
"import/extensions": [".js"],
}
}
Loading

0 comments on commit 5e643dc

Please sign in to comment.