-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbuild_lib.js
More file actions
189 lines (176 loc) · 6.9 KB
/
build_lib.js
File metadata and controls
189 lines (176 loc) · 6.9 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
const CONFIG = require('config')
const __ = CONFIG.universalPath
const _ = __.require('lib', 'utils')
const db = __.require('lib', 'db/db')('things', 'journals')
const Journal = require('./models/commons/journal')
const Version = require('./models/commons/version')
const versions_ = require('./lib/versions')
const upload = require('./lib/upload.js')
const promises_ = __.require('lib', 'promises')
const error_ = __.require('lib', 'error')
module.exports = function (typeName, model) {
return {
byId: function (id) {
return db.viewByKey('byId', [typeName, id])
.then(_.Log(`${typeName} byId`))
},
filter: function(filter_string) {
const convertArrayToTypeFeatureCollection = function (data_array) {
return convertArrayToFeatureCollection(data_array,typeName,filter_string)
}
if(filter_string == '') {
return db.viewByKeyRange('currentVersionById', [typeName, '0'], [typeName, 'z'])
.then(convertArrayToTypeFeatureCollection)
.then(_.Log(`${typeName} filter all`))
} else {
const key = filter_string.replace(/=.*$/,''),
value = filter_string.split('=')[1]
var startkey, endkey
if(value) {
startkey = [typeName, key, value]
endkey = startkey
} else {
startkey = [typeName, key, ' ']
endkey = [typeName, key, '\u9999']
}
return db.viewByKeyRange('byAttribute', startkey, endkey)
.then(convertArrayToTypeFeatureCollection)
.then(_.Log(`${typeName} filter byAttribute "${key}"="${value}"`))
}
},
create: function (data) {
// first make sure we have valid data
// we don't want to create a journal or anything if the data isn't valid
try {
model.validateData(data)
} catch (err) {
// A function should either return sync values
// or async values (as a promise) but never both.
// So, to stay consistant, we return a rejected promise
// instead of just throwing the error
return promises_.reject(err)
}
// then knowning that the data is valid, create a journal document
return db.post(Journal.create(typeName))
.then(_.Log('journal post res'))
// extracting the journalId
.then(_.property('id'))
// then create a first version document and update the journal
.then(_.partial(updateJournal, data))
.then(_.Log('thing created'))
.catch(_.ErrorRethrow('thing creation err'))
},
currentVersionById: function (id) {
// there is some magic happening in the currentVersionById view (see db/design_docs/journal.json):
// as the journal document emits the id of another document in the format {'_id': lastVersionId},
// using the parameter include_doc will not return the emitting document but the document with the id doc.current._id.
// This is called Linked documents https://wiki.apache.org/couchdb/Introduction_to_CouchDB_views#Linked_documents
// The complex key [typeName, id] allows to make sure we don't
// return a document that doesn't belong to the required type
return db.viewByKey('currentVersionById', [typeName, id])
.then(_.Log('currentVersionById'))
.then(reject404)
.then(Version.parseCurrentVersion)
},
update: function (data, journalId) {
// same as in create
try {
model.validateData(data)
} catch (err) {
return promises_.reject(err)
}
if (!_.isUuid(journalId)) {
return promises_.reject(`err in update, path not an uuid: '${journalId}'`)
}
return db.viewByKey('byId', [typeName, journalId])
// DB will return just 'undefined' if nothing is found
.then(reject404)
// Insert version object into journal.
// journalId and data are already available
// but we need to wait for the validation
// to execute updateJournal, thus the partial
.then(_.partial(updateJournal, data, journalId))
.then(_.Log('thing updated'))
.catch(_.ErrorRethrow('thing update err'))
},
delete: function (journalId) {
if (!_.isUuid(journalId)) {
return promises_.reject(`err in update, path not an uuid: '${journalId}'`)
}
_.log(journalId, 'update with id')
return db.viewByKey('byId', [typeName, journalId])
// DB will return just 'undefined' if nothing is found
.then(function (journal) {
_.log(journal, 'delete: got journal')
if (!_.isPlainObject(journal)) {
throw error_.new('no object with this id in db', 404, journal)
}
if (_.isPlainObject(journal.status) && journal.status.deleted === true) {
throw error_.new('already deleted', 208, journal) // "already reported", borrowed from WebDAV
}
if (!_.isPlainObject(journal.status)) {
journal['status'] = { deleted: true }
} else {
journal.status.deleted = true
}
return versions_.create(journalId, journal.data, journal.status)
})
// insert version object into journal
.then(function (newVersionObject) {
return db.update(journalId, function (journalDoc) {
return Journal.update(journalDoc, newVersionObject)
})
})
.then(_.Log('return value of insert'))
},
upload: function (data, file) {
try {
model.validateData(data)
} catch (err) {
return promises_.reject(err)
}
data.hash = upload(file)
return db.post(Journal.create(typeName))
.then(_.Log('journal post res'))
.then(_.property('id'))
.then(_.partial(updateJournal, data))
.then(_.Log('thing created'))
.catch(_.ErrorRethrow('thing creation err'))
}
}
}
const reject404 = function (doc) {
if (!_.isPlainObject(doc)) {
throw error_.new('no object with this id in db', 404, doc)
}
return doc
}
const updateJournal = function (data, journalId) {
// create a new version associated to this journal
return versions_.create(journalId, data)
// then update the journal document to reference the new version
.then(function (newVersionObject) {
return db.update(journalId, function (journalDoc) {
return Journal.update(journalDoc, newVersionObject)
})
})
}
const convertArrayToFeatureCollection = function (data_array, item_type, query_string) {
const hostname = 'https://data.transformap.co'
var feature_collection = {
'type': 'FeatureCollection',
'source': hostname + '/' + item_type + '/' + query_string,
'license': 'Public Domain', // only temporarly here
'features': []
}
data_array.forEach( item => {
var feature = item.data
if(!feature.properties)
feature.properties = {}
feature.properties._uri = hostname + '/' + item_type + '/' + item.journal
feature.properties._timestamp = item.timestamp
feature.properties._id = item.journal
feature_collection.features.push(feature)
})
return feature_collection
}