├── .editorconfig
├── .gitattributes
├── .gitignore
├── .pnp.cjs
├── .travis.yml
├── .vscode
├── extensions.json
└── settings.json
├── README.md
├── package-lock.json
├── package.json
└── packages
├── arkhamjs-devtools-extension
├── .eslintrc
├── .gitignore
├── LICENSE
├── README.md
├── jest.setup.js
├── package.json
├── src
│ ├── actions
│ │ ├── InspectorActions.ts
│ │ └── index.ts
│ ├── app.html
│ ├── app.tsx
│ ├── components
│ │ ├── ActionItem
│ │ │ └── ActionItem.tsx
│ │ ├── TabBar
│ │ │ └── TabBar.tsx
│ │ └── index.ts
│ ├── constants
│ │ ├── InspectorConstants.ts
│ │ └── index.ts
│ ├── contentScripts.ts
│ ├── devtoolsBackground.html
│ ├── devtoolsBackground.ts
│ ├── manifest.json
│ ├── types
│ │ └── inspector.ts
│ └── views
│ │ ├── ActionsView
│ │ └── ActionsView.tsx
│ │ ├── InfoView
│ │ └── InfoView.tsx
│ │ ├── InspectorView
│ │ └── InspectorView.tsx
│ │ ├── LayoutView
│ │ └── LayoutView.tsx
│ │ ├── StateView
│ │ └── StateView.tsx
│ │ └── index.ts
├── tsconfig.json
└── webpack.config.ts
├── arkhamjs-example-ts-react
├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── .vscode
│ ├── extensions.json
│ └── settings.json
├── LICENSE
├── README.md
├── lex.config.js
├── package.json
├── src
│ ├── actions
│ │ └── AppActions
│ │ │ ├── AppActions.test.ts
│ │ │ └── AppActions.ts
│ ├── app.css
│ ├── components
│ │ └── Icon
│ │ │ ├── Icon.test.tsx
│ │ │ ├── Icon.tsx
│ │ │ └── Icon.types.ts
│ ├── config
│ │ ├── config.types.ts
│ │ └── index.ts
│ ├── constants
│ │ └── AppConstants.ts
│ ├── errors
│ │ └── UserError.ts
│ ├── fonts
│ │ └── readme.txt
│ ├── icons
│ │ ├── pencil.svg
│ │ └── readme.txt
│ ├── img
│ │ ├── arkhamjs-logo.png
│ │ └── readme.txt
│ ├── index.html
│ ├── index.tsx
│ ├── services
│ │ ├── StringService.test.ts
│ │ └── StringService.ts
│ ├── stores
│ │ └── AppStore
│ │ │ ├── appStore.test.ts
│ │ │ ├── appStore.ts
│ │ │ └── appStore.types.ts
│ └── views
│ │ ├── AppView.test.tsx
│ │ ├── AppView.tsx
│ │ ├── HomeView.test.tsx
│ │ └── HomeView.tsx
└── tsconfig.json
├── arkhamjs-middleware-devtools
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── jest.setup.js
├── package.json
├── src
│ ├── index.ts
│ └── middleware
│ │ └── DevTools.ts
└── tsconfig.json
├── arkhamjs-middleware-logger
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── lex.config.js
├── package.json
├── src
│ ├── Logger
│ │ ├── Logger.test.ts
│ │ └── Logger.ts
│ ├── index.ts
│ └── types
│ │ └── main.ts
└── tsconfig.json
├── arkhamjs-middleware-redux
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── lex.config.js
├── package.json
├── src
│ ├── createArkhamStore.ts
│ ├── index.ts
│ ├── middleware
│ │ ├── ReduxMiddleware.ts
│ │ ├── arkhamMiddleware.test.ts
│ │ └── arkhamMiddleware.ts
│ └── types
│ │ └── main.ts
└── tsconfig.json
├── arkhamjs-storage-browser
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── lex.config.js
├── package.json
├── src
│ ├── BrowserStorage
│ │ ├── BrowserStorage.test.ts
│ │ └── BrowserStorage.ts
│ ├── index.ts
│ └── types
│ │ └── main.ts
└── tsconfig.json
├── arkhamjs-storage-native
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── lex.config.js
├── package.json
├── src
│ ├── NativeStorage
│ │ ├── NativeStorage.test.ts
│ │ ├── NativeStorage.ts
│ │ └── NativeStorage.types.ts
│ └── index.ts
└── tsconfig.json
├── arkhamjs-storage-node
├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── index.js
├── jest.setup.js
├── lex.config.js
├── package.json
├── src
│ ├── NodeStorage
│ │ ├── NodeStorage.test.ts
│ │ └── NodeStorage.ts
│ └── index.ts
└── tsconfig.json
├── arkhamjs-utils-react
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README
├── index.js
├── lex.config.js
├── package.json
├── src
│ ├── FluxContext.ts
│ ├── FluxProvider.test.tsx
│ ├── FluxProvider.tsx
│ ├── FluxProvider.types.ts
│ ├── ResizeObserver.d.ts
│ ├── index.ts
│ ├── useComponentSize.ts
│ ├── useFlux.ts
│ ├── useFluxDispatch.ts
│ ├── useFluxListener.ts
│ ├── useFluxState.ts
│ ├── useFluxValue.ts
│ ├── useRefSize.ts
│ ├── useState.ts
│ ├── useWindowSize.ts
│ └── useWindowSize.types.ts
└── tsconfig.json
└── arkhamjs
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── index.js
├── lex.config.js
├── package.json
├── src
├── Flux
│ ├── Flux.test.ts
│ ├── Flux.ts
│ └── Flux.types.ts
├── constants
│ └── ArkhamConstants.ts
└── index.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 |
7 | [*.{js,json,yml}]
8 | charset = utf-8
9 | indent_style = space
10 | indent_size = 2
11 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | /.yarn/** linguist-vendored
2 | /.yarn/releases/* binary
3 | /.yarn/plugins/**/* binary
4 | /.pnp.* binary linguist-generated
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | .DS_Store
3 | *.bash_profile
4 | *.log
5 |
6 | # node.js
7 | node_modules
8 |
9 | # Client Editor
10 | build
11 | .idea
12 |
13 | # App
14 | coverage
15 | lib
16 | docs
17 | tmp
18 |
19 | # Docusaurus
20 | lib/core/metadata.js
21 | lib/core/MetadataBlog.js
22 |
23 | website/translated_docs
24 | website/build/
25 | website/node_modules
26 | website/i18n/*
27 | /packages/arkhamjs-example-ts-react/dist
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "20"
4 | install:
5 | - npm install
6 | - lex versions
7 | script:
8 | - npm run lint
9 | - npm run build
10 | - npm run test
11 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "enabled": [
3 | "streetsidesoftware.code-spell-checker",
4 | "bierner.markdown-preview-github-styles",
5 | "DavidAnson.vscode-markdownlint",
6 | "ricard.postcss",
7 | "shinnn.stylelint"
8 | ],
9 | "recommendations": [
10 | "dbaeumer.vscode-eslint",
11 | "streetsidesoftware.code-spell-checker",
12 | "bierner.markdown-preview-github-styles",
13 | "DavidAnson.vscode-markdownlint",
14 | "ricard.postcss",
15 | "shinnn.stylelint",
16 | "flowtype.flow-for-vscode",
17 | "rbbit.typescript-hero",
18 | "Equinusocio.vsc-material-theme",
19 | "PKief.material-icon-theme"
20 | ]
21 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": ["arkham", "arkhamjs", "nitrogenlabs", "nlabs", "transpiler"],
3 | "css.validate": false,
4 | "editor.autoClosingBrackets": "never",
5 | "editor.detectIndentation": false,
6 | "editor.formatOnSave": true,
7 | "editor.rulers": [120],
8 | "editor.tabCompletion": "onlySnippets",
9 | "editor.tabSize": 2,
10 | "editor.wordWrap": "off",
11 | "editor.wordWrapColumn": 120,
12 | "editor.wrappingIndent": "indent",
13 | "emmet.includeLanguages": {
14 | "postcss": "css"
15 | },
16 | "emmet.syntaxProfiles": {
17 | "postcss": "css"
18 | },
19 | "eslint.codeActionsOnSave": true,
20 | "eslint.alwaysShowStatus": true,
21 | "eslint.enable": true,
22 | "eslint.validate": [
23 | "javascript",
24 | "javascriptreact",
25 | "typescript",
26 | "typescriptreact"
27 | ],
28 | "explorer.confirmDragAndDrop": false,
29 | "explorer.decorations.badges": false,
30 | "files.trimTrailingWhitespace": true,
31 | "flow.runOnAllFiles": true,
32 | "html.format.indentInnerHtml": true,
33 | "html.format.indentHandlebars": true,
34 | "html.format.extraLiners": "",
35 | "html.format.enable": false,
36 | "html.format.endWithNewline": true,
37 | "javascript.format.enable": false,
38 | "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
39 | "javascript.format.insertSpaceAfterKeywordsInControlFlowStatements": false,
40 | "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
41 | "javascript.validate.enable": false,
42 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": false,
43 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
44 | "typescriptHero.imports.insertSpaceBeforeAndAfterImportBraces": false,
45 | "typescriptHero.imports.multiLineTrailingComma": false,
46 | "typescriptHero.imports.multiLineWrapThreshold": 120,
47 | "typescriptHero.imports.organizeOnSave": true,
48 | "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
49 | "tslint.enable": true,
50 | "tslint.packageManager": "npm",
51 | "tslint.autoFixOnSave": true,
52 | "tslint.configFile": "./tslint.json",
53 | "editor.codeActionsOnSave": {
54 | "source.fixAll.eslint": "explicit"
55 | },
56 | "editor.autoClosingQuotes": "never",
57 | "editor.autoSurround": "never",
58 | "eslint.workingDirectories": ["./node_modules/@nlabs/lex/"]
59 | }
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ArkhamJS
2 |
3 |
4 |
5 | [](https://lernajs.io/)
6 | [](https://www.npmjs.com/package/arkhamjs)
7 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
8 | [](https://github.com/ellerbrock/typescript-badges/)
9 | [](http://opensource.org/licenses/MIT)
10 | [](https://discord.gg/Ttgev58)
11 |
12 | ## Flux Framework
13 |
14 | ArkhamJS is a lightweight framework that can accommodate a project of any size, small or large. From small start-up ideas to large enterprise projects. A simple, flexible framework. Consisting of a singular state tree with a unidirectional data flow.
15 |
16 | ## Lightweight
17 |
18 | The framework is small. The bulk of your app should lay within your code, not the framework. While larger frameworks come with lots of "magic", they become very limited when new features arise within your project.
19 |
20 | ## Typescript
21 |
22 | Compatible with typescript. Definitions are included to support your Typescript project.
23 |
24 | ## Single Store
25 |
26 | All data is stored within a single store. The data can be accessed through all your views and components. Data is organized into multiple stores within the single store.
27 |
28 | ## Immutability
29 |
30 | To prevent object referencing, we use immutable objects. When the state changes, the state's property is not the only item that is changed, the item it references is also updated. To prevent passing around an object between different scopes, immutable objects give your data a one way update path. You may also have returned values converted into ImmutableJS objects.
31 |
32 | ## Debugger
33 |
34 | The most important factor in choosing a framework is how easy it is to build with it. And with building comes debugging. A state debugger can be added with the middleware, [@nlabs/arkhamjs-middleware-logger](https://github.com/nitrogenlabs/arkhamjs-middleware-logger). When turned on, it will display any actions and state changes that come through the framework. Making the previous and next state visible to the developer. Great way to make your data transparent! Supported browsers: Chrome, Firefox, and Safari.
35 |
36 | ## Cache Storage
37 |
38 | An app state is clears after a browser refresh. Keeping the state after a reload can be very useful when requiring a persistent state.
39 |
40 | If you plan to persist data, you will need to add a storage to the framework:
41 |
42 | - React [@nlabs/arkhamjs-storage-browser](https://github.com/nitrogenlabs/arkhamjs-storage-browser)
43 | - React Native [@nlabs/arkhamjs-storage-native](https://github.com/nitrogenlabs/arkhamjs-storage-native)
44 | - NodeJS [@nlabs/arkhamjs-storage-node](https://github.com/nitrogenlabs/arkhamjs-storage-node)
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "arkhamjs",
3 | "scripts": {
4 | "build": "npm run build --workspaces",
5 | "lint": "npm run lint --workspaces",
6 | "clean": "npm run clean --workspaces && npm run clean:root",
7 | "clean:root": "rm -rf *.log node_modules *.lock package-lock.json",
8 | "publish:major": "npm run publish:major --workspaces && npm run publish:tags",
9 | "publish:minor": "npm run publish:minor --workspaces && npm run publish:tags",
10 | "publish:patch": "npm run publish:patch --workspaces && npm run publish:tags",
11 | "publish:tags": "git push --tags && git push origin HEAD",
12 | "test": "jest",
13 | "update": "npm run update --workspaces"
14 | },
15 | "devDependencies": {
16 | "@nlabs/lex": "^1.21.2",
17 | "npm-check-updates": "^17.1.14"
18 | },
19 | "workspaces": [
20 | "packages/arkhamjs",
21 | "packages/arkhamjs-middleware-logger",
22 | "packages/arkhamjs-middleware-redux",
23 | "packages/arkhamjs-storage-browser",
24 | "packages/arkhamjs-storage-native",
25 | "packages/arkhamjs-storage-node",
26 | "packages/arkhamjs-utils-react"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript"
3 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Nitrogen Labs
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/README.md:
--------------------------------------------------------------------------------
1 | # arkhamjs-devtools-extension
2 |
3 | ArkhamJS Development Tools Browser Extension
4 |
5 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
6 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
7 | [](https://github.com/ellerbrock/typescript-badges/)
8 | [](http://opensource.org/licenses/MIT)
9 | [](https://discord.gg/Ttgev58)
10 |
11 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/jest.setup.js:
--------------------------------------------------------------------------------
1 | global.requestAnimationFrame = function(callback) {
2 | setTimeout(callback, 0);
3 | };
4 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-devtools-extension",
3 | "version": "3.11.8",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "ArkhamJS DevTools Extension",
8 | "license": "MIT",
9 | "main": "index.js",
10 | "types": "./dist/index.d.ts",
11 | "keywords": [
12 | "arkhamjs",
13 | "chrome",
14 | "devtools",
15 | "firefox",
16 | "nitrogenlabs",
17 | "react"
18 | ],
19 | "author": {
20 | "name": "Giraldo Rosales",
21 | "email": "giraldo@nitrogenlabs.com",
22 | "url": "http://nitrogenlabs.com"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "nitrogenlabs/arkhamjs.git"
27 | },
28 | "homepage": "https://arkhamjs.io",
29 | "bugs": {
30 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
31 | },
32 | "scripts": {
33 | "clean": "lex clean",
34 | "compile": "NODE_ENV=production tsc && webpack",
35 | "development": "NODE_ENV=development webpack -w",
36 | "lint": "eslint ./src --ext .ts,.tsx",
37 | "prepublishOnly": "npm run build",
38 | "publish:major": "npm version major && npm publish",
39 | "publish:minor": "npm version minor && npm publish",
40 | "publish:patch": "npm version patch && npm publish",
41 | "pretest": "npm run lint",
42 | "start": "npm run development",
43 | "test": "",
44 | "update": "npm-check-updates --interactive"
45 | },
46 | "dependencies": {
47 | "@nlabs/arkhamjs": "^3.11.8",
48 | "@nlabs/arkhamjs-storage-browser": "^3.11.8",
49 | "@nlabs/arkhamjs-views-react": "^1.2.2",
50 | "history": "^4.7.2",
51 | "lodash": "^4.17.20",
52 | "rc-tabs": "^9.4.1",
53 | "react": "^19.0.0",
54 | "react-dom": "^19.0.0",
55 | "react-router": "^4.2.0",
56 | "react-router-dom": "^4.2.2"
57 | },
58 | "devDependencies": {
59 | "@types/chrome": "^0.0.73",
60 | "@types/jest": "^23.3.2",
61 | "@types/node": "^10.9.4",
62 | "@types/react": "^16.4.14",
63 | "@types/react-dom": "^16.0.7",
64 | "@types/react-router-dom": "^4.3.0",
65 | "clean-webpack-plugin": "^0.1.19",
66 | "copy-webpack-plugin": "^4.5.1",
67 | "del": "^3.0.0",
68 | "eslint": "^5.5.0",
69 | "eslint-config-styleguidejs": "^0.7.9",
70 | "exports-loader": "^0.7.0",
71 | "file-loader": "^2.0.0",
72 | "fs": "0.0.2",
73 | "html-webpack-plugin": "^3.2.0",
74 | "imports-loader": "^0.8.0",
75 | "json-d-ts": "^1.0.1",
76 | "react-addons-test-utils": "^15.6.2",
77 | "react-test-renderer": "^16.5.0",
78 | "react-transform-catch-errors": "^1.0.2",
79 | "react-transform-hmr": "^1.0.4",
80 | "redbox-react": "^1.5.0",
81 | "regenerator-runtime": "^0.12.1",
82 | "source-map-loader": "^0.2.4",
83 | "source-map-support": "^0.5.9",
84 | "typescript": "^3.0.3",
85 | "webpack": "^4.18.0",
86 | "webpack-cli": "^3.1.0",
87 | "webpack-dev-middleware": "^3.3.0",
88 | "webpack-hot-middleware": "^2.23.1"
89 | },
90 | "gitHead": "ca196f147316f6590794c49f53965ab6770b2dd6"
91 | }
92 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/actions/InspectorActions.ts:
--------------------------------------------------------------------------------
1 | import {FluxAction} from '@nlabs/arkhamjs';
2 | import {createBrowserHistory, History} from 'history';
3 |
4 | export class InspectorActions {
5 | static dispatch(action: FluxAction): void {
6 | this.message({
7 | _arkhamCall: {
8 | args: [action],
9 | method: 'dispatch'
10 | }
11 | });
12 | }
13 |
14 | static goto(routePath: string): History {
15 | const history = createBrowserHistory();
16 | history.push(`/${routePath}`);
17 | return history;
18 | }
19 |
20 | static onDispatch(data): void {
21 | const {action, duration, state, stack} = data;
22 | const formatDuration: string = InspectorActions.msToTime(duration);
23 | console.log('InspectorActions::action', action);
24 | console.log('InspectorActions::state', state);
25 | console.log('InspectorActions::stack', stack);
26 | console.log('InspectorActions::formatDuration', formatDuration);
27 | }
28 |
29 | static onInfo(data): void {
30 | console.log('InspectorActions::onInfo::data', data);
31 | }
32 |
33 | static message(data): void {
34 | window.postMessage(data, '*');
35 | }
36 |
37 | static msToTime(duration: number): string {
38 | const milliseconds: number = Math.floor(duration % 1000);
39 | const seconds: number = Math.floor((duration / 1000) % 60);
40 | const minutes: number = Math.floor((duration / (1000 * 60)) % 60);
41 | const hours: number = Math.floor((duration / (1000 * 60 * 60)) % 24);
42 |
43 | const formatHours: string = (hours < 10) ? `0${hours}` : hours.toString();
44 | const formatMinutes: string = (minutes < 10) ? `0${minutes}` : minutes.toString();
45 | const formatSeconds: string = (seconds < 10) ? `0${seconds}` : seconds.toString();
46 |
47 | return `${formatHours}:${formatMinutes}:${formatSeconds}.${milliseconds.toString()}`;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/actions/index.ts:
--------------------------------------------------------------------------------
1 | export {InspectorActions} from './InspectorActions';
2 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ArkhamJS DevTools
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/app.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 |
4 | import {InspectorView} from './views/InspectorView/InspectorView';
5 |
6 | const target = document.getElementById('app');
7 |
8 | console.log('target', target);
9 | // Render initial inspector panel
10 | ReactDOM.render(, target);
11 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/components/ActionItem/ActionItem.tsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitrogenlabs/arkhamjs/9428e95a52f4a7323609da35ad9c29223eb8eafa/packages/arkhamjs-devtools-extension/src/components/ActionItem/ActionItem.tsx
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/components/TabBar/TabBar.tsx:
--------------------------------------------------------------------------------
1 | import Tabs, {TabPane} from 'rc-tabs';
2 | import ScrollableInkTabBar from 'rc-tabs/lib/ScrollableInkTabBar';
3 | import TabContent from 'rc-tabs/lib/TabContent';
4 | import * as React from 'react';
5 |
6 | import {InspectorActions} from '../../actions';
7 | import {ActionsView, InfoView, StateView} from '../../views';
8 |
9 | export class TabBar extends React.Component {
10 | data;
11 |
12 | constructor(props) {
13 | super(props);
14 |
15 | // Set tab data
16 | this.data = [
17 | {component: , key: 'actions'},
18 | {component: , key: 'stateTree'},
19 | {component: , key: 'appDetails'}
20 | ];
21 |
22 | // Methods
23 | this.onSelect = this.onSelect.bind(this);
24 | }
25 |
26 | onSelect(key): void {
27 | console.log('key', key);
28 | InspectorActions.goto(key);
29 | }
30 |
31 | render(): JSX.Element {
32 | let activeKey: string = 'actions';
33 | const {children} = this.props;
34 |
35 | if(children) {
36 | this.data.forEach((dataItem) => {
37 | const typeProp: string = 'type';
38 | if(dataItem.component.type === children[typeProp]) {
39 | // for demo, better immutable
40 | dataItem.component = children;
41 | activeKey = dataItem.key;
42 | }
43 | });
44 | }
45 |
46 | const tabs: TabPane[] = this.data.map(
47 | (dataItem) => {dataItem.component}
48 | );
49 |
50 | return (
51 | }
55 | renderTabContent={() => }>
56 | {tabs}
57 |
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export {TabBar} from './TabBar/TabBar';
2 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/constants/InspectorConstants.ts:
--------------------------------------------------------------------------------
1 | export class InspectorConstants {
2 | static DISPATCH: string = 'INPECTOR_DISPATCH';
3 | }
4 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/constants/index.ts:
--------------------------------------------------------------------------------
1 | export {InspectorConstants} from './InspectorConstants';
2 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/contentScripts.ts:
--------------------------------------------------------------------------------
1 | // chrome.runtime.onInstalled.addListener(function() {
2 | // // Replace all rules ...
3 | // chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
4 | // // With a new rule ...
5 | // chrome.declarativeContent.onPageChanged.addRules([
6 | // {
7 | // // That fires when a page's URL contains a 'g' ...
8 | // conditions: [
9 | // new chrome.declarativeContent.PageStateMatcher({
10 | // pageUrl: { urlContains: 'g' },
11 | // })
12 | // ],
13 | // // And shows the extension's page action.
14 | // actions: [ new chrome.declarativeContent.ShowPageAction() ]
15 | // }
16 | // ]);
17 | // });
18 | // });
19 | // const win = (window);
20 |
21 | // console.log('win', win);
22 |
23 | // win.addEventListener('load', loadEvent => {
24 | // let window = loadEvent.currentTarget;
25 | // console.log('window', window);
26 | // console.log('loadEvent', loadEvent);
27 | // window.document.title = 'You changed me!';
28 | // });
29 |
30 | // win.addEventListener('ARKHAMJS_INIT', () => {
31 | // const Flux = win.arkhamjs;
32 |
33 | // console.log('ArkhamJS DevTools', Flux.getState());
34 |
35 | // Flux.on('APP_UPDATE_CONTENT', () => {
36 | // console.log('ArkhamJS::Content', Flux.getState());
37 | // });
38 | // });
39 |
40 | // chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
41 | // if(request.cmd == "any command") {
42 | // sendResponse({result: "any response from background"});
43 | // } else {
44 | // sendResponse({result: "error", message: `Invalid 'cmd'`});
45 | // }
46 | // // Note: Returning true is required here!
47 | // // ref: http://stackoverflow.com/questions/20077487/chrome-extension-message-passing-response-not-sent
48 | // return true;
49 | // });
50 | console.log('load::bg');
51 |
52 | window.addEventListener('load', () => {
53 | window.postMessage({_arkhamCall: {method: 'storeClasses'}}, '*');
54 | });
55 |
56 | // chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
57 | // // port.postMessage({greeting:"hello"});
58 | // console.log('chrome::onMessage::request', request);
59 | // });
60 | window.addEventListener('message', (event) => {
61 | const {data = {}, source} = event;
62 |
63 | // We only accept messages from ourselves
64 | if(source !== window) {
65 | return;
66 | }
67 |
68 | chrome.runtime.sendMessage(data);
69 | });
70 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/devtoolsBackground.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Background
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/devtoolsBackground.ts:
--------------------------------------------------------------------------------
1 | // import {Flux} from '@nlabs/arkhamjs';
2 | const {devtools: {panels}} = chrome || {};
3 |
4 | // Create panel
5 | if(panels) {
6 | panels.create('ArkhamJS', null, 'app.html', () => {});
7 | }
8 | console.log('load::devtoolsbg');
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ArkhamJS DevTools",
3 | "description": "ArkhamJS development tool used to debug apps",
4 | "devtools_page": "devtoolsBackground.html",
5 | "version": "0.1.0",
6 | "manifest_version": 2,
7 | "minimum_chrome_version": "50",
8 | "permissions": [
9 | "storage",
10 | "tabs",
11 | "background",
12 | "activeTab",
13 | ""
14 | ],
15 | "content_scripts": [
16 | {
17 | "matches": [
18 | ""
19 | ],
20 | "js": [
21 | "contentScripts.js"
22 | ]
23 | }
24 | ],
25 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
26 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/types/inspector.ts:
--------------------------------------------------------------------------------
1 | import {FluxAction} from '@nlabs/arkhamjs';
2 |
3 | export interface InspectorStackType {
4 | readonly columnNumber: number;
5 | readonly fileName: string;
6 | readonly functionName: string;
7 | readonly lineNumber: number;
8 | readonly source: string;
9 | }
10 |
11 | export interface InspectorDispatchType {
12 | readonly action: FluxAction;
13 | readonly duration: number;
14 | readonly state: any;
15 | readonly stack: InspectorStackType[];
16 | }
17 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/views/ActionsView/ActionsView.tsx:
--------------------------------------------------------------------------------
1 | import {ViewBase, ViewProps} from '@nlabs/arkhamjs-views-react';
2 | import * as React from 'react';
3 |
4 | export interface ActionsViewProps extends ViewProps {
5 | }
6 |
7 | export class ActionsView extends ViewBase {
8 | render(): JSX.Element {
9 | return (
10 | Actions
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/views/InfoView/InfoView.tsx:
--------------------------------------------------------------------------------
1 | import {ViewBase, ViewProps} from '@nlabs/arkhamjs-views-react';
2 | import * as React from 'react';
3 |
4 | export interface InfoViewProps extends ViewProps {
5 | }
6 |
7 | export class InfoView extends ViewBase {
8 | render(): JSX.Element {
9 | return (
10 | Info
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/views/InspectorView/InspectorView.tsx:
--------------------------------------------------------------------------------
1 | import {Flux, FluxOptions} from '@nlabs/arkhamjs';
2 | import {BrowserStorage} from '@nlabs/arkhamjs-storage-browser';
3 | import * as React from 'react';
4 | import {HashRouter, Route} from 'react-router-dom';
5 |
6 | import {InspectorActions} from '../../actions';
7 | import {TabBar} from '../../components';
8 | import {InspectorDispatchType} from '../../types/inspector';
9 | import {ActionsView} from '../ActionsView/ActionsView';
10 | import {InfoView} from '../InfoView/InfoView';
11 | import {StateView} from '../StateView/StateView';
12 |
13 | export class InspectorView extends React.Component<{}, {}> {
14 | constructor(props) {
15 | super(props);
16 |
17 | // ArkhamJS Configuration
18 | const storage = new BrowserStorage({type: 'session'});
19 | Flux.init({
20 | storage
21 | });
22 |
23 | // Methods
24 | this.onData = this.onData.bind(this);
25 | }
26 |
27 | componentDidMount(): void {
28 | chrome.runtime.onMessage.addListener(this.onData);
29 | }
30 |
31 | componentWillUnmount(): void {
32 | chrome.runtime.onMessage.removeListener(this.onData);
33 | }
34 |
35 | onData(eventData): void {
36 | console.log('app::message::eventData', eventData);
37 | const {_arkhamDispatch, _arkhamInfo} = eventData;
38 |
39 | if(_arkhamDispatch) {
40 | const dispatchData: InspectorDispatchType = JSON.parse(_arkhamDispatch);
41 | InspectorActions.onDispatch(dispatchData);
42 | }
43 |
44 | if(_arkhamInfo) {
45 | const infoData: FluxOptions = JSON.parse(_arkhamInfo);
46 | InspectorActions.onInfo(infoData);
47 | }
48 | }
49 |
50 | render(): JSX.Element {
51 | return (
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | );
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/views/LayoutView/LayoutView.tsx:
--------------------------------------------------------------------------------
1 | import {ViewBase, ViewContainer, ViewProps} from '@nlabs/arkhamjs-views-react';
2 | import * as React from 'react';
3 | import {RouteProps} from 'react-router';
4 |
5 | import {ActionsView, InfoView, StateView} from '../../views';
6 |
7 | export interface LayoutProps extends ViewProps {
8 | readonly children?: React.ReactNode;
9 | }
10 |
11 | export class LayoutView extends ViewBase {
12 | routes: RouteProps[];
13 |
14 | constructor(props) {
15 | super(props);
16 | this.routes = [
17 | {component: ActionsView, path: '/'},
18 | {component: StateView, path: '/state'},
19 | {component: InfoView, path: '/info'}
20 | ];
21 | }
22 |
23 | render(): JSX.Element {
24 | return (
25 |
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/views/StateView/StateView.tsx:
--------------------------------------------------------------------------------
1 | import {ViewBase, ViewProps} from '@nlabs/arkhamjs-views-react';
2 | import * as React from 'react';
3 |
4 | export interface StateViewProps extends ViewProps {
5 | }
6 |
7 | export class StateView extends ViewBase {
8 | render(): JSX.Element {
9 | return (
10 | State
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/src/views/index.ts:
--------------------------------------------------------------------------------
1 | export {ActionsView} from './ActionsView/ActionsView';
2 | export {InfoView} from './InfoView/InfoView';
3 | export {LayoutView} from './LayoutView/LayoutView';
4 | export {StateView} from './StateView/StateView';
5 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "./dist",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018"
23 | },
24 | "include": [
25 | "./src/**/*"
26 | ],
27 | "exclude": [
28 | "**/*.test.*",
29 | "./dist",
30 | "./node_modules",
31 | "./test"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/packages/arkhamjs-devtools-extension/webpack.config.ts:
--------------------------------------------------------------------------------
1 | import {CheckerPlugin} from 'awesome-typescript-loader';
2 | import * as path from 'path';
3 | import * as webpack from 'webpack';
4 | import * as CopyWebpackPlugin from 'copy-webpack-plugin';
5 | import * as HtmlWebpackPlugin from 'html-webpack-plugin';
6 | import * as CleanWebpackPlugin from 'clean-webpack-plugin';
7 | const {name, version} = require('./package.json');
8 |
9 | module.exports = {
10 | mode: 'production',
11 | devtool: process.env.NODE_ENV === 'development' ? 'cheap-module-eval-source-map' : null,
12 | entry: {
13 | app: './src/app.tsx',
14 | contentScripts: './src/contentScripts.ts',
15 | devToolsBackground: './src/devToolsBackground.ts'
16 | },
17 | output: {
18 | path: path.resolve(__dirname, 'lib'),
19 | filename: '[name].js'
20 | },
21 | resolve: {
22 | extensions: ['.ts', '.tsx', '.js'],
23 | modules: [path.resolve(__dirname, 'src'), 'node_modules']
24 | },
25 | plugins: [
26 | new CleanWebpackPlugin(['lib']),
27 | new webpack.DefinePlugin({
28 | 'process.env.NODE_ENV': process.env.NODE_ENV ? JSON.stringify(process.env.NODE_ENV) : 'development'
29 | }),
30 | new CheckerPlugin(),
31 | new CopyWebpackPlugin([{from: './src/*.+(json)', to: './', flatten: true}]),
32 | new HtmlWebpackPlugin({
33 | template: path.join(__dirname, 'src', 'app.html'),
34 | filename: 'app.html',
35 | chunks: ["app"]
36 | }),
37 | new HtmlWebpackPlugin({
38 | template: path.join(__dirname, 'src', 'devToolsBackground.html'),
39 | filename: 'devToolsBackground.html',
40 | chunks: ["devToolsBackground"]
41 | }),
42 | ],
43 | module: {
44 | rules: [
45 | {
46 | test: /\.tsx?$/,
47 | loader: 'awesome-typescript-loader',
48 | exclude: /node_modules/,
49 | query: {
50 | declaration: false
51 | }
52 | },
53 | {
54 | test: /\.(json)$/,
55 | loader: 'file-loader'
56 | }
57 | ]
58 | }
59 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript"
3 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | dist
3 | docs
4 | node_modules
5 | package-lock.json
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "20"
4 | before_install:
5 | - export CHROME_BIN=chromium-browser
6 | - export DISPLAY=:99.0
7 | - sh -e /etc/init.d/xvfb start
8 | install:
9 | - npm install
10 | - lex versions
11 | script:
12 | - npm run build
13 | - npm run test
14 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "enabled": [
3 | "streetsidesoftware.code-spell-checker",
4 | "bierner.markdown-preview-github-styles",
5 | "DavidAnson.vscode-markdownlint",
6 | "ricard.postcss",
7 | "shinnn.stylelint"
8 | ],
9 | "recommendations": [
10 | "dbaeumer.vscode-eslint",
11 | "streetsidesoftware.code-spell-checker",
12 | "bierner.markdown-preview-github-styles",
13 | "DavidAnson.vscode-markdownlint",
14 | "ricard.postcss",
15 | "shinnn.stylelint",
16 | "flowtype.flow-for-vscode",
17 | "rbbit.typescript-hero",
18 | "Equinusocio.vsc-material-theme",
19 | "PKief.material-icon-theme"
20 | ]
21 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "arkham",
4 | "arkhamjs",
5 | "nitrogenlabs",
6 | "nlabs",
7 | "transpiler"
8 | ],
9 | "css.validate": false,
10 | "editor.autoClosingBrackets": false,
11 | "editor.detectIndentation": false,
12 | "editor.formatOnSave": true,
13 | "editor.rulers": [
14 | 120
15 | ],
16 | "editor.tabCompletion": true,
17 | "editor.tabSize": 2,
18 | "editor.wordWrap": "off",
19 | "editor.wordWrapColumn": 120,
20 | "editor.wrappingIndent": "indent",
21 | "emmet.includeLanguages": {
22 | "postcss": "css"
23 | },
24 | "emmet.syntaxProfiles": {
25 | "postcss": "css"
26 | },
27 | "eslint.codeActionsOnSave": true,
28 | "eslint.alwaysShowStatus": true,
29 | "eslint.enable": true,
30 | "eslint.validate": [
31 | "javascript",
32 | "javascriptreact",
33 | "typescript",
34 | "typescriptreact"
35 | ],
36 | "explorer.confirmDragAndDrop": false,
37 | "explorer.decorations.badges": false,
38 | "files.trimTrailingWhitespace": true,
39 | "flow.runOnAllFiles": true,
40 | "html.format.indentInnerHtml": true,
41 | "html.format.indentHandlebars": true,
42 | "html.format.extraLiners": "",
43 | "html.format.enable": false,
44 | "html.format.endWithNewline": true,
45 | "javascript.format.enable": false,
46 | "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
47 | "javascript.format.insertSpaceAfterKeywordsInControlFlowStatements": false,
48 | "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
49 | "javascript.validate.enable": false,
50 | "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": false,
51 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
52 | "typescriptHero.imports.insertSpaceBeforeAndAfterImportBraces": false,
53 | "typescriptHero.imports.multiLineTrailingComma": false,
54 | "typescriptHero.imports.multiLineWrapThreshold": 120,
55 | "typescriptHero.imports.organizeOnSave": true,
56 | "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
57 | "tslint.enable": true,
58 | "tslint.packageManager": "npm",
59 | "tslint.autoFixOnSave": true,
60 | "tslint.configFile": "./tslint.json"
61 | }
62 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Nitrogen Labs
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-example-ts-react
2 |
3 | An ArkhamJS React TypeScript example. A simple base application to start you off on your ReactJS project. Uses the following modules:
4 |
5 | - [react](https://www.npmjs.com/package/react) - A declarative, efficient, and flexible JavaScript library for building user interfaces.
6 | - [@nlabs/arkhamjs](https://www.npmjs.com/package/arkhamjs) - A clean, simple Flux framework.
7 | - [@nlabs/lex](https://www.npmjs.com/package/@nlabs/lex) - CLI tool to assist in development. Initialize, test, and compile your apps with zero setup. Using [Jest](https://facebook.github.io/jest/), [Webpack](https://webpack.js.org/), and [Typescript](http://www.typescriptlang.org/).
8 | - [@nlabs/arkhamjs-storage-browser](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-browser) - ArkhamJS browser storage. Caches state in session or local storage.
9 | - [@nlabs/arkhamjs-middleware-logger](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-logger) - ArkhamJS console log middleware.
10 |
11 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-example-ts-react)
12 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-example-ts-react)
13 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
14 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
15 | [](https://github.com/ellerbrock/typescript-badges/)
16 | [](http://opensource.org/licenses/MIT)
17 | [](https://discord.gg/Ttgev58)
18 |
19 | ## Getting Started
20 |
21 | ---------------
22 |
23 | - Clone the repo and install the necessary node modules:
24 |
25 | ```shell
26 | # Install Lex globally
27 | $ npm install -g @nlabs/lex
28 |
29 | # Download example app package and install dependencies (may take awhile the first time)
30 | $ lex init exampleApp @nlabs/arkhamjs-example-ts-react -i
31 | ```
32 |
33 | ## Usage
34 |
35 | ---------------
36 |
37 | ### `npm run start` also `npm run development`
38 |
39 | Runs the webpack build system to compile scripts on the fly. Also runs a local development web server which can be found at `localhost:9000`. The port can be changed in the config.
40 |
41 | ### `npm run build`
42 |
43 | Compile your application and copy static files for a production environment.
44 |
45 | ### `npm run clean`
46 |
47 | Clean your app directory. Removes *coverage*, *node_modules*, *npm-debug.log*, *package-lock.log*.
48 |
49 | ### `npm run lint`
50 |
51 | Lint your app with tslint.
52 |
53 | ### `npm run test`
54 |
55 | Runs all unit tests within the app with Jest.
56 |
57 | ### `npm run production`
58 |
59 | Run tests and then, on success, compile your application for a production environment.
60 |
61 | ## Configuration
62 |
63 | ---------------
64 |
65 | See [@nlabs/lex](https://www.npmjs.com/package/@nlabs/lex) for documentation on custom configuration.
66 |
67 | ## Structure
68 |
69 | ---------------
70 |
71 | The folder structure provided is only meant to serve as a guide, it is by no means prescriptive. It is something that has worked very well for me and my team, but use only what makes sense to you.
72 |
73 | ```shell
74 | .
75 | ├── coverage # Unit test coverage reports
76 | ├── dist # Compiled files ready to be deployed
77 | ├── src # Application source code
78 | │ ├── actions # ArkhamJS Flux actions
79 | │ ├── components # React components
80 | │ ├── config # App configuration
81 | │ ├── constants # App constants
82 | │ ├── errors # Custom errors
83 | │ ├── fonts # Font files
84 | │ ├── icons # SVG files
85 | │ ├── img # Images
86 | │ ├── services # Helpers and utilities
87 | │ ├── stores # ArkhamJS store configurations
88 | │ ├── styles # CSS styles
89 | │ ├── views # React components/views that live at a route
90 | │ ├── app.css # Entry CSS file
91 | │ ├── index.html # Entry HTML file
92 | │ └── index.tsx # Entry JS to bootstrap and render
93 | ├── .eslintrc # ESLint rules
94 | ├── .travis.yml # Travis-CI configuration
95 | ├── lex.config.js # Optional Lex configuration
96 | ├── LICENSE # License details
97 | ├── package.json # Package dependencies and configuration
98 | ├── README.md # Readme file to detail the app and configurations
99 | └── tsconfig.json # Typescript configuration (only used for definitions)
100 | ```
101 |
102 | ### Components vs. Views vs. Layouts
103 |
104 | **TL;DR:** They're all components.
105 |
106 | This distinction may not be important for you, but as an explanation: A **Layout** is something that describes an entire page structure, such as a fixed navigation, viewport, sidebar, and footer. Most applications will probably only have one layout, but keeping these components separate makes their intent clear. **Views** are components that live at routes, and are generally rendered within a **Layout**. What this ends up meaning is that, with this structure, nearly everything inside of **Components** ends up being a dumb component.
107 |
108 | ## Styles
109 |
110 | ---------------
111 |
112 | All `.css` imports will be run through postcss and cssnext, extracted and compiled during builds. CSS features included are nested classes and SASS-like variables. Styles must be imported either directly within the js file or via another stylesheet which has already been imported.
113 |
114 | ```js
115 | // JS
116 | import `./component.css`;
117 | ```
118 |
119 | ## Testing
120 |
121 | ---------------
122 |
123 | To add a unit test, simply create a `*.test.ts` or `*.test.tsx` file within the `/src` directory. Jest will look for these for and test these files.
124 |
125 | ## Troubleshooting
126 |
127 | ---------------
128 |
129 | Nothing yet. Having an issue? Report it and We'll get to it as soon as possible!
130 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'web',
3 | useTypescript: true
4 | };
5 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-example-ts-react",
3 | "version": "3.28.0",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "ArkhamJS React Typescript Example App",
8 | "license": "MIT",
9 | "keywords": [
10 | "arkhamjs",
11 | "example",
12 | "nitrogenlabs",
13 | "react",
14 | "typescript",
15 | "skeleton",
16 | "lex"
17 | ],
18 | "author": {
19 | "name": "Giraldo Rosales",
20 | "email": "giraldo@nitrogenlabs.com",
21 | "url": "http://nitrogenlabs.com"
22 | },
23 | "repository": {
24 | "type": "git",
25 | "url": "nitrogenlabs/arkhamjs.git"
26 | },
27 | "homepage": "https://arkhamjs.io",
28 | "bugs": {
29 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
30 | },
31 | "scripts": {
32 | "build": "lex build --remove",
33 | "clean": "lex clean",
34 | "dev": "lex dev",
35 | "lint": "eslint ./src --ext .ts,.tsx",
36 | "prepublishOnly": "npm run build",
37 | "publish:major": "npm version major && npm publish",
38 | "publish:minor": "npm version minor && npm publish",
39 | "publish:patch": "npm version patch && npm publish",
40 | "pretest": "npm run lint",
41 | "prod": "npm run test && npm run build",
42 | "start": "lex dev --open",
43 | "test": "lex test",
44 | "update": "npm-check-updates --interactive"
45 | },
46 | "dependencies": {
47 | "@nlabs/arkhamjs": "*",
48 | "@nlabs/arkhamjs-middleware-logger": "*",
49 | "@nlabs/arkhamjs-storage-browser": "*",
50 | "@nlabs/arkhamjs-utils-react": "*",
51 | "bootstrap": "^5.3.2",
52 | "lodash": "^4.17.21",
53 | "react": "^19.0.0",
54 | "react-dom": "^19.0.0",
55 | "react-jss": "^10.10.0"
56 | },
57 | "devDependencies": {
58 | "@types/jest": "^29.5.11",
59 | "@types/node": "^20.11.5",
60 | "@types/react": "^18.2.48",
61 | "@types/react-dom": "^18.2.18",
62 | "eslint": "^8.56.0",
63 | "eslint-config-styleguidejs": "^3.2.1",
64 | "react-test-renderer": "^19.0.0",
65 | "typescript": "^5.3.3"
66 | },
67 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
68 | }
69 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/actions/AppActions/AppActions.test.ts:
--------------------------------------------------------------------------------
1 | import {AppConstants} from '../../constants/AppConstants';
2 | import {updateContent} from './AppActions';
3 |
4 | describe('AppActions', () => {
5 | const content: string = 'test';
6 |
7 | describe('updateContent', () => {
8 | let action;
9 |
10 | beforeAll(async () => {
11 | // Method
12 | action = await updateContent(content);
13 | });
14 |
15 | it('should dispatch AppConstants.UPDATE_CONTENT', () => {
16 | expect(action.type).toBe(AppConstants.UPDATE_CONTENT);
17 | });
18 |
19 | it('should contain content in action', () => {
20 | expect(action.content).toBe(content);
21 | });
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/actions/AppActions/AppActions.ts:
--------------------------------------------------------------------------------
1 | import {Flux, FluxAction} from '@nlabs/arkhamjs';
2 |
3 | import {AppConstants} from '../../constants/AppConstants';
4 |
5 | export const updateContent = (content: string): Promise =>
6 | Flux.dispatch({content, type: AppConstants.UPDATE_CONTENT});
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/app.css:
--------------------------------------------------------------------------------
1 | /* Base */
2 | @import 'bootstrap/dist/css/bootstrap.css';
3 |
4 | body, p, h1 {
5 | font-family: 'Open Sans', sans-serif;
6 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/components/Icon/Icon.test.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as renderer from 'react-test-renderer';
3 |
4 | import {Icon} from './Icon';
5 |
6 | describe('Icon', () => {
7 | let rendered;
8 |
9 | beforeAll(() => {
10 | rendered = renderer.create();
11 | });
12 |
13 | it('should render', () => expect(rendered).toBeDefined());
14 | });
15 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/components/Icon/Icon.tsx:
--------------------------------------------------------------------------------
1 | import {createUseStyles} from 'react-jss';
2 |
3 | import {IconProps, IconSize} from './Icon.types';
4 |
5 | const useStyles = createUseStyles({
6 | icon: ({iconSize}) => ({
7 | backgroundColor: 'transparent',
8 | color: 'inherit',
9 | display: 'block',
10 | fill: 'currentColor',
11 | height: iconSize,
12 | verticalAlign: 'middle',
13 | width: iconSize,
14 |
15 | '& svg': {
16 | fill: 'inherit',
17 | height: '100%',
18 | width: '100%',
19 |
20 | '& symbol path': {
21 | all: 'inherit'
22 | }
23 | }
24 | })
25 | });
26 |
27 | export const Icon = (props: IconProps): JSX.Element => {
28 | const {
29 | className = '',
30 | name = 'icon',
31 | size: propSize = ''
32 | } = props;
33 | const size: IconSize = propSize.toLowerCase().trim() as IconSize;
34 |
35 | // Icon sizes
36 | let iconSize;
37 |
38 | switch(size) {
39 | case 'md':
40 | iconSize = 32;
41 | break;
42 | case 'lg':
43 | iconSize = 64;
44 | break;
45 | case 'xl':
46 | iconSize = 128;
47 | break;
48 | case 'xx':
49 | iconSize = 256;
50 | break;
51 | default:
52 | iconSize = 16;
53 | break;
54 | }
55 |
56 | // Styles
57 | const classes = useStyles({iconSize});
58 | const styleClasses: string[] = [name, classes.icon, className];
59 |
60 | // SVG
61 | const useTag: string = ``;
62 | return ;
63 | };
64 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/components/Icon/Icon.types.ts:
--------------------------------------------------------------------------------
1 | export type IconSize = 'sm' | 'md' | 'lg' | 'xl' | 'xx';
2 |
3 | export interface IconProps {
4 | readonly className?: string;
5 | readonly name: string;
6 | readonly size?: IconSize;
7 | }
8 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/config/config.types.ts:
--------------------------------------------------------------------------------
1 | export interface AppConfig {
2 | readonly appId?: string;
3 | readonly appName?: string;
4 | readonly env?: string;
5 | }
6 |
7 | export interface EnvConfig {
8 | readonly default: AppConfig;
9 | readonly development: AppConfig;
10 | readonly preprod: AppConfig;
11 | readonly production: AppConfig;
12 | readonly test: AppConfig;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/config/index.ts:
--------------------------------------------------------------------------------
1 | import get from 'lodash/get';
2 | import merge from 'lodash/merge';
3 |
4 | import {EnvConfig} from './config.types';
5 |
6 | const {NODE_ENV} = process.env;
7 |
8 | export class Config {
9 | static values: EnvConfig = {
10 | default: {
11 | appId: 'arkhamjs-skeleton',
12 | env: NODE_ENV
13 | },
14 | development: {
15 | appName: 'Arkham Skeleton Development'
16 | },
17 | preprod: {
18 | appName: 'Arkham Skeleton Pre-Production'
19 | },
20 | production: {
21 | appName: 'Arkham Skeleton Production'
22 | },
23 | test: {
24 | appName: 'Arkham Skeleton Test'
25 | }
26 | };
27 |
28 | static get(path: string | string[]): any {
29 | const environment: string = NODE_ENV || 'development';
30 | const configValues: object = merge(this.values.default, this.values[environment], {environment});
31 | return get(configValues, path);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/constants/AppConstants.ts:
--------------------------------------------------------------------------------
1 | export class AppConstants {
2 | static readonly UPDATE_CONTENT: string = 'APP_UPDATE_CONTENT';
3 | }
4 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/errors/UserError.ts:
--------------------------------------------------------------------------------
1 | export class UserError extends Error {
2 | errors: string[];
3 |
4 | constructor(msg: string, errors: string[] = []) {
5 | super(msg);
6 | this.errors = errors || [];
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/fonts/readme.txt:
--------------------------------------------------------------------------------
1 | Any font files to be imported would be placed in the fonts directory.
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/icons/pencil.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/icons/readme.txt:
--------------------------------------------------------------------------------
1 | Any SVG icons to be imported would be placed in the icons directory. They will be consolidated into one file, icons.svg.
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/img/arkhamjs-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitrogenlabs/arkhamjs/9428e95a52f4a7323609da35ad9c29223eb8eafa/packages/arkhamjs-example-ts-react/src/img/arkhamjs-logo.png
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/img/readme.txt:
--------------------------------------------------------------------------------
1 | Any images to be imported would be placed in the img directory.
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ArkhamJS
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/index.tsx:
--------------------------------------------------------------------------------
1 | import './app.css';
2 |
3 | import * as ReactDOM from 'react-dom';
4 |
5 | import {AppView} from './views/AppView';
6 |
7 | const target = document.getElementById('app');
8 |
9 | // Render initial ReactJS code
10 | ReactDOM.render(, target);
11 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/services/StringService.test.ts:
--------------------------------------------------------------------------------
1 | import {capitalize, uppercaseWords} from './StringService';
2 |
3 | describe('StringService', () => {
4 | describe('.uppercaseWords', () => {
5 | it('should uppercase words', () => {
6 | const str = 'test string';
7 | const expected = 'Test String';
8 | return expect(uppercaseWords(str)).toBe(expected);
9 | });
10 | });
11 |
12 | describe('.capitalize', () => {
13 | it('should capitalize word', () => {
14 | const str = 'test';
15 | const expected = 'Test';
16 | return expect(capitalize(str)).toBe(expected);
17 | });
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/services/StringService.ts:
--------------------------------------------------------------------------------
1 |
2 | export const capitalize = (str: string = ''): string => {
3 | if(str.length > 1) {
4 | return `${str.charAt(0).toUpperCase()}${str.substr(1).toLowerCase()}`;
5 | }
6 |
7 | return str.toUpperCase();
8 | };
9 | export const uppercaseWords = (str: string = ''): string => (str || '').replace(/\w\S*/g, (txt: string) => capitalize(txt));
10 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/stores/AppStore/appStore.test.ts:
--------------------------------------------------------------------------------
1 | import {AppConstants} from '../../constants/AppConstants';
2 | import {app, initialState} from './appStore';
3 |
4 | describe('app', () => {
5 | describe('action', () => {
6 | it('should listen for default', () => {
7 | const content = 'test';
8 | const data = {content};
9 | const state = app('default', data, initialState);
10 | return expect(state).toBe(initialState);
11 | });
12 |
13 | it('should listen for AppConstants.UPDATE_CONTENT', () => {
14 | const content = 'test';
15 | const data = {content};
16 | const state = app(AppConstants.UPDATE_CONTENT, data, initialState);
17 | return expect(state.content).toBe(content);
18 | });
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/stores/AppStore/appStore.ts:
--------------------------------------------------------------------------------
1 | import {AppConstants} from '../../constants/AppConstants';
2 | import {AppState} from './appStore.types';
3 |
4 | export const initialState: AppState = {
5 | content: 'Hello World'
6 | };
7 |
8 | export const app = (type: string, data: any, state: AppState = initialState): AppState => {
9 | switch(type) {
10 | case AppConstants.UPDATE_CONTENT: {
11 | const {content} = data;
12 | return {...state, content};
13 | }
14 | default:
15 | return state;
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/stores/AppStore/appStore.types.ts:
--------------------------------------------------------------------------------
1 | export interface AppState {
2 | readonly content: string;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/views/AppView.test.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as renderer from 'react-test-renderer';
3 |
4 | import {AppView} from './AppView';
5 |
6 | describe('AppView', () => {
7 | let rendered;
8 |
9 | beforeAll(() => {
10 | // Render
11 | rendered = renderer.create();
12 | });
13 |
14 | it('should render', () => expect(rendered).toBeDefined());
15 | });
16 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/views/AppView.tsx:
--------------------------------------------------------------------------------
1 | import {Flux} from '@nlabs/arkhamjs';
2 | import {Logger, LoggerDebugLevel} from '@nlabs/arkhamjs-middleware-logger';
3 | import {BrowserStorage} from '@nlabs/arkhamjs-storage-browser';
4 | import {FluxProvider} from '@nlabs/arkhamjs-utils-react';
5 | import {useEffect, useState} from 'react';
6 |
7 | import {Config} from '../config';
8 | import {app} from '../stores/appStore/appStore';
9 | import {HomeView} from './HomeView';
10 |
11 | export const onUpdateContent = (setContent) => (): void => {
12 | const content = Flux.getState('app.content', '');
13 | setContent(content);
14 | };
15 |
16 | export const AppView = (): JSX.Element => {
17 | // ArkhamJS Middleware
18 | const env: string = Config.get('environment');
19 | const logger: Logger = new Logger({
20 | debugLevel: env === 'development' ? LoggerDebugLevel.DISPATCH : LoggerDebugLevel.DISABLED
21 | });
22 |
23 | const [content, setContent] = useState(Flux.getState('app.content', ''));
24 |
25 | // ArkhamJS Configuration
26 | Flux.init({
27 | middleware: [logger],
28 | name: 'arkhamExampleReact',
29 | storage: new BrowserStorage({type: 'session'}),
30 | stores: [app]
31 | });
32 |
33 | useEffect(() => {
34 | const onUpdate = onUpdateContent(setContent);
35 |
36 | // When app initializes and gets any data from persistent storage
37 | Flux.onInit(onUpdate);
38 |
39 | return () => {
40 | Flux.offInit(onUpdate);
41 | };
42 | });
43 |
44 | return (
45 |
46 |
47 |
48 | );
49 | };
50 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/views/HomeView.test.tsx:
--------------------------------------------------------------------------------
1 | import {FluxProvider} from '@nlabs/arkhamjs-utils-react';
2 | import * as React from 'react';
3 | import * as renderer from 'react-test-renderer';
4 |
5 | import {HomeView} from './HomeView';
6 |
7 | describe('HomeView', () => {
8 | let rendered;
9 |
10 | beforeAll(() => {
11 | const fluxMock: any = jest.fn();
12 |
13 | // Render
14 | rendered = renderer.create();
15 | });
16 |
17 | it('should render', () => expect(rendered).toBeDefined());
18 | });
19 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/src/views/HomeView.tsx:
--------------------------------------------------------------------------------
1 | import {useFluxListener} from '@nlabs/arkhamjs-utils-react';
2 | import {useRef, useState} from 'react';
3 | import {createUseStyles} from 'react-jss';
4 |
5 | import {updateContent} from '../actions/AppActions/AppActions';
6 | import {Icon} from '../components/Icon/Icon';
7 | import {AppConstants} from '../constants/AppConstants';
8 | import {uppercaseWords} from '../services/StringService';
9 |
10 | const useStyles = createUseStyles({
11 | logo: {
12 | display: 'flex',
13 | justifyContent: 'center',
14 | marginBottom: 100
15 | },
16 | logoImg: {
17 | height: 94,
18 | width: 403
19 | },
20 | helloTxt: {
21 | fontSize: 30,
22 | fontStyle: 'italic',
23 | fontWeight: 100,
24 | textAlign: 'center'
25 | },
26 | form: {
27 | display: 'flex',
28 | flexDirection: 'column'
29 | },
30 | input: {
31 | alignSelf: 'stretch',
32 | border: '1px solid #ccc',
33 | padding: '10px 15px',
34 | margin: '30px 0'
35 | },
36 | button: {
37 | alignSelf: 'flex-end',
38 | alignContent: 'center',
39 | display: 'flex',
40 | flexDirection: 'row',
41 | justifyContent: 'center'
42 |
43 | },
44 | btnIcon: {
45 | alignSelf: 'center',
46 | marginRight: 5
47 | }
48 | });
49 |
50 | export const onChange = (inputRef) => () => {
51 | if(inputRef.current) {
52 | const {value} = inputRef.current;
53 | updateContent(value);
54 | }
55 | };
56 |
57 | export const onUpdateContent = (setContent) => ({content}) => {
58 | setContent(content);
59 | };
60 |
61 | export const HomeView = ({initialContent}) => {
62 | // State
63 | const [content, setContent] = useState(initialContent);
64 | const inputRef = useRef();
65 |
66 | useFluxListener(AppConstants.UPDATE_CONTENT, onUpdateContent(setContent));
67 |
68 | // Styles
69 | const classes = useStyles();
70 |
71 | return (
72 |
73 |
74 |
75 |
80 |
{uppercaseWords(content)}
81 |
82 |
83 |
87 |
88 |
89 |
90 |
91 | );
92 | };
93 |
--------------------------------------------------------------------------------
/packages/arkhamjs-example-ts-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018"
23 | },
24 | "include": [
25 | "./src/**/*"
26 | ],
27 | "exclude": [
28 | "**/*.test.*",
29 | "lib",
30 | "./node_modules",
31 | "./test"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript",
3 | "rules": {
4 | "import/no-extraneous-dependencies": 0
5 | }
6 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | jest.setup.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Nitrogen Labs
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-middleware-devtools
2 |
3 | ArkhamJS DevTools Middleware
4 |
5 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-devtools)
6 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-devtools)
7 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
8 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
9 | [](https://github.com/ellerbrock/typescript-badges/)
10 | [](http://opensource.org/licenses/MIT)
11 | [](https://discord.gg/Ttgev58)
12 |
13 | ## Installation
14 |
15 | Using [npm](https://www.npmjs.com/):
16 |
17 | ```shell
18 | npm i --save @nlabs/arkhamjs-middleware-devtools
19 | ```
20 |
21 | ## Documentation
22 |
23 | For detailed [Documentation](https://arkhamjs.io) and additional options.
24 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | const lib = require('./lib');
6 |
7 | // ArkhamJS middleware
8 | exports.DevTools = lib.DevTools;
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/jest.setup.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitrogenlabs/arkhamjs/9428e95a52f4a7323609da35ad9c29223eb8eafa/packages/arkhamjs-middleware-devtools/jest.setup.js
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-middleware-devtools",
3 | "version": "3.11.8",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "Add devtools to ArkhamJS app",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "module": "./lib/index.js",
11 | "browser": "./lib/index.js",
12 | "types": "./lib/index.d.ts",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "immutable",
17 | "middleware",
18 | "nitrogenlabs",
19 | "devtools"
20 | ],
21 | "author": {
22 | "name": "Giraldo Rosales",
23 | "email": "giraldo@nitrogenlabs.com",
24 | "url": "http://nitrogenlabs.com"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "nitrogenlabs/arkhamjs.git"
29 | },
30 | "homepage": "https://arkhamjs.io",
31 | "bugs": {
32 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
33 | },
34 | "scripts": {
35 | "build": "lex compile --remove",
36 | "clean": "lex clean",
37 | "lint": "eslint ./src --ext .ts,.tsx",
38 | "prepublishOnly": "npm run build",
39 | "publish:major": "npm version major && npm publish",
40 | "publish:minor": "npm version minor && npm publish",
41 | "publish:patch": "npm version patch && npm publish",
42 | "pretest": "npm run lint",
43 | "test": "lex test",
44 | "update": "npm-check-updates --interactive"
45 | },
46 | "peerDependencies": {
47 | "@nlabs/arkhamjs": "^3.23",
48 | "redux": "^3.0"
49 | },
50 | "devDependencies": {
51 | "@nlabs/arkhamjs": "^3.22.0",
52 | "@types/jest": "^27.4.0",
53 | "@types/node": "^17.0.17",
54 | "eslint": "^7.32.0",
55 | "eslint-config-styleguidejs": "^1.5.4",
56 | "typescript": "^4.5.5"
57 | },
58 | "gitHead": "ca196f147316f6590794c49f53965ab6770b2dd6"
59 | }
60 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | // Middleware for ArkhamJS
7 | export {DevTools} from './middleware/DevTools';
8 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/src/middleware/DevTools.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {Flux, FluxAction} from '@nlabs/arkhamjs';
6 |
7 | export class DevTools {
8 | name: string = 'DevTools';
9 | mode: string = 'development';
10 |
11 | constructor(options) {
12 | // Methods
13 | this.postDispatch = this.postDispatch.bind(this);
14 | this.postMessage = this.postMessage.bind(this);
15 | this.setMode = this.setMode.bind(this);
16 |
17 | // Set options
18 | Flux.onInit(() => {
19 | const arkhamOptions: string = JSON.stringify(Flux.getOptions(), null, 0);
20 | this.postMessage({_arkhamInfo: arkhamOptions});
21 | });
22 |
23 | // Set initial mode
24 | const {mode = 'development'} = options;
25 | this.setMode(mode);
26 | }
27 |
28 | get isActive(): boolean {
29 | return this.mode === 'development';
30 | }
31 |
32 | setMode(mode: string = 'development'): void {
33 | this.mode = mode;
34 |
35 | if(mode === 'development') {
36 | window.addEventListener('message', this.sendMethod);
37 | } else {
38 | window.removeEventListener('message', this.sendMethod);
39 | }
40 | }
41 |
42 | sendMethod(event): void {
43 | const {_arkhamCall: {method = '', args = []} = {}} = event.data;
44 | console.log('middleware::method', method);
45 |
46 | if(method !== '') {
47 | switch(method) {
48 | case 'dispatch':
49 | Flux[method](...args);
50 | break;
51 | case 'storeClasses': {
52 | const stores = Flux[method];
53 | const storeDetails = Object.keys(stores).map((storeName: string) => {
54 | const store = stores[storeName];
55 | return {initialState: store.initialState(), name: store.name};
56 | });
57 | console.log('storeClasses', storeDetails);
58 | break;
59 | }
60 | }
61 | }
62 | }
63 |
64 | postMessage(data): void {
65 | window.postMessage(data, '*');
66 | }
67 |
68 | postDispatch(action, state, {duration, options, stack}): Promise {
69 | if(this.isActive) {
70 | const dispatchData = {action, duration, stack, state};
71 | const data: string = JSON.stringify(dispatchData, null, 0);
72 | const optionsData: string = JSON.stringify(options, null, 0);
73 | this.postMessage({_arkhamDispatch: data, _arkhamInfo: optionsData});
74 | }
75 |
76 | return Promise.resolve(action);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-devtools/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018",
23 | "typeRoots": [
24 | "node_modules/@types",
25 | "node_modules/json-d-ts"
26 | ]
27 | },
28 | "include": [
29 | "./src/**/*"
30 | ],
31 | "exclude": [
32 | "**/*.test.*",
33 | "lib",
34 | "./node_modules",
35 | "./test"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript",
3 | "rules": {
4 | "import/no-extraneous-dependencies": 0
5 | }
6 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | lex.config.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Nitrogen Labs, Inc.
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-middleware-logger
2 |
3 | Add console logging for ArkhamJS
4 |
5 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-logger)
6 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-logger)
7 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
8 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
9 | [](https://github.com/ellerbrock/typescript-badges/)
10 | [](http://opensource.org/licenses/MIT)
11 | [](https://discord.gg/Ttgev58)
12 |
13 | ## Installation
14 |
15 | Using [npm](https://www.npmjs.com/):
16 |
17 | ```shell
18 | npm i --save @nlabs/arkhamjs-middleware-logger
19 | ```
20 |
21 | ## Documentation
22 |
23 | For detailed [Documentation](https://arkhamjs.io) and additional options.
24 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | module.exports = require('./lib');
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'web',
4 | useTypescript: true
5 | };
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-middleware-logger",
3 | "version": "3.28.5",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "Add console logging for ArkhamJS",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "module": "./lib/index.js",
11 | "browser": "./lib/index.js",
12 | "types": "./lib/index.d.ts",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "logging",
17 | "nitrogenlabs"
18 | ],
19 | "author": {
20 | "name": "Giraldo Rosales",
21 | "email": "giraldo@nitrogenlabs.com",
22 | "url": "http://nitrogenlabs.com"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "nitrogenlabs/arkhamjs.git"
27 | },
28 | "homepage": "https://arkhamjs.io",
29 | "bugs": {
30 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
31 | },
32 | "scripts": {
33 | "build": "lex compile --remove",
34 | "clean": "lex clean",
35 | "lint": "eslint ./src --ext .ts,.tsx",
36 | "prepublishOnly": "npm run build",
37 | "publish:major": "npm version major && npm publish",
38 | "publish:minor": "npm version minor && npm publish",
39 | "publish:patch": "npm version patch && npm publish",
40 | "pretest": "lex lint",
41 | "test": "lex test",
42 | "update": "npm-check-updates --interactive"
43 | },
44 | "peerDependencies": {
45 | "@nlabs/arkhamjs": "*",
46 | "lodash": "^4.17"
47 | },
48 | "devDependencies": {
49 | "@nlabs/arkhamjs": "*",
50 | "@types/jest": "^29.5.14",
51 | "@types/node": "^22.13.1",
52 | "eslint": "^9.19.0",
53 | "eslint-config-styleguidejs": "^3.2.1",
54 | "lodash": "^4.17.21",
55 | "typescript": "^5.7.3"
56 | },
57 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
58 | }
59 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/src/Logger/Logger.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {Flux, FluxAction} from '@nlabs/arkhamjs';
6 | import set from 'lodash/set';
7 |
8 | import {LoggerDebugLevel, LoggerOptions} from '../types/main';
9 | import {Logger} from './Logger';
10 |
11 | const test = (type: string, data, state = {hello: 'world'}) => {
12 | switch(type) {
13 | case 'TEST_EVENT':
14 | return set(state, 'testAction', data.testVar);
15 | default:
16 | return state;
17 | }
18 | };
19 |
20 | describe('Logger', () => {
21 | const cfg: LoggerOptions = {debugLevel: LoggerDebugLevel.DISPATCH};
22 | const logger: Logger = new Logger(cfg);
23 | const testAction: FluxAction = {hello: 'world', type: 'TEST_EVENT'};
24 |
25 | beforeAll(async () => {
26 | await Flux.init({
27 | stores: [test]
28 | });
29 | });
30 |
31 | describe('#config', () => {
32 | // Vars
33 | const opts: LoggerOptions = {
34 | debugLevel: 0
35 | };
36 |
37 | beforeAll(() => {
38 | // Method
39 | logger.config(opts);
40 | });
41 |
42 | afterAll(() => {
43 | logger.config(cfg);
44 | });
45 |
46 | it('should set debugLevel', () => {
47 | const privateProperty: string = 'options';
48 | expect(logger[privateProperty].debugLevel).toEqual(opts.debugLevel);
49 | });
50 | });
51 |
52 | describe('#debugError', () => {
53 | let consoleSpy;
54 | const msg: string = 'test';
55 |
56 | beforeAll(() => {
57 | // Spy
58 | consoleSpy = jest.spyOn(console, 'error');
59 |
60 | // Method
61 | logger.debugError(msg);
62 | });
63 |
64 | afterAll(() => {
65 | consoleSpy.mockRestore();
66 | });
67 |
68 | it('should send data to console.error', () => {
69 | expect(consoleSpy.mock.calls[0][0]).toEqual(msg);
70 | });
71 | });
72 |
73 | describe('#debugInfo', () => {
74 | let consoleSpy;
75 | const msg: string = 'test';
76 |
77 | beforeAll(() => {
78 | // Spy
79 | consoleSpy = jest.spyOn(console, 'info');
80 |
81 | // Method
82 | logger.debugInfo(msg);
83 | });
84 |
85 | afterAll(() => {
86 | consoleSpy.mockRestore();
87 | });
88 |
89 | it('should send data to console.info', () => {
90 | expect(consoleSpy.mock.calls[0][0]).toEqual(msg);
91 | });
92 | });
93 |
94 | describe('#debugLog', () => {
95 | let consoleSpy;
96 | const msg: string = 'test';
97 |
98 | beforeAll(() => {
99 | // Spy
100 | consoleSpy = jest.spyOn(console, 'log');
101 |
102 | // Method
103 | logger.debugLog(msg);
104 | });
105 |
106 | afterAll(() => {
107 | consoleSpy.mockRestore();
108 | });
109 |
110 | it('should send data to console.log', () => {
111 | expect(consoleSpy.mock.calls[0][0]).toEqual(msg);
112 | });
113 | });
114 |
115 | describe('#enableDebugger', () => {
116 | it('should disable debugger', () => {
117 | logger.enableDebugger(LoggerDebugLevel.DISABLED);
118 | const options: LoggerOptions = logger.getOptions();
119 | expect(options.debugLevel).toEqual(0);
120 | });
121 |
122 | it('should enable debugger for logs', () => {
123 | logger.enableDebugger(LoggerDebugLevel.LOGS);
124 | const options: LoggerOptions = logger.getOptions();
125 | expect(options.debugLevel).toEqual(1);
126 | });
127 |
128 | it('should enable debugger for dispatch actions', () => {
129 | logger.enableDebugger(LoggerDebugLevel.DISPATCH);
130 | const options: LoggerOptions = logger.getOptions();
131 | expect(options.debugLevel).toEqual(2);
132 | });
133 | });
134 |
135 | describe('#preDispatch', () => {
136 | it('should update the previous store', () => {
137 | const testStore = {test: 'test'};
138 | const privateProperty: string = 'previousStore';
139 | logger.preDispatch(testAction, testStore);
140 | expect(JSON.stringify(logger[privateProperty])).toEqual(JSON.stringify(testStore));
141 | });
142 | });
143 |
144 | describe('#postDispatch', () => {
145 | let consoleSpy;
146 | const prevStore = {test: 'previous'};
147 | const nextStore = {test: 'next'};
148 |
149 | beforeEach(() => {
150 | // Spy
151 | consoleSpy = jest.spyOn(console, 'log');
152 | });
153 |
154 | afterEach(() => {
155 | consoleSpy.mockRestore();
156 | });
157 |
158 | it('should dispatch logs for a changed state', () => {
159 | // Method
160 | logger.preDispatch(testAction, prevStore);
161 | logger.postDispatch(testAction, nextStore);
162 |
163 | // expect(consoleSpy.mock.calls[0][0]).toEqual('%c Action: ');
164 | // expect(consoleSpy.mock.calls[0][2]).toEqual(testAction);
165 | // expect(consoleSpy.mock.calls[1][0]).toEqual('%c Last State: ');
166 | // expect(consoleSpy.mock.calls[1][2]).toEqual(prevStore);
167 | expect(consoleSpy.mock.calls[2][0]).toEqual('%c Changed State: ');
168 | expect(consoleSpy.mock.calls[2][2]).toEqual(nextStore);
169 | });
170 |
171 | // it('should dispatch logs for an unchanged state', () => {
172 | // // Method
173 | // logger.preDispatch(testAction, prevStore);
174 | // logger.postDispatch(testAction, prevStore);
175 |
176 | // expect(consoleSpy.mock.calls[0][0]).toEqual('%c Action: ');
177 | // expect(consoleSpy.mock.calls[0][2]).toEqual(testAction);
178 | // expect(consoleSpy.mock.calls[1][0]).toEqual('%c Last State: ');
179 | // expect(consoleSpy.mock.calls[1][2]).toEqual(prevStore);
180 | // expect(consoleSpy.mock.calls[2][0]).toEqual('%c Unchanged State: ');
181 | // expect(consoleSpy.mock.calls[2][2]).toEqual(prevStore);
182 | // });
183 | });
184 | });
185 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/src/Logger/Logger.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | import {FluxAction} from '@nlabs/arkhamjs';
7 | import cloneDeep from 'lodash/cloneDeep';
8 | import isEqual from 'lodash/isEqual';
9 |
10 | import {LoggerDebugLevel, LoggerOptions} from '../types/main';
11 |
12 | /**
13 | * FluxLogger
14 | * @type {EventEmitter}
15 | */
16 | export class Logger {
17 | // Public properties
18 | name: string = 'Logger';
19 |
20 | // Private properties
21 | private previousStore: any = {};
22 | private defaultOptions: LoggerOptions = {
23 | debugLevel: LoggerDebugLevel.DISABLED
24 | };
25 | private options: LoggerOptions = this.defaultOptions;
26 |
27 | /**
28 | * Create a new instance of the FluxLogger.
29 | *
30 | * @constructor
31 | * @this {FluxLogger}
32 | */
33 | constructor(options: LoggerOptions) {
34 | // Methods
35 | this.config = this.config.bind(this);
36 | this.debugError = this.debugError.bind(this);
37 | this.debugInfo = this.debugInfo.bind(this);
38 | this.debugLog = this.debugLog.bind(this);
39 | this.enableDebugger = this.enableDebugger.bind(this);
40 | this.getOptions = this.getOptions.bind(this);
41 | this.postDispatch = this.postDispatch.bind(this);
42 | this.preDispatch = this.preDispatch.bind(this);
43 |
44 | // Configuration
45 | this.config(options);
46 | }
47 |
48 | /**
49 | * Set configuration options.
50 | *
51 | * @param {object} options Configuration options.
52 | */
53 | config(options: LoggerOptions): void {
54 | this.options = {...this.defaultOptions, ...options};
55 | }
56 |
57 | /**
58 | * Logs errors in the console. Will also call the debugErrorFnc method set in the config.
59 | *
60 | * @param {object} obj A list of JavaScript objects to output. The string representations of each of these objects
61 | * are appended together in the order listed and output.
62 | */
63 | debugError(...obj): void {
64 | const {debugErrorFnc, debugLevel} = this.options;
65 |
66 | if(debugLevel) {
67 | console.error(...obj);
68 | }
69 |
70 | if(debugErrorFnc) {
71 | debugErrorFnc(debugLevel, ...obj);
72 | }
73 | }
74 |
75 | /**
76 | * Logs informational messages to the console. Will also call the debugInfoFnc method set in the config.
77 | *
78 | * @param {object} obj A list of JavaScript objects to output. The string representations of each of these objects
79 | * are appended together in the order listed and output.
80 | */
81 | debugInfo(...obj): void {
82 | const {debugInfoFnc, debugLevel} = this.options;
83 |
84 | if(debugLevel) {
85 | console.info(...obj);
86 | }
87 |
88 | if(debugInfoFnc) {
89 | debugInfoFnc(debugLevel, ...obj);
90 | }
91 | }
92 |
93 | /**
94 | * Logs data in the console. Only logs when in debug mode. Will also call the debugLogFnc method set in the config.
95 | *
96 | * @param {object} obj A list of JavaScript objects to output. The string representations of each of these objects
97 | * are appended together in the order listed and output.
98 | */
99 | debugLog(...obj): void {
100 | const {debugLogFnc, debugLevel} = this.options;
101 |
102 | if(debugLevel) {
103 | console.log(...obj);
104 | }
105 |
106 | if(debugLogFnc) {
107 | debugLogFnc(debugLevel, ...obj);
108 | }
109 | }
110 |
111 | /**
112 | * Enables the console debugger.
113 | *
114 | * @param {number} level Enable or disable the debugger. Uses the constants:
115 | * LoggerDebugLevel.DISABLED (0) - Disable.
116 | * LoggerDebugLevel.LOGS (1) - Enable console logs.
117 | * LoggerDebugLevel.DISPATCH (2) - Enable console logs and dispatch action data (default).
118 | */
119 | enableDebugger(level: number = LoggerDebugLevel.DISPATCH): void {
120 | this.options = {...this.options, debugLevel: level};
121 | }
122 |
123 | /**
124 | * Get the current FluxLogger options.
125 | *
126 | * @returns {LoggerOptions} the FluxLogger options object.
127 | */
128 | getOptions(): LoggerOptions {
129 | return this.options;
130 | }
131 |
132 | preDispatch(action: FluxAction, store): Promise {
133 | this.previousStore = store;
134 | return Promise.resolve(action);
135 | }
136 |
137 | postDispatch(action: FluxAction, store: object): Promise {
138 | const {debugLevel} = this.options;
139 |
140 | if(debugLevel > LoggerDebugLevel.LOGS) {
141 | const {type} = action;
142 | const hasChanged = !isEqual(store, this.previousStore);
143 | const updatedLabel = hasChanged ? 'Changed State' : 'Unchanged State';
144 | const updatedColor = hasChanged ? '#00d484' : '#959595';
145 | const updatedStore = cloneDeep(store);
146 |
147 | if(console.groupCollapsed) {
148 | console.groupCollapsed(`FLUX DISPATCH: ${type}`);
149 | console.log('%c Action: ', 'color: #00C4FF', action);
150 | console.log('%c Last State: ', 'color: #959595', this.previousStore);
151 | console.log(`%c ${updatedLabel}: `, `color: ${updatedColor}`, updatedStore);
152 | console.groupEnd();
153 | } else {
154 | console.log(`FLUX DISPATCH: ${type}`);
155 | console.log('Action: ', action);
156 | console.log('Last State: ', this.previousStore);
157 | console.log(`${updatedLabel}: `, updatedStore);
158 | }
159 | }
160 |
161 | return Promise.resolve(action);
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | import {Logger} from './Logger/Logger';
7 |
8 | export * from './types/main';
9 | export {Logger};
10 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/src/types/main.ts:
--------------------------------------------------------------------------------
1 | export enum LoggerDebugLevel {
2 | DISABLED = 0,
3 | LOGS = 1,
4 | DISPATCH = 2
5 | }
6 |
7 | export interface LoggerOptions {
8 | readonly debugLevel?: LoggerDebugLevel;
9 | readonly debugErrorFnc?: (debugLevel: number, ...args) => void;
10 | readonly debugInfoFnc?: (debugLevel: number, ...args) => void;
11 | readonly debugLogFnc?: (debugLevel: number, ...args) => void;
12 | }
13 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-logger/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018"
23 | },
24 | "include": [
25 | "./src/**/*"
26 | ],
27 | "exclude": [
28 | "**/*.test.*",
29 | "lib",
30 | "./node_modules",
31 | "./test"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "styleguidejs/typescript"
4 | ],
5 | "rules": {
6 | "no-underscore-dangle": 0
7 | }
8 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | lex.config.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Nitrogen Labs
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-middleware-redux
2 |
3 | ArkhamJS Redux middleware integrates ArkhamJS into existing redux applications to provide access to ArkhamJS features and/or provide a simple migration path to ArkhamJS.
4 |
5 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-redux)
6 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-middleware-redux)
7 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
8 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
9 | [](https://github.com/ellerbrock/typescript-badges/)
10 | [](http://opensource.org/licenses/MIT)
11 | [](https://discord.gg/Ttgev58)
12 |
13 | ## Installation
14 |
15 | ```shell
16 | npm i @nlabs/arkhamjs-middleware-redux
17 | ```
18 |
19 | ## Usage
20 |
21 | ### `createArkhamStore`
22 |
23 | Create a Redux store that creates a two-way binding with ArkhamJS.
24 |
25 | ```javascript
26 | // Create Redux store
27 | const store = createArkhamStore({
28 | arkhamMiddleware,
29 | devTools,
30 | flux,
31 | reducers,
32 | reduxMiddleware,
33 | statePath
34 | });
35 | ```
36 |
37 | A quick example on usage.
38 |
39 | ```javascript
40 | import {createArkhamStore} from '@nlabs/arkhamjs-middleware-redux';
41 | import {Flux} from '@nlabs/arkhamjs';
42 | import * as React from 'react';
43 | import {render} from 'react-dom';
44 | import {Provider} from 'react-redux';
45 | import {App} from './components/App';
46 | import {reducers} from './reducers';
47 |
48 | // Initialize ArkhamJS
49 | Flux.init({name: 'reduxTodos'});
50 |
51 | // Create Redux store
52 | const store = createArkhamStore({
53 | flux: Flux,
54 | reducers,
55 | statePath: 'todos'
56 | });
57 |
58 | // Render root component with store
59 | render(
60 |
61 |
62 | ,
63 | document.getElementById('root')
64 | );
65 | ```
66 |
67 | #### Options
68 |
69 | - **flux** - *(Flux)* The Flux object you initialized in your app.
70 | - **reducers** - *(Reducer)* Redux root reducer. The reducer created by `combineReducers()`.
71 | - **statePath** - *(string[] | string)* State tree path where to set this branch of the store's state tree.
72 | - **arkhamMiddleware** - *(any[])* (optional) ArkhamJS options. Use only if intending to initialize a new instance.
73 | - **devTools** - *(boolean)* (optional) Enable/disable Redux dev tools. Default: false.
74 | - **reduxMiddleware** - *(Middleware[])* (optional) Redux middleware. Any additional Redux middleware used in the app.
75 |
76 | ### `ReduxMiddleware`
77 |
78 | ArkhamJS middleware to relay dispatched actions to Redux.
79 |
80 | ```javascript
81 | // Create ArkhamJS middleware
82 | const reduxMiddleware = new ReduxMiddleware(store, name);
83 | ```
84 |
85 | A simple usage example:
86 |
87 | ```javascript
88 | import {ReduxMiddleware} from '@nlabs/arkhamjs-middleware-redux';
89 | import {createStore} from 'redux';
90 | import {reducers} from './reducers';
91 |
92 | const store = createStore(reducers);
93 | const middleware = [new ReduxMiddleware(store, 'myApp')];
94 |
95 | Flux.init({middleware});
96 | ```
97 |
98 | - **store** - *(Store)* Redux root store. The store created by `createStore()`.
99 | - **name** - *(string)* (optional) Middleware name. Should be unique if integrating with multiple Redux stores.
100 |
101 | ### `arkhamMiddleware`
102 |
103 | Redux middleware to relay Redux action dispatches to ArkhamJS.
104 |
105 | ```javascript
106 | // Create Redux middleware
107 | const middleware = arkhamMiddleware(statePath);
108 | ```
109 |
110 | A simple usage example:
111 |
112 | ```javascript
113 | import {arkhamMiddleware} from '@nlabs/arkhamjs-middleware-redux';
114 | import {applyMiddleware, createStore} from 'redux';
115 | import {reducers} from './reducers';
116 |
117 | const store = createStore(reducers, applyMiddleware(arkhamMiddleware('myApp')));
118 | ```
119 |
120 | - **statePath** - *(string[] | string)* State tree path where to set this branch of the store's state tree.
121 |
122 | ## Additional Documentation
123 |
124 | Additional details may be found in the [ArkhamJS Documentation](https://docs.arkhamjs.io).
125 |
126 | ## Redux Todo example
127 |
128 | The following is a full example using the [Todo example](https://github.com/reactjs/redux/tree/master/examples/todos) within the Redux repository. The middleware will be added using the `Flux.addMiddleware()` automatically via the `createArkhamStore()` function.
129 |
130 | ```javascript
131 | import {Logger, LoggerDebugLevel} from '@nlabs/arkhamjs-middleware-logger';
132 | import {createArkhamStore} from '@nlabs/arkhamjs-middleware-redux';
133 | import {BrowserStorage} from '@nlabs/arkhamjs-storage-browser';
134 | import {Flux} from '@nlabs/arkhamjs';
135 | import * as React from 'react';
136 | import {render} from 'react-dom';
137 | import {Provider} from 'react-redux';
138 | import App from './components/App';
139 | import rootReducer from './reducers';
140 |
141 | // Add a console logger for Arkham (optional).
142 | const logger = new Logger({
143 | debugLevel: LoggerDebugLevel.DISPATCH
144 | });
145 |
146 | // Initialize ArkhamJS.
147 | const Flux.init({
148 | name: 'reduxDemo', // Optional name of application, defaults to 'arkhamjs'
149 | storage: new BrowserStorage(), // Optional persistent storage cache
150 | middleware: [logger] // Optional console logger
151 | });
152 |
153 | // Create an ArkhamJS store for Redux
154 | const store = createArkhamStore({
155 | flux: Flux,
156 | reducers: rootReducer,
157 | statePath: 'demo'
158 | });
159 |
160 | render(
161 |
162 |
163 | ,
164 | document.getElementById('root')
165 | );
166 | ```
167 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | module.exports = require('./lib');
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'web',
4 | useTypescript: true
5 | };
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-middleware-redux",
3 | "version": "3.28.4",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "Integrate ArkhamJS state management within Redux",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "module": "./lib/index.js",
11 | "browser": "./lib/index.js",
12 | "types": "./lib/index.d.ts",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "immutable",
17 | "middleware",
18 | "nitrogenlabs",
19 | "redux"
20 | ],
21 | "author": {
22 | "name": "Giraldo Rosales",
23 | "email": "giraldo@nitrogenlabs.com",
24 | "url": "http://nitrogenlabs.com"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "nitrogenlabs/arkhamjs.git"
29 | },
30 | "homepage": "https://arkhamjs.io",
31 | "bugs": {
32 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
33 | },
34 | "scripts": {
35 | "build": "lex compile --remove",
36 | "clean": "lex clean",
37 | "lint": "eslint ./src --ext .ts,.tsx",
38 | "prepublishOnly": "npm run build",
39 | "publish:major": "npm version major && npm publish",
40 | "publish:minor": "npm version minor && npm publish",
41 | "publish:patch": "npm version patch && npm publish",
42 | "pretest": "npm run lint",
43 | "test": "lex test",
44 | "update": "npm-check-updates --interactive"
45 | },
46 | "peerDependencies": {
47 | "@nlabs/arkhamjs": "^3.23",
48 | "redux": "^3.0"
49 | },
50 | "dependencies": {
51 | "lodash": "^4.17.21"
52 | },
53 | "devDependencies": {
54 | "@nlabs/arkhamjs": "*",
55 | "@types/jest": "^29.5.14",
56 | "@types/node": "^22.13.1",
57 | "@types/redux": "^3.6.31",
58 | "@types/webpack": "^5.28.5",
59 | "eslint": "^9.19.0",
60 | "eslint-config-styleguidejs": "^3.2.1",
61 | "redux": "^5.0.1",
62 | "typescript": "^5.7.3"
63 | },
64 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
65 | }
66 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/src/createArkhamStore.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {Flux} from '@nlabs/arkhamjs';
6 | import isPlainObject from 'lodash/isPlainObject';
7 | import merge from 'lodash/merge';
8 | import {applyMiddleware, createStore, Store} from 'redux';
9 |
10 | import {arkhamMiddleware} from './middleware/arkhamMiddleware';
11 | import {ReduxMiddleware} from './middleware/ReduxMiddleware';
12 | import {ArkhamReduxStoreType} from './types/main';
13 |
14 | export const createArkhamStore = (configuration: ArkhamReduxStoreType): Store => {
15 | const {
16 | arkhamMiddleware: middleware = [],
17 | flux,
18 | reducers,
19 | sagas,
20 | statePath = '',
21 | reduxMiddleware = [],
22 | devTools
23 | } = configuration;
24 |
25 | // Save initial state tree
26 | const {storage} = Flux.getOptions();
27 | let store: Store;
28 |
29 | if(storage) {
30 | const cachedState = Flux.getState(statePath);
31 |
32 | if(devTools) {
33 | store = createStore(
34 | devTools(reducers, cachedState),
35 | applyMiddleware(...reduxMiddleware, arkhamMiddleware(statePath, flux)));
36 | } else {
37 | store = createStore(
38 | reducers,
39 | cachedState,
40 | applyMiddleware(...reduxMiddleware, arkhamMiddleware(statePath, flux)));
41 | }
42 |
43 | if(cachedState === undefined) {
44 | const stateTree = store.getState();
45 | const updatedState = isPlainObject(stateTree) ? merge(stateTree, cachedState) : stateTree;
46 | Flux.setState(statePath, updatedState);
47 | }
48 | } else {
49 | store = createStore(
50 | reducers,
51 | devTools,
52 | applyMiddleware(...reduxMiddleware, arkhamMiddleware(statePath, flux))
53 | );
54 |
55 | Flux.setState(statePath, store.getState());
56 | }
57 |
58 | // If saga is being added, run.
59 | reduxMiddleware.every((item: any) => {
60 | if(sagas) {
61 | item.run(sagas);
62 | return false;
63 | }
64 |
65 | return true;
66 | });
67 |
68 | // Add redux middleware to Arkham to relay dispatches to Redux
69 | middleware.push(new ReduxMiddleware(store, statePath));
70 |
71 | // Initialize ArkhamJS
72 | Flux.addMiddleware(middleware);
73 |
74 | return store;
75 | };
76 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {createArkhamStore} from './createArkhamStore';
6 | import {arkhamMiddleware} from './middleware/arkhamMiddleware';
7 | import {ReduxMiddleware} from './middleware/ReduxMiddleware';
8 |
9 | export * from './types/main';
10 | export {ReduxMiddleware, arkhamMiddleware, createArkhamStore};
11 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/src/middleware/ReduxMiddleware.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {FluxAction} from '@nlabs/arkhamjs';
6 | import {Store} from 'redux';
7 |
8 | export class ReduxMiddleware {
9 | name: string;
10 | reduxStore: Store;
11 |
12 | constructor(reduxStore: Store, name: string) {
13 | this.name = name ? `reduxMiddleware-${name}` : 'reduxMiddleware';
14 | this.reduxStore = reduxStore;
15 |
16 | // Methods
17 | this.postDispatch = this.postDispatch.bind(this);
18 | }
19 |
20 | postDispatch(action): Promise {
21 | // ... Alter action if needed
22 | const {__ARKHAMJS_DISPATCH: isArkhamJs} = action;
23 |
24 | if(!isArkhamJs) {
25 | action.__ARKHAMJS_DISPATCH = true;
26 | this.reduxStore.dispatch(action);
27 | }
28 |
29 | return Promise.resolve(action);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/src/middleware/arkhamMiddleware.test.ts:
--------------------------------------------------------------------------------
1 | describe('arkhamMiddleware', () => {
2 | it('should emit altered data', () => {
3 | expect(true).toBe(true);
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/src/middleware/arkhamMiddleware.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | export const arkhamMiddleware = (statePath: string, Flux) => (store) => (next) => (action) => {
6 | const {__ARKHAMJS_DISPATCH: isArkhamJs} = action;
7 | delete action.__ARKHAMJS_DISPATCH;
8 |
9 | // Run the action through the redux reducers
10 | next(action);
11 |
12 | // Save the new, altered state within ArkhamJS
13 | Flux.setState(statePath, store.getState());
14 |
15 | // Make sure we emit the event through ArkhamJS for any listeners.
16 | if(!isArkhamJs) {
17 | action.__ARKHAMJS_DISPATCH = true;
18 | Flux.dispatch(action);
19 | }
20 |
21 | return null;
22 | };
23 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/src/types/main.ts:
--------------------------------------------------------------------------------
1 | import {AnyAction, Dispatch, Middleware} from 'redux';
2 |
3 | export interface ArkhamReduxStoreType {
4 | arkhamMiddleware: any[];
5 | devTools: any;
6 | flux: any;
7 | reducers: Dispatch;
8 | reduxMiddleware: Middleware[];
9 | sagas: any;
10 | statePath: string;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/arkhamjs-middleware-redux/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018"
23 | },
24 | "include": [
25 | "./src/**/*"
26 | ],
27 | "exclude": [
28 | "**/*.test.*",
29 | "lib",
30 | "./node_modules",
31 | "./test"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript"
3 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/.npmignore:
--------------------------------------------------------------------------------
1 | converage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | lex.config.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Nitrogen Labs, Inc.
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-storage-browser
2 |
3 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-browser)
4 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-browser)
5 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
6 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
7 | [](https://github.com/ellerbrock/typescript-badges/)
8 | [](http://opensource.org/licenses/MIT)
9 | [](https://discord.gg/Ttgev58)
10 |
11 | ## Installation
12 |
13 | Using [npm](https://www.npmjs.com/):
14 |
15 | ```shell
16 | npm i --save @nlabs/arkhamjs-storage-browser
17 | ```
18 |
19 | ## Documentation
20 |
21 | For detailed [Documentation](https://arkhamjs.io) and additional options.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | module.exports = require('./lib');
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'web',
4 | useTypescript: true
5 | };
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-storage-browser",
3 | "version": "3.28.3",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "Browser storage for ArkhamJS",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "module": "./lib/index.js",
11 | "browser": "./lib/index.js",
12 | "types": "./lib/index.d.ts",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "browser",
17 | "nitrogenlabs",
18 | "storage"
19 | ],
20 | "author": {
21 | "name": "Giraldo Rosales",
22 | "email": "giraldo@nitrogenlabs.com",
23 | "url": "http://nitrogenlabs.com"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "nitrogenlabs/arkhamjs.git"
28 | },
29 | "homepage": "https://arkhamjs.io",
30 | "bugs": {
31 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
32 | },
33 | "scripts": {
34 | "build": "lex compile --remove",
35 | "clean": "lex clean",
36 | "lint": "eslint ./src --ext .ts,.tsx",
37 | "prepublishOnly": "npm run build",
38 | "publish:major": "npm version major && npm publish",
39 | "publish:minor": "npm version minor && npm publish",
40 | "publish:patch": "npm version patch && npm publish",
41 | "pretest": "npm run lint",
42 | "reset": "lex clean",
43 | "test": "lex test",
44 | "update": "npm-check-updates --interactive"
45 | },
46 | "peerDependencies": {
47 | "@nlabs/arkhamjs": "^3.26.0"
48 | },
49 | "devDependencies": {
50 | "@nlabs/arkhamjs": "*",
51 | "@types/jest": "^29.5.14",
52 | "@types/node": "^22.13.1",
53 | "eslint": "^9.19.0",
54 | "eslint-config-styleguidejs": "^3.2.1",
55 | "typescript": "^5.7.3"
56 | },
57 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
58 | }
59 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/src/BrowserStorage/BrowserStorage.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {BrowserStorage} from './BrowserStorage';
6 |
7 |
8 | describe('BrowserStorage', () => {
9 | let localSpy;
10 | let sessionSpy;
11 | const val: string = 'hello_world';
12 | const key: string = 'test';
13 | const storage: BrowserStorage = new BrowserStorage({type: 'session'});
14 | BrowserStorage.window = {localStorage: jest.fn(), sessionStorage: jest.fn()};
15 |
16 | beforeAll(() => {
17 | // Mock storage
18 | const storageMock = () => {
19 | const storage: object = {};
20 |
21 | return {
22 | getItem: (storageGetKey: string) => storage[storageGetKey] || null,
23 | removeItem: (storageRemoveKey: string) => {
24 | delete storage[storageRemoveKey];
25 | },
26 | setItem: (storageSetKey, storageSetValue) => {
27 | storage[storageSetKey] = storageSetValue || '';
28 | }
29 | };
30 | };
31 |
32 | // Vars
33 | BrowserStorage.window.sessionStorage = storageMock();
34 | BrowserStorage.window.localStorage = storageMock();
35 |
36 | localSpy = jest.spyOn(BrowserStorage.window.localStorage, 'setItem');
37 | sessionSpy = jest.spyOn(BrowserStorage.window.sessionStorage, 'setItem');
38 | });
39 |
40 | afterEach(() => {
41 | localSpy.mockClear();
42 | sessionSpy.mockClear();
43 | });
44 |
45 | afterAll(() => {
46 | localSpy.mockRestore();
47 | sessionSpy.mockRestore();
48 | });
49 |
50 | describe('.delLocalData', () => {
51 | it('should remove local data', () => {
52 | // Method
53 | BrowserStorage.delLocalData(key);
54 | const testVal: string = BrowserStorage.getLocalData(key);
55 | expect(testVal).toEqual(null);
56 | });
57 | });
58 |
59 | describe('.delSessionData', () => {
60 | it('should remove session data', () => {
61 | // Method
62 | BrowserStorage.delSessionData(key);
63 | const testVal: string = BrowserStorage.getSessionData(key);
64 | expect(testVal).toEqual(null);
65 | });
66 | });
67 |
68 | describe('#getLocalData', () => {
69 | it('should get local data', () => {
70 | // Set data
71 | BrowserStorage.setLocalData(key, val);
72 |
73 | // Method
74 | const testVal: string = BrowserStorage.getLocalData(key);
75 | expect(testVal).toEqual(val);
76 | });
77 | });
78 |
79 | describe('.getLocalStorage', () => {
80 | it('check if localStorage exists', () => {
81 | const localStorage = BrowserStorage.getLocalStorage();
82 | expect(BrowserStorage.window.localStorage).toBe(localStorage);
83 | });
84 | });
85 |
86 | describe('.getSessionData', () => {
87 | it('should get session data', () => {
88 | // Method
89 | BrowserStorage.setSessionData(key, val);
90 | const testVal: string = BrowserStorage.getSessionData(key);
91 | expect(testVal).toEqual(val);
92 | });
93 | });
94 |
95 | describe('.getSessionStorage', () => {
96 | it('check if sessionStorage exists', () => {
97 | const sessionStorage = BrowserStorage.getSessionStorage();
98 | expect(BrowserStorage.window.sessionStorage).toBe(sessionStorage);
99 | });
100 | });
101 |
102 | describe('#getStorageData', () => {
103 | it('should get storage data', async () => {
104 | // Method
105 | BrowserStorage.setSessionData(key, val);
106 | const testVal: string = await storage.getStorageData(key);
107 | expect(testVal).toEqual(val);
108 | });
109 | });
110 |
111 | describe('#setLocalData', () => {
112 | it('should set local data', () => {
113 | // Method
114 | BrowserStorage.setLocalData(key, val);
115 | expect(localSpy.mock.calls.length).toEqual(1);
116 | });
117 | });
118 |
119 | describe('#setSessionData', () => {
120 | it('should set session data', () => {
121 | // Method
122 | BrowserStorage.setSessionData(key, val);
123 | expect(sessionSpy.mock.calls.length).toEqual(1);
124 | });
125 | });
126 |
127 | describe('#setStorageData', () => {
128 | it('should set storage data', () => {
129 | // Method
130 | storage.setStorageData(key, val);
131 | expect(sessionSpy.mock.calls.length).toEqual(1);
132 | });
133 | });
134 | });
135 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/src/BrowserStorage/BrowserStorage.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {BrowserStorageOptions} from '../types/main';
6 |
7 | export class BrowserStorage {
8 | static window: any = window || {};
9 | private options: BrowserStorageOptions = {
10 | type: 'session'
11 | };
12 |
13 | constructor(options: BrowserStorageOptions = {}) {
14 | // Methods
15 | this.getStorageData = this.getStorageData.bind(this);
16 | this.setStorageData = this.setStorageData.bind(this);
17 |
18 | // Configuration
19 | this.options = {...this.options, ...options};
20 | }
21 |
22 | /**
23 | * Removes a key from localStorage.
24 | *
25 | * @param {string} key Key associated with the data to remove.
26 | * @returns {boolean} Whether data was successfully removed.
27 | */
28 | static delLocalData(key: string): boolean {
29 | const localStorage = BrowserStorage.getLocalStorage();
30 |
31 | if(localStorage) {
32 | try {
33 | localStorage.removeItem(key);
34 | return true;
35 | } catch(error) {
36 | return false;
37 | }
38 | } else {
39 | return false;
40 | }
41 | }
42 |
43 | /**
44 | * Removes a key from sessionStorage.
45 | *
46 | * @param {string} key Key associated with the data to remove.
47 | * @returns {boolean} Whether data was successfully removed.
48 | */
49 | static delSessionData(key: string): boolean {
50 | const sessionStorage = BrowserStorage.getSessionStorage();
51 |
52 | if(sessionStorage) {
53 | try {
54 | sessionStorage.removeItem(key);
55 | return true;
56 | } catch(error) {
57 | return false;
58 | }
59 | } else {
60 | return false;
61 | }
62 | }
63 |
64 | /**
65 | * Get a key value from localStorage.
66 | *
67 | * @param {string} key The key for data.
68 | * @returns {any} the data object associated with the key.
69 | */
70 | static getLocalData(key: string): any {
71 | const localStorage = BrowserStorage.getLocalStorage();
72 |
73 | if(localStorage) {
74 | try {
75 | const item = localStorage.getItem(key);
76 |
77 | if(item) {
78 | return JSON.parse(item);
79 | }
80 |
81 | return null;
82 | } catch(error) {
83 | return null;
84 | }
85 | } else {
86 | return null;
87 | }
88 | }
89 |
90 | /**
91 | * Get localStorage from global window object.
92 | *
93 | * @param {string} key Key to store data.
94 | * @param {any} value Data to store.
95 | * @returns {any} window.localStorage.
96 | */
97 | static getLocalStorage(): any {
98 | const {localStorage} = BrowserStorage.window;
99 | return localStorage;
100 | }
101 |
102 | /**
103 | * Get a key value from sessionStorage.
104 | *
105 | * @param {string} key The key for data.
106 | * @returns {any} the data object associated with the key.
107 | */
108 | static getSessionData(key: string): any {
109 | const sessionStorage = BrowserStorage.getSessionStorage();
110 |
111 | if(sessionStorage) {
112 | try {
113 | const item = sessionStorage.getItem(key);
114 |
115 | if(item) {
116 | return item ? JSON.parse(item) : null;
117 | }
118 |
119 | return null;
120 | } catch(error) {
121 | return null;
122 | }
123 | } else {
124 | return null;
125 | }
126 | }
127 |
128 | /**
129 | * Get sessionStorage from global window object.
130 | *
131 | * @param {string} key Key to store data.
132 | * @param {any} value Data to store.
133 | * @returns {any} window.sessionStorage.
134 | */
135 | static getSessionStorage(): any {
136 | const {sessionStorage} = BrowserStorage.window;
137 |
138 | return sessionStorage;
139 | }
140 |
141 | /**
142 | * Saves data to localStorage.
143 | *
144 | * @param {string} key Key to store data.
145 | * @param {any} value Data to store.
146 | * @returns {boolean} Whether data was successfully saved.
147 | */
148 | static setLocalData(key: string, value): boolean {
149 | const localStorage = BrowserStorage.getLocalStorage();
150 |
151 | if(localStorage) {
152 | try {
153 | localStorage.setItem(key, JSON.stringify(value));
154 | return true;
155 | } catch(error) {
156 | return false;
157 | }
158 | } else {
159 | return false;
160 | }
161 | }
162 |
163 | /**
164 | * Saves data to sessionStorage.
165 | *
166 | * @param {string} key Key to store data.
167 | * @param {any} value Data to store.
168 | * @returns {boolean} Whether data was successfully saved.
169 | */
170 | static setSessionData(key: string, value): boolean {
171 | const sessionStorage = BrowserStorage.getSessionStorage();
172 |
173 | if(sessionStorage) {
174 | try {
175 | sessionStorage.setItem(key, JSON.stringify(value));
176 | return true;
177 | } catch(error) {
178 | return false;
179 | }
180 | } else {
181 | return false;
182 | }
183 | }
184 |
185 | /**
186 | * Get a key value from storage.
187 | *
188 | * @param {string} key The key for data.
189 | * @returns {Promise} the data object associated with the key.
190 | */
191 | getStorageData(key: string): Promise {
192 | const {type} = this.options;
193 | const results = type === 'local' ? BrowserStorage.getLocalData(key) : BrowserStorage.getSessionData(key);
194 | return Promise.resolve(results);
195 | }
196 |
197 | /**
198 | * Saves data to storage.
199 | *
200 | * @param {string} key Key to store data.
201 | * @param {any} value Data to store.
202 | * @returns {Promise} Whether data was successfully saved.
203 | */
204 | setStorageData(key: string, value): Promise {
205 | const {type} = this.options;
206 | const results: boolean = type === 'local' ?
207 | BrowserStorage.setLocalData(key, value) :
208 | BrowserStorage.setSessionData(key, value);
209 | return Promise.resolve(results);
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {BrowserStorage} from './BrowserStorage/BrowserStorage';
6 |
7 | // Storage
8 | export * from './types/main';
9 | export {BrowserStorage};
10 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/src/types/main.ts:
--------------------------------------------------------------------------------
1 | export interface BrowserStorageOptions {
2 | readonly type?: 'local' | 'session';
3 | }
4 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-browser/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018"
23 | },
24 | "include": [
25 | "./src/**/*"
26 | ],
27 | "exclude": [
28 | "**/*.test.*",
29 | "lib",
30 | "./node_modules",
31 | "./test"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript",
3 | "rules": {
4 | "import/no-deprecated": 0,
5 | "import/no-named-as-default": 0,
6 | "import/no-named-as-default-member": 0
7 | }
8 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | lex.config.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Nitrogen Labs, Inc.
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-storage-native
2 |
3 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-native)
4 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-native)
5 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
6 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
7 | [](https://github.com/ellerbrock/typescript-badges/)
8 | [](http://opensource.org/licenses/MIT)
9 | [](https://discord.gg/Ttgev58)
10 |
11 | ## Installation
12 |
13 | Using [npm](https://www.npmjs.com/):
14 |
15 | ```shell
16 | npm install --save @nlabs/arkhamjs-storage-native
17 | ```
18 |
19 | ## Documentation
20 |
21 | For detailed [Documentation](https://arkhamjs.io) and additional options.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | module.exports = require('./lib');
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'react-native',
4 | useTypescript: true
5 | };
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-storage-native",
3 | "version": "3.29.0",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "React Native storage for ArkhamJS",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "module": "./lib/index.js",
11 | "browser": "./lib/index.js",
12 | "types": "./lib/index.d.ts",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "native",
17 | "nitrogenlabs",
18 | "storage"
19 | ],
20 | "author": {
21 | "name": "Giraldo Rosales",
22 | "email": "giraldo@nitrogenlabs.com",
23 | "url": "http://nitrogenlabs.com"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "nitrogenlabs/arkhamjs.git"
28 | },
29 | "homepage": "https://arkhamjs.io",
30 | "bugs": {
31 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
32 | },
33 | "scripts": {
34 | "build": "lex compile --remove",
35 | "clean": "lex clean",
36 | "deploy": "lex build --remove && s3-deploy './lib/static/**' --cwd './lib/static/' --region us-east-1 --bucket arkhamjs.io/versions --gzip",
37 | "lint": "eslint ./src --ext .ts,.tsx",
38 | "prepublishOnly": "npm run build",
39 | "publish:major": "npm version major && npm publish",
40 | "publish:minor": "npm version minor && npm publish",
41 | "publish:patch": "npm version patch && npm publish",
42 | "pretest": "npm run lint",
43 | "test": "lex test",
44 | "update": "npm-check-updates --interactive"
45 | },
46 | "peerDependencies": {
47 | "@nlabs/arkhamjs": "^3.26.0",
48 | "react": "^18.0.0 || ^19.0.0"
49 | },
50 | "devDependencies": {
51 | "@nlabs/arkhamjs": "*",
52 | "@types/jest": "^29.5.14",
53 | "@types/node": "^22.13.1",
54 | "eslint": "^9.19.0",
55 | "eslint-config-styleguidejs": "^3.2.1",
56 | "lodash": "^4.17.21",
57 | "typescript": "^5.7.3"
58 | },
59 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a",
60 | "dependencies": {
61 | "@react-native-async-storage/async-storage": "^2.1.1"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/src/NativeStorage/NativeStorage.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {NativeStorage} from './NativeStorage';
6 |
7 | describe('NativeStorage', () => {
8 | it('should set async data', async () => {
9 | const hasExistingData = await NativeStorage.getAsyncData('test');
10 | expect(hasExistingData).toBe(undefined);
11 |
12 | const result = await NativeStorage.setAsyncData('test', 'hello world');
13 | expect(result).toBe(true);
14 |
15 | const hasNewData = await NativeStorage.getAsyncData('test');
16 | expect(hasNewData).toBe('hello world');
17 | });
18 |
19 | it('should delete async data', async () => {
20 | const hasExistingData = await NativeStorage.getAsyncData('test');
21 | expect(hasExistingData).toBe(undefined);
22 |
23 | const result = await NativeStorage.delAsyncData('test');
24 | expect(result).toBe(true);
25 |
26 | const hasNewData = await NativeStorage.getAsyncData('test');
27 | expect(hasNewData).toBe(undefined);
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/src/NativeStorage/NativeStorage.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import AsyncStorage from '@react-native-async-storage/async-storage';
6 |
7 | import {NativeStorageOptions} from './NativeStorage.types';
8 |
9 | export class NativeStorage {
10 | private options: NativeStorageOptions = {};
11 |
12 | constructor(options: NativeStorageOptions = {}) {
13 | // Methods
14 | this.getStorageData = this.getStorageData.bind(this);
15 | this.setStorageData = this.setStorageData.bind(this);
16 |
17 | // Configuration
18 | this.options = {...this.options, ...options};
19 | }
20 |
21 | /**
22 | * Removes a key from AsyncStorage.
23 | *
24 | * @param {string} key Key associated with the data to remove.
25 | * @returns {Promise} Whether data was successfully removed.
26 | */
27 | static delAsyncData(key: string): Promise {
28 | try {
29 | return AsyncStorage.removeItem(key)
30 | .then(() => Promise.resolve(true))
31 | .catch(() => Promise.resolve(false));
32 | } catch(error) {
33 | return Promise.resolve(false);
34 | }
35 | }
36 |
37 | /**
38 | * Get a key value from AsyncStorage.
39 | *
40 | * @param {string} key The key for data.
41 | * @returns {Promise} the data object associated with the key.
42 | */
43 | static getAsyncData(key: string): Promise {
44 | try {
45 | return AsyncStorage.getItem(key)
46 | .then((value: string) => {
47 | const updatedValue = value ? JSON.parse(value) : null;
48 | return updatedValue;
49 | })
50 | .catch(() => Promise.resolve(null));
51 | } catch(error) {
52 | return Promise.resolve(null);
53 | }
54 | }
55 |
56 | /**
57 | * Saves data to AsyncStorage.
58 | *
59 | * @param {string} key Key to store data.
60 | * @param {any} value Data to store.
61 | * @returns {Promise} Whether data was successfully saved.
62 | */
63 | static setAsyncData(key: string, value): Promise {
64 | const updatedValue = value !== undefined && JSON.stringify(value);
65 |
66 | try {
67 | return AsyncStorage.setItem(key, updatedValue)
68 | .then(() => true)
69 | .catch(() => Promise.resolve(false));
70 | } catch(error) {
71 | return Promise.resolve(false);
72 | }
73 | }
74 |
75 | /**
76 | * Get a key value from storage.
77 | *
78 | * @param {string} key The key for data.
79 | * @returns {Promise} the data object associated with the key.
80 | */
81 | getStorageData(key: string): Promise {
82 | return NativeStorage.getAsyncData(key);
83 | }
84 |
85 | /**
86 | * Saves data to storage.
87 | *
88 | * @param {string} key Key to store data.
89 | * @param {any} value Data to store.
90 | * @returns {Promise} Whether data was successfully saved.
91 | */
92 | setStorageData(key: string, value): Promise {
93 | return NativeStorage.setAsyncData(key, value);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/src/NativeStorage/NativeStorage.types.ts:
--------------------------------------------------------------------------------
1 | export interface NativeStorageOptions {}
2 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {NativeStorage} from './NativeStorage/NativeStorage';
6 |
7 |
8 | // Storage
9 | export * from './NativeStorage/NativeStorage.types';
10 |
11 | export {NativeStorage};
12 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-native/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "allowSyntheticDefaultImports": true,
5 | "baseUrl": "./src",
6 | "declaration": true,
7 | "emitDeclarationOnly": true,
8 | "esModuleInterop": true,
9 | "inlineSourceMap": true,
10 | "jsx": "react-jsx",
11 | "lib": [
12 | "esnext",
13 | "dom"
14 | ],
15 | "module": "commonjs",
16 | "moduleResolution": "node",
17 | "noImplicitReturns": true,
18 | "noImplicitThis": true,
19 | "noUnusedLocals": true,
20 | "outDir": "lib",
21 | "pretty": true,
22 | "skipLibCheck": true,
23 | "target": "ES2018"
24 | },
25 | "include": [
26 | "./src/**/*"
27 | ],
28 | "exclude": [
29 | "**/*.test.*",
30 | "lib",
31 | "./node_modules",
32 | "./test"
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript"
3 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/.npmignore:
--------------------------------------------------------------------------------
1 | .node-persist
2 | coverage
3 | docs
4 | node_modules
5 | src
6 | .eslintrc
7 | .travis.yml
8 | jest.setup.js
9 | lex.config.js
10 | package-lock.json
11 | tsconfig.json
12 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "20"
4 | install:
5 | - npm i -g @nlabs/lex
6 | - lex versions
7 | script:
8 | - npm run build
9 | - npm run test
10 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Nitrogen Labs, Inc.
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs-storage-node
2 |
3 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-node)
4 | [](https://www.npmjs.com/package/@nlabs/arkhamjs-storage-node)
5 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
6 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
7 | [](https://github.com/ellerbrock/typescript-badges/)
8 | [](http://opensource.org/licenses/MIT)
9 | [](https://discord.gg/Ttgev58)
10 |
11 | ## Installation
12 |
13 | Using [npm](https://www.npmjs.com/):
14 |
15 | ```shell
16 | npm i --save @nlabs/arkhamjs-storage-node
17 | ```
18 |
19 | ## Documentation
20 |
21 | For detailed [Documentation](https://arkhamjs.io) and additional options.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | module.exports = require('./lib');
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/jest.setup.js:
--------------------------------------------------------------------------------
1 | jest.mock('node-persist', () => ({
2 | init: (options) => jest.fn(),
3 | getItem: (key) => Promise.resolve(jest.fn()),
4 | removeItem: (key) => Promise.resolve(jest.fn()),
5 | setItem: (key, val) => Promise.resolve(jest.fn())
6 | }));
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'node',
4 | useTypescript: true
5 | };
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-storage-node",
3 | "version": "3.28.3",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "NodeJS storage for ArkhamJS",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "module": "./lib/index.js",
11 | "browser": "./lib/index.js",
12 | "types": "./lib/index.d.ts",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "node",
17 | "nitrogenlabs",
18 | "storage"
19 | ],
20 | "author": {
21 | "name": "Giraldo Rosales",
22 | "email": "giraldo@nitrogenlabs.com",
23 | "url": "http://nitrogenlabs.com"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "nitrogenlabs/arkhamjs.git"
28 | },
29 | "homepage": "https://arkhamjs.io",
30 | "bugs": {
31 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
32 | },
33 | "scripts": {
34 | "build": "lex compile --remove",
35 | "clean": "lex clean",
36 | "lint": "eslint ./src --ext .ts,.tsx",
37 | "prepublishOnly": "npm run build",
38 | "publish:major": "npm version major && npm publish",
39 | "publish:minor": "npm version minor && npm publish",
40 | "publish:patch": "npm version patch && npm publish",
41 | "pretest": "npm run lint",
42 | "test": "lex test --setup ./jest.setup.js",
43 | "update": "npm-check-updates --interactive"
44 | },
45 | "dependencies": {
46 | "node-persist": "^4.0.4"
47 | },
48 | "peerDependencies": {
49 | "@nlabs/arkhamjs": "^3.26.0"
50 | },
51 | "devDependencies": {
52 | "@nlabs/arkhamjs": "*",
53 | "@types/jest": "^29.5.14",
54 | "@types/node": "^22.13.1",
55 | "@types/node-persist": "^3.1.8",
56 | "eslint": "^9.19.0",
57 | "eslint-config-styleguidejs": "^3.2.1",
58 | "typescript": "^5.7.3"
59 | },
60 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
61 | }
62 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/src/NodeStorage/NodeStorage.test.ts:
--------------------------------------------------------------------------------
1 | import PersistStorage from 'node-persist';
2 |
3 | import {NodeStorage} from './NodeStorage';
4 |
5 | /**
6 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
7 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
8 | */
9 |
10 | describe('NodeStorage', () => {
11 | beforeAll(() => {
12 | new NodeStorage();
13 | });
14 |
15 | describe('.delPersistData', () => {
16 | let storageSpy;
17 |
18 | beforeAll(() => {
19 | // Spy
20 | storageSpy = jest.spyOn(PersistStorage, 'removeItem');
21 | });
22 |
23 | afterAll(() => {
24 | storageSpy.mockRestore();
25 | });
26 |
27 | it('should delete async data', async () => {
28 | await NodeStorage.delPersistData('test');
29 | expect(storageSpy.mock.calls.length).toBe(1);
30 | });
31 | });
32 |
33 | describe('.getPersistData', () => {
34 | let storageSpy;
35 |
36 | beforeAll(() => {
37 | // Spy
38 | storageSpy = jest.spyOn(PersistStorage, 'getItem');
39 | });
40 |
41 | afterAll(() => {
42 | storageSpy.mockRestore();
43 | });
44 |
45 | it('should delete async data', async () => {
46 | await NodeStorage.getPersistData('test');
47 | expect(storageSpy.mock.calls.length).toBe(1);
48 | });
49 | });
50 |
51 | describe('.setPersistData', () => {
52 | let storageSpy;
53 |
54 | beforeAll(() => {
55 | // Spy
56 | storageSpy = jest.spyOn(PersistStorage, 'setItem');
57 | });
58 |
59 | afterAll(() => {
60 | storageSpy.mockRestore();
61 | });
62 |
63 | it('should delete async data', async () => {
64 | await NodeStorage.setPersistData('test', 'hello world');
65 | expect(storageSpy.mock.calls.length).toBe(1);
66 | });
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/src/NodeStorage/NodeStorage.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import PersistStorage, {InitOptions} from 'node-persist';
6 |
7 | export class NodeStorage {
8 | private options: InitOptions = {
9 | dir: '/tmp',
10 | encoding: 'utf8',
11 | expiredInterval: 3 * 60 * 1000,
12 | forgiveParseErrors: false,
13 | logging: false,
14 | parse: JSON.parse,
15 | stringify: JSON.stringify
16 | };
17 |
18 | constructor(options: InitOptions = {}) {
19 | // Methods
20 | this.clearStorageData = this.clearStorageData.bind(this);
21 | this.getStorageData = this.getStorageData.bind(this);
22 | this.setStorageData = this.setStorageData.bind(this);
23 |
24 | // Configuration
25 | this.options = {...this.options, ...options};
26 | PersistStorage.init(this.options);
27 | }
28 |
29 | /**
30 | * Removes all keys from persistent data.
31 | *
32 | * @returns {Promise} Whether data was successfully removed.
33 | */
34 | static clearPersistData(): Promise {
35 | try {
36 | return new Promise((resolve) => {
37 | PersistStorage.clear()
38 | .then(() => resolve(true))
39 | .catch(() => resolve(false));
40 | });
41 | } catch(error) {
42 | return Promise.resolve(false);
43 | }
44 | }
45 |
46 | /**
47 | * Removes a key from persistent data.
48 | *
49 | * @param {string} key Key associated with the data to remove.
50 | * @returns {Promise} Whether data was successfully removed.
51 | */
52 | static delPersistData(key: string): Promise {
53 | try {
54 | return new Promise((resolve) => {
55 | PersistStorage.removeItem(key)
56 | .then(() => resolve(true))
57 | .catch(() => resolve(false));
58 | });
59 | } catch(error) {
60 | return Promise.resolve(false);
61 | }
62 | }
63 |
64 | /**
65 | * Get a key value from persistent data.
66 | *
67 | * @param {string} key The key for data.
68 | * @returns {Promise} the data object associated with the key.
69 | */
70 | static getPersistData(key: string): Promise {
71 | try {
72 | return new Promise((resolve) => {
73 | PersistStorage.getItem(key)
74 | .then((value: string) => {
75 | const updatedValue = value ? JSON.parse(value) : null;
76 | resolve(updatedValue);
77 | })
78 | .catch(() => resolve(null));
79 | });
80 | } catch(error) {
81 | return Promise.resolve(null);
82 | }
83 | }
84 |
85 | /**
86 | * Saves data to persistent data.
87 | *
88 | * @param {string} key Key to store data.
89 | * @param {any} value Data to store.
90 | * @returns {Promise} Whether data was successfully saved.
91 | */
92 | static setPersistData(key: string, value): Promise {
93 | try {
94 | return new Promise((resolve) => {
95 | PersistStorage.setItem(key, value)
96 | .then(() => resolve(true))
97 | .catch(() => resolve(false));
98 | });
99 | } catch(error) {
100 | return Promise.resolve(false);
101 | }
102 | }
103 |
104 | /**
105 | * Clears all data from storage.
106 | *
107 | * @returns {Promise} Whether data was successfully saved.
108 | */
109 | clearStorageData(): Promise {
110 | return NodeStorage.clearPersistData();
111 | }
112 |
113 | /**
114 | * Get a key value from storage.
115 | *
116 | * @param {string} key The key for data.
117 | * @returns {Promise} the data object associated with the key.
118 | */
119 | getStorageData(key: string): Promise {
120 | return NodeStorage.getPersistData(key);
121 | }
122 |
123 | /**
124 | * Saves data to storage.
125 | *
126 | * @param {string} key Key to store data.
127 | * @param {any} value Data to store.
128 | * @returns {Promise} Whether data was successfully saved.
129 | */
130 | setStorageData(key: string, value): Promise {
131 | return NodeStorage.setPersistData(key, value);
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {NodeStorage} from './NodeStorage/NodeStorage';
6 |
7 | // Storage
8 | export {NodeStorage};
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-storage-node/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018",
23 | "typeRoots": [
24 | "node_modules/@types",
25 | "node_modules/json-d-ts"
26 | ]
27 | },
28 | "include": [
29 | "./src/**/*"
30 | ],
31 | "exclude": [
32 | "**/*.test.*",
33 | "lib",
34 | "./node_modules",
35 | "./test"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/.eslintignore:
--------------------------------------------------------------------------------
1 | ResizeObserver.d.ts
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript"
3 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | lex.config.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Nitrogen Labs, Inc.
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/README:
--------------------------------------------------------------------------------
1 | # arkhamjs-utils-react
2 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | module.exports = require('./lib');
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'web',
4 | useTypescript: true
5 | };
6 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs-utils-react",
3 | "version": "3.29.0",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "ArkhamJS React Utilities",
8 | "license": "MIT",
9 | "main": "./lib/index.js",
10 | "browser": "./lib/index.js",
11 | "types": "./lib/index.d.js",
12 | "keywords": [
13 | "arkhamjs",
14 | "flux",
15 | "global state",
16 | "nitrogenlabs",
17 | "state",
18 | "state management",
19 | "useFlux",
20 | "useComponentSize",
21 | "useRefSize",
22 | "useWindowSize"
23 | ],
24 | "contributors": [
25 | {
26 | "name": "Giraldo Rosales",
27 | "email": "giraldo@nitrogenlabs.com",
28 | "url": "http://nitrogenlabs.com"
29 | },
30 | {
31 | "name": "Sartaj Chowdhury",
32 | "email": "sartaj@sartaj.me",
33 | "url": "http://github.com/Sartaj"
34 | }
35 | ],
36 | "repository": {
37 | "type": "git",
38 | "url": "nitrogenlabs/arkhamjs.git"
39 | },
40 | "homepage": "https://arkhamjs.io",
41 | "bugs": {
42 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
43 | },
44 | "scripts": {
45 | "build": "lex compile --remove",
46 | "clean": "lex clean",
47 | "lint": "eslint ./src --ext .ts,.tsx",
48 | "prepublishOnly": "npm run build",
49 | "publish:major": "npm version major && npm publish",
50 | "publish:minor": "npm version minor && npm publish",
51 | "publish:patch": "npm version patch && npm publish",
52 | "pretest": "npm run lint",
53 | "test": "lex test",
54 | "update": "npm-check-updates --interactive"
55 | },
56 | "dependencies": {
57 | "lodash": "^4.17.21"
58 | },
59 | "devDependencies": {
60 | "@nlabs/arkhamjs": "*",
61 | "@types/jest": "^29.5.14",
62 | "@types/lodash": "^4.17.15",
63 | "@types/node": "^22.13.1",
64 | "eslint": "^9.19.0",
65 | "eslint-config-styleguidejs": "^3.2.1",
66 | "react": "^19.0.0",
67 | "react-test-renderer": "^19.0.0",
68 | "typescript": "^5.7.3"
69 | },
70 | "peerDependencies": {
71 | "@nlabs/arkhamjs": "^3.26.0",
72 | "react": "^18.0.0 || ^19.0.0"
73 | },
74 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
75 | }
76 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/FluxContext.ts:
--------------------------------------------------------------------------------
1 | import {createContext} from 'react';
2 |
3 | export const FluxContext = createContext(null);
4 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/FluxProvider.test.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {Flux} from '@nlabs/arkhamjs';
6 |
7 | import {FluxProvider} from './FluxProvider';
8 |
9 | describe('FluxProvider', () => {
10 | let children: any[];
11 | let provider;
12 |
13 | beforeAll(() => {
14 | Flux.init();
15 | children = [];
16 | const props = {Flux, children};
17 | provider = ;
18 | });
19 |
20 | it('should create a provider with Flux', () => {
21 | expect(provider.props.Flux).toEqual(Flux);
22 | });
23 |
24 | it('should create a provider with children', () => {
25 | expect(provider.props.children).toEqual(children);
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/FluxProvider.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import isEqual from 'lodash/isEqual';
6 | import {FC, useEffect, useRef, useState} from 'react';
7 |
8 | import {FluxContext} from './FluxContext';
9 | import {FluxProviderProps} from './FluxProvider.types';
10 |
11 | export const FluxProvider: FC = ({children, flux}) => {
12 | const [state, setState] = useState(flux.getState());
13 | const ref = useRef(state);
14 |
15 | useEffect(() => {
16 | const updateState = (newState) => {
17 | if(!isEqual(newState, ref.current)) {
18 | ref.current = newState;
19 | setState(newState);
20 | }
21 | };
22 | flux.addListener('arkhamjs', updateState);
23 |
24 | return () => {
25 | flux.removeListener('arkhamjs', updateState);
26 | };
27 | }, []);
28 |
29 | return {children};
30 | };
31 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/FluxProvider.types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {FluxFramework} from '@nlabs/arkhamjs';
6 |
7 | export interface FluxProviderProps {
8 | children?: any;
9 | flux: FluxFramework;
10 | state?: any;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/ResizeObserver.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The **ResizeObserver** interface reports changes to the dimensions of an
3 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)'s content
4 | * or border box, or the bounding box of an
5 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement).
6 | *
7 | * > **Note**: The content box is the box in which content can be placed,
8 | * > meaning the border box minus the padding and border width. The border box
9 | * > encompasses the content, padding, and border. See
10 | * > [The box model](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model)
11 | * > for further explanation.
12 | *
13 | * `ResizeObserver` avoids infinite callback loops and cyclic dependencies that
14 | * are often created when resizing via a callback function. It does this by only
15 | * processing elements deeper in the DOM in subsequent frames. Implementations
16 | * should, if they follow the specification, invoke resize events before paint
17 | * and after layout.
18 | *
19 | * @see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
20 | */
21 | class ResizeObserver {
22 | /**
23 | * The **ResizeObserver** constructor creates a new `ResizeObserver` object,
24 | * which can be used to report changes to the content or border box of an
25 | * `Element` or the bounding box of an `SVGElement`.
26 | *
27 | * @example
28 | * var ResizeObserver = new ResizeObserver(callback)
29 | *
30 | * @param callback
31 | * The function called whenever an observed resize occurs. The function is
32 | * called with two parameters:
33 | * * **entries**
34 | * An array of
35 | * [ResizeObserverEntry](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry)
36 | * objects that can be used to access the new dimensions of the element
37 | * after each change.
38 | * * **observer**
39 | * A reference to the `ResizeObserver` itself, so it will definitely be
40 | * accessible from inside the callback, should you need it. This could be
41 | * used for example to automatically unobserve the observer when a certain
42 | * condition is reached, but you can omit it if you don't need it.
43 | *
44 | * The callback will generally follow a pattern along the lines of:
45 | * ```js
46 | * function(entries, observer) {
47 | * for (let entry of entries) {
48 | * // Do something to each entry
49 | * // and possibly something to the observer itself
50 | * }
51 | * }
52 | * ```
53 | *
54 | * The following snippet is taken from the
55 | * [resize-observer-text.html](https://mdn.github.io/dom-examples/resize-observer/resize-observer-text.html)
56 | * ([see source](https://github.com/mdn/dom-examples/blob/master/resize-observer/resize-observer-text.html))
57 | * example:
58 | * @example
59 | * const resizeObserver = new ResizeObserver(entries => {
60 | * for (let entry of entries) {
61 | * if(entry.contentBoxSize) {
62 | * h1Elem.style.fontSize = Math.max(1.5, entry.contentBoxSize.inlineSize/200) + 'rem';
63 | * pElem.style.fontSize = Math.max(1, entry.contentBoxSize.inlineSize/600) + 'rem';
64 | * } else {
65 | * h1Elem.style.fontSize = Math.max(1.5, entry.contentRect.width/200) + 'rem';
66 | * pElem.style.fontSize = Math.max(1, entry.contentRect.width/600) + 'rem';
67 | * }
68 | * }
69 | * });
70 | *
71 | * resizeObserver.observe(divElem);
72 | */
73 | constructor(callback: ResizeObserverCallback);
74 |
75 | /**
76 | * The **disconnect()** method of the
77 | * [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver)
78 | * interface unobserves all observed
79 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) or
80 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement)
81 | * targets.
82 | */
83 | disconnect: () => void;
84 |
85 | /**
86 | * The `observe()` method of the
87 | * [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver)
88 | * interface starts observing the specified
89 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) or
90 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement).
91 | *
92 | * @example
93 | * resizeObserver.observe(target, options);
94 | *
95 | * @param target
96 | * A reference to an
97 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) or
98 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement)
99 | * to be observed.
100 | *
101 | * @param options
102 | * An options object allowing you to set options for the observation.
103 | * Currently this only has one possible option that can be set.
104 | */
105 | observe: (target: Element, options?: ResizeObserverObserveOptions) => void;
106 |
107 | /**
108 | * The **unobserve()** method of the
109 | * [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver)
110 | * interface ends the observing of a specified
111 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) or
112 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement).
113 | */
114 | unobserve: (target: Element) => void;
115 | }
116 |
117 | interface ResizeObserverObserveOptions {
118 | /**
119 | * Sets which box model the observer will observe changes to. Possible values
120 | * are `content-box` (the default), and `border-box`.
121 | *
122 | * @default "content-box"
123 | */
124 | box?: "content-box" | "border-box";
125 | }
126 |
127 | /**
128 | * The function called whenever an observed resize occurs. The function is
129 | * called with two parameters:
130 | *
131 | * @param entries
132 | * An array of
133 | * [ResizeObserverEntry](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry)
134 | * objects that can be used to access the new dimensions of the element after
135 | * each change.
136 | *
137 | * @param observer
138 | * A reference to the `ResizeObserver` itself, so it will definitely be
139 | * accessible from inside the callback, should you need it. This could be used
140 | * for example to automatically unobserve the observer when a certain condition
141 | * is reached, but you can omit it if you don't need it.
142 | *
143 | * The callback will generally follow a pattern along the lines of:
144 | * @example
145 | * function(entries, observer) {
146 | * for (let entry of entries) {
147 | * // Do something to each entry
148 | * // and possibly something to the observer itself
149 | * }
150 | * }
151 | *
152 | * @example
153 | * const resizeObserver = new ResizeObserver(entries => {
154 | * for (let entry of entries) {
155 | * if(entry.contentBoxSize) {
156 | * h1Elem.style.fontSize = Math.max(1.5, entry.contentBoxSize.inlineSize/200) + 'rem';
157 | * pElem.style.fontSize = Math.max(1, entry.contentBoxSize.inlineSize/600) + 'rem';
158 | * } else {
159 | * h1Elem.style.fontSize = Math.max(1.5, entry.contentRect.width/200) + 'rem';
160 | * pElem.style.fontSize = Math.max(1, entry.contentRect.width/600) + 'rem';
161 | * }
162 | * }
163 | * });
164 | *
165 | * resizeObserver.observe(divElem);
166 | */
167 | type ResizeObserverCallback = (
168 | entries: ResizeObserverEntry[],
169 | observer: ResizeObserver,
170 | ) => void;
171 |
172 | /**
173 | * The **ResizeObserverEntry** interface represents the object passed to the
174 | * [ResizeObserver()](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver)
175 | * constructor's callback function, which allows you to access the new
176 | * dimensions of the
177 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) or
178 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement)
179 | * being observed.
180 | */
181 | interface ResizeObserverEntry {
182 | /**
183 | * An object containing the new border box size of the observed element when
184 | * the callback is run.
185 | */
186 | readonly borderBoxSize: ResizeObserverEntryBoxSize;
187 |
188 | /**
189 | * An object containing the new content box size of the observed element when
190 | * the callback is run.
191 | */
192 | readonly contentBoxSize: ResizeObserverEntryBoxSize;
193 |
194 | /**
195 | * A [DOMRectReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly)
196 | * object containing the new size of the observed element when the callback is
197 | * run. Note that this is better supported than the above two properties, but
198 | * it is left over from an earlier implementation of the Resize Observer API,
199 | * is still included in the spec for web compat reasons, and may be deprecated
200 | * in future versions.
201 | */
202 | // node_modules/typescript/lib/lib.dom.d.ts
203 | readonly contentRect: DOMRectReadOnly;
204 |
205 | /**
206 | * A reference to the
207 | * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) or
208 | * [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement)
209 | * being observed.
210 | */
211 | readonly target: Element;
212 | }
213 |
214 | /**
215 | * The **borderBoxSize** read-only property of the
216 | * [ResizeObserverEntry](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry)
217 | * interface returns an object containing the new border box size of the
218 | * observed element when the callback is run.
219 | */
220 | interface ResizeObserverEntryBoxSize {
221 | /**
222 | * The length of the observed element's border box in the block dimension. For
223 | * boxes with a horizontal
224 | * [writing-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode),
225 | * this is the vertical dimension, or height; if the writing-mode is vertical,
226 | * this is the horizontal dimension, or width.
227 | */
228 | blockSize: number;
229 |
230 | /**
231 | * The length of the observed element's border box in the inline dimension.
232 | * For boxes with a horizontal
233 | * [writing-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode),
234 | * this is the horizontal dimension, or width; if the writing-mode is
235 | * vertical, this is the vertical dimension, or height.
236 | */
237 | inlineSize: number;
238 | }
239 |
240 | interface Window {
241 | ResizeObserver: ResizeObserver;
242 | }
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | export {FluxContext} from './FluxContext';
6 | export {FluxProvider} from './FluxProvider';
7 | export {useComponentSize} from './useComponentSize';
8 | export {useFlux} from './useFlux';
9 | export {useFluxDispatch} from './useFluxDispatch';
10 | export {useFluxListener} from './useFluxListener';
11 | export {useFluxState} from './useFluxState';
12 | export {useFluxValue} from './useFluxValue';
13 | export {useRefSize} from './useRefSize';
14 | export {useState} from './useState';
15 | export {useWindowSize} from './useWindowSize';
16 |
17 | export * from './FluxProvider.types';
18 | export * from './useWindowSize.types';
19 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useComponentSize.ts:
--------------------------------------------------------------------------------
1 | import {useCallback, useLayoutEffect, useState} from 'react';
2 |
3 | export const getComponentSize = (element) => {
4 | if(!element) {
5 | return {height: undefined, width: undefined};
6 | }
7 |
8 | const {offsetHeight: height, offsetWidth: width} = element;
9 | return {height, width};
10 | };
11 |
12 | export const useComponentSize = (component) => {
13 | const [componentSize, setComponentSize] = useState(getComponentSize(component));
14 | const onResize = useCallback(() => {
15 | if(component) {
16 | setComponentSize(getComponentSize(component));
17 | }
18 | }, [component]);
19 |
20 | useLayoutEffect(() => {
21 | if(!component) {
22 | return () => {};
23 | }
24 |
25 | onResize();
26 |
27 | if(typeof ResizeObserver === 'function') {
28 | let resizeObserver = new ResizeObserver(onResize);
29 | resizeObserver.observe(component);
30 |
31 | return () => {
32 | resizeObserver.disconnect();
33 | resizeObserver = null;
34 | };
35 | }
36 |
37 | window.addEventListener('resize', onResize);
38 | return () => window.removeEventListener('resize', onResize);
39 | }, [component]);
40 |
41 | return componentSize;
42 | };
43 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useFlux.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2022-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {useContext} from 'react';
6 |
7 | import {FluxContext} from './FluxContext';
8 |
9 | export const useFlux = (): any => {
10 | const {flux} = useContext(FluxContext);
11 | return flux;
12 | };
13 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useFluxDispatch.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {useContext} from 'react';
6 |
7 | import {FluxContext} from './FluxContext';
8 |
9 | export const useFluxDispatch = (type: string, data: any = {}, silent: boolean = false) => {
10 | const {flux} = useContext(FluxContext);
11 | return flux.dispatch({...data, type}, silent);
12 | };
13 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useFluxListener.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {useContext, useEffect} from 'react';
6 |
7 | import {FluxContext} from './FluxContext';
8 |
9 | export const useFluxListener = (type: string, handler: (data?: any) => any) => {
10 | const {flux} = useContext(FluxContext);
11 |
12 | useEffect(() => {
13 | flux.on(type, handler);
14 |
15 | return () => {
16 | flux.off(type, handler);
17 | };
18 | }, []);
19 |
20 | return handler;
21 | };
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useFluxState.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import isEqual from 'lodash/isEqual';
6 | import {useContext, useEffect, useRef, useState} from 'react';
7 |
8 | import {FluxContext} from './FluxContext';
9 |
10 | export const useFluxState = (key: string | string[], defaultValue?: any): any => {
11 | const {flux, state} = useContext(FluxContext);
12 | const ref = useRef();
13 | const value = flux.getState(key, defaultValue);
14 | const [updatedValue, setValue] = useState(value);
15 |
16 | useEffect(() => {
17 | if(!isEqual(value, ref.current)) {
18 | ref.current = value;
19 | setValue(value);
20 | }
21 | }, [state]);
22 |
23 | return updatedValue;
24 | };
25 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useFluxValue.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {useContext} from 'react';
6 |
7 | import {FluxContext} from './FluxContext';
8 |
9 | export const useFluxValue = (key: string | string[], defaultValue?: any): any => {
10 | const {flux} = useContext(FluxContext);
11 | return flux.getState(key, defaultValue);
12 | };
13 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useRefSize.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {useComponentSize} from './useComponentSize';
6 |
7 | export const useRefSize = (ref) => {
8 | const {current: component = {}} = ref;
9 | return useComponentSize(component);
10 | };
11 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useState.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import isPlainObject from 'lodash/isPlainObject';
6 | import merge from 'lodash/merge';
7 | import {useState as useReactState} from 'react';
8 |
9 | export const useState = (initialState: any) => {
10 | const [state, setNewState] = useReactState(
11 | (prevState: any) => {
12 | if(isPlainObject(initialState)) {
13 | return merge(prevState, initialState);
14 | }
15 |
16 | return initialState;
17 | });
18 |
19 | return [
20 | state,
21 | setNewState
22 | ];
23 | };
24 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useWindowSize.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import {useEffect, useState} from 'react';
6 |
7 | import {WindowSize} from './useWindowSize.types';
8 |
9 | export const isClient = typeof window === 'object';
10 |
11 | export const getWindowSize = () => {
12 | if(isClient) {
13 | const {innerHeight: height, innerWidth: width} = window;
14 | return {height, width};
15 | }
16 |
17 | return {height: undefined, width: undefined};
18 | };
19 |
20 | export const useWindowSize = (): WindowSize => {
21 | const [size, setSize] = useState(getWindowSize());
22 |
23 | useEffect(() => {
24 | if(!isClient) {
25 | return () => {};
26 | }
27 |
28 | const onResize = () => setSize(getWindowSize());
29 | window.addEventListener('resize', onResize);
30 | return () => window.removeEventListener('resize', onResize);
31 | }, []);
32 |
33 | return size;
34 | };
35 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/src/useWindowSize.types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | export interface WindowSize {
6 | readonly height: number;
7 | readonly width: number;
8 | }
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs-utils-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": true,
4 | "baseUrl": "./src",
5 | "declaration": true,
6 | "emitDeclarationOnly": true,
7 | "esModuleInterop": true,
8 | "inlineSourceMap": true,
9 | "jsx": "react-jsx",
10 | "lib": [
11 | "esnext",
12 | "dom"
13 | ],
14 | "module": "commonjs",
15 | "moduleResolution": "node",
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": true,
19 | "outDir": "lib",
20 | "pretty": true,
21 | "skipLibCheck": true,
22 | "target": "ES2018",
23 | "typeRoots": [
24 | "node_modules/@types",
25 | "node_modules/json-d-ts"
26 | ]
27 | },
28 | "include": [
29 | "./src/**/*"
30 | ],
31 | "exclude": [
32 | "**/*.test.*",
33 | "lib",
34 | "./node_modules",
35 | "./test"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/packages/arkhamjs/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "styleguidejs/typescript"
3 | }
--------------------------------------------------------------------------------
/packages/arkhamjs/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | lib
3 | node_modules
4 | *.log
--------------------------------------------------------------------------------
/packages/arkhamjs/.npmignore:
--------------------------------------------------------------------------------
1 | coverage
2 | docs
3 | node_modules
4 | src
5 | .eslintrc
6 | lex.config.js
7 | package-lock.json
8 | tsconfig.json
9 |
--------------------------------------------------------------------------------
/packages/arkhamjs/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Nitrogen Labs, Inc.
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.
22 |
--------------------------------------------------------------------------------
/packages/arkhamjs/README.md:
--------------------------------------------------------------------------------
1 | # @nlabs/arkhamjs
2 |
3 |
4 |
5 | [](https://www.npmjs.com/package/@nlabs/arkhamjs)
6 | [](https://www.npmjs.com/package/@nlabs/arkhamjs)
7 | [](https://travis-ci.org/nitrogenlabs/arkhamjs)
8 | [](https://github.com/nitrogenlabs/arkhamjs/issues)
9 | [](https://github.com/ellerbrock/typescript-badges/)
10 | [](http://opensource.org/licenses/MIT)
11 | [](https://discord.gg/Ttgev58)
12 |
13 | ## Features
14 |
15 | ### Flux Framework
16 |
17 | ArkhamJS is a lightweight framework that can accommodate a project of any size, small or large. From small start-up ideas to large enterprise projects. A simple, flexible framework. Consisting of a singular state tree with a unidirectional data flow.
18 |
19 | ### Lightweight
20 |
21 | The framework is small. The bulk of your app should lay within your code, not the framework. While larger frameworks come with lots of "magic", they become very limited when new features arise within your project.
22 |
23 | ### Typescript
24 |
25 | Compatible with typescript. Definitions are included to support your Typescript project.
26 |
27 | ### Single Store
28 |
29 | All data is stored within a single store. The data can be accessed through all your views and components. Data is organized into multiple stores within the single store.
30 |
31 | ### Immutability
32 |
33 | To prevent object referencing, we use immutable objects. When the state changes, the state's property is not the only item that is changed, the item it references is also updated. To prevent passing around an object between different scopes, immutable objects give your data a one way update path. You may also have returned values converted into ImmutableJS objects.
34 |
35 | ### Debugger
36 |
37 | The most important factor in choosing a framework is how easy it is to build with it. And with building comes debugging. A state debugger can be added with the middleware, [@nlabs/arkhamjs-middleware-logger](https://github.com/nitrogenlabs/arkhamjs-middleware-logger). When turned on, it will display any actions and state changes that come through the framework. Making the previous and next state visible to the developer. Great way to make your data transparent! Supported browsers: Chrome, Firefox, and Safari.
38 |
39 | ### Cache Storage
40 |
41 | An app state is clears after a browser refresh. Keeping the state after a reload can be very useful when requiring a persistent state.
42 |
43 | If you plan to persist data, you will need to add a storage to the framework:
44 |
45 | - React [@nlabs/arkhamjs-storage-browser](https://github.com/nitrogenlabs/arkhamjs-storage-browser)
46 | - React Native [@nlabs/arkhamjs-storage-native](https://github.com/nitrogenlabs/arkhamjs-storage-native)
47 | - NodeJS [@nlabs/arkhamjs-storage-node](https://github.com/nitrogenlabs/arkhamjs-storage-node)
48 |
49 | ## Installation
50 |
51 | Using [npm](https://www.npmjs.com/):
52 |
53 | ```shell
54 | npm install --save @nlabs/arkhamjs
55 | ```
56 |
57 | ## Documentation
58 |
59 | For detailed [Documentation](https://arkhamjs.io) and additional options.
60 |
61 | ## Demo
62 |
63 | Try tinkering with a simplified demo in [JSFiddle](https://jsfiddle.net/nitrog7/j3k762vd/)!
64 |
65 | ## Examples
66 |
67 | ### React Typescript Example
68 |
69 | For a complete example of a React setup using Typescript, feel free to start your project with [arkhamjs-example-ts-react](https://github.com/nitrogenlabs/arkhamjs-example-ts-react).
70 |
--------------------------------------------------------------------------------
/packages/arkhamjs/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 |
6 | module.exports = require('./lib');
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs/lex.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | outputPath: 'lib',
3 | preset: 'web',
4 | remove: true,
5 | useTypescript: true
6 | };
7 |
--------------------------------------------------------------------------------
/packages/arkhamjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nlabs/arkhamjs",
3 | "version": "3.28.5",
4 | "publishConfig": {
5 | "access": "public"
6 | },
7 | "description": "Javascript Flux Library",
8 | "license": "MIT",
9 | "main": "./index.js",
10 | "module": "./index.js",
11 | "browser": "./index.js",
12 | "types": "./lib/index.d.js",
13 | "keywords": [
14 | "arkhamjs",
15 | "flux",
16 | "global state",
17 | "immutable",
18 | "nitrogenlabs",
19 | "state",
20 | "state management"
21 | ],
22 | "author": {
23 | "name": "Giraldo Rosales",
24 | "email": "giraldo@nitrogenlabs.com",
25 | "url": "http://nitrogenlabs.com"
26 | },
27 | "repository": {
28 | "type": "git",
29 | "url": "nitrogenlabs/arkhamjs.git"
30 | },
31 | "homepage": "https://arkhamjs.io",
32 | "bugs": {
33 | "url": "https://github.com/nitrogenlabs/arkhamjs/issues"
34 | },
35 | "scripts": {
36 | "build": "lex compile --remove",
37 | "clean": "lex clean",
38 | "lint": "eslint ./src --ext .ts,.tsx",
39 | "prepublishOnly": "npm run build",
40 | "publish:major": "npm version major && npm publish",
41 | "publish:minor": "npm version minor && npm publish",
42 | "publish:patch": "npm version patch && npm publish",
43 | "pretest": "npm run lint",
44 | "test": "lex test",
45 | "update": "npm-check-updates --interactive"
46 | },
47 | "dependencies": {
48 | "error-stack-parser": "^2.1.4",
49 | "events": "^3.3.0",
50 | "lodash": "^4.17.21"
51 | },
52 | "devDependencies": {
53 | "@types/events": "^3.0.3",
54 | "@types/jest": "^29.5.14",
55 | "@types/lodash": "^4.17.15",
56 | "@types/node": "^22.13.1",
57 | "eslint": "^9.19.0",
58 | "eslint-config-styleguidejs": "^3.2.1",
59 | "typescript": "^5.7.3"
60 | },
61 | "gitHead": "fc371e1e28fe0ae35d40d29a217d5f0e990ec32a"
62 | }
63 |
--------------------------------------------------------------------------------
/packages/arkhamjs/src/Flux/Flux.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3 | * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4 | */
5 | import ErrorStackParser from 'error-stack-parser';
6 | import {EventEmitter} from 'events';
7 | import debounce from 'lodash/debounce';
8 | import cloneDeep from 'lodash/fp/cloneDeep';
9 | import get from 'lodash/fp/get';
10 | import isEmpty from 'lodash/fp/isEmpty';
11 | import merge from 'lodash/fp/merge';
12 | import set from 'lodash/fp/set';
13 |
14 | import {ArkhamConstants} from '../constants/ArkhamConstants';
15 | import {FluxAction, FluxMiddlewareType, FluxOptions, FluxPluginType, FluxStore} from './Flux.types';
16 |
17 | /**
18 | * FluxFramework
19 | * @type {EventEmitter}
20 | */
21 | export class FluxFramework extends EventEmitter {
22 | static initFlux: boolean = false;
23 | isInit: boolean = false;
24 | // Public properties
25 | pluginTypes: string[] = ['preDispatch', 'postDispatch'];
26 | // Private properties
27 | private state: any = {};
28 | private storeActions: any = {};
29 | private defaultOptions: FluxOptions = {
30 | name: 'arkhamjs',
31 | routerType: 'browser',
32 | scrollToTop: true,
33 | state: null,
34 | storage: null,
35 | storageWait: 300,
36 | stores: [],
37 | title: 'ArkhamJS'
38 | };
39 | private middleware: any = {};
40 | private options: FluxOptions = this.defaultOptions;
41 | /**
42 | * Create a new instance of Flux. Note that the Flux object
43 | * is a Singleton pattern, so only one should ever exist.
44 | *
45 | * @constructor
46 | * @this {FluxFramework}
47 | */
48 | constructor() {
49 | super();
50 |
51 | // Methods
52 | this.addMiddleware = this.addMiddleware.bind(this);
53 | this.addStores = this.addStores.bind(this);
54 | this.clearAppData = this.clearAppData.bind(this);
55 | this.clearMiddleware = this.clearMiddleware.bind(this);
56 | this.deregister = this.deregister.bind(this);
57 | this.dispatch = this.dispatch.bind(this);
58 | this.getOptions = this.getOptions.bind(this);
59 | this.getState = this.getState.bind(this);
60 | this.getStore = this.getStore.bind(this);
61 | this.init = this.init.bind(this);
62 | this.off = this.off.bind(this);
63 | this.register = this.register.bind(this);
64 | this.removeMiddleware = this.removeMiddleware.bind(this);
65 | this.removeStores = this.removeStores.bind(this);
66 | this.reset = this.reset.bind(this);
67 | this.setState = this.setState.bind(this);
68 |
69 | // Add middleware plugin types
70 | this.pluginTypes.forEach((type: string) => this.middleware[`${type}List`] = []);
71 | }
72 |
73 | /**
74 | * Add middleware to framework.
75 | *
76 | * @param {array} middleware An array of middleware to add to the framework.
77 | */
78 | addMiddleware(middleware: FluxMiddlewareType[]): void {
79 | middleware.forEach((middleObj: FluxMiddlewareType) => {
80 | // Make sure middleware is either a class or object.
81 | if(!!middleObj && ((typeof middleObj === 'function') || (typeof middleObj === 'object'))) {
82 | const middleName: string = middleObj.name || '';
83 |
84 | if(!middleName) {
85 | throw Error('Unknown middleware is not configured properly. Requires name property. Cannot add to Flux.');
86 | }
87 |
88 | // Sort middleware plugins for efficiency
89 | this.pluginTypes.forEach((type: string) => {
90 | const method = middleObj[type];
91 | const plugin: FluxPluginType = {method, name: middleName};
92 | this.middleware[`${type}List`] = this.addPlugin(type, plugin);
93 | });
94 | } else {
95 | throw Error('Unknown middleware is not configured properly. Cannot add to Flux.');
96 | }
97 | });
98 | }
99 |
100 | /**
101 | * Remove all app data from storage.
102 | *
103 | * @returns {Promise} Whether app data was successfully removed.
104 | */
105 | clearAppData(): Promise {
106 | // Set all store data to initial state
107 | Object
108 | .keys(this.storeActions)
109 | .forEach((storeName: string) => {
110 | const storeFn = this.storeActions[storeName];
111 | this.state[storeFn.name] = cloneDeep(storeFn.initialState);
112 | });
113 |
114 | const {name, storage} = this.options;
115 |
116 | if(storage?.setStorageData) {
117 | return storage.setStorageData(name, this.state);
118 | }
119 |
120 | return Promise.resolve(true);
121 | }
122 |
123 | /**
124 | * Remove all middleware.
125 | *
126 | * @returns {boolean} Whether middleware was successfully removed.
127 | */
128 | clearMiddleware(): boolean {
129 | // Set all store data to initial state
130 | Object
131 | .keys(this.middleware)
132 | .forEach((pluginType: string) => {
133 | this.middleware[pluginType] = [];
134 | });
135 |
136 | return true;
137 | }
138 |
139 | /**
140 | * De-registers named stores.
141 | *
142 | * @param {array} storeNames An array of store names to remove from the framework.
143 | */
144 | removeStores(storeNames: string[]): void {
145 | storeNames.forEach((name: string) => this.deregister(name));
146 | }
147 |
148 | /**
149 | * Dispatches an action to all stores.
150 | *
151 | * @param {object} action to dispatch to all the stores.
152 | * @param {boolean} silent To silence any events.
153 | * @returns {Promise} The promise is resolved when and if the app saves data to storage, returning
154 | * the action.
155 | */
156 | async dispatch(action: FluxAction, silent: boolean = false): Promise {
157 | if(!action) {
158 | throw new Error('ArkhamJS Error: Flux.dispatch requires an action.');
159 | }
160 |
161 | let clonedAction: FluxAction = cloneDeep(action);
162 |
163 | // Log duration of dispatch
164 | const startTime: number = Date.now();
165 |
166 | // Get stack
167 | let stack = [];
168 |
169 | try {
170 | const stackProperty: string = 'stackTraceLimit';
171 | const {stackTraceLimit}: any = Error;
172 | Error[stackProperty] = Infinity;
173 | stack = ErrorStackParser.parse(new Error());
174 | Error[stackProperty] = stackTraceLimit;
175 | } catch(error) {}
176 |
177 | // Get options
178 | const options = cloneDeep(this.options);
179 |
180 | // App info
181 | const appInfo = {duration: 0, options, stack};
182 |
183 | // Apply middleware before the action is processed
184 | const {postDispatchList = [], preDispatchList = []} = this.middleware;
185 |
186 | if(preDispatchList.length) {
187 | clonedAction = await Promise
188 | .all(
189 | preDispatchList.map((plugin: FluxPluginType) => plugin.method(
190 | cloneDeep(clonedAction), cloneDeep(this.state), appInfo)
191 | )
192 | )
193 | .then(
194 | (actions) => actions.reduce((updatedAction, action) =>
195 | merge(updatedAction, action), clonedAction) as FluxAction
196 | )
197 | .catch((error) => {
198 | throw error;
199 | });
200 | }
201 |
202 | const {type, ...data} = clonedAction;
203 |
204 | // Require a type
205 | if(!type || type === '') {
206 | console.warn('ArkhamJS Warning: Flux.dispatch is missing an action type for the payload:', data);
207 | return Promise.resolve(clonedAction);
208 | }
209 |
210 | // When an action comes in, it must be completely handled by all stores
211 | Object
212 | .keys(this.storeActions)
213 | .forEach((storeName: string) => {
214 | const storeFn = this.storeActions[storeName];
215 | const state = cloneDeep(this.state[storeName]) || cloneDeep(storeFn.initialState) || {};
216 | this.state[storeName] = cloneDeep(storeFn.action(type, data, state)) || state;
217 | });
218 |
219 | // Save cache in storage
220 | const {storage} = this.options;
221 |
222 | if(storage && this.updateStorage) {
223 | try {
224 | await this.updateStorage();
225 | } catch(error) {}
226 | }
227 |
228 | const endTime: number = +(new Date());
229 | const duration: number = endTime - startTime;
230 | appInfo.duration = duration;
231 |
232 | if(postDispatchList.length) {
233 | clonedAction = await Promise
234 | .all(
235 | postDispatchList.map(
236 | async (plugin: FluxPluginType) => plugin.method(cloneDeep(clonedAction), cloneDeep(this.state), appInfo)
237 | )
238 | )
239 | .then(
240 | (actions) => actions.reduce((updatedAction, action) =>
241 | merge(updatedAction, action), clonedAction) as FluxAction
242 | )
243 | .catch((error) => {
244 | throw error;
245 | });
246 | }
247 |
248 | if(!silent) {
249 | this.emit(type, clonedAction);
250 | this.emit('arkhamjs', this.state);
251 | }
252 |
253 | return Promise.resolve(clonedAction);
254 | }
255 |
256 | /**
257 | * Get the current Flux options.
258 | *
259 | * @returns {FluxOptions} the Flux options object.
260 | */
261 | getOptions(): FluxOptions {
262 | return this.options;
263 | }
264 |
265 | /**
266 | * Get the current state object.
267 | *
268 | * @param {string|array} [name] (optional) The name of the store for an object, otherwise it will return all store
269 | * objects. You can also use an array to specify a property path within the object.
270 | * @param {any} [defaultValue] (optional) A default value to return if null.
271 | * @returns {any} the state object or a property value within.
272 | */
273 | getState(path: string | string[] = '', defaultValue?): any {
274 | let storeValue;
275 |
276 | if(!path) {
277 | storeValue = this.state || {};
278 | } else {
279 | storeValue = get(path, this.state);
280 | }
281 |
282 | const value = storeValue ? cloneDeep(storeValue) : storeValue;
283 | return value === undefined ? defaultValue : value;
284 | }
285 |
286 | /**
287 | * Get a store object registered with Flux.
288 | *
289 | * @param {string} name The name of the store.
290 | * @returns {FluxStore} the store object.
291 | */
292 | getStore(name: string = ''): FluxStore {
293 | return this.storeActions[name];
294 | }
295 |
296 | /**
297 | * Initialize and set configuration options.
298 | *
299 | * @param {object} options Configuration options.
300 | */
301 | async init(options: FluxOptions = {}, reset: boolean = false): Promise {
302 | // Should reset previous params
303 | if(reset) {
304 | this.isInit = false;
305 | this.reset(false);
306 | }
307 |
308 | // Set options
309 | const updatedOptions = {...options};
310 |
311 | if(this.isInit) {
312 | // Remove the name from options if already initialized, otherwise the root app will not be able to access
313 | // the state tree
314 | updatedOptions.name = this.options.name;
315 | }
316 |
317 | this.options = {...this.defaultOptions, ...updatedOptions};
318 | const {debug, middleware, name, stores} = this.options;
319 |
320 | // Update default store
321 | try {
322 | await this.useStorage(name);
323 | } catch(error) {
324 | console.error('Arkham Error: There was an error while using storage.', name);
325 | throw error;
326 | }
327 |
328 | if(!!stores && stores.length) {
329 | try {
330 | await this.addStores(stores);
331 | } catch(error) {
332 | console.error('Arkham Error: There was an error while adding stores.', stores);
333 | throw error;
334 | }
335 | }
336 |
337 | if(!!middleware && middleware.length) {
338 | this.addMiddleware(middleware);
339 | }
340 |
341 | const windowProperty: string = 'arkhamjs';
342 |
343 | if(debug) {
344 | window[windowProperty] = this;
345 | } else {
346 | delete window[windowProperty];
347 | }
348 |
349 | this.isInit = true;
350 | this.emit(ArkhamConstants.INIT);
351 |
352 | return this;
353 | }
354 |
355 | /**
356 | * Adds an initialization listener.
357 | *
358 | * @param {function} [listener] The callback associated with the subscribed event.
359 | */
360 | onInit(listener: (...args: any[]) => void): void {
361 | this.on(ArkhamConstants.INIT, listener);
362 |
363 | if(this.isInit) {
364 | listener();
365 | }
366 | }
367 |
368 | /**
369 | * Removes the initialization listener.
370 | *
371 | * @param {function} [listener] The callback associated with the subscribed event.
372 | */
373 | offInit(listener: (...args: any[]) => void): void {
374 | this.off(ArkhamConstants.INIT, listener);
375 | }
376 |
377 | /**
378 | * Removes an event listener.
379 | *
380 | * @param {string} [eventType] Event to unsubscribe.
381 | * @param {function} [listener] The callback associated with the subscribed event.
382 | */
383 | off(eventType: string, listener: (...args: any[]) => void): this {
384 | return this.removeListener(eventType, listener);
385 | }
386 |
387 | /**
388 | * Adds an event listener.
389 | *
390 | * @param {string} [eventType] Event to subscribe.
391 | * @param {function} [listener] The callback associated with the subscribed event.
392 | */
393 | on(eventType: string, listener: (...args: any[]) => void): this {
394 | return this.addListener(eventType, listener);
395 | }
396 |
397 | /**
398 | * Registers new Stores.
399 | *
400 | * @param {array} stores Store class.
401 | * @returns {Promise