├── .gitattributes
├── .gitignore
├── .travis.yml
├── README.md
├── client
├── ripple.bundle.js
├── ripple.js
├── ripple.min.js
└── ripple.min.js.gz
├── index.js
├── package-lock.json
├── package.json
├── rollup.config.js
├── rollup.pure.config.js
└── tests
├── basic.test.js
└── resources
├── _components
├── x-foo.css
└── x-foo.js
├── components
└── auto-loaded-component.js
└── utils
└── foo.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | dist/* -diff
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | *.log
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "stable"
5 |
6 | after_script: NODE_ENV=test istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ripple Fullstack
2 |
3 | On the server:
4 |
5 | **`index.js`**
6 | ```js
7 | const ripple = require('rijs')({ dir: __dirname })
8 | ```
9 |
10 | On the client:
11 |
12 | **`pages/index.html`**
13 | ```html
14 |
15 | ```
16 |
17 | Run it:
18 |
19 | ```
20 | $ node index.js
21 | ```
22 |
23 | This starts up a server on a random port and statically serves your `/pages` directory. You can also specify a `port` to always use, or pass an existing HTTP `server` (e.g. from express).
24 |
25 | Clients will then just be streamed the fine-grained resources they are using (i.e. everything is lazy loaded, no bundling, no over-fetching).
26 |
27 | Ripple keeps clients/servers in sync by replicating an immutable log of actions in the background, and subsequently the view - or other modules - which are reactively updated when the local store is updated.
28 |
29 | That's it! No boilerplate necessary, no build pipeline, no special transpilation, no magical CLI.
30 |
31 | The basic API is:
32 |
33 | ```js
34 | ripple(name) // getter
35 | ripple(name, body) // setter
36 | ripple.on('change', (name, change) => { .. })
37 | ```
38 |
39 |
40 | ## Components
41 |
42 | Let's add a (Web) Component to the page:
43 |
44 | **`index.html`**
45 | ```diff
46 |
47 | +
48 | ```
49 |
50 | Let's define the component:
51 |
52 | **`resources/my-app.js:`**
53 |
54 | ```js
55 | export default () => ()
56 | ```
57 |
58 | Ripple is agnostic to _how_ you write your components, they should just be idempotent: a single render function.
59 |
60 | This is fine:
61 |
62 | **`resources/my-app.js:`**
63 |
64 | ```js
65 | export default (node, data) => node.innerHTML = 'Hello World!'
66 | ```
67 |
68 | Or using some DOM-diff helper:
69 |
70 | **`resources/my-app.js:`**
71 |
72 | ```js
73 | export default (node, data) => jsx(node)`
Hello World
`
74 | ```
75 |
76 | Or using [once](https://github.com/utilise/once#once)/D3 joins:
77 |
78 | **`resources/my-app.js:`**
79 |
80 | ```js
81 | export default (node, data) => {
82 | once(node)
83 | ('h1', 1)
84 | .text('Hello World')
85 | })
86 | ```
87 |
88 | For more info about writing idempotent components, see [this spec](https://github.com/pemrouz/vanilla).
89 |
90 |
91 | ## State/Data
92 |
93 | The first parameter of the component is the node to update.
94 |
95 | The second parameter contains all the state and data the component needs to render:
96 |
97 | ```js
98 | export default function component(node, data){ ... }
99 | ```
100 |
101 | * You can inject data resources by adding the name of the resources to the data attribute:
102 |
103 | ```html
104 |
105 | ```
106 |
107 | ```js
108 | export default function shop({ stock }){ ... }
109 | ```
110 |
111 | Declaring the data needed on a component is used to reactively rerender it when the data changes.
112 |
113 | Alternatively, you can use `ripple.pull` directly to retrieve a resource, which has similar semantics to [dynamic `import()`](https://github.com/tc39/proposal-dynamic-import) (i.e. resolves from local cache or returns a single promise):
114 |
115 | ```js
116 | const dependency = await pull('dependency')
117 | ```
118 |
119 | * The other option is to explicitly pass down data to the component from the parent:
120 |
121 | ```js
122 | once(node)
123 | ('my-shop', { stock })
124 | ```
125 |
126 | The helper function will set the state and redraw, so redrawing a parent will redraw it's children. If you want to do it yourself:
127 |
128 | ```js
129 | element.state = { stock }
130 | element.draw()
131 | ```
132 |
133 |
134 | ## Defaults
135 |
136 | You can set defaults using the ES6 syntax:
137 |
138 | ```js
139 | export default function shop({ stock = [] }){ ... }
140 | ```
141 |
142 | If you need to persist defaults on the component's state object, you can use a small [helper function](https://github.com/utilise/utilise#--defaults):
143 |
144 | ```js
145 | export default function shop(state){
146 | const stock = defaults(state, 'stock', [])
147 | }
148 | ```
149 |
150 |
151 | ## Updates
152 |
153 | #### Local state
154 |
155 | Whenever you need to update local state, just change the `state` and invoke a redraw (like a game loop):
156 |
157 | ```js
158 | export default function abacus(node, state){
159 | const o = once(node)
160 | , { counter = 0 } = state
161 |
162 | o('span', 1)
163 | .text(counter)
164 |
165 | o('button', 1)
166 | .text('increment')
167 | .on('click.increment' d => {
168 | state.counter++
169 | o.draw()
170 | })
171 | }
172 | ```
173 |
174 | #### Global state
175 |
176 | Whenever you need to update global state, you can simply compute the new value and register it again which will trigger an update:
177 |
178 | ```js
179 | ripple('stock', {
180 | apples: 10
181 | , oranges: 20
182 | , pomegranates: 30
183 | })
184 | ```
185 |
186 | Or if you just want to change a part of the resource, use a [functional operator](https://github.com/utilise/utilise#--set) to apply a finer-grained diff and trigger an update:
187 |
188 | ```js
189 | update('pomegranates', 20)(ripple('stock'))
190 | // same as: set({ type: 'update', key: 'pomegranate', value: 20 })(ripple('stock'))
191 | ```
192 |
193 | Using logs of atomic diffs combines the benefits of immutability with a saner way to synchronise state across a distributed environment.
194 |
195 | Components are rAF batched by default. You can access the list of all relevant changes since the last render in your component via `node.changes` to make it more performant if necessary.
196 |
197 |
198 | ## Events
199 |
200 | Dispatch an event on the root element to communicate changes to parents (`node.dispatchEvent`).
201 |
202 |
203 | ## Routing
204 |
205 | Routing is handled by your top-level component: Simply parse the URL to determine what children to render and invoke a redraw of your application when the route has changed:
206 |
207 | ```js
208 | export function app(node, data){
209 | const o = once(node)
210 | , { pathname } = location
211 |
212 | o('page-dashboard', pathname == '/dashboard')
213 | o('page-login', pathname == '/login')
214 |
215 | once(window)
216 | .on('popstate.nav', d => o.draw())
217 | }
218 | ```
219 |
220 | This solution is not tied to any library, and you may not need one at all.
221 |
222 | For advanced uses cases, checkout [decouter](https://github.com/pemrouz/decouter).
223 |
224 |
225 | ## Styling
226 |
227 | You can author your stylesheets assuming they are completely isolated, using the Web Component syntax (`:host` etc).
228 |
229 | They will either be inserted in the shadow root of the element, or scoped and added to the head if there is no shadow.
230 |
231 | By default, the CSS resource `component-name.css` will be automatically applied to the component `component-name`.
232 |
233 | But you can apply multiple stylesheets to a component too: just extend the `css` attribute.
234 |
235 |
236 | ## Folder Convention
237 |
238 | All files in your `/resources` folder will be automatically registered (except tests etc). You can organise it as you like, but I recommend using the convention: a folder for each component (to co-locate JS, CSS and tests), and a `data` folder for the resources that make up your domain model.
239 |
240 | ```
241 | resources
242 | ├── data
243 | │ ├── stock.js
244 | │ ├── order.js
245 | │ └── ...
246 | ├── my-app
247 | │ ├── my-app.js
248 | │ ├── my-app.css
249 | │ └── test.js
250 | ├── another-component
251 | │ ├── another-component.js
252 | │ ├── another-component.css
253 | │ └── test.js
254 | └── ...
255 | ```
256 |
257 | Hot reloading works out of the box. Any changes to these files will be instantly reflected everywhere.
258 |
259 |
260 | ## Loading Resources
261 |
262 | You can also get/set resources yourselves imperatively:
263 |
264 | ```js
265 | ripple(name) // getter
266 | ripple(name, body) // setter
267 | ```
268 |
269 | Or for example import resources from other packages:
270 |
271 | ```js
272 | ripple
273 | .resource(require('external-module-1'))
274 | .resource(require('external-module-2'))
275 | .resource(require('external-module-3'))
276 | ```
277 |
278 | You can also create resources that proxy to [fero](https://github.com/pemrouz/fero)) services too.
279 |
280 |
281 | ## Offline
282 |
283 | Resources are currently cached in `localStorage`.
284 |
285 | This means even _before_ any network interaction, your application renders the last-known-good-state for a superfast startup.
286 |
287 | Then as resources are streamed in, the relevant parts of the application are updated.
288 |
289 | Note: Caching of resources will be improved by using ServiceWorkers under the hood instead soon ([#27](https://github.com/rijs/fullstack/issues/27))
290 |
291 |
292 | ## Render Middleware
293 |
294 | By default the draw function just invokes the function on an element. You can extend this without any framework hooks using the explicit decorator pattern:
295 |
296 | ```js
297 | // in component
298 | export default function component(node, data){
299 | middleware(node, data)
300 | }
301 |
302 | // around component
303 | export default middleware(function component(node, data){
304 |
305 | })
306 |
307 | // for all components
308 | ripple.draw = middleware(ripple.draw)
309 | ```
310 |
311 | A few useful middleware included in this build are:
312 |
313 | ### Needs
314 |
315 | [This middleware](https://github.com/rijs/needs#ripple--needs) reads the `needs` header and applies the attributes onto the element. The component does not render until all dependencies are available. This is useful when a component needs to define its own dependencies. You can also supply a function to dynamically calculate the required resources.
316 |
317 | ```js
318 | export default {
319 | name: 'my-component'
320 | , body: function(){}
321 | , headers: { needs: '[css=..][data=..]' }
322 | }
323 | ```
324 |
325 | ### Shadow
326 |
327 | If supported by the browser, a shadow root will be created for each component. The component will render into the shadow DOM rather than the light DOM.
328 |
329 |
330 | ### Perf (Optional)
331 |
332 | This one is not included by default, but you can use this to log out the time each component takes to render.
333 |
334 | Other debugging tips:
335 |
336 | * Check `ripple.resources` for a snapshot of your application. Resources are in the [tuple format](https://github.com/rijs/core#ripple--core) `{ name, body, headers }`.
337 |
338 | * Check `$0.state` on an element to see the state object it was last rendered with or manipulate it.
339 |
340 |
341 | ## Sync
342 |
343 | You can define a `from` function in the resource headers which will process requests from the client:
344 |
345 | ```js
346 | const from = (req, res) =>
347 | req.data.type == 'REGISTER' ? register(req, res)
348 | : req.data.type == 'FORGOT' ? forgot(req, res)
349 | : req.data.type == 'LOGOUT' ? logout(req, res)
350 | : req.data.type == 'RESET' ? reset(req, res)
351 | : req.data.type == 'LOGIN' ? login(req, res)
352 | : false
353 |
354 | module.exports = {
355 | name: 'users'
356 | , body: {}
357 | , headers: { from }
358 | }
359 | ```
360 |
361 | This can return a single value, a promise or a stream. On the client you make requests with `ripple.send(name, type, value)`. This returns an awaitable [stream](https://github.com/utilise/emitterify/#emitterify).
362 |
363 | You can also use the `.subscribe` API to subscribe to all or part of a resource. The key can be arbitrarily deep, and multiple keys will be merged into a single object.
364 |
365 | ```js
366 | ripple.subscribe(name, key)
367 | ripple.subscribe(name, [keys])
368 | ```
369 |
370 | Subscriptions are automatically deduplicated are ref-counted, so components can indepedently subscribe to the data they need without worrying about this.
371 |
372 | Note that you can also use `ripple.get` instead of subscribe if you just want to get a single value and then automatically unsubscribe.
373 |
374 |
375 | ## Ripple Minimal
376 |
377 | If you have don't have backend for your frontend, checkout [rijs/minimal](https://github.com/rijs/minimal) which is a client-side only build of Ripple.
378 |
379 | You can also adjust your own framework by [adding/removing modules](https://github.com/rijs/minimal/blob/master/src/index.js#L1-L11).
380 |
381 |
382 | ## Docs
383 |
384 | See [rijs/docs](https://github.com/rijs/docs) for more guides, index of modules, API reference, etc
385 |
--------------------------------------------------------------------------------
/client/ripple.bundle.js:
--------------------------------------------------------------------------------
1 | var rijs = (function () {
2 | 'use strict';
3 |
4 | function commonjsRequire () {
5 | throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
6 | }
7 |
8 | function createCommonjsModule(fn, module) {
9 | return module = { exports: {} }, fn(module, module.exports), module.exports;
10 | }
11 |
12 | var client = typeof window != 'undefined';
13 |
14 | var client$1 = /*#__PURE__*/Object.freeze({
15 | default: client,
16 | __moduleExports: client
17 | });
18 |
19 | var promise_1 = promise;
20 |
21 | function promise() {
22 | var resolve
23 | , reject
24 | , p = new Promise(function(res, rej){
25 | resolve = res, reject = rej;
26 | });
27 |
28 | arguments.length && resolve(arguments[0]);
29 | p.resolve = resolve;
30 | p.reject = reject;
31 | return p
32 | }
33 |
34 | var promise$1 = /*#__PURE__*/Object.freeze({
35 | default: promise_1,
36 | __moduleExports: promise_1
37 | });
38 |
39 | var flatten = function flatten(p,v){
40 | if (v instanceof Array) { v = v.reduce(flatten, []); }
41 | return (p = p || []), p.concat(v)
42 | };
43 |
44 | var flatten$1 = /*#__PURE__*/Object.freeze({
45 | default: flatten,
46 | __moduleExports: flatten
47 | });
48 |
49 | var has = function has(o, k) {
50 | return k in o
51 | };
52 |
53 | var has$1 = /*#__PURE__*/Object.freeze({
54 | default: has,
55 | __moduleExports: has
56 | });
57 |
58 | var has$2 = ( has$1 && has ) || has$1;
59 |
60 | var def = function def(o, p, v, w){
61 | if (o.host && o.host.nodeName) { o = o.host; }
62 | if (p.name) { v = p, p = p.name; }
63 | !has$2(o, p) && Object.defineProperty(o, p, { value: v, writable: w });
64 | return o[p]
65 | };
66 |
67 | var def$1 = /*#__PURE__*/Object.freeze({
68 | default: def,
69 | __moduleExports: def
70 | });
71 |
72 | var promise$2 = ( promise$1 && promise_1 ) || promise$1;
73 |
74 | var flatten$2 = ( flatten$1 && flatten ) || flatten$1;
75 |
76 | var def$2 = ( def$1 && def ) || def$1;
77 |
78 | var noop = function(){};
79 |
80 | var emitterify = function emitterify(body, hooks) {
81 | body = body || {};
82 | hooks = hooks || {};
83 | def$2(body, 'emit', emit, 1);
84 | def$2(body, 'once', once, 1);
85 | def$2(body, 'off', off, 1);
86 | def$2(body, 'on', on, 1);
87 | body.on['*'] = body.on['*'] || [];
88 | return body
89 |
90 | function emit(type, pm, filter) {
91 | var li = body.on[type.split('.')[0]] || []
92 | , results = [];
93 |
94 | for (var i = 0; i < li.length; i++)
95 | { if (!li[i].ns || !filter || filter(li[i].ns))
96 | { results.push(call(li[i].isOnce ? li.splice(i--, 1)[0] : li[i], pm)); } }
97 |
98 | for (var i = 0; i < body.on['*'].length; i++)
99 | { results.push(call(body.on['*'][i], [type, pm])); }
100 |
101 | return results.reduce(flatten$2, [])
102 | }
103 |
104 | function call(cb, pm){
105 | return cb.next ? cb.next(pm)
106 | : pm instanceof Array ? cb.apply(body, pm)
107 | : cb.call(body, pm)
108 | }
109 |
110 | function on(type, opts, isOnce) {
111 | var id = type.split('.')[0]
112 | , ns = type.split('.')[1]
113 | , li = body.on[id] = body.on[id] || []
114 | , cb = typeof opts == 'function' ? opts : 0;
115 |
116 | return !cb && ns ? (cb = body.on[id]['$'+ns]) ? cb : push(observable(body, opts))
117 | : !cb && !ns ? push(observable(body, opts))
118 | : cb && ns ? push((remove(li, body.on[id]['$'+ns] || -1), cb))
119 | : cb && !ns ? push(cb)
120 | : false
121 |
122 | function push(cb){
123 | cb.isOnce = isOnce;
124 | cb.type = id;
125 | if (ns) { body.on[id]['$'+(cb.ns = ns)] = cb; }
126 | li.push(cb)
127 | ;(hooks.on || noop)(cb);
128 | return cb.next ? cb : body
129 | }
130 | }
131 |
132 | function once(type, callback){
133 | return body.on(type, callback, true)
134 | }
135 |
136 | function remove(li, cb) {
137 | var i = li.length;
138 | while (~--i)
139 | { if (cb == li[i] || cb == li[i].fn || !cb)
140 | { (hooks.off || noop)(li.splice(i, 1)[0]); } }
141 | }
142 |
143 | function off(type, cb) {
144 | remove((body.on[type] || []), cb);
145 | if (cb && cb.ns) { delete body.on[type]['$'+cb.ns]; }
146 | return body
147 | }
148 |
149 | function observable(parent, opts) {
150 | opts = opts || {};
151 | var o = emitterify(opts.base || promise$2());
152 | o.i = 0;
153 | o.li = [];
154 | o.fn = opts.fn;
155 | o.parent = parent;
156 | o.source = opts.fn ? o.parent.source : o;
157 |
158 | o.on('stop', function(reason){
159 | o.type
160 | ? o.parent.off(o.type, o)
161 | : o.parent.off(o);
162 | return o.reason = reason
163 | });
164 |
165 | o.each = function(fn) {
166 | var n = fn.next ? fn : observable(o, { fn: fn });
167 | o.li.push(n);
168 | return n
169 | };
170 |
171 | o.pipe = function(fn) {
172 | return fn(o)
173 | };
174 |
175 | o.map = function(fn){
176 | return o.each(function(d, i, n){ return n.next(fn(d, i, n)) })
177 | };
178 |
179 | o.filter = function(fn){
180 | return o.each(function(d, i, n){ return fn(d, i, n) && n.next(d) })
181 | };
182 |
183 | o.reduce = function(fn, acc) {
184 | return o.each(function(d, i, n){ return n.next(acc = fn(acc, d, i, n)) })
185 | };
186 |
187 | o.unpromise = function(){
188 | var n = observable(o, { base: {}, fn: function(d){ return n.next(d) } });
189 | o.li.push(n);
190 | return n
191 | };
192 |
193 | o.next = function(value) {
194 | o.resolve && o.resolve(value);
195 | return o.li.length
196 | ? o.li.map(function(n){ return n.fn(value, n.i++, n) })
197 | : value
198 | };
199 |
200 | o.until = function(stop){
201 | return stop.each ? stop.each(o.stop) // TODO: check clean up on stop too
202 | : stop.then ? stop.then(o.stop)
203 | : stop.call ? o.filter(stop).map(o.stop)
204 | : 0
205 | };
206 |
207 | o.off = function(fn){
208 | return remove(o.li, fn), o
209 | };
210 |
211 | o.start = function(){
212 | o.source.emit('start');
213 | return o
214 | };
215 |
216 | o.stop = function(reason){
217 | return o.source.emit('stop', reason)
218 | };
219 |
220 | o[Symbol.asyncIterator] = function(){
221 | return {
222 | next: function(){
223 | return o.wait = new Promise(function(resolve){
224 | o.wait = true;
225 | o.map(function(d, i, n){
226 | delete o.wait;
227 | o.off(n);
228 | resolve({ value: d, done: false });
229 | });
230 | o.emit('pull', o);
231 | })
232 | }
233 | }
234 | };
235 |
236 | return o
237 | }
238 | };
239 |
240 | var emitterify$1 = /*#__PURE__*/Object.freeze({
241 | default: emitterify,
242 | __moduleExports: emitterify
243 | });
244 |
245 | var is_1 = is;
246 | is.fn = isFunction;
247 | is.str = isString;
248 | is.num = isNumber;
249 | is.obj = isObject;
250 | is.lit = isLiteral;
251 | is.bol = isBoolean;
252 | is.truthy = isTruthy;
253 | is.falsy = isFalsy;
254 | is.arr = isArray;
255 | is.null = isNull;
256 | is.def = isDef;
257 | is.in = isIn;
258 | is.promise = isPromise;
259 | is.stream = isStream;
260 |
261 | function is(v){
262 | return function(d){
263 | return d == v
264 | }
265 | }
266 |
267 | function isFunction(d) {
268 | return typeof d == 'function'
269 | }
270 |
271 | function isBoolean(d) {
272 | return typeof d == 'boolean'
273 | }
274 |
275 | function isString(d) {
276 | return typeof d == 'string'
277 | }
278 |
279 | function isNumber(d) {
280 | return typeof d == 'number'
281 | }
282 |
283 | function isObject(d) {
284 | return typeof d == 'object'
285 | }
286 |
287 | function isLiteral(d) {
288 | return d.constructor == Object
289 | }
290 |
291 | function isTruthy(d) {
292 | return !!d == true
293 | }
294 |
295 | function isFalsy(d) {
296 | return !!d == false
297 | }
298 |
299 | function isArray(d) {
300 | return d instanceof Array
301 | }
302 |
303 | function isNull(d) {
304 | return d === null
305 | }
306 |
307 | function isDef(d) {
308 | return typeof d !== 'undefined'
309 | }
310 |
311 | function isPromise(d) {
312 | return d instanceof Promise
313 | }
314 |
315 | function isStream(d) {
316 | return !!(d && d.next)
317 | }
318 |
319 | function isIn(set) {
320 | return function(d){
321 | return !set ? false
322 | : set.indexOf ? ~set.indexOf(d)
323 | : d in set
324 | }
325 | }
326 |
327 | var is$1 = /*#__PURE__*/Object.freeze({
328 | default: is_1,
329 | __moduleExports: is_1
330 | });
331 |
332 | var client$2 = ( client$1 && client ) || client$1;
333 |
334 | var is$2 = ( is$1 && is_1 ) || is$1;
335 |
336 | var colorfill_1 = colorfill();
337 |
338 | function colorfill(){
339 | /* istanbul ignore next */
340 | ['red', 'green', 'bold', 'grey', 'strip'].forEach(function(color) {
341 | !is$2.str(String.prototype[color]) && Object.defineProperty(String.prototype, color, {
342 | get: function() {
343 | return String(this)
344 | }
345 | });
346 | });
347 | }
348 |
349 | var identity = function identity(d) {
350 | return d
351 | };
352 |
353 | var identity$1 = /*#__PURE__*/Object.freeze({
354 | default: identity,
355 | __moduleExports: identity
356 | });
357 |
358 | var wrap = function wrap(d){
359 | return function(){
360 | return d
361 | }
362 | };
363 |
364 | var wrap$1 = /*#__PURE__*/Object.freeze({
365 | default: wrap,
366 | __moduleExports: wrap
367 | });
368 |
369 | var keys = function keys(o) {
370 | return Object.keys(is$2.obj(o) || is$2.fn(o) ? o : {})
371 | };
372 |
373 | var keys$1 = /*#__PURE__*/Object.freeze({
374 | default: keys,
375 | __moduleExports: keys
376 | });
377 |
378 | var str = function str(d){
379 | return d === 0 ? '0'
380 | : !d ? ''
381 | : is$2.fn(d) ? '' + d
382 | : is$2.obj(d) ? JSON.stringify(d)
383 | : String(d)
384 | };
385 |
386 | var str$1 = /*#__PURE__*/Object.freeze({
387 | default: str,
388 | __moduleExports: str
389 | });
390 |
391 | var wrap$2 = ( wrap$1 && wrap ) || wrap$1;
392 |
393 | var keys$2 = ( keys$1 && keys ) || keys$1;
394 |
395 | var str$2 = ( str$1 && str ) || str$1;
396 |
397 | var key = function key(k, v){
398 | var set = arguments.length > 1
399 | , keys = is$2.fn(k) ? [] : str$2(k).split('.').filter(Boolean)
400 | , root = keys.shift();
401 |
402 | return function deep(o, i){
403 | var masked = {};
404 |
405 | return !o ? undefined
406 | : !is$2.num(k) && !k ? (set ? replace(o, v) : o)
407 | : is$2.arr(k) ? (k.map(copy), masked)
408 | : o[k] || !keys.length ? (set ? ((o[k] = is$2.fn(v) ? v(o[k], i) : v), o)
409 | : (is$2.fn(k) ? k(o) : o[k]))
410 | : (set ? (key(keys.join('.'), v)(o[root] ? o[root] : (o[root] = {})), o)
411 | : key(keys.join('.'))(o[root]))
412 |
413 | function copy(k){
414 | var val = key(k)(o);
415 | val = is$2.fn(v) ? v(val)
416 | : val == undefined ? v
417 | : val;
418 | if (val != undefined)
419 | { key(k, is$2.fn(val) ? wrap$2(val) : val)(masked); }
420 | }
421 |
422 | function replace(o, v) {
423 | keys$2(o).map(function(k){ delete o[k]; });
424 | keys$2(v).map(function(k){ o[k] = v[k]; });
425 | return o
426 | }
427 | }
428 | };
429 |
430 | var key$1 = /*#__PURE__*/Object.freeze({
431 | default: key,
432 | __moduleExports: key
433 | });
434 |
435 | var key$2 = ( key$1 && key ) || key$1;
436 |
437 | var header = function header(header$1, value) {
438 | var getter = arguments.length == 1;
439 | return function(d){
440 | return !d || !d.headers ? null
441 | : getter ? key$2(header$1)(d.headers)
442 | : key$2(header$1)(d.headers) == value
443 | }
444 | };
445 |
446 | var header$1 = /*#__PURE__*/Object.freeze({
447 | default: header,
448 | __moduleExports: header
449 | });
450 |
451 | var datum = function datum(node){
452 | return node.__data__
453 | };
454 |
455 | var datum$1 = /*#__PURE__*/Object.freeze({
456 | default: datum,
457 | __moduleExports: datum
458 | });
459 |
460 | var datum$2 = ( datum$1 && datum ) || datum$1;
461 |
462 | var from_1 = from;
463 | from.parent = fromParent;
464 |
465 | function from(o){
466 | return function(k){
467 | return key$2(k)(o)
468 | }
469 | }
470 |
471 | function fromParent(k){
472 | return datum$2(this.parentNode)[k]
473 | }
474 |
475 | var from$1 = /*#__PURE__*/Object.freeze({
476 | default: from_1,
477 | __moduleExports: from_1
478 | });
479 |
480 | var from$2 = ( from$1 && from_1 ) || from$1;
481 |
482 | var values = function values(o) {
483 | return !o ? [] : keys$2(o).map(from$2(o))
484 | };
485 |
486 | var values$1 = /*#__PURE__*/Object.freeze({
487 | default: values,
488 | __moduleExports: values
489 | });
490 |
491 | var to = {
492 | arr: toArray
493 | , obj: toObject
494 | };
495 |
496 | function toArray(d){
497 | return Array.prototype.slice.call(d, 0)
498 | }
499 |
500 | function toObject(d) {
501 | var by = 'id'
502 | ;
503 |
504 | return arguments.length == 1
505 | ? (by = d, reduce)
506 | : reduce.apply(this, arguments)
507 |
508 | function reduce(p,v,i){
509 | if (i === 0) { p = {}; }
510 | p[is$2.fn(by) ? by(v, i) : v[by]] = v;
511 | return p
512 | }
513 | }
514 | var to_1 = to.arr;
515 | var to_2 = to.obj;
516 |
517 | var to$1 = /*#__PURE__*/Object.freeze({
518 | default: to,
519 | __moduleExports: to,
520 | arr: to_1,
521 | obj: to_2
522 | });
523 |
524 | var to$2 = ( to$1 && to ) || to$1;
525 |
526 | var za = function az() {
527 | return compare(to$2.arr(arguments))
528 | };
529 |
530 | function compare(keys){
531 | return function(a, b){
532 | if (!keys.length) { return 0 }
533 | var k = keys[0]
534 | , ka = key$2(k)(a) || ''
535 | , kb = key$2(k)(b) || '';
536 |
537 | return ka < kb ? 1
538 | : ka > kb ? -1
539 | : compare(keys.slice(1))(a, b)
540 | }
541 | }
542 |
543 | var za$1 = /*#__PURE__*/Object.freeze({
544 | default: za,
545 | __moduleExports: za
546 | });
547 |
548 | var includes = function includes(pattern){
549 | return function(d){
550 | return d && d.indexOf && ~d.indexOf(pattern)
551 | }
552 | };
553 |
554 | var includes$1 = /*#__PURE__*/Object.freeze({
555 | default: includes,
556 | __moduleExports: includes
557 | });
558 |
559 | var includes$2 = ( includes$1 && includes ) || includes$1;
560 |
561 | var text = {
562 | header: 'text/plain'
563 | , check: function check(res){ return !includes$2('.html')(res.name) && !includes$2('.css')(res.name) && is$2.str(res.body) }
564 | };
565 | var text_1 = text.header;
566 | var text_2 = text.check;
567 |
568 | var text$1 = /*#__PURE__*/Object.freeze({
569 | default: text,
570 | __moduleExports: text,
571 | header: text_1,
572 | check: text_2
573 | });
574 |
575 | var owner = client$2 ? /* istanbul ignore next */ window : global;
576 |
577 | var owner$1 = /*#__PURE__*/Object.freeze({
578 | default: owner,
579 | __moduleExports: owner
580 | });
581 |
582 | var owner$2 = ( owner$1 && owner ) || owner$1;
583 |
584 | var err = function err(ns){
585 | return function(d){
586 | if (!owner$2.console || !console.error.apply) { return d; }
587 | is$2.arr(arguments[2]) && (arguments[2] = arguments[2].length);
588 | var args = to$2.arr(arguments)
589 | , prefix = '[err][' + (new Date()).toISOString() + ']' + ns;
590 |
591 | args.unshift(prefix.red ? prefix.red : prefix);
592 | return console.error.apply(console, args), d
593 | }
594 | };
595 |
596 | var err$1 = /*#__PURE__*/Object.freeze({
597 | default: err,
598 | __moduleExports: err
599 | });
600 |
601 | var log = function log(ns){
602 | return function(d){
603 | if (!owner$2.console || !console.log.apply) { return d; }
604 | is$2.arr(arguments[2]) && (arguments[2] = arguments[2].length);
605 | var args = to$2.arr(arguments)
606 | , prefix = '[log][' + (new Date()).toISOString() + ']' + ns;
607 |
608 | args.unshift(prefix.grey ? prefix.grey : prefix);
609 | return console.log.apply(console, args), d
610 | }
611 | };
612 |
613 | var log$1 = /*#__PURE__*/Object.freeze({
614 | default: log,
615 | __moduleExports: log
616 | });
617 |
618 | var split = function split(delimiter){
619 | return function(d){
620 | return d.split(delimiter)
621 | }
622 | };
623 |
624 | var split$1 = /*#__PURE__*/Object.freeze({
625 | default: split,
626 | __moduleExports: split
627 | });
628 |
629 | var split$2 = ( split$1 && split ) || split$1;
630 |
631 | var identity$2 = ( identity$1 && identity ) || identity$1;
632 |
633 | var DEBUG = strip((client$2 ? (owner$2.location.search.match(/debug=(.*?)(&|$)/) || [])[1] : key$2('process.env.DEBUG')(owner$2)) || '')
634 | , whitelist = DEBUG.split(',').map(split$2('/'));
635 |
636 | var deb = function deb(ns){
637 | return DEBUG == '*' || whitelist.some(matches(ns)) ? out : identity$2
638 |
639 | function out(d){
640 | if (!owner$2.console || !console.log.apply) { return d; }
641 | is$2.arr(arguments[2]) && (arguments[2] = arguments[2].length);
642 | var args = to$2.arr(arguments)
643 | , prefix = '[deb][' + (new Date()).toISOString() + ']' + ns;
644 |
645 | args.unshift(prefix.grey ? prefix.grey : prefix);
646 | return console.log.apply(console, args), d
647 | }
648 | };
649 |
650 | function matches(ns) {
651 | ns = strip(ns).split('/');
652 | return function(arr){
653 | return arr.length == 1 ? arr[0] == ns[0]
654 | : arr.length == 2 ? arr[0] == ns[0] && arr[1] == ns[1]
655 | : false
656 | }
657 | }
658 |
659 | function strip(str) {
660 | return str.replace(/(\[|\])/g, '')
661 | }
662 |
663 | var deb$1 = /*#__PURE__*/Object.freeze({
664 | default: deb,
665 | __moduleExports: deb
666 | });
667 |
668 | var emitterify$2 = ( emitterify$1 && emitterify ) || emitterify$1;
669 |
670 | var header$2 = ( header$1 && header ) || header$1;
671 |
672 | var values$2 = ( values$1 && values ) || values$1;
673 |
674 | var za$2 = ( za$1 && za ) || za$1;
675 |
676 | var text$2 = ( text$1 && text ) || text$1;
677 |
678 | var require$$0$1 = ( err$1 && err ) || err$1;
679 |
680 | var require$$0$2 = ( log$1 && log ) || log$1;
681 |
682 | var require$$2 = ( deb$1 && deb ) || deb$1;
683 |
684 | // -------------------------------------------
685 | // API: Gets or sets a resource
686 | // -------------------------------------------
687 | // ripple('name') - returns the resource body if it exists
688 | // ripple('name') - creates & returns resource if it doesn't exist
689 | // ripple('name', {}) - creates & returns resource, with specified name and body
690 | // ripple({ ... }) - creates & returns resource, with specified name, body and headers
691 | // ripple.resources - returns raw resources
692 | // ripple.register - alias for ripple
693 | // ripple.on - event listener for changes - all resources
694 | // ripple('name').on - event listener for changes - resource-specific
695 |
696 | var rijs_core = function core(ref){
697 | if ( ref === void 0 ) ref = {};
698 | var aliases = ref.aliases; if ( aliases === void 0 ) aliases = {};
699 |
700 | log$2('creating');
701 |
702 | ripple.resources = {};
703 | ripple.link = link(ripple);
704 | ripple.register = ripple;
705 | ripple.types = types();
706 | return linkify(emitterify$2(ripple), aliases)
707 |
708 | function ripple(name, body, headers){
709 | return !name ? ripple
710 | : is$2.arr(name) ? name.map(ripple)
711 | : is$2.promise(name) ? name.then(ripple).catch(err$2)
712 | : is$2.obj(name) && !name.name ? ripple(values$2(name))
713 | : is$2.fn(name) && name.resources ? ripple(values$2(name.resources))
714 | : is$2.str(name) && !body && ripple.resources[name] ? ripple.resources[name].body
715 | : is$2.str(name) && !body && !ripple.resources[name] ? undefined
716 | : is$2.str(name) && body ? register(ripple)({ name: name, body: body, headers: headers })
717 | : is$2.obj(name) ? register(ripple)(name)
718 | : (err$2('could not find or create resource', name), false)
719 | }
720 | };
721 |
722 | var register = function (ripple) { return function (ref) {
723 | var name = ref.name;
724 | var body = ref.body;
725 | var headers = ref.headers; if ( headers === void 0 ) headers = {};
726 |
727 | name = ripple.aliases.src[name] || name;
728 | if (is$2.promise(body)) { return body.then(function (body) { return register(ripple)({ name: name, body: body, headers: headers }); }).catch(err$2) }
729 | deb$2('registering', name);
730 | var res = normalise(ripple)({ name: name, body: body, headers: headers });
731 |
732 | if (!res) { return err$2('failed to register', name), false }
733 | ripple.resources[name] = res;
734 | ripple.emit('change', [name, {
735 | type: 'update'
736 | , value: res.body
737 | , time: now(res)
738 | }]);
739 |
740 | return ripple.resources[name].body
741 | }; };
742 |
743 | var normalise = function (ripple) { return function (res) {
744 | if (!header$2('content-type')(res)) { values$2(ripple.types).sort(za$2('priority')).some(contentType(res)); }
745 | if (!header$2('content-type')(res)) { return err$2('could not understand resource', res), false }
746 | return parse(ripple)(res)
747 | }; };
748 |
749 | var parse = function (ripple) { return function (res) {
750 | var type = header$2('content-type')(res);
751 | if (!ripple.types[type]) { return err$2('could not understand type', type), false }
752 | return (ripple.types[type].parse || identity$2)(res)
753 | }; };
754 |
755 | var contentType = function (res) { return function (type) { return type.check(res) && (res.headers['content-type'] = type.header); }; };
756 |
757 | var types = function () { return [text$2].reduce(to$2.obj('header'), 1); };
758 |
759 | var linkify = function (ripple, aliases) {
760 | ripple.aliases = { dst: {}, src: {} };
761 | for (var name in aliases)
762 | { ripple.link(aliases[name], name); }
763 | return ripple
764 | };
765 |
766 | var link = function (ripple) { return function (from, to) {
767 | ripple.aliases.src[from] = to;
768 | ripple.aliases.dst[to] = from;
769 | Object.defineProperty(ripple.resources, from, {
770 | get: function get(){ return ripple.resources[to] }
771 | , set: function set(value){ ripple.resources[to] = value; }
772 | });
773 | }; };
774 |
775 | var err$2 = require$$0$1('[ri/core]')
776 | , log$2 = require$$0$2('[ri/core]')
777 | , deb$2 = require$$2('[ri/core]')
778 | , now = function (d, t) { return (t = key$2('body.log.length')(d), is$2.num(t) ? t - 1 : t); };
779 |
780 | var rijs_core$1 = /*#__PURE__*/Object.freeze({
781 | default: rijs_core,
782 | __moduleExports: rijs_core
783 | });
784 |
785 | // -------------------------------------------
786 | // Exposes a convenient global instance
787 | // -------------------------------------------
788 | var rijs_singleton = function singleton(ripple){
789 | log$3('creating');
790 | if (!owner$2.ripple) { owner$2.ripple = ripple; }
791 | return ripple
792 | };
793 |
794 | var log$3 = require$$0$2('[ri/singleton]');
795 |
796 | var rijs_singleton$1 = /*#__PURE__*/Object.freeze({
797 | default: rijs_singleton,
798 | __moduleExports: rijs_singleton
799 | });
800 |
801 | var copy = function copy(from, to){
802 | return function(d){
803 | return to[d] = from[d], d
804 | }
805 | };
806 |
807 | var copy$1 = /*#__PURE__*/Object.freeze({
808 | default: copy,
809 | __moduleExports: copy
810 | });
811 |
812 | var copy$2 = ( copy$1 && copy ) || copy$1;
813 |
814 | var overwrite = function overwrite(to){
815 | return function(from){
816 | keys$2(from)
817 | .map(copy$2(from, to));
818 |
819 | return to
820 | }
821 | };
822 |
823 | var overwrite$1 = /*#__PURE__*/Object.freeze({
824 | default: overwrite,
825 | __moduleExports: overwrite
826 | });
827 |
828 | var not = function not(fn){
829 | return function(){
830 | return !fn.apply(this, arguments)
831 | }
832 | };
833 |
834 | var not$1 = /*#__PURE__*/Object.freeze({
835 | default: not,
836 | __moduleExports: not
837 | });
838 |
839 | var not$2 = ( not$1 && not ) || not$1;
840 |
841 | var extend = function extend(to){
842 | return function(from){
843 | keys$2(from)
844 | .filter(not$2(is$2.in(to)))
845 | .map(copy$2(from, to));
846 |
847 | return to
848 | }
849 | };
850 |
851 | var extend$1 = /*#__PURE__*/Object.freeze({
852 | default: extend,
853 | __moduleExports: extend
854 | });
855 |
856 | var merge_1 = merge;
857 |
858 | function merge(to){
859 | return function(from){
860 | for (x in from)
861 | { is$2.obj(from[x]) && is$2.obj(to[x])
862 | ? merge(to[x])(from[x])
863 | : (to[x] = from[x]); }
864 | return to
865 | }
866 | }
867 |
868 | var merge$1 = /*#__PURE__*/Object.freeze({
869 | default: merge_1,
870 | __moduleExports: merge_1
871 | });
872 |
873 | var attr = function attr(name, value) {
874 | var args = arguments.length;
875 |
876 | return !is$2.str(name) && args == 2 ? attr(arguments[1]).call(this, arguments[0])
877 | : !is$2.str(name) && args == 3 ? attr(arguments[1], arguments[2]).call(this, arguments[0])
878 | : function(el){
879 | var ctx = this || {};
880 | el = ctx.nodeName || is$2.fn(ctx.node) ? ctx : el;
881 | el = el.node ? el.node() : el;
882 | el = el.host || el;
883 |
884 | return args > 1 && value === false ? el.removeAttribute(name)
885 | : args > 1 ? (el.setAttribute(name, value), value)
886 | : el.attributes.getNamedItem(name)
887 | && el.attributes.getNamedItem(name).value
888 | }
889 | };
890 |
891 | var attr$1 = /*#__PURE__*/Object.freeze({
892 | default: attr,
893 | __moduleExports: attr
894 | });
895 |
896 | var act = { add: add, update: update, remove: remove }
897 | , str$3 = JSON.stringify
898 | , parse$1 = JSON.parse;
899 |
900 | var set = function set(d, skipEmit) {
901 | return function(o, existing, max) {
902 | if (!is$2.obj(o) && !is$2.fn(o))
903 | { return o }
904 |
905 | if (!is$2.obj(d)) {
906 | var log = existing || o.log || []
907 | , root = o;
908 |
909 | if (!is$2.def(max)) { max = log.max || 0; }
910 | if (!max) { log = []; }
911 | if (max < 0) { log = log.concat(null); }
912 | if (max > 0) {
913 | var s = str$3(o);
914 | root = parse$1(s);
915 | log = log.concat({ type: 'update', value: parse$1(s), time: log.length });
916 | }
917 |
918 | def$2(log, 'max', max);
919 |
920 | root.log
921 | ? (root.log = log)
922 | : def$2(emitterify$2(root, null), 'log', log, 1);
923 |
924 | return root
925 | }
926 |
927 | if (is$2.def(d.key)) {
928 | if (!apply(o, d.type, (d.key = '' + d.key).split('.').filter(Boolean), d.value))
929 | { return false }
930 | } else
931 | { return false }
932 |
933 | if (o.log && o.log.max)
934 | { o.log.push((d.time = o.log.length, o.log.max > 0 ? d : null)); }
935 |
936 | if (!skipEmit && o.emit)
937 | { o.emit('change', d); }
938 |
939 | return o
940 | }
941 | };
942 |
943 | function apply(body, type, path, value) {
944 | var next = path.shift();
945 |
946 | if (!act[type])
947 | { return false }
948 | if (path.length) {
949 | if (!(next in body))
950 | { if (type == 'remove') { return true }
951 | else { body[next] = {}; } }
952 | return apply(body[next], type, path, value)
953 | }
954 | else {
955 | return !act[type](body, next, value)
956 | }
957 | }
958 |
959 | function add(o, k, v) {
960 | is$2.arr(o)
961 | ? o.splice(k, 0, v)
962 | : (o[k] = v);
963 | }
964 |
965 | function update(o, k, v) {
966 | if (!is$2.num(k) && !k) {
967 | if (!is$2.obj(v)) { return true }
968 | for (var x in o) { delete o[x]; }
969 | for (var x in v) { o[x] = v[x]; }
970 | } else
971 | { o[k] = v; }
972 | }
973 |
974 | function remove(o, k, v) {
975 | is$2.arr(o)
976 | ? o.splice(k, 1)
977 | : delete o[k];
978 | }
979 |
980 | var set$1 = /*#__PURE__*/Object.freeze({
981 | default: set,
982 | __moduleExports: set
983 | });
984 |
985 | var overwrite$2 = ( overwrite$1 && overwrite ) || overwrite$1;
986 |
987 | var extend$2 = ( extend$1 && extend ) || extend$1;
988 |
989 | var merge$2 = ( merge$1 && merge_1 ) || merge$1;
990 |
991 | var attr$2 = ( attr$1 && attr ) || attr$1;
992 |
993 | var set$2 = ( set$1 && set ) || set$1;
994 |
995 | // -------------------------------------------
996 | // Adds support for data resources
997 | // -------------------------------------------
998 | var rijs_data = function data(ripple){
999 | log$4('creating');
1000 | ripple
1001 | .on('change.data')
1002 | .filter(function (ref) {
1003 | var name = ref[0];
1004 | var change = ref[1];
1005 |
1006 | return header$2('content-type', 'application/data')(ripple.resources[name]);
1007 | })
1008 | .filter(function (ref) {
1009 | var name = ref[0];
1010 | var change = ref[1];
1011 |
1012 | return change && change.key;
1013 | })
1014 | .map(function (ref) {
1015 | var name = ref[0];
1016 | var change = ref[1];
1017 |
1018 | return ripple
1019 | .resources[name]
1020 | .body
1021 | .emit('change', (change || null), not$2(is$2.in(['bubble'])));
1022 | });
1023 |
1024 | ripple.types['application/data'] = {
1025 | header: 'application/data'
1026 | , ext: '*.data.js'
1027 | , selector: function (res) { return ("[data~=\"" + (res.name) + "\"]"); }
1028 | , extract: function (el) { return (attr$2("data")(el) || '').split(' '); }
1029 | , check: function (res) { return is$2.obj(res.body); }
1030 | , load: function load(res) {
1031 | var exported = commonjsRequire(res.headers.path);
1032 | exported = exported.default || exported;
1033 | exported = is$2.fn(exported) ? exported(ripple) : exported;
1034 | res.headers['content-type'] = this.header;
1035 | ripple(merge$2(res)(exported));
1036 | return ripple.resources[res.name]
1037 | }
1038 | , parse: function parse(res){
1039 | var existing = ripple.resources[res.name] || {};
1040 |
1041 | extend$2(res.headers)(existing.headers);
1042 | res.body = set$2()(
1043 | res.body || []
1044 | , existing.body && existing.body.log
1045 | , is$2.num(res.headers.log) ? res.headers.log : -1
1046 | );
1047 | overwrite$2(res.body.on)(listeners(existing));
1048 | res.body.on('change.bubble', function (change) {
1049 | ripple.emit('change', ripple.change = [res.name, change], not$2(is$2.in(['data'])));
1050 | delete ripple.change;
1051 | });
1052 |
1053 | if (res.headers.loaded && !res.headers.loading)
1054 | { res.headers.loading = Promise.resolve(res.headers.loaded(ripple, res))
1055 | .then(function () {
1056 | delete res.headers.loading;
1057 | return res
1058 | }); }
1059 |
1060 | return res
1061 | }
1062 | };
1063 |
1064 | return ripple
1065 | };
1066 |
1067 | var log$4 = require$$0$2('[ri/types/data]')
1068 | , listeners = key$2('body.on');
1069 |
1070 | var rijs_data$1 = /*#__PURE__*/Object.freeze({
1071 | default: rijs_data,
1072 | __moduleExports: rijs_data
1073 | });
1074 |
1075 | var djbx = function (str) {
1076 | var hash = 5381
1077 | , i = str.length;
1078 |
1079 | while (i)
1080 | { hash = (hash * 33) ^ str.charCodeAt(--i); }
1081 |
1082 | return hash >>> 0
1083 | };
1084 |
1085 | var djbx$1 = /*#__PURE__*/Object.freeze({
1086 | default: djbx,
1087 | __moduleExports: djbx
1088 | });
1089 |
1090 | var hash = ( djbx$1 && djbx ) || djbx$1;
1091 |
1092 | var client_1 = function(ripple) {
1093 | return log$5("creating"), ripple.types["text/css"] = {
1094 | header: "text/css",
1095 | ext: "*.css",
1096 | selector: function (res) { return ("[css~=\"" + (res.name) + "\"]"); },
1097 | extract: function (el) { return (attr$2("css")(el) || "").split(" "); },
1098 | check: function (res) { return includes$2(".css")(res.name); },
1099 | shortname: function (path) { return basename(path); },
1100 | load: !1,
1101 | parse: function (res) { return (res.headers.hash = res.headers.hash || hash(res.body), res); }
1102 | }, ripple;
1103 | };
1104 |
1105 | var log$5 = require$$0$2("[ri/types/css]");
1106 |
1107 | var basename;
1108 |
1109 | var client$3 = /*#__PURE__*/Object.freeze({
1110 | default: client_1,
1111 | __moduleExports: client_1
1112 | });
1113 |
1114 | var lo = function lo(d){
1115 | return (d || '').toLowerCase()
1116 | };
1117 |
1118 | var lo$1 = /*#__PURE__*/Object.freeze({
1119 | default: lo,
1120 | __moduleExports: lo
1121 | });
1122 |
1123 | var lo$2 = ( lo$1 && lo ) || lo$1;
1124 |
1125 | var client_1$1 = function(ripple, ref) {
1126 | if ( ref === void 0 ) ref = {};
1127 | var dir = ref.dir; if ( dir === void 0 ) dir = ".";
1128 |
1129 | return log$6("creating"), ripple.require = (function (res) { return function (module) {
1130 | if (module in res.headers.dependencies && ripple.resources[res.headers.dependencies[module]]) { return ripple(res.headers.dependencies[module]); }
1131 | throw new Error(("Cannot find module: " + module + " for " + (res.name)));
1132 | }; }), ripple.types["application/javascript"] = {
1133 | header: header$3,
1134 | selector: function (res) { return ((res.name) + ",[is~=\"" + (res.name) + "\"]"); },
1135 | extract: function (el) { return (attr$2("is")(el) || "").split(" ").concat(lo$2(el.nodeName)); },
1136 | ext: "*.js",
1137 | shortname: function (path) { return basename$1(path).split(".").slice(0, -1).join("."); },
1138 | check: function (res) { return is$2.fn(res.body); },
1139 | load: !1,
1140 | parse: function (res) {
1141 | if ("cjs" == res.headers.format) {
1142 | var m = {
1143 | exports: {}
1144 | };
1145 | res.body(m, m.exports, ripple.require(res), {
1146 | env: {}
1147 | }), res.body = m.exports;
1148 | }
1149 | return res;
1150 | }
1151 | }, ripple;
1152 | };
1153 |
1154 | var log$6 = require$$0$2("[ri/types/fn]"), header$3 = "application/javascript";
1155 |
1156 | var basename$1;
1157 |
1158 | var client$4 = /*#__PURE__*/Object.freeze({
1159 | default: client_1$1,
1160 | __moduleExports: client_1$1
1161 | });
1162 |
1163 | var nanosocket = function(url){
1164 | if ( url === void 0 ) url = location.href.replace('http', 'ws');
1165 |
1166 | var io = emitterify$2({ attempt: 0 });
1167 | io.ready = io.once('connected');
1168 | io.connect = connect(io, url);
1169 | io.connect();
1170 | io.send = function (data) { return io.ready.then(function (socket) { return socket.send(data); }); };
1171 | return io
1172 | };
1173 |
1174 | var min = Math.min;
1175 | var pow = Math.pow;
1176 |
1177 | var connect = function (io, url) { return function () {
1178 | var WebSocket = window.WebSocket;
1179 | var location = window.location;
1180 | var setTimeout = window.setTimeout;
1181 | var socket = new WebSocket(url);
1182 | socket.onopen = function (d) { return io.emit('connected', socket); };
1183 | socket.onmessage = function (d) { return io.emit('recv', d.data); };
1184 | socket.onclose = function (d) {
1185 | io.ready = io.once('connected');
1186 | io.emit('disconnected');
1187 | setTimeout(io.connect, backoff(++io.attempt));
1188 | };
1189 | }; };
1190 |
1191 | var backoff = function (attempt, base, cap) {
1192 | if ( base === void 0 ) base = 100;
1193 | if ( cap === void 0 ) cap = 10000;
1194 |
1195 | return min(cap, base * pow(2, attempt));
1196 | };
1197 |
1198 | var nanosocket$1 = /*#__PURE__*/Object.freeze({
1199 | default: nanosocket,
1200 | __moduleExports: nanosocket
1201 | });
1202 |
1203 | var require$$0$3 = ( nanosocket$1 && nanosocket ) || nanosocket$1;
1204 |
1205 | var client$5 = function(ref){
1206 | if ( ref === void 0 ) ref = {};
1207 | var socket = ref.socket; if ( socket === void 0 ) socket = require$$0$3();
1208 |
1209 | socket.id = 0;
1210 |
1211 | var server = emitterify$2({
1212 | socket: socket
1213 | , send: send(socket)
1214 | , get subscriptions(){
1215 | return values$2(socket.on)
1216 | .map(function (d) { return d && d[0]; })
1217 | .filter(function (d) { return d && d.type && d.type[0] == '$'; })
1218 | }
1219 | });
1220 |
1221 | socket
1222 | .once('disconnected')
1223 | .map(function (d) { return socket
1224 | .on('connected')
1225 | .map(reconnect(server)); }
1226 | );
1227 |
1228 | socket
1229 | .on('recv')
1230 | .map(deserialise)
1231 | .each(function (ref) {
1232 | var id = ref.id;
1233 | var data = ref.data;
1234 |
1235 | // TODO: check/warn if no sub
1236 | var sink = socket.on[("$" + id)] && socket.on[("$" + id)][0];
1237 |
1238 | data.exec ? data.exec(sink, data.value)
1239 | : !id ? server.emit('recv', data)
1240 | : socket.emit(("$" + id), data);
1241 | });
1242 |
1243 | return server
1244 | };
1245 |
1246 | var deserialise = function (input) { return (new Function(("return " + input)))(); };
1247 |
1248 | var reconnect = function (server) { return function () { return server.subscriptions
1249 | .map(function (ref) {
1250 | var subscription = ref.subscription;
1251 |
1252 | return server.socket.send(subscription);
1253 | }); }; };
1254 |
1255 |
1256 |
1257 | var send = function (socket, type) { return function (data, meta) {
1258 | if (data instanceof window.Blob)
1259 | { return binary(socket, data, meta) }
1260 |
1261 | var id = str$2(++socket.id)
1262 | , output = socket.on(("$" + id))
1263 | , next = function (data, count) {
1264 | if ( count === void 0 ) count = 0;
1265 |
1266 | return socket
1267 | .send(output.source.subscription = str$2({ id: id, data: data, type: type }))
1268 | .then(function (d) { return output.emit('sent', { id: id, count: count }); });
1269 | };
1270 |
1271 | data.next
1272 | ? data.map(next).source.emit('start')
1273 | : next(data);
1274 |
1275 | output
1276 | .source
1277 | .once('stop')
1278 | .filter(function (reason) { return reason != 'CLOSED'; })
1279 | .map(function (d) { return send(socket, 'UNSUBSCRIBE')(id)
1280 | // TODO: also force stop on close of server created sub (?)
1281 | .filter(function (d, i, n) { return n.source.emit('stop', 'CLOSED'); }); }
1282 | );
1283 |
1284 | return output
1285 | }; };
1286 |
1287 | var binary = function (socket, blob, meta, start, blockSize) {
1288 | if ( start === void 0 ) start = 0;
1289 | if ( blockSize === void 0 ) blockSize = 1024;
1290 |
1291 | var output = emitterify$2().on('recv')
1292 | , next = function (id) { return function () { return start >= blob.size
1293 | ? output.emit('sent', { id: id })
1294 | : ( socket.send(blob.slice(start, start += blockSize))
1295 | , window.setTimeout(next(id))
1296 | ); }; };
1297 |
1298 | send(socket, 'BINARY')({ size: blob.size, meta: meta })
1299 | .on('sent', function (ref) {
1300 | var id = ref.id;
1301 |
1302 | return next(id)();
1303 | })
1304 | .on('progress', function (received) { return output.emit('progress', { received: received, total: blob.size }); })
1305 | .map(output.next)
1306 | .source
1307 | .until(output.once('stop'));
1308 |
1309 | return output
1310 | };
1311 |
1312 | var client$6 = /*#__PURE__*/Object.freeze({
1313 | default: client$5,
1314 | __moduleExports: client$5
1315 | });
1316 |
1317 | var time = function time(ms, fn) {
1318 | return arguments.length === 1
1319 | ? setTimeout(ms)
1320 | : setTimeout(fn, ms)
1321 | };
1322 |
1323 | var time$1 = /*#__PURE__*/Object.freeze({
1324 | default: time,
1325 | __moduleExports: time
1326 | });
1327 |
1328 | var require$$0$4 = ( client$6 && client$5 ) || client$6;
1329 |
1330 | var time$2 = ( time$1 && time ) || time$1;
1331 |
1332 | var client$7 = function sync(
1333 | ripple
1334 | , ref
1335 | , ref$1
1336 | ){
1337 | if ( ref === void 0 ) ref = {};
1338 | if ( ref$1 === void 0 ) ref$1 = {};
1339 | var xrs = ref$1.xrs; if ( xrs === void 0 ) xrs = require$$0$4;
1340 |
1341 | ripple.server = xrs();
1342 | ripple.send = send$1(ripple);
1343 | ripple.subscribe = subscribe(ripple);
1344 | ripple.subscriptions = {};
1345 | ripple.get = get(ripple);
1346 | ripple.upload = upload(ripple);
1347 | ripple.upload.id = 0;
1348 |
1349 | // TODO: other than cache pushes? ans: use server.type
1350 | ripple
1351 | .server
1352 | .on('recv')
1353 | .map(function (data, i, n) { return cache(ripple)(data, i, n); });
1354 |
1355 | return ripple
1356 | };
1357 |
1358 | var send$1 = function (ref) {
1359 | var server = ref.server;
1360 |
1361 | return function (name, type, value) { return name instanceof Blob ? server.send(name, type)
1362 | : is$2.obj(name) ? server.send(name)
1363 | : server.send({ name: name, type: type, value: value }); };
1364 | };
1365 |
1366 | var get = function (ripple) { return function (name, k) { return ripple
1367 | .subscribe(name, k)
1368 | .filter(function (d, i, n) { return n.source.emit('stop'); })
1369 | .start(); }; };
1370 |
1371 | var cache = function (ripple, n, k) { return function (change) {
1372 | // if (name && change.name && name != change.name) ripple.link(name, change.name)
1373 | var name = change.name = change.name || n;
1374 | if (!change.type) { change.type = 'update'; }
1375 | if (is$2.def(k)) { change.key = k + "." + (str$2(change.key)); }
1376 | !change.key && change.type == 'update'
1377 | ? ripple(body(change))
1378 | : set$2(change)(ripple.resources[name] ? ripple(name) : ripple(name, {}));
1379 |
1380 | ripple.change = change;
1381 |
1382 | return key$2(k)(ripple(name))
1383 | }; };
1384 |
1385 | var subscribe = function (ripple) { return function (name, k) {
1386 | if (is$2.arr(name)) { return merge$3(name.map(function (n) { return ripple.subscribe(n, k); }))
1387 | .map(function (d) { return name.reduce(function (p, v, i) { return (p[v] = d[i], p); }, {}); }) }
1388 |
1389 | ripple.subscriptions[name] = ripple.subscriptions[name] || {};
1390 | if (is$2.arr(k)) { return merge$3(k.map(function (k) { return ripple.subscribe(name, k); }))
1391 | .map(function (d) { return key$2(k)(ripple(name)); }) }
1392 | var output = emitterify$2().on('subscription');
1393 |
1394 | output
1395 | .on('stop')
1396 | .each(function (d, i, n) {
1397 | raw.subs.splice(raw.subs.indexOf(output), 1);
1398 | time$2(1000, function () {
1399 | if (raw.subs.length) { return }
1400 | raw.source.emit('stop');
1401 | ripple.subscriptions[name][k] = undefined;
1402 | output.emit('end');
1403 | });
1404 | });
1405 |
1406 | if (ripple.subscriptions[name][k])
1407 | { output
1408 | .on('start')
1409 | .map(function () { return key$2(k)(ripple(name)); })
1410 | .filter(is$2.def)
1411 | .map(function (initial) { return output.next(initial); }); }
1412 |
1413 | var raw = ripple.subscriptions[name][k] = ripple.subscriptions[name][k] || ripple
1414 | .send(name, 'SUBSCRIBE', k)
1415 | .map(cache(ripple, name, k))
1416 | .each(function (value) {
1417 | raw.subs.map(function (o) { return o.next(value); });
1418 | delete ripple.change;
1419 | });
1420 |
1421 | raw.subs = raw.subs || [];
1422 | raw.subs.push(output);
1423 |
1424 | return output
1425 | }; };
1426 |
1427 | var upload = function (ripple) { return function (name, form) {
1428 | var index = ++ripple.upload.id
1429 | , fields = {}
1430 | , size = 0
1431 | , next = function () {
1432 | if (!files.length) { return true }
1433 | var ref = files.shift();
1434 | var field = ref.field;
1435 | var filename = ref.filename;
1436 | var i = ref.i;
1437 | var blob = ref.blob;
1438 | return ripple
1439 | .send(blob, { filename: filename, field: field, i: i, index: index })
1440 | .on('progress', function (ref) {
1441 | var received = ref.received;
1442 | var total = ref.total;
1443 |
1444 | return output.emit('progress', {
1445 | total: size
1446 | , received:
1447 | size
1448 | - (blob.size - received)
1449 | - files.reduce(function (acc, d) { return (acc += d.blob.size); }, 0)
1450 | });
1451 | })
1452 | .then(next)
1453 | };
1454 |
1455 | var files = keys$2(form)
1456 | .map(function (field) { return (fields[field] = form[field], field); })
1457 | .filter(function (field) { return form[field] instanceof FileList; })
1458 | .map(function (field) {
1459 | fields[field] = [];
1460 | return to$2.arr(form[field])
1461 | .map(function (f) { return (size += f.size, f); })
1462 | .map(function (f, i) { return ({ field: field, filename: f.name, i: i, blob: f, sent: 0 }); })
1463 | })
1464 | .reduce(flatten$2, []);
1465 |
1466 | var output = ripple.send({
1467 | files: files.length
1468 | , type: 'PREUPLOAD'
1469 | , fields: fields
1470 | , index: index
1471 | , size: size
1472 | , name: name
1473 | }).once('sent', next);
1474 |
1475 | return output
1476 | }; };
1477 |
1478 | var body = function (ref) {
1479 | var name = ref.name;
1480 | var value = ref.value;
1481 | var headers = ref.headers;
1482 |
1483 | return ({ name: name, headers: headers, body: value });
1484 | };
1485 |
1486 | // TODO: factor out
1487 | var merge$3 = function (streams) {
1488 | var output = emitterify$2().on('merged');
1489 | output.streams = streams;
1490 |
1491 | streams.map(function (stream, i) { return stream.each(function (value) {
1492 | stream.latest = value;
1493 | var latest = streams.map(function (d) { return d.latest; });
1494 | if (latest.every(is$2.def)) { output.next(latest); }
1495 | }); }
1496 | );
1497 |
1498 | output
1499 | .once('start')
1500 | .map(function (d) { return streams.map(function ($) { return $.source.emit('start'); }); });
1501 |
1502 | output
1503 | .once('stop')
1504 | .map(function (d) { return streams.map(function ($) { return $.source.emit('stop'); }); });
1505 |
1506 | return output
1507 | };
1508 |
1509 | var client$8 = /*#__PURE__*/Object.freeze({
1510 | default: client$7,
1511 | __moduleExports: client$7
1512 | });
1513 |
1514 | var ready = function ready(fn){
1515 | return document.body ? fn() : document.addEventListener('DOMContentLoaded', fn.bind(this))
1516 | };
1517 |
1518 | var ready$1 = /*#__PURE__*/Object.freeze({
1519 | default: ready,
1520 | __moduleExports: ready
1521 | });
1522 |
1523 | var _class = function (definition) { return assign$1(
1524 | definition.class ? definition.class
1525 | : !definition.prototype ? classed(definition)
1526 | : definition.prototype.render ? definition
1527 | : definition.prototype.connected ? definition
1528 | : classed(definition)
1529 | ); };
1530 |
1531 | var assign$1 = Object.assign;
1532 |
1533 | var classed = function (render) { return render.class = render.class || class {
1534 | render(){ render.apply(this, arguments); }
1535 | }; };
1536 |
1537 | var _class$1 = /*#__PURE__*/Object.freeze({
1538 | default: _class,
1539 | __moduleExports: _class
1540 | });
1541 |
1542 | var event = function event(node, index) {
1543 | node = node.host && node.host.nodeName ? node.host : node;
1544 | if (node.on) { return }
1545 | node.listeners = {};
1546 |
1547 | var on = function (o) {
1548 | var type = o.type.split('.').shift();
1549 | if (!node.listeners[type])
1550 | { node.addEventListener(type, node.listeners[type] =
1551 | function (event) { return (!event.detail || !event.detail.emitted ? emit(type, event) : 0); }
1552 | ); }
1553 | };
1554 |
1555 | var off = function (o) {
1556 | if (!node.on[o.type].length) {
1557 | node.removeEventListener(o.type, node.listeners[o.type]);
1558 | delete node.listeners[o.type];
1559 | }
1560 | };
1561 |
1562 | emitterify$2(node, { on: on, off: off });
1563 | var emit = node.emit;
1564 |
1565 | node.emit = function(type, params){
1566 | var detail = { params: params, emitted: true }
1567 | , event = new CustomEvent(type, { detail: detail, bubbles: false, cancelable: true });
1568 | node.dispatchEvent(event);
1569 | return emit(type, event)
1570 | };
1571 | };
1572 |
1573 | var event$1 = /*#__PURE__*/Object.freeze({
1574 | default: event,
1575 | __moduleExports: event
1576 | });
1577 |
1578 | var classed$1 = ( _class$1 && _class ) || _class$1;
1579 |
1580 | var event$2 = ( event$1 && event ) || event$1;
1581 |
1582 | var noop$1 = function () {}
1583 | , HTMLElement = client$2 && window.HTMLElement || class {}
1584 | , registry = client$2 && window.customElements || {};
1585 |
1586 | var define = function define(name, component) {
1587 | if (arguments.length == 1) { component = name, name = "anon-" + (registry.anon++); }
1588 | if (component.wrapper) { return component.wrapper }
1589 | if (!name.includes('-')) { return; }
1590 | if (!client$2) { return wrap$3(classed$1(component)) }
1591 | var wrapped = registry.get(name);
1592 |
1593 | if (wrapped) {
1594 | if (wrapped.class == classed$1(component)) { return wrapped }
1595 | wrapped.class = classed$1(component);
1596 | var instances = Array.from(document.querySelectorAll(name));
1597 | instances.map(function (node) {
1598 | node.disconnectedCallback();
1599 | node.methods.map(function (method) { delete node[method]; });
1600 | node.connectedCallback();
1601 | });
1602 | } else {
1603 | registry.define(name, wrapped = wrap$3(classed$1(component)));
1604 | }
1605 |
1606 | return wrapped
1607 | };
1608 |
1609 | var wrap$3 = function (component) {
1610 | component.wrapper = component.wrapper || class extends HTMLElement {
1611 | connectedCallback(){
1612 | var this$1 = this;
1613 |
1614 | var ref = component.wrapper.class;
1615 | var prototype = ref.prototype;
1616 | event$2(this);
1617 | this.state = this.state || {};
1618 | this.methods = Object
1619 | .getOwnPropertyNames(prototype)
1620 | .filter(function (method) { return !(method in disallowed); })
1621 | .map(function (method) { return ((this$1[method] = prototype[method].bind(this$1)), method); });
1622 |
1623 | return Promise.resolve((this.connected || noop$1).call(this, this, this.state))
1624 | .then(function (d) {
1625 | this$1.initialised = true;
1626 | this$1.render();
1627 | })
1628 | }
1629 |
1630 | render(){
1631 | var ref = component.wrapper.class;
1632 | var prototype = ref.prototype;
1633 | if (!this.initialised) { return }
1634 | return prototype.render.call(this, this, this.state)
1635 | }
1636 |
1637 | disconnectedCallback(){
1638 | (this.disconnected || noop$1).call(this, this, this.state);
1639 | this.dispatchEvent(new CustomEvent('disconnected'));
1640 | this.initialised = false;
1641 | }
1642 | };
1643 |
1644 | component.wrapper.class = component;
1645 | return component.wrapper
1646 | };
1647 |
1648 | var disallowed = { length: 1, prototype: 1, name: 1, render: 1 };
1649 |
1650 | registry.anon = registry.anon || 1;
1651 |
1652 | var define$1 = /*#__PURE__*/Object.freeze({
1653 | default: define,
1654 | __moduleExports: define
1655 | });
1656 |
1657 | var ready$2 = ( ready$1 && ready ) || ready$1;
1658 |
1659 | var define$2 = ( define$1 && define ) || define$1;
1660 |
1661 | var rijs_components = function components(ripple){
1662 | if (!client$2) { return ripple }
1663 | log$7('creating');
1664 |
1665 | // if no render is defined on a component, load up definition
1666 | Node.prototype.render = function(){
1667 | var name = this.nodeName.toLowerCase();
1668 | if (name.includes('-'))
1669 | { return this.fn$ = this.fn$ || ripple
1670 | .subscribe(name)
1671 | .map(function (component) { return define$2(name, component); }) }
1672 | // TODO: test this works well across all instances
1673 | // .until(new Promise(resolve => this.addEventListener('disconnected', () => {
1674 | // if (!this.isConnected) resolve()
1675 | // })))
1676 | };
1677 |
1678 | // this is for backwards compatibility
1679 | Node.prototype.draw = function(){
1680 | this.render();
1681 | };
1682 |
1683 | ready$2(function () { return Array.from(document.querySelectorAll('*'))
1684 | .filter(function (d) { return d.nodeName.includes('-'); })
1685 | .map(function (node) { return node.render(); }); }
1686 | );
1687 |
1688 | return ripple
1689 | };
1690 |
1691 | var log$7 = require$$0$2('[ri/components]');
1692 |
1693 | var rijs_components$1 = /*#__PURE__*/Object.freeze({
1694 | default: rijs_components,
1695 | __moduleExports: rijs_components
1696 | });
1697 |
1698 | var require$$0$5 = ( rijs_core$1 && rijs_core ) || rijs_core$1;
1699 |
1700 | var require$$1 = ( rijs_singleton$1 && rijs_singleton ) || rijs_singleton$1;
1701 |
1702 | var require$$2$1 = ( rijs_data$1 && rijs_data ) || rijs_data$1;
1703 |
1704 | var require$$3 = ( client$3 && client_1 ) || client$3;
1705 |
1706 | var require$$4 = ( client$4 && client_1$1 ) || client$4;
1707 |
1708 | var require$$5 = ( client$8 && client$7 ) || client$8;
1709 |
1710 | var require$$6 = ( rijs_components$1 && rijs_components ) || rijs_components$1;
1711 |
1712 | var ripple = createCommonjsModule(function (module) {
1713 | function create(opts) {
1714 | var ripple = require$$0$5(opts);
1715 | return require$$1(ripple, opts), require$$2$1(ripple, opts),
1716 | require$$3(ripple, opts), require$$4(ripple, opts), require$$5(ripple, opts),
1717 | require$$6(ripple, opts), ripple;
1718 | }
1719 |
1720 | !window.ripple && create(), module.exports = create;
1721 | });
1722 |
1723 | return ripple;
1724 |
1725 | }());
1726 |
--------------------------------------------------------------------------------
/client/ripple.js:
--------------------------------------------------------------------------------
1 | const client = require("utilise/client");
2 |
3 | function create(opts) {
4 | const ripple = require("rijs.core")(opts);
5 | return require("rijs.singleton")(ripple, opts), require("rijs.data")(ripple, opts),
6 | require("rijs.css")(ripple, opts), require("rijs.fn")(ripple, opts), require("rijs.sync")(ripple, opts),
7 | require("rijs.components")(ripple, opts), ripple;
8 | }
9 |
10 | !window.ripple && create(), module.exports = create;
11 |
--------------------------------------------------------------------------------
/client/ripple.min.js:
--------------------------------------------------------------------------------
1 | var rijs=function(){"use strict";var e="undefined"!=typeof window,n=Object.freeze({default:e,__moduleExports:e}),t=function(){var e,n,t=new Promise(function(t,r){e=t,n=r});return arguments.length&&e(arguments[0]),t.resolve=e,t.reject=n,t};var r=Object.freeze({default:t,__moduleExports:t}),o=function e(n,t){return t instanceof Array&&(t=t.reduce(e,[])),(n=n||[]).concat(t)},u=Object.freeze({default:o,__moduleExports:o}),i=function(e,n){return n in e},c=Object.freeze({default:i,__moduleExports:i}),s=c&&i||c,a=function(e,n,t,r){return e.host&&e.host.nodeName&&(e=e.host),n.name&&(t=n,n=n.name),!s(e,n)&&Object.defineProperty(e,n,{value:t,writable:r}),e[n]},f=Object.freeze({default:a,__moduleExports:a}),l=r&&t||r,d=u&&o||u,p=f&&a||f,m=function(){},h=function e(n,t){return t=t||{},p(n=n||{},"emit",function(e,t,o){for(var u=n.on[e.split(".")[0]]||[],i=[],c=0;c1,o=j.fn(n)?[]:L(n).split(".").filter(Boolean),u=o.shift();return function(i,c){var s={};return i?j.num(n)||n?j.arr(n)?(n.map(function(n){var r=e(n)(i);null!=(r=j.fn(t)?t(r):null==r?t:r)&&e(n,j.fn(r)?A(r):r)(s)}),s):i[n]||!o.length?r?(i[n]=j.fn(t)?t(i[n],c):t,i):j.fn(n)?n(i):i[n]:r?(e(o.join("."),t)(i[u]?i[u]:i[u]={}),i):e(o.join("."))(i[u]):r?function(e,n){return $(e).map(function(n){delete e[n]}),$(n).map(function(t){e[t]=n[t]}),e}(i,t):i:void 0}},B=Object.freeze({default:P,__moduleExports:P}),D=B&&P||B,I=function(e,n){var t=1==arguments.length;return function(r){return r&&r.headers?t?D(e)(r.headers):D(e)(r.headers)==n:null}},q=Object.freeze({default:I,__moduleExports:I}),T=function(e){return e.__data__},U=Object.freeze({default:T,__moduleExports:T}),M=U&&T||U,R=J;function J(e){return function(n){return D(n)(e)}}J.parent=function(e){return M(this.parentNode)[e]};var F=Object.freeze({default:R,__moduleExports:R}),G=F&&R||F,H=function(e){return e?$(e).map(G(e)):[]},W=Object.freeze({default:H,__moduleExports:H}),Y={arr:function(e){return Array.prototype.slice.call(e,0)},obj:function(e){var n="id";return 1==arguments.length?(n=e,t):t.apply(this,arguments);function t(e,t,r){return 0===r&&(e={}),e[j.fn(n)?n(t,r):t[n]]=t,e}}};var K=Y.arr,Q=Y.obj,V=Object.freeze({default:Y,__moduleExports:Y,arr:K,obj:Q}),X=V&&Y||V,Z=function(){return function e(n){return function(t,r){if(!n.length)return 0;var o=n[0],u=D(o)(t)||"",i=D(o)(r)||"";return ui?-1:e(n.slice(1))(t,r)}}(X.arr(arguments))};var ee=Object.freeze({default:Z,__moduleExports:Z}),ne=function(e){return function(n){return n&&n.indexOf&&~n.indexOf(e)}},te=Object.freeze({default:ne,__moduleExports:ne}),re=te&&ne||te,oe={header:"text/plain",check:function(e){return!re(".html")(e.name)&&!re(".css")(e.name)&&j.str(e.body)}},ue=oe.header,ie=oe.check,ce=Object.freeze({default:oe,__moduleExports:oe,header:ue,check:ie}),se=_?window:global,ae=Object.freeze({default:se,__moduleExports:se}),fe=ae&&se||ae,le=function(e){return function(n){if(!fe.console||!console.error.apply)return n;j.arr(arguments[2])&&(arguments[2]=arguments[2].length);var t=X.arr(arguments),r="[err]["+(new Date).toISOString()+"]"+e;return t.unshift(r.red?r.red:r),console.error.apply(console,t),n}},de=Object.freeze({default:le,__moduleExports:le}),pe=function(e){return function(n){if(!fe.console||!console.log.apply)return n;j.arr(arguments[2])&&(arguments[2]=arguments[2].length);var t=X.arr(arguments),r="[log]["+(new Date).toISOString()+"]"+e;return t.unshift(r.grey?r.grey:r),console.log.apply(console,t),n}},me=Object.freeze({default:pe,__moduleExports:pe}),he=function(e){return function(n){return n.split(e)}},be=Object.freeze({default:he,__moduleExports:he}),ve=be&&he||be,ye=E&&O||E,ge=je((_?(fe.location.search.match(/debug=(.*?)(&|$)/)||[])[1]:D("process.env.DEBUG")(fe))||""),xe=ge.split(",").map(ve("/")),_e=function(e){return"*"==ge||xe.some(function(e){return e=je(e).split("/"),function(n){return 1==n.length?n[0]==e[0]:2==n.length&&n[0]==e[0]&&n[1]==e[1]}}(e))?function(n){if(!fe.console||!console.log.apply)return n;j.arr(arguments[2])&&(arguments[2]=arguments[2].length);var t=X.arr(arguments),r="[deb]["+(new Date).toISOString()+"]"+e;return t.unshift(r.grey?r.grey:r),console.log.apply(console,t),n}:ye};function je(e){return e.replace(/(\[|\])/g,"")}var Oe=Object.freeze({default:_e,__moduleExports:_e}),Ee=b&&h||b,ze=q&&I||q,we=W&&H||W,ke=ee&&Z||ee,Se=ce&&oe||ce,Ne=me&&pe||me,Ce=Oe&&_e||Oe,Ae=function(e){void 0===e&&(e={});var n=e.aliases;return void 0===n&&(n={}),Ue("creating"),t.resources={},t.link=qe(t),t.register=t,t.types=De(),Ie(Ee(t),n);function t(e,n,r){return e?j.arr(e)?e.map(t):j.promise(e)?e.then(t).catch(Te):j.obj(e)&&!e.name?t(we(e)):j.fn(e)&&e.resources?t(we(e.resources)):j.str(e)&&!n&&t.resources[e]?t.resources[e].body:!j.str(e)||n||t.resources[e]?j.str(e)&&n?$e(t)({name:e,body:n,headers:r}):j.obj(e)?$e(t)(e):(Te("could not find or create resource",e),!1):void 0:t}},$e=function(e){return function(n){var t=n.name,r=n.body,o=n.headers;if(void 0===o&&(o={}),t=e.aliases.src[t]||t,j.promise(r))return r.then(function(n){return $e(e)({name:t,body:n,headers:o})}).catch(Te);Me("registering",t);var u=Le(e)({name:t,body:r,headers:o});return u?(e.resources[t]=u,e.emit("change",[t,{type:"update",value:u.body,time:Re(u)}]),e.resources[t].body):(Te("failed to register",t),!1)}},Le=function(e){return function(n){return ze("content-type")(n)||we(e.types).sort(ke("priority")).some(Be(n)),ze("content-type")(n)?Pe(e)(n):(Te("could not understand resource",n),!1)}},Pe=function(e){return function(n){var t=ze("content-type")(n);return e.types[t]?(e.types[t].parse||ye)(n):(Te("could not understand type",t),!1)}},Be=function(e){return function(n){return n.check(e)&&(e.headers["content-type"]=n.header)}},De=function(){return[Se].reduce(X.obj("header"),1)},Ie=function(e,n){for(var t in e.aliases={dst:{},src:{}},n)e.link(n[t],t);return e},qe=function(e){return function(n,t){e.aliases.src[n]=t,e.aliases.dst[t]=n,Object.defineProperty(e.resources,n,{get:function(){return e.resources[t]},set:function(n){e.resources[t]=n}})}},Te=(de&&le||de)("[ri/core]"),Ue=Ne("[ri/core]"),Me=Ce("[ri/core]"),Re=function(e,n){return n=D("body.log.length")(e),j.num(n)?n-1:n},Je=Object.freeze({default:Ae,__moduleExports:Ae}),Fe=function(e){return Ge("creating"),fe.ripple||(fe.ripple=e),e},Ge=Ne("[ri/singleton]"),He=Object.freeze({default:Fe,__moduleExports:Fe}),We=function(e,n){return function(t){return n[t]=e[t],t}},Ye=Object.freeze({default:We,__moduleExports:We}),Ke=Ye&&We||Ye,Qe=function(e){return function(n){return $(n).map(Ke(n,e)),e}},Ve=Object.freeze({default:Qe,__moduleExports:Qe}),Xe=function(e){return function(){return!e.apply(this,arguments)}},Ze=Object.freeze({default:Xe,__moduleExports:Xe}),en=Ze&&Xe||Ze,nn=function(e){return function(n){return $(n).filter(en(j.in(e))).map(Ke(n,e)),e}},tn=Object.freeze({default:nn,__moduleExports:nn}),rn=function e(n){return function(t){for(x in t)j.obj(t[x])&&j.obj(n[x])?e(n[x])(t[x]):n[x]=t[x];return n}};var on=Object.freeze({default:rn,__moduleExports:rn}),un=function e(n,t){var r=arguments.length;return j.str(n)||2!=r?j.str(n)||3!=r?function(e){var o=this||{};return e=(e=(e=o.nodeName||j.fn(o.node)?o:e).node?e.node():e).host||e,r>1&&!1===t?e.removeAttribute(n):r>1?(e.setAttribute(n,t),t):e.attributes.getNamedItem(n)&&e.attributes.getNamedItem(n).value}:e(arguments[1],arguments[2]).call(this,arguments[0]):e(arguments[1]).call(this,arguments[0])},cn=Object.freeze({default:un,__moduleExports:un}),sn={add:function(e,n,t){j.arr(e)?e.splice(n,0,t):e[n]=t},update:function(e,n,t){if(j.num(n)||n)e[n]=t;else{if(!j.obj(t))return!0;for(var r in e)delete e[r];for(var r in t)e[r]=t[r]}},remove:function(e,n){j.arr(e)?e.splice(n,1):delete e[n]}},an=JSON.stringify,fn=JSON.parse,ln=function(e,n){return function(t,r,o){if(!j.obj(t)&&!j.fn(t))return t;if(!j.obj(e)){var u=r||t.log||[],i=t;if(j.def(o)||(o=u.max||0),o||(u=[]),o<0&&(u=u.concat(null)),o>0){var c=an(t);i=fn(c),u=u.concat({type:"update",value:fn(c),time:u.length})}return p(u,"max",o),i.log?i.log=u:p(Ee(i,null),"log",u,1),i}return!!j.def(e.key)&&(!!function e(n,t,r,o){var u=r.shift();if(!sn[t])return!1;if(r.length){if(!(u in n)){if("remove"==t)return!0;n[u]={}}return e(n[u],t,r,o)}return!sn[t](n,u,o)}(t,e.type,(e.key=""+e.key).split(".").filter(Boolean),e.value)&&(t.log&&t.log.max&&t.log.push((e.time=t.log.length,t.log.max>0?e:null)),!n&&t.emit&&t.emit("change",e),t))}};var dn=Object.freeze({default:ln,__moduleExports:ln}),pn=Ve&&Qe||Ve,mn=tn&&nn||tn,hn=on&&rn||on,bn=cn&&un||cn,vn=dn&&ln||dn,yn=function(e){return gn("creating"),e.on("change.data").filter(function(n){var t=n[0];n[1];return ze("content-type","application/data")(e.resources[t])}).filter(function(e){e[0];var n=e[1];return n&&n.key}).map(function(n){var t=n[0],r=n[1];return e.resources[t].body.emit("change",r||null,en(j.in(["bubble"])))}),e.types["application/data"]={header:"application/data",ext:"*.data.js",selector:function(e){return'[data~="'+e.name+'"]'},extract:function(e){return(bn("data")(e)||"").split(" ")},check:function(e){return j.obj(e.body)},load:function(n){var t=function(){throw new Error("Dynamic requires are not currently supported by rollup-plugin-commonjs")}(n.headers.path);return t=t.default||t,t=j.fn(t)?t(e):t,n.headers["content-type"]=this.header,e(hn(n)(t)),e.resources[n.name]},parse:function(n){var t=e.resources[n.name]||{};return mn(n.headers)(t.headers),n.body=vn()(n.body||[],t.body&&t.body.log,j.num(n.headers.log)?n.headers.log:-1),pn(n.body.on)(xn(t)),n.body.on("change.bubble",function(t){e.emit("change",e.change=[n.name,t],en(j.in(["data"]))),delete e.change}),n.headers.loaded&&!n.headers.loading&&(n.headers.loading=Promise.resolve(n.headers.loaded(e,n)).then(function(){return delete n.headers.loading,n})),n}},e},gn=Ne("[ri/types/data]"),xn=D("body.on"),_n=Object.freeze({default:yn,__moduleExports:yn}),jn=function(e){for(var n=5381,t=e.length;t;)n=33*n^e.charCodeAt(--t);return n>>>0},On=Object.freeze({default:jn,__moduleExports:jn}),En=On&&jn||On,zn=function(e){return wn("creating"),e.types["text/css"]={header:"text/css",ext:"*.css",selector:function(e){return'[css~="'+e.name+'"]'},extract:function(e){return(bn("css")(e)||"").split(" ")},check:function(e){return re(".css")(e.name)},shortname:function(e){return(void 0)(e)},load:!1,parse:function(e){return e.headers.hash=e.headers.hash||En(e.body),e}},e},wn=Ne("[ri/types/css]"),kn=Object.freeze({default:zn,__moduleExports:zn}),Sn=function(e){return(e||"").toLowerCase()},Nn=Object.freeze({default:Sn,__moduleExports:Sn}),Cn=Nn&&Sn||Nn,An=function(e,n){void 0===n&&(n={});var t=n.dir;return void 0===t&&(t="."),$n("creating"),e.require=function(n){return function(t){if(t in n.headers.dependencies&&e.resources[n.headers.dependencies[t]])return e(n.headers.dependencies[t]);throw new Error("Cannot find module: "+t+" for "+n.name)}},e.types["application/javascript"]={header:Ln,selector:function(e){return e.name+',[is~="'+e.name+'"]'},extract:function(e){return(bn("is")(e)||"").split(" ").concat(Cn(e.nodeName))},ext:"*.js",shortname:function(e){return(void 0)(e).split(".").slice(0,-1).join(".")},check:function(e){return j.fn(e.body)},load:!1,parse:function(n){if("cjs"==n.headers.format){var t={exports:{}};n.body(t,t.exports,e.require(n),{env:{}}),n.body=t.exports}return n}},e},$n=Ne("[ri/types/fn]"),Ln="application/javascript",Pn=Object.freeze({default:An,__moduleExports:An}),Bn=function(e){void 0===e&&(e=location.href.replace("http","ws"));var n=Ee({attempt:0});return n.ready=n.once("connected"),n.connect=qn(n,e),n.connect(),n.send=function(e){return n.ready.then(function(n){return n.send(e)})},n},Dn=Math.min,In=Math.pow,qn=function(e,n){return function(){var t=window.WebSocket,r=(window.location,window.setTimeout),o=new t(n);o.onopen=function(){return e.emit("connected",o)},o.onmessage=function(n){return e.emit("recv",n.data)},o.onclose=function(){e.ready=e.once("connected"),e.emit("disconnected"),r(e.connect,Tn(++e.attempt))}}},Tn=function(e,n,t){return void 0===n&&(n=100),void 0===t&&(t=1e4),Dn(t,n*In(2,e))},Un=Object.freeze({default:Bn,__moduleExports:Bn}),Mn=Un&&Bn||Un,Rn=function(e){void 0===e&&(e={});var n=e.socket;void 0===n&&(n=Mn()),n.id=0;var t=Ee({socket:n,send:Gn(n),get subscriptions(){return we(n.on).map(function(e){return e&&e[0]}).filter(function(e){return e&&e.type&&"$"==e.type[0]})}});return n.once("disconnected").map(function(){return n.on("connected").map(Fn(t))}),n.on("recv").map(Jn).each(function(e){var r=e.id,o=e.data,u=n.on["$"+r]&&n.on["$"+r][0];o.exec?o.exec(u,o.value):r?n.emit("$"+r,o):t.emit("recv",o)}),t},Jn=function(e){return new Function("return "+e)()},Fn=function(e){return function(){return e.subscriptions.map(function(n){var t=n.subscription;return e.socket.send(t)})}},Gn=function(e,n){return function(t,r){if(t instanceof window.Blob)return Hn(e,t,r);var o=L(++e.id),u=e.on("$"+o),i=function(t,r){return void 0===r&&(r=0),e.send(u.source.subscription=L({id:o,data:t,type:n})).then(function(){return u.emit("sent",{id:o,count:r})})};return t.next?t.map(i).source.emit("start"):i(t),u.source.once("stop").filter(function(e){return"CLOSED"!=e}).map(function(){return Gn(e,"UNSUBSCRIBE")(o).filter(function(e,n,t){return t.source.emit("stop","CLOSED")})}),u}},Hn=function(e,n,t,r,o){void 0===r&&(r=0),void 0===o&&(o=1024);var u=Ee().on("recv"),i=function(t){return function(){return r>=n.size?u.emit("sent",{id:t}):(e.send(n.slice(r,r+=o)),window.setTimeout(i(t)))}};return Gn(e,"BINARY")({size:n.size,meta:t}).on("sent",function(e){var n=e.id;return i(n)()}).on("progress",function(e){return u.emit("progress",{received:e,total:n.size})}).map(u.next).source.until(u.once("stop")),u},Wn=Object.freeze({default:Rn,__moduleExports:Rn}),Yn=function(e,n){return 1===arguments.length?setTimeout(e):setTimeout(n,e)},Kn=Object.freeze({default:Yn,__moduleExports:Yn}),Qn=Wn&&Rn||Wn,Vn=Kn&&Yn||Kn,Xn=function(e,n,t){void 0===n&&(n={}),void 0===t&&(t={});var r=t.xrs;return void 0===r&&(r=Qn),e.server=r(),e.send=Zn(e),e.subscribe=tt(e),e.subscriptions={},e.get=et(e),e.upload=rt(e),e.upload.id=0,e.server.on("recv").map(function(n,t,r){return nt(e)(n,t,r)}),e},Zn=function(e){var n=e.server;return function(e,t,r){return e instanceof Blob?n.send(e,t):j.obj(e)?n.send(e):n.send({name:e,type:t,value:r})}},et=function(e){return function(n,t){return e.subscribe(n,t).filter(function(e,n,t){return t.source.emit("stop")}).start()}},nt=function(e,n,t){return function(r){var o=r.name=r.name||n;return r.type||(r.type="update"),j.def(t)&&(r.key=t+"."+L(r.key)),r.key||"update"!=r.type?vn(r)(e.resources[o]?e(o):e(o,{})):e(ot(r)),e.change=r,D(t)(e(o))}},tt=function(e){return function(n,t){if(j.arr(n))return ut(n.map(function(n){return e.subscribe(n,t)})).map(function(e){return n.reduce(function(n,t,r){return n[t]=e[r],n},{})});if(e.subscriptions[n]=e.subscriptions[n]||{},j.arr(t))return ut(t.map(function(t){return e.subscribe(n,t)})).map(function(){return D(t)(e(n))});var r=Ee().on("subscription");r.on("stop").each(function(){o.subs.splice(o.subs.indexOf(r),1),Vn(1e3,function(){o.subs.length||(o.source.emit("stop"),e.subscriptions[n][t]=void 0,r.emit("end"))})}),e.subscriptions[n][t]&&r.on("start").map(function(){return D(t)(e(n))}).filter(j.def).map(function(e){return r.next(e)});var o=e.subscriptions[n][t]=e.subscriptions[n][t]||e.send(n,"SUBSCRIBE",t).map(nt(e,n,t)).each(function(n){o.subs.map(function(e){return e.next(n)}),delete e.change});return o.subs=o.subs||[],o.subs.push(r),r}},rt=function(e){return function(n,t){var r=++e.upload.id,o={},u=0,i=function(){if(!c.length)return!0;var n=c.shift(),t=n.field,o=n.filename,a=n.i,f=n.blob;return e.send(f,{filename:o,field:t,i:a,index:r}).on("progress",function(e){var n=e.received;e.total;return s.emit("progress",{total:u,received:u-(f.size-n)-c.reduce(function(e,n){return e+n.blob.size},0)})}).then(i)},c=$(t).map(function(e){return o[e]=t[e],e}).filter(function(e){return t[e]instanceof FileList}).map(function(e){return o[e]=[],X.arr(t[e]).map(function(e){return u+=e.size,e}).map(function(n,t){return{field:e,filename:n.name,i:t,blob:n,sent:0}})}).reduce(d,[]),s=e.send({files:c.length,type:"PREUPLOAD",fields:o,index:r,size:u,name:n}).once("sent",i);return s}},ot=function(e){var n=e.name,t=e.value;return{name:n,headers:e.headers,body:t}},ut=function(e){var n=Ee().on("merged");return n.streams=e,e.map(function(t){return t.each(function(r){t.latest=r;var o=e.map(function(e){return e.latest});o.every(j.def)&&n.next(o)})}),n.once("start").map(function(){return e.map(function(e){return e.source.emit("start")})}),n.once("stop").map(function(){return e.map(function(e){return e.source.emit("stop")})}),n},it=Object.freeze({default:Xn,__moduleExports:Xn}),ct=function(e){return document.body?e():document.addEventListener("DOMContentLoaded",e.bind(this))},st=Object.freeze({default:ct,__moduleExports:ct}),at=function(e){return ft(e.class?e.class:e.prototype?e.prototype.render?e:e.prototype.connected?e:lt(e):lt(e))},ft=Object.assign,lt=function(e){return e.class=e.class||class{render(){e.apply(this,arguments)}}},dt=Object.freeze({default:at,__moduleExports:at}),pt=function(e){if(!(e=e.host&&e.host.nodeName?e.host:e).on){e.listeners={};Ee(e,{on:function(t){var r=t.type.split(".").shift();e.listeners[r]||e.addEventListener(r,e.listeners[r]=function(e){return e.detail&&e.detail.emitted?0:n(r,e)})},off:function(n){e.on[n.type].length||(e.removeEventListener(n.type,e.listeners[n.type]),delete e.listeners[n.type])}});var n=e.emit;e.emit=function(t,r){var o=new CustomEvent(t,{detail:{params:r,emitted:!0},bubbles:!1,cancelable:!0});return e.dispatchEvent(o),n(t,o)}}},mt=Object.freeze({default:pt,__moduleExports:pt}),ht=dt&&at||dt,bt=mt&&pt||mt,vt=function(){},yt=_&&window.HTMLElement||class{},gt=_&&window.customElements||{},xt=function(e,n){if(1==arguments.length&&(n=e,e="anon-"+gt.anon++),n.wrapper)return n.wrapper;if(e.includes("-")){if(!_)return _t(ht(n));var t=gt.get(e);if(t){if(t.class==ht(n))return t;t.class=ht(n),Array.from(document.querySelectorAll(e)).map(function(e){e.disconnectedCallback(),e.methods.map(function(n){delete e[n]}),e.connectedCallback()})}else gt.define(e,t=_t(ht(n)));return t}},_t=function(e){return e.wrapper=e.wrapper||class extends yt{connectedCallback(){var n=this,t=e.wrapper.class.prototype;return bt(this),this.state=this.state||{},this.methods=Object.getOwnPropertyNames(t).filter(function(e){return!(e in jt)}).map(function(e){return n[e]=t[e].bind(n),e}),Promise.resolve((this.connected||vt).call(this,this,this.state)).then(function(){n.initialised=!0,n.render()})}render(){var n=e.wrapper.class.prototype;if(this.initialised)return n.render.call(this,this,this.state)}disconnectedCallback(){(this.disconnected||vt).call(this,this,this.state),this.dispatchEvent(new CustomEvent("disconnected")),this.initialised=!1}},e.wrapper.class=e,e.wrapper},jt={length:1,prototype:1,name:1,render:1};gt.anon=gt.anon||1;var Ot,Et=Object.freeze({default:xt,__moduleExports:xt}),zt=st&&ct||st,wt=Et&&xt||Et,kt=function(e){return _?(St("creating"),Node.prototype.render=function(){var n=this.nodeName.toLowerCase();if(n.includes("-"))return this.fn$=this.fn$||e.subscribe(n).map(function(e){return wt(n,e)})},Node.prototype.draw=function(){this.render()},zt(function(){return Array.from(document.querySelectorAll("*")).filter(function(e){return e.nodeName.includes("-")}).map(function(e){return e.render()})}),e):e},St=Ne("[ri/components]"),Nt=Object.freeze({default:kt,__moduleExports:kt}),Ct=Je&&Ae||Je,At=He&&Fe||He,$t=_n&&yn||_n,Lt=kn&&zn||kn,Pt=Pn&&An||Pn,Bt=it&&Xn||it,Dt=Nt&&kt||Nt;return function(e){function n(e){var n=Ct(e);return At(n,e),$t(n,e),Lt(n,e),Pt(n,e),Bt(n,e),Dt(n,e),n}!window.ripple&&n(),e.exports=n}(Ot={exports:{}},Ot.exports),Ot.exports}();
2 |
--------------------------------------------------------------------------------
/client/ripple.min.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rijs/fullstack/82f6e5ebe4a5c73471137a16142f519bc0aa3394/client/ripple.min.js.gz
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const client = require('utilise/client')
2 |
3 | if (client) !window.ripple && create()
4 |
5 | module.exports = create
6 |
7 | function create(opts){
8 | const ripple = require('rijs.core')(opts)
9 | require('rijs.singleton')(ripple, opts)
10 | require('rijs.data')(ripple, opts)
11 | require('rijs.css')(ripple, opts)
12 | require('rijs.fn')(ripple, opts)
13 | require('rijs.sync')(ripple, opts)
14 | require('rijs.components')(ripple, opts)
15 |
16 | if (!client) {
17 | const { dirname, resolve } = require('path')
18 | opts.dir = opts.dir || dirname(module.parent.filename)
19 | opts.serve = resolve(__dirname, 'client')
20 | require('rijs.sessions')(ripple, opts)
21 | require('rijs.serve')(ripple, opts)
22 | require('rijs.pages')(ripple, opts)
23 | require('rijs.resdir')(ripple, opts)
24 | }
25 |
26 | return ripple
27 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rijs",
3 | "version": "0.9.1",
4 | "main": ".",
5 | "author": "Pedram Emrouznejad (https://github.com/pemrouz)",
6 | "license": "pemrouz.mit-license.org",
7 | "repository": {
8 | "type": "git",
9 | "url": "git://github.com/rijs/fullstack.git"
10 | },
11 | "scripts": {
12 | "clean": "rm -rf ./client/ripple.*",
13 | "build": "npm run clean && npm run client && npm run rollup && npm run minify && npm run gzip",
14 | "client": "uglifyjs index.js -b -d client=true -c > ./client/ripple.js",
15 | "rollup": "rollup -c",
16 | "minify": "uglifyjs ./client/ripple.bundle.js -m -c keep_fargs=false > ./client/ripple.min.js",
17 | "gzip": "gzip -c ./client/ripple.min.js > ./client/ripple.min.js.gz",
18 | "version": "npm run build && git add -A",
19 | "postversion": "git push && git push --tags",
20 | "test": "tap ./tests/*.js"
21 | },
22 | "dependencies": {
23 | "rijs.components": "*",
24 | "rijs.core": "*",
25 | "rijs.css": "*",
26 | "rijs.data": "*",
27 | "rijs.fn": "*",
28 | "rijs.pages": "*",
29 | "rijs.resdir": "*",
30 | "rijs.serve": "*",
31 | "rijs.sessions": "*",
32 | "rijs.singleton": "*",
33 | "rijs.sync": "*",
34 | "utilise": "*"
35 | },
36 | "devDependencies": {
37 | "puppeteer": "^1.3.0",
38 | "rollup": "^0.58.0",
39 | "rollup-plugin-async": "*",
40 | "rollup-plugin-buble": "*",
41 | "rollup-plugin-commonjs": "*",
42 | "rollup-plugin-node-resolve": "*",
43 | "rollup-plugin-nodent": "*",
44 | "tap": "^10.7.3",
45 | "uglify-es": "^3.3.10"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import nodeResolve from 'rollup-plugin-node-resolve';
2 | import commonjs from 'rollup-plugin-commonjs';
3 | import async from 'rollup-plugin-async';
4 | import buble from 'rollup-plugin-buble'
5 |
6 | export default {
7 | input: 'client/ripple.js'
8 | , output: {
9 | file: 'client/ripple.bundle.js'
10 | , format: 'iife'
11 | }
12 | , name: 'rijs'
13 | , plugins: [
14 | nodeResolve({ browser: true })
15 | , commonjs({ ignoreGlobal: true })
16 | , async()
17 | , buble({
18 | transforms: {
19 | generator: false
20 | , classes: false
21 | }
22 | })
23 | ]
24 | }
--------------------------------------------------------------------------------
/rollup.pure.config.js:
--------------------------------------------------------------------------------
1 | import nodeResolve from 'rollup-plugin-node-resolve'
2 | import commonjs from 'rollup-plugin-commonjs'
3 | import replace from 'rollup-plugin-replace'
4 | import buble from 'rollup-plugin-buble'
5 |
6 | export default {
7 | input: 'index.js'
8 | , output: {
9 | file: 'ripple.pure.js'
10 | , format: 'iife'
11 | }
12 | , name: 'rijs'
13 | , plugins: [
14 | replace({
15 | delimiters: ['','']
16 | , values: {
17 | "require('utilise/emitterify')": "window.emitterify"
18 | , "require('utilise/overwrite')": "window.overwrite"
19 | , "require('utilise/colorfill')": "window.colorfill"
20 | , "require('utilise/includes')": "window.includes"
21 | , "require('utilise/identity')": "window.identity"
22 | , "require('utilise/debounce')": "window.debounce"
23 | , "require('utilise/flatten')": "window.flatten"
24 | , "require('utilise/replace')": "window.replace"
25 | , "require('utilise/header')": "window.header"
26 | , "require('utilise/extend')": "window.extend"
27 | , "require('utilise/append')": "window.append"
28 | , "require('utilise/values')": "window.values"
29 | , "require('utilise/ready')": "window.ready"
30 | , "require('utilise/proxy')": "window.proxy"
31 | , "require('utilise/split')": "window.split"
32 | , "require('utilise/clone')": "window.clone"
33 | , "require('utilise/group')": "window.group"
34 | , "require('utilise/parse')": "window.parse"
35 | , "require('utilise/attr')": "window.attr"
36 | , "require('utilise/keys')": "window.keys"
37 | , "require('utilise/time')": "window.time"
38 | , "require('utilise/noop')": "window.noop"
39 | , "require('utilise/from')": "window.from"
40 | , "require('utilise/all')": "window.all"
41 | , "require('utilise/raw')": "window.raw"
42 | , "require('utilise/log')": "window.log"
43 | , "require('utilise/not')": "window.not"
44 | , "require('utilise/key')": "window.key"
45 | , "require('utilise/set')": "window.set"
46 | , "require('utilise/err')": "window.err"
47 | , "require('utilise/str')": "window.str"
48 | , "require('utilise/is')": "window.is"
49 | , "require('utilise/by')": "window.by"
50 | , "require('utilise/el')": "window.el"
51 | , "require('utilise/to')": "window.to"
52 | , "require('utilise/lo')": "window.lo"
53 | , "require('utilise/fn')": "window.fn"
54 | , "require('utilise/za')": "window.za"
55 | , "require('utilise/owner')": "window"
56 | , "require('utilise/client')": "true"
57 |
58 | , "require('rijs.sessions')": "d => d"
59 | , "require('rijs.resdir')": "d => d"
60 | , "require('rijs.pages')": "d => d"
61 | , "require('rijs.serve')": "d => d"
62 | }
63 | })
64 | , nodeResolve({ browser: true })
65 | , commonjs({ ignoreGlobal: true })
66 | , buble()
67 | ]
68 | }
--------------------------------------------------------------------------------
/tests/basic.test.js:
--------------------------------------------------------------------------------
1 | (async () => {
2 | const puppeteer = require('puppeteer')
3 | , browser = await puppeteer.launch({ headless: process.env.HEADLESS !== 'false' })
4 | , { test } = require('tap')
5 |
6 | await test('define, use component on page, with stylesheet, hot reload', async ({ plan, same }) => {
7 | plan(2)
8 | const { ripple, page } = await startup()
9 |
10 | // register component and css
11 | ripple
12 | .resource('web-component', node => node.innerHTML = 'foo')
13 |
14 | // append to page
15 | await page.evaluate(() => {
16 | foo = document.createElement('web-component')
17 | document.body.appendChild(foo)
18 | foo.render()
19 | })
20 |
21 | // check rendered
22 | await page.waitFor('web-component')
23 | same('foo', await page.evaluate(() => foo.innerHTML))
24 |
25 | // register new version of component
26 | ripple('web-component', node => node.innerHTML = 'boo')
27 | same('boo', await page.evaluate(() => foo.innerHTML))
28 |
29 | await page.close()
30 | })
31 |
32 | await test('auto load components, with dependencies', async ({ plan, same }) => {
33 | plan(1)
34 | const { ripple, page } = await startup(``)
35 |
36 | // check rendered
37 | await page.waitFor(() => component.innerHTML == 'foo')
38 | same(['./resources/utils/foo.js', 'auto-loaded-component'], await page.evaluate(() => Object.keys(ripple.resources)))
39 |
40 | await page.close()
41 | })
42 |
43 | await browser.close()
44 | process.exit(0)
45 |
46 | async function startup(body = ''){
47 | const ripple = require('..')({ port: 0, dir: __dirname })
48 | ripple.server.express.use((req, res) => res.send(`
49 |
50 | ${body}
51 | `))
52 |
53 | await ripple.server.once('listening')
54 |
55 | const page = await browser.newPage()
56 |
57 | await page.goto(`http://localhost:${ripple.server.port}`)
58 |
59 | if (process.env.DEBUG == 'true')
60 | page.on('console', (...args) => console.log('(CLIENT):', ...args))
61 |
62 | return { ripple, page }
63 | }
64 | })()
--------------------------------------------------------------------------------
/tests/resources/_components/x-foo.css:
--------------------------------------------------------------------------------
1 | :host { background: red }
--------------------------------------------------------------------------------
/tests/resources/_components/x-foo.js:
--------------------------------------------------------------------------------
1 | const define = require('@compone/define')
2 | , style = require('@compone/style')
3 |
4 | module.exports = define('x-foo', async (node, state) => {
5 | await style(node, await ripple.get('x-foo.css'))
6 |
7 | node.innerHTML = await ripple.get('some-data')
8 | })
--------------------------------------------------------------------------------
/tests/resources/components/auto-loaded-component.js:
--------------------------------------------------------------------------------
1 | const foo = require('../utils/foo')
2 |
3 | module.exports = node => (node.innerHTML = foo)
--------------------------------------------------------------------------------
/tests/resources/utils/foo.js:
--------------------------------------------------------------------------------
1 | module.exports = 'foo'
--------------------------------------------------------------------------------