Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[**]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4

# Standard at: https://github.com/felixge/node-style-guide
[**.js, **.json]
trim_trailing_whitespace = true
quote_type = single
curly_bracket_next_line = false
spaces_around_operators = true
space_after_control_statements = true
space_after_anonymous_functions = false
spaces_in_brackets = false

# No Standard. Please document a standard if different from .js
[**.yml, **.html, **.css]
trim_trailing_whitespace = true

# No standard. Please document a standard if different from .js
[**.md]

# Standard at:
[Makefile]

[package*]
indent_style = space
indent_size = 2
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
extends: 'expensify',
rules: {
// Overwriting this for now because web-e will conflict with this
'react/jsx-filename-extension': [1, {extensions: ['.js']}],
},
};
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# OSX
#
.DS_Store

# node.js
#
node_modules/
npm-debug.log
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# React-Native-Onyx
This is a persistent storage solution wrapped in a Pub/Sub library. In general that means:

- Onyx stores and retrieves data from persistent storage
- Data is stored as key/value pairs, where the value can be anything from a single piece of data to a complex object
- Collections of data are usually not stored as a single key (eg. an array with multiple objects), but as individual keys+ID (eg. `report_1234`, `report_4567`, etc.). Store collections as individual keys when a component will bind directly to one of those keys. For example: reports are stored as individual keys because `SidebarLink.js` binds to the individual report keys for each link. However, report actions are stored as an array of objects because nothing binds directly to a single report action.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not needed right now, but we might want to be more neutral with our examples if this is getting open sourced.

- Onyx allows other code to subscribe to changes in data, and then publishes change events whenever data is changed
- Anything needing to read Onyx data needs to:
1. Know what key the data is stored in (for web, you can find this by looking in the JS console > Application > local storage)
2. Subscribe to changes of the data for a particular key or set of keys. React components use `withOnyx()` and non-React libs use `Onyx.connect()`.
3. Get initialized with the current value of that key from persistent storage (Onyx does this by calling `setState()` or triggering the `callback` with the values currently on disk as part of the connection process)
- Subscribing to Onyx keys is done using a constant defined in `IONKEYS`. Each Onyx key represents either a collection of items or a specific entry in storage. For example, since all reports are stored as individual keys like `report_1234`, if code needs to know about all the reports (eg. display a list of them in the nav menu), then it would subscribe to the key `IONKEYS.COLLECTION.REPORT`.

### Storage Eviction

Different platforms come with varying storage capacities and Onyx has a way to gracefully fail when those storage limits are encountered. When Onyx fails to set or modify a key the following steps are taken:
1. Onyx looks at a list of recently accessed keys (access is defined as subscribed to or modified) and locates the key that was least recently accessed
2. It then deletes this key and retries the original operation

By default, Onyx will not evict anything from storage and will presume all keys are "unsafe" to remove unless explicitly told otherwise.

**To flag a key as safe for removal:**
- Add the key to the `safeEvictionKeys` option in `Onyx.init(options)`
- Implement `canEvict` in the Onyx config for each component subscribing to a key
- The key will only be deleted when all subscribers return `true` for `canEvict`

e.g.
```js
Onyx.init({
safeEvictionKeys: [IONKEYS.COLLECTION.REPORT_ACTIONS],
});
```

```js
export default withOnyx({
reportActions: {
key: ({reportID}) => `${IONKEYS.COLLECTION.REPORT_ACTIONS}${reportID}_`,
canEvict: props => !props.isActiveReport,
},
})(ReportActionsView);
```
5 changes: 5 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Onyx from './lib/Onyx';
import withOnyx from './lib/withOnyx';

export default Onyx;
export {withOnyx};
35 changes: 35 additions & 0 deletions lib/Logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Logging callback
let logger;

/**
* Register the logging callback
*
* @param {Function} callback
*/
function registerLogger(callback) {
logger = callback;
}

/**
* Send an alert message to the logger
*
* @param {String} message
*/
function logAlert(message) {
logger({message: `[Onyx] ${message}`, level: 'alert'});
}

/**
* Send an info message to the logger
*
* @param {String} message
*/
function logInfo(message) {
logger({message: `[Onyx] ${message}`, level: 'info'});
}

export {
registerLogger,
logInfo,
logAlert,
};
Loading