forked from Multiply/meteor-publish-with-relations
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathserver.coffee
132 lines (100 loc) · 3.24 KB
/
server.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
unless original_publish
original_publish = Meteor.publish
Meteor.publish = (name,func) ->
original_publish name, (args...) -> #args... "soaks up" arguments
publish = this
publish.relations = (params) ->
_.extend params,
handle:publish
Meteor.publishWithRelations params
func.apply publish,args
Meteor.publishWithRelations = (params) ->
pub = params.handle
collection = params.collection
filter = params.filter or {}
options = params.options or {}
# console.log "filter:"
# console.log filter
associations = {}
publishAssoc = (collection, filter, options) ->
collection.find(filter, options).observeChanges
added: (id, fields) =>
pub.added(collection._name, id, fields)
changed: (id, fields) =>
pub.changed(collection._name, id, fields)
removed: (id) =>
pub.removed(collection._name, id)
doMapping = (id, obj, mappings) ->
return unless mappings
for mapping in mappings
mapFilter = {}
mapOptions = {}
_.defaults mapping,
key:"_id"
foreign_key:"_id"
objKey = mapping.foreign_key + mapping.key
_.extend obj,
_id:id
key_map = mapping.foreign_key.split "."
if key_map.length > 1
if obj[key_map[0]]
ids = []
_.each key_map, (k,i) ->
if i is 0 #if start
if _.isArray(obj[key_map[0]])
ids = _.pluck obj[k],key_map[i+1]
else if _.isObject(obj[key_map[0]])
ids = [obj[k][key_map[i+1]]]
else if i isnt key_map.length-1 #if not last
ids = _.flatten ids
ids = _.pluck ids,key_map[i+1]
mapFilter[mapping.key] =
$in:ids
else
mapFilter = null
else
mapFilter[mapping.key] = obj[mapping.foreign_key]
if mapFilter and mapFilter[mapping.key] and _.isArray(mapFilter[mapping.key])
mapFilter[mapping.key] = {$in: mapFilter[mapping.key]}
if mapFilter
_.extend(mapFilter, mapping.filter)
_.extend(mapOptions, mapping.options)
if mapping.mappings
# console.log "mapFilter with mapping.mappings:"
# console.log mapFilter
if mapFilter #prevent filter from being {} and bringing in everything in the collection in case of null
Meteor.publishWithRelations
handle: pub
collection: mapping.collection
filter: mapFilter
options: mapOptions
mappings: mapping.mappings
# _noReady: true
else
associations[id][objKey]?.stop()
# console.log "mapFilter to publishAssoc:"
# console.log mapFilter
if mapFilter
associations[id][objKey] =
publishAssoc(mapping.collection, mapFilter, mapOptions)
collectionHandle = collection.find(filter, options).observeChanges
added: (id, fields) ->
pub.added(collection._name, id, fields)
associations[id] ?= {}
doMapping(id, fields, params.mappings)
changed: (id, fields) ->
_.each fields, (value, key) ->
changedMappings = _.where(params.mappings, {foreign_key: key})
doMapping(id, fields, changedMappings)
pub.changed(collection._name, id, fields)
removed: (id) ->
handle.stop() for handle in associations[id]
pub.removed(collection._name, id)
# No more auto ready, that's annoying
# unless params._noReady
# pub.ready()
pub.onStop ->
for id, association of associations
for key, handle of association
handle.stop()
collectionHandle.stop()