├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── docs
├── crown.svg
├── index.html
└── raj.svg
├── index.js
├── package.json
└── test
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | package-lock.json
61 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - node
4 | deploy:
5 | provider: npm
6 | email: christopher.andrejewski@gmail.com
7 | api_key:
8 | secure: rgQRT6Sd89F0ywRkIKSLHPoOTuRPgzODKud79vOiX7Xt3aqmVAPFTxZbpZlSyjPwT+I31YTeJxdRdNKnuJKqxrlmsTWEkcCWFzrbQ9VGfCzK0V00VWOU1sdUZseBSSIevSfD9j5835RWhnLbOo8OR3PTgvkhVcr4+E9szP3vEtCN4T1XVrm5wkx2hgQWFpGBBw2lqrckzUoioiHuh360vtcplrqPszVgLXqXmsPzd0M6VEe/+yBIxGN+yZUIRTrjIbyeNHiCoR60liAOxfzx/tt/q2hvnxhiKqyGREGb8qryiYTGygO457Rp9DideVDtjtyawVotaYNvnaBCdVv9LJeSH2VkMM29+bfoRcQ5XzJDG8XPVRgrogwlPIPMKi7XGngVBxI9QFyGcBnWtmp/z/aFDpJnfgKFesR6x9ThZDr2eOXhBS7fR0q5N+IRjWAcowmS/fgBY9VN/CgToCsu5be7/XYvVJwHBYnDre3ORhIiXs2P5zaJHa2br4rPY0bxipfieKFAksmxC5mm3N0WCxP3nUnLi/kjItBt3GfmWhEv3WlZIMdU+m4s779l+4//xA3lcGv23aZfQ0RlHSqCuilrK54UbA/fyBCqMj6rNnHWpH3zPBf8DivBdf1/WpnjIxkAUGpvnmVnBxlDC66mECP4svDDCfS4F373nuqTHj4=
9 | on:
10 | tags: true
11 | repo: andrejewski/raj
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Chris Andrejewski
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | > The Elm Architecture for JavaScript
8 |
9 | ```sh
10 | npm install raj
11 | ```
12 |
13 | [](https://www.npmjs.com/package/raj)
14 | [](https://travis-ci.org/andrejewski/raj)
15 | [](https://greenkeeper.io/)
16 |
17 | ## Features
18 |
19 | - **Understandable**
20 | Raj is 34 lines; 190 bytes minified. This framework can fit in your head or even a tweet.
21 |
22 | - **Testable**
23 | Raj forces us to design for better separated concerns, simpler logic, and easier tests.
24 |
25 | - **Minimal**
26 | Raj provides a tiny foundation for libraries and applications.
27 |
28 | - **Portable**
29 | Raj is view layer agnostic. The view is a side effect of state.
30 |
31 | Check out the [homepage](https://jew.ski/raj/) for resources and ecosystem packages.
32 |
33 | ## Example
34 | A counter that increments by one every time the user confirms.
35 |
36 | ```js
37 | import { runtime } from 'raj'
38 |
39 | runtime({
40 | init: [0], // State is an integer to count
41 | update (message, state) {
42 | return [state + 1] // Increment the state
43 | },
44 | view (state, dispatch) {
45 | const keepCounting = window.confirm(`Count is ${state}. Increment?`)
46 | if (keepCounting) {
47 | dispatch()
48 | }
49 | }
50 | })
51 | ```
52 |
53 | *Note:* Raj is view layer agnostic.
54 | Here we use the browser's built-in view to play the part.
55 |
56 | ## Architecture
57 |
58 | Raj applications are structured as programs.
59 |
60 | Every program begins with an initial state, which can be anything, and an optional effect.
61 | These are put into an array which is the `init` property of the program.
62 |
63 | ```js
64 | const init = [initialState, /* optional */ initialEffect]
65 | ```
66 |
67 | "Effects" are functions which receive a function `dispatch`.
68 | Effects handle asynchronous work like data-fetching, timers, and managing event listeners.
69 | They can pass `dispatch` messages and Raj uses those to update the state.
70 |
71 | ```js
72 | function effect (dispatch) {
73 | // do anything or nothing; preferably something asynchronous
74 | // call dispatch 0, 1, or N times
75 | dispatch(message)
76 | }
77 | ```
78 |
79 | A "message" can be anything; a server response, the current time, even `undefined`.
80 |
81 | When a message is dispatched, Raj passes that message and the current state to `update`.
82 | The `update` function returns a new state and optional effect.
83 | The business logic of the program is handled with this function.
84 |
85 | ```js
86 | function update (message, currentState) {
87 | return [newState, /* optional */ effect]
88 | }
89 | ```
90 |
91 | The `view` is a special effect that receives both the current state and the `dispatch` function.
92 | The `view` can return anything.
93 | For the [React view layer](https://github.com/andrejewski/raj-react), the `view` returns React elements to be rendered.
94 |
95 | ```js
96 | function view (currentState, dispatch) {
97 | // anything, depending on choice of view library
98 | }
99 | ```
100 |
101 | The `init`, `update`, and `view` form a "program" which is just an object with those properties:
102 |
103 | ```js
104 | const program = {
105 | init: [initialState, /* optional */ initialEffect],
106 | update (message, currentState) {
107 | return [newState, /* optional */ effect]
108 | },
109 | view (currentState, dispatch) {
110 | // anything, depending on choice of view library
111 | }
112 | };
113 | ```
114 |
115 | Building any program follows the same steps:
116 |
117 | 1. Define the initial state and effect with `init`
118 | 1. Define the state transitions and effects with `update(message, state)`
119 | 1. Define the view with `view(state, dispatch)`
120 | 1. Tie it all together into a `program`
121 |
122 | Programs compose, so a parent program might contain child programs.
123 |
124 | - The parent's `init` may contain the child's `init`.
125 | - The parent's `update` may call the child's `update` with messages for the child and the child's state.
126 | - The parent's `view` may call the child's `view` with the child's state and `dispatch`.
127 |
128 | In this way, programs most often compose into a tree structure.
129 |
130 | The root program is passed to Raj's `runtime`.
131 | The runtime calls the program, manages its state, and runs its effects.
132 |
133 | ```js
134 | import { runtime } from 'raj'
135 | import { program } from './app'
136 |
137 | runtime(program)
138 | ```
139 |
140 | The [Raj by Example](https://github.com/andrejewski/raj-by-example) documentation covers this in greater detail.
141 |
--------------------------------------------------------------------------------
/docs/crown.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Raj - The Elm Architecture for JavaScript
4 |
5 |
6 |
7 |
249 |
250 |
251 |
252 |
253 |