hermes-io 2.2.4 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -42
- package/package.json +1 -1
- package/examples/sneaker-store/. quokka +0 -25
- package/examples/sneaker-store/.editorconfig +0 -32
- package/examples/sneaker-store/.eslintrc.js +0 -24
- package/examples/sneaker-store/LICENSE +0 -21
- package/examples/sneaker-store/README.md +0 -1
- package/examples/sneaker-store/config-overrides.js +0 -35
- package/examples/sneaker-store/jsconfig.json +0 -20
- package/examples/sneaker-store/package-lock.json +0 -39849
- package/examples/sneaker-store/package.json +0 -48
- package/examples/sneaker-store/public/assets/images/addidas.webp +0 -0
- package/examples/sneaker-store/public/assets/images/jordan_3.webp +0 -0
- package/examples/sneaker-store/public/favicon.ico +0 -0
- package/examples/sneaker-store/public/index.html +0 -46
- package/examples/sneaker-store/public/logo192.png +0 -0
- package/examples/sneaker-store/public/logo512.png +0 -0
- package/examples/sneaker-store/public/manifest.json +0 -25
- package/examples/sneaker-store/public/reset.css +0 -48
- package/examples/sneaker-store/public/robots.txt +0 -3
- package/examples/sneaker-store/src/core/App.js +0 -72
- package/examples/sneaker-store/src/core/actions/Theme.js +0 -5
- package/examples/sneaker-store/src/core/actions/index.js +0 -3
- package/examples/sneaker-store/src/core/constants.js +0 -4
- package/examples/sneaker-store/src/core/contexts.js +0 -4
- package/examples/sneaker-store/src/core/factory/Actions.js +0 -8
- package/examples/sneaker-store/src/core/factory/Observer.js +0 -3
- package/examples/sneaker-store/src/core/observers/products.js +0 -6
- package/examples/sneaker-store/src/core/theme.js +0 -26
- package/examples/sneaker-store/src/core/views/components/Products/Products.js +0 -60
- package/examples/sneaker-store/src/core/views/components/Products/Styles.js +0 -112
- package/examples/sneaker-store/src/core/views/components/ShoppingCar/ShoppingCar.js +0 -56
- package/examples/sneaker-store/src/core/views/components/ShoppingCar/Styles.js +0 -59
- package/examples/sneaker-store/src/core/views/hooks/index.js +0 -0
- package/examples/sneaker-store/src/index.js +0 -10
package/README.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# hermes-io
|
|
2
|
-
A lightweight javascript library that allows communication between
|
|
2
|
+
A lightweight javascript library that allows communication between components by using the observer pattern and the hook api.
|
|
3
|
+
|
|
4
|
+
# Summary
|
|
5
|
+
- [Installation](#installation)
|
|
6
|
+
- [Get started](#get-started)
|
|
7
|
+
- [Observer](#observer)
|
|
8
|
+
- [Context](#context)
|
|
9
|
+
- [useObserver](#useobserver-hook)
|
|
10
|
+
- [notify](#notify)
|
|
11
|
+
- Devtools (TODO)
|
|
12
|
+
|
|
3
13
|
|
|
4
14
|
# Installation
|
|
5
15
|
```
|
|
@@ -7,63 +17,155 @@ npm i hermes-io --save
|
|
|
7
17
|
```
|
|
8
18
|
|
|
9
19
|
# Get started
|
|
10
|
-
|
|
11
|
-
|
|
20
|
+
`hermes-io` is a set of toolkits that combined allows communication between components let's explore every tool by following the `sneaker store example`:
|
|
21
|
+
|
|
22
|
+
# Observer
|
|
23
|
+
`hermes-io` provide an `Observer` class to create instances that can be `subscribable` that means many subscribers can listen for notifications on the instance by using the method `subscribe`, check the following example:
|
|
24
|
+
|
|
25
|
+
We are exporting an `object` with two instances of the class `Observer` each key of the object has invidual propuses one for handle notifications about `add` a product and the other for `remove` a product.
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// observers/products.js
|
|
29
|
+
import { Observer } from "hermes-io";
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
add: new Observer(),
|
|
33
|
+
remove: new Observer(),
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
# Context
|
|
38
|
+
`NOTICE` this concept has nothing to do with the `react context api`.
|
|
39
|
+
|
|
40
|
+
`hermes-io` provide a `Context` class to create instances that can be used to create `notification context` that means that only notification
|
|
41
|
+
submited on on specific context will be listened otherwise will be ignored, you can think on this like a `whitelist` let's analyze the following example:
|
|
42
|
+
|
|
43
|
+
In our sneaker store we have a `product list` and a `shopping car` the user can `add` a `product` to the `shopping car`
|
|
44
|
+
and also can `remove` a `product`, in both cases the one component can talk to the other by using `notifications`
|
|
45
|
+
on one specific observer and update the `ui`, this leads us to any part of the code with access to the observers can trigger `unexpected behaviors`,
|
|
46
|
+
there is when the concept of a `context` comes in, the context constrains the observer by telling which `notifications` must listen.
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import { Context } from 'hermes-io';
|
|
50
|
+
|
|
51
|
+
export const products = new Context('Product');
|
|
52
|
+
export const shoppingCar = new Context('ShoppingCar');
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
const sneakerList = [
|
|
58
|
+
{
|
|
59
|
+
id: '1',
|
|
60
|
+
name: 'Jordan',
|
|
61
|
+
image: '/assets/images/jordan_3.webp',
|
|
62
|
+
description: 'Air Jordan 3 Retro OG',
|
|
63
|
+
price: '250'
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: '2',
|
|
67
|
+
image: '/assets/images/addidas.webp',
|
|
68
|
+
description: 'Bad Bunny Forum Buckle Low sneakers',
|
|
69
|
+
name: 'Adidas Forum',
|
|
70
|
+
price: '200'
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: '3',
|
|
74
|
+
image: '/assets/images/addidas.webp',
|
|
75
|
+
description: 'Bad Bunny Forum Buckle Low sneakers',
|
|
76
|
+
name: 'Adidas Forum',
|
|
77
|
+
price: '200'
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
const productsStore = new Map();
|
|
82
|
+
productsStore.set('collection', sneakerList);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
# useObserver (hook)
|
|
86
|
+
`hermes-io` provide a `react custom hook` to integrate `Observer` with `Context`, this hook can be used to subscribe listeners and receive `notifications` under cetains contrains provided by the `notification context`, let's analize this in detail.
|
|
87
|
+
|
|
88
|
+
| key | value | required | description |
|
|
89
|
+
|----------|-------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
90
|
+
| observer | Observer instance | true | An instance of the class Observer |
|
|
91
|
+
| listener | Function | true | A standar javascript function |
|
|
92
|
+
| contexts | Context[] | true | An array of instances of the class Context, when a notification comes and is not signed with any of the contexts in the array the listener never will be called |
|
|
93
|
+
|
|
12
94
|
|
|
13
95
|
```javascript
|
|
14
|
-
|
|
15
|
-
export const AddProductObserver = new Observer();
|
|
16
|
-
export const RemoveProductObserver = new Observer();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// App.js
|
|
20
|
-
import { useState } from 'react';
|
|
21
|
-
import { useObserver, Observer } from 'hermes-io';
|
|
22
|
-
import { RemoveProductObserver, AddProductObserver } from './observers';
|
|
23
|
-
import { Products } from './components/Products';
|
|
24
|
-
import { ShoppingCar } from './components/ShoppingCar';
|
|
25
|
-
|
|
26
|
-
export const App = (props = {}) => {
|
|
27
|
-
const [productsToBy, setProductsToBy] = useState([]);
|
|
28
|
-
const productsStore = useProductStore(); // get products from some store
|
|
29
|
-
const products = productsStore.get();
|
|
96
|
+
import { useObserver } from "hermes-io";
|
|
30
97
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
98
|
+
useObserver({
|
|
99
|
+
observer: ProductsObservers.add,
|
|
100
|
+
listener: handleAddProduct,
|
|
101
|
+
contexts: [contexts.products],
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
import React, { useState } from "react";
|
|
107
|
+
import Products from "./components/Products/Products"
|
|
108
|
+
import ShoppingCar from "./components/ShoppingCar/ShoppingCar";
|
|
109
|
+
import { useObserver } from "hermes-io";
|
|
110
|
+
import ProductsObservers from './observers/products';
|
|
111
|
+
import theme from '@theme';
|
|
112
|
+
import * as contexts from './contexts';
|
|
113
|
+
|
|
114
|
+
const filterSelectes = (collection) => collection.filter((item) => item.selected); //filter selectes products
|
|
115
|
+
|
|
116
|
+
function App() {
|
|
117
|
+
const [products, setProducts] = useState(ProductsStore.get('collection'));
|
|
118
|
+
|
|
119
|
+
const handleRemoveProduct = ({ value: product = {} }) => {
|
|
120
|
+
product.selected = false;
|
|
121
|
+
setProducts([...ProductsStore.get('collection')]);
|
|
35
122
|
};
|
|
36
123
|
|
|
37
|
-
const handleAddProduct = (product = {}) => {
|
|
38
|
-
|
|
39
|
-
|
|
124
|
+
const handleAddProduct = ({ value: product = {} }) => {
|
|
125
|
+
product.selected = true;
|
|
126
|
+
setProducts([...ProductsStore.get('collection')]);
|
|
40
127
|
};
|
|
41
128
|
|
|
42
129
|
useObserver({
|
|
43
|
-
observer:
|
|
130
|
+
observer: ProductsObservers.add,
|
|
44
131
|
listener: handleAddProduct,
|
|
45
|
-
|
|
132
|
+
contexts: [contexts.products],
|
|
46
133
|
});
|
|
47
134
|
|
|
48
135
|
useObserver({
|
|
49
|
-
observer:
|
|
136
|
+
observer: ProductsObservers.remove,
|
|
50
137
|
listener: handleRemoveProduct,
|
|
51
|
-
|
|
138
|
+
contexts: [contexts.shoppingCar, contexts.products],
|
|
52
139
|
});
|
|
53
|
-
|
|
54
|
-
return <div>
|
|
55
|
-
<Products data={products} />
|
|
56
|
-
<ShoppingCar data={productsToBy}/>
|
|
57
|
-
</div>
|
|
58
|
-
};
|
|
59
140
|
|
|
141
|
+
return (
|
|
142
|
+
<>
|
|
143
|
+
<ShoppingCar data={filterSelectes(products)} />
|
|
144
|
+
<Products data={products} />
|
|
145
|
+
</>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
60
148
|
|
|
149
|
+
export default App;
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
# Notify
|
|
153
|
+
Is a method that allows sending notifications to the `subscribers` of a specific `observer` signed with a `context` that way we create a `notification context`, let's see this in details:
|
|
154
|
+
|
|
155
|
+
| key | value | required | description |
|
|
156
|
+
|---------|---------|----------|-----------------------------------|
|
|
157
|
+
| value | any | true | Payload with business information |
|
|
158
|
+
| context | context | true | A context instance |
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
61
162
|
// ShoppingCar.js
|
|
62
|
-
import
|
|
163
|
+
import ProductsObservers from './observers/products';
|
|
164
|
+
import * as contexts from '../contexts';
|
|
63
165
|
|
|
64
166
|
export const ShoppingCar = (props = {}) => {
|
|
65
167
|
const handleRemoveProduct = (product = {}) => {
|
|
66
|
-
|
|
168
|
+
ProductsObservers.remove.notify({ value: product, context: contexts.shoppingCar });
|
|
67
169
|
};
|
|
68
170
|
return <div>
|
|
69
171
|
<ul>
|
|
@@ -80,15 +182,17 @@ export const ShoppingCar = (props = {}) => {
|
|
|
80
182
|
</ul>
|
|
81
183
|
</div>
|
|
82
184
|
};
|
|
83
|
-
|
|
185
|
+
```
|
|
186
|
+
```javascript
|
|
84
187
|
// Products.js
|
|
85
|
-
import
|
|
188
|
+
import ProductsObservers from './observers/products';
|
|
189
|
+
import * as contexts from '../contexts';
|
|
86
190
|
|
|
87
191
|
export const Products = (props = {}) => {
|
|
88
192
|
const { data = [] } = props;
|
|
89
193
|
|
|
90
194
|
const handleAddProduct = (product = {}) => {
|
|
91
|
-
|
|
195
|
+
ProductsObservers.add.notify({ value: product, context: contexts.products });
|
|
92
196
|
};
|
|
93
197
|
|
|
94
198
|
return <ul>
|
|
@@ -104,7 +208,6 @@ export const Products = (props = {}) => {
|
|
|
104
208
|
}
|
|
105
209
|
</ul>
|
|
106
210
|
};
|
|
107
|
-
|
|
108
211
|
```
|
|
109
212
|
|
|
110
213
|
|
package/package.json
CHANGED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"babel": {
|
|
3
|
-
"presets": [
|
|
4
|
-
"react-app"
|
|
5
|
-
]
|
|
6
|
-
},
|
|
7
|
-
"plugins": [
|
|
8
|
-
"alias-quokka-plugin",
|
|
9
|
-
"jsdom-quokka-plugin"
|
|
10
|
-
],
|
|
11
|
-
"alias": {
|
|
12
|
-
"@core": "./src/core",
|
|
13
|
-
"@components": "./src/core/components",
|
|
14
|
-
"@contexts": "./src/core/contexts",
|
|
15
|
-
"@factory": "./src/core/factory",
|
|
16
|
-
"@hooks": "./src/core/hooks",
|
|
17
|
-
"@utils": "./src/core/utils",
|
|
18
|
-
"@libs": "./src/libs",
|
|
19
|
-
"@constants": "./src/core/constants",
|
|
20
|
-
"@translations": "./src/core/translations",
|
|
21
|
-
"@theme": "./src/core/theme",
|
|
22
|
-
"@routes": "./src/core/routes"
|
|
23
|
-
},
|
|
24
|
-
"node": "~/.nvm/versions/node/v16.18.1/bin/node"
|
|
25
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
-
|
|
3
|
-
# top-most EditorConfig file
|
|
4
|
-
root = true
|
|
5
|
-
|
|
6
|
-
# Unix-style newlines with a newline ending every file
|
|
7
|
-
[*]
|
|
8
|
-
end_of_line = lf
|
|
9
|
-
insert_final_newline = true
|
|
10
|
-
|
|
11
|
-
# Matches multiple files with brace expansion notation
|
|
12
|
-
# Set default charset
|
|
13
|
-
[*.{js,py}]
|
|
14
|
-
charset = utf-8
|
|
15
|
-
|
|
16
|
-
# 4 space indentation
|
|
17
|
-
[*.py]
|
|
18
|
-
indent_style = space
|
|
19
|
-
indent_size = 4
|
|
20
|
-
|
|
21
|
-
# Tab indentation (no size specified)
|
|
22
|
-
[Makefile]
|
|
23
|
-
indent_style = tab
|
|
24
|
-
|
|
25
|
-
# Indentation override for all JS under lib directory
|
|
26
|
-
[*.js]
|
|
27
|
-
indent_style = space
|
|
28
|
-
indent_size = 2
|
|
29
|
-
|
|
30
|
-
[{package.json,.travis.yml}]
|
|
31
|
-
indent_style = space
|
|
32
|
-
indent_size = 2
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
"env": {
|
|
3
|
-
"browser": true,
|
|
4
|
-
"es2021": true
|
|
5
|
-
},
|
|
6
|
-
"extends": [
|
|
7
|
-
"eslint:recommended",
|
|
8
|
-
"plugin:react/recommended"
|
|
9
|
-
],
|
|
10
|
-
"overrides": [
|
|
11
|
-
],
|
|
12
|
-
"parserOptions": {
|
|
13
|
-
"ecmaVersion": "latest",
|
|
14
|
-
"sourceType": "module"
|
|
15
|
-
},
|
|
16
|
-
"plugins": [
|
|
17
|
-
"react"
|
|
18
|
-
],
|
|
19
|
-
"rules": {
|
|
20
|
-
"react/prop-types": "off",
|
|
21
|
-
"no-unused-vars": 0,
|
|
22
|
-
"react/display-name": 0
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2022 Esneyder Amin
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# atomic-client
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const path = require("path");
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
webpack: function (config) {
|
|
5
|
-
config.devtool = "source-map";
|
|
6
|
-
config.resolve = {
|
|
7
|
-
extensions: [".js", ".html"],
|
|
8
|
-
alias: {
|
|
9
|
-
"@actions": path.resolve(__dirname, "src/core/actions"),
|
|
10
|
-
"@core": path.resolve(__dirname, "src/core"),
|
|
11
|
-
"@views": path.resolve(__dirname, "src/core/views"),
|
|
12
|
-
"@components": path.resolve(__dirname, "src/core/views/components"),
|
|
13
|
-
"@factory": path.resolve(__dirname, "src/core/factory"),
|
|
14
|
-
"@hooks": path.resolve(__dirname, "src/core/views/hooks"),
|
|
15
|
-
"@constants": path.resolve(__dirname, "src/core/constants"),
|
|
16
|
-
"@contexts": path.resolve(__dirname, "src/core/contexts"),
|
|
17
|
-
"@observers": path.resolve(__dirname, "src/core/observers"),
|
|
18
|
-
"@theme": path.resolve(__dirname, "src/core/theme"),
|
|
19
|
-
"@src": path.resolve(__dirname, "src"),
|
|
20
|
-
"hermes-io": path.resolve(__dirname, "../../"),
|
|
21
|
-
"react": path.resolve(__dirname, "../../node_modules/react"),
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
config.module.rules.push({
|
|
25
|
-
test: /\.js$/,
|
|
26
|
-
loader: "esbuild-loader",
|
|
27
|
-
options: {
|
|
28
|
-
loader: "jsx",
|
|
29
|
-
target: "es2020",
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
console.log(JSON.stringify(config));
|
|
33
|
-
return config;
|
|
34
|
-
},
|
|
35
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"baseUrl": ".",
|
|
4
|
-
"paths": {
|
|
5
|
-
"actions/*": ["src/core/actions/*"],
|
|
6
|
-
"@core/*": ["src/core/*"],
|
|
7
|
-
"@views/*": ["src/core/views/*"],
|
|
8
|
-
"@components/*": ["src/core/views/components/*"],
|
|
9
|
-
"@factory/*": ["src/core/factory/*"],
|
|
10
|
-
"@hooks/*": ["src/core/views/hooks/*"],
|
|
11
|
-
"@constants": ["src/core/constants"],
|
|
12
|
-
"@observers/*": ["src/core/observers/*"],
|
|
13
|
-
"@contexts/*": ["src/core/contexts"],
|
|
14
|
-
"@src/*": ["src/*"],
|
|
15
|
-
"@hermes-io/*": ["../../*"],
|
|
16
|
-
"react": ["../../node_modules/react"]
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"exclude": ["node_modules"]
|
|
20
|
-
}
|