Skip to content

Commit

Permalink
deep subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
rickiesmooth committed Oct 2, 2016
1 parent 7d9a253 commit f5df166
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 144 deletions.
40 changes: 16 additions & 24 deletions lib/sync/subscription/serialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,27 @@ function merge (a, b) {
}

module.exports = function serializeSubscription (state, subs) {
if (subs.client) {
if (!subs.clients) {
subs.clients = {}
}
if (!subs.clients[state.root.id]) {
subs.clients[state.root.id] = subs.client
} else {
merge(subs.clients[state.root.id], subs.client)
}
delete subs.client
}
return parse(subs)
console.log('IN:', JSON.stringify(subs, false, 2))
const parsed = parse(subs, false, false, state)
console.log('parsed:', JSON.stringify(parsed, false, 2))
return parsed
}

function parse (obj) {
function parse (obj, key, root, state) {
const result = {}
if (!root) { root = result }
for (let i in obj) {
if (i !== '_') {
if (i === 'exec' && typeof obj[i] === 'function') {
// @todo more resolve for parent
if (i === 'client' && (!key || key === '$root' || key === '$parent')) {
let id = state.root.id
if (!root.clients) { root.clients = {} }
if (!root.clients[id]) { root.clients[id] = {} }
merge(root.clients[id], obj.client)
delete obj.client
} else if (i === 'exec' && typeof obj[i] === 'function') {
let val = obj[i].toString()
// convert es6 function probably....
// add function for extra functions that you can add to it
// parse var names -- uglify it as well?
if (!/^(function|\()/.test(val)) {
val = 'function ' + val
}
// const body = val.match(/{((.|\s)*?)}/)[1]
// const fns = body.match(/[a-z]{0,30}\((.*?)\)/g)
// console.log('got some fn calls...', fns) -- we can do some requires pretty fance
if (!/^(function|\()/.test(val)) { val = 'function ' + val }
result['$fn|' + i] = val
} else if (i === 'val') {
if (obj._ && obj._.sync) {
Expand All @@ -48,7 +40,7 @@ function parse (obj) {
result[i] = obj[i]
}
} else {
result[i] = parse(obj[i])
result[i] = parse(obj[i], i, root, state)
}
}
}
Expand Down
240 changes: 120 additions & 120 deletions test/subscribe.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,73 @@ const test = require('tape')
const Hub = require('../')
const vstamp = require('vigour-stamp')

test('subscribe - exec function gaurds', (t) => {
const server = new Hub({ port: 6000 })
// test('subscribe - exec function gaurds', (t) => {
// const server = new Hub({ port: 6000 })

const client = new Hub({
id: 1,
context: false
})
client.subscribe({
bla: {
$test: {
$: { title: { val: true } },
$pass: { title: { val: true } },
exec (state, subs, tree, key) {
return state.blabla.gurken === true
}
}
}
})
// const client = new Hub({
// id: 1,
// context: false
// })
// client.subscribe({
// bla: {
// $test: {
// $: { title: { val: true } },
// $pass: { title: { val: true } },
// exec (state, subs, tree, key) {
// return state.blabla.gurken === true
// }
// }
// }
// })

process.nextTick(() => client.set({ url: 'ws://localhost:6000' }))
// process.nextTick(() => client.set({ url: 'ws://localhost:6000' }))

server.once('error', (err) => {
t.equal(
err.message.indexOf('cannot run function $test.exec'),
0,
'emits run error for false exec'
)
const subsHash = Object.keys(client.subscriptions)[0]
const subsId = client.id + subsHash
process.nextTick(() => {
t.same(
server.emitters.subscription.attach.keys(),
[ subsId ],
'correct subscription listeners on server'
)
client.client.origin().sendMeta()
})
setTimeout(() => {
t.same(
server.emitters.subscription.attach.keys(),
[ subsId ],
'correct subscription listeners after resending subscriptions on server'
)
client.subscriptions[subsHash].bla.$test['$fn|exec'] = 'im trolling'
client.client.origin().sendMeta()
server.once('error', (err) => {
t.equal(
err.message.indexOf('cannot parse function $test.exec'),
0,
'emits parse error for illegal function'
)
client.remove()
server.clients.once((val, stamp) => {
vstamp.done(stamp, () => {
t.same(
server.emitters.subscription.attach.keys(),
[],
'correct subscriptions listeners on server after removing client'
)
server.remove()
t.end()
})
})
})
}, 500)
})
})
// server.once('error', (err) => {
// t.equal(
// err.message.indexOf('cannot run function $test.exec'),
// 0,
// 'emits run error for false exec'
// )
// const subsHash = Object.keys(client.subscriptions)[0]
// const subsId = client.id + subsHash
// process.nextTick(() => {
// t.same(
// server.emitters.subscription.attach.keys(),
// [ subsId ],
// 'correct subscription listeners on server'
// )
// client.client.origin().sendMeta()
// })
// setTimeout(() => {
// t.same(
// server.emitters.subscription.attach.keys(),
// [ subsId ],
// 'correct subscription listeners after resending subscriptions on server'
// )
// client.subscriptions[subsHash].bla.$test['$fn|exec'] = 'im trolling'
// client.client.origin().sendMeta()
// server.once('error', (err) => {
// t.equal(
// err.message.indexOf('cannot parse function $test.exec'),
// 0,
// 'emits parse error for illegal function'
// )
// client.remove()
// server.clients.once((val, stamp) => {
// vstamp.done(stamp, () => {
// t.same(
// server.emitters.subscription.attach.keys(),
// [],
// 'correct subscriptions listeners on server after removing client'
// )
// server.remove()
// t.end()
// })
// })
// })
// }, 500)
// })
// })

test('subscribe - client', { timeout: 1e3 }, (t) => {
const server = new Hub({
Expand Down Expand Up @@ -114,59 +114,59 @@ test('subscribe - client', { timeout: 1e3 }, (t) => {
})
})

test('subscribe - switch', { timeout: 1e3 }, (t) => {
// make this failing
const server = new Hub({
id: 'server',
port: 6000,
field: '$root.a',
a: { title: 'it\'s a' },
b: { title: 'it\'s b' }
})
const client = new Hub({
id: 1,
context: false,
url: 'ws://localhost:6000'
})
const client2 = new Hub({
id: 2,
context: false,
url: 'ws://localhost:6000'
})
const subs = {
field: {
val: 1, // this should not be nessecary -- add val: 1 or somethign when switch or listen to switch
$switch: {
val: true, // support this
$remove: true,
exec (state) {
return state.key
},
a: { val: 1, $remove: true, title: { val: true } },
b: { val: 1, $remove: true, title: { val: true } }
}
}
}
client.subscribe(subs)
client2.subscribe(subs)
client.get('field', {}).once((val, stamp) => vstamp.done(stamp, () => {
t.same(client.field.val, client.a, 'client receives reference on "field"')
t.same(client.a.title.val, 'it\'s a', 'client receives "a.title"')
client.set({ field: '$root.b' })
Promise.all([
client2.get('b.title', {}).is('it\'s b'),
client.get('b.title', {}).is('it\'s b'),
client2.get('field', {}).is(client2.b),
client.get('field', {}).is(client.b)
]).then(() => {
t.ok(true, 'client2 received "b.title"')
t.ok(true, 'client received "b.title"')
t.ok(true, 'client2 received "field"')
t.ok(true, 'client received "field"')
client.remove()
client2.remove()
server.remove()
t.end()
})
}))
})
// test('subscribe - switch', { timeout: 1e3 }, (t) => {
// // make this failing
// const server = new Hub({
// id: 'server',
// port: 6000,
// field: '$root.a',
// a: { title: 'it\'s a' },
// b: { title: 'it\'s b' }
// })
// const client = new Hub({
// id: 1,
// context: false,
// url: 'ws://localhost:6000'
// })
// const client2 = new Hub({
// id: 2,
// context: false,
// url: 'ws://localhost:6000'
// })
// const subs = {
// field: {
// val: 1, // this should not be nessecary -- add val: 1 or somethign when switch or listen to switch
// $switch: {
// val: true, // support this
// $remove: true,
// exec (state) {
// return state.key
// },
// a: { val: 1, $remove: true, title: { val: true } },
// b: { val: 1, $remove: true, title: { val: true } }
// }
// }
// }
// client.subscribe(subs)
// client2.subscribe(subs)
// client.get('field', {}).once((val, stamp) => vstamp.done(stamp, () => {
// t.same(client.field.val, client.a, 'client receives reference on "field"')
// t.same(client.a.title.val, 'it\'s a', 'client receives "a.title"')
// client.set({ field: '$root.b' })
// Promise.all([
// client2.get('b.title', {}).is('it\'s b'),
// client.get('b.title', {}).is('it\'s b'),
// client2.get('field', {}).is(client2.b),
// client.get('field', {}).is(client.b)
// ]).then(() => {
// t.ok(true, 'client2 received "b.title"')
// t.ok(true, 'client received "b.title"')
// t.ok(true, 'client2 received "field"')
// t.ok(true, 'client received "field"')
// client.remove()
// client2.remove()
// server.remove()
// t.end()
// })
// }))
// })

0 comments on commit f5df166

Please sign in to comment.