git ssb

0+

regular / ssb-cms



Tree: 43af34efb145e2705ff168ae3e6f3cc6832314ac

Files: 43af34efb145e2705ff168ae3e6f3cc6832314ac / drafts.js

4919 bytesRaw
1const levelup = require('levelup')
2const pl = require('pull-level')
3const pull = require('pull-stream')
4const crypto = require('crypto')
5
6
7module.exports = function (root) {
8 console.log('drafts root', root)
9
10 function overrideCriticalProperties(msg, value) {
11 let content = (msg.content = msg.content || {})
12 content.revisionRoot = value.revisionRoot
13 content.revisionBranch = value.revisionBranch
14 content.branch = value.branch
15 content.root = root
16 }
17
18 function tryToParse(value) {
19 let msg = value
20 msg.syntaxOkay = false
21 try {
22 msg = JSON.parse(value.msgString)
23 msg.syntaxOkay = true
24 } catch(e) { }
25 overrideCriticalProperties(msg, value)
26 msg.draft = true
27 return msg
28 }
29
30 const db = levelup('drafts', {
31 db: require('level-js'),
32 valueEncoding: 'utf8',
33 keyEncoding: 'utf8'
34 })
35
36 function processEntry(e, cb) {
37 if (e.sync) return cb(null, e)
38 if (e.type && e.type !== 'put') {
39 let key = e.key.substr(e.key.lastIndexOf('~')+1)
40 return cb(null, {key, value: null, type: e.type})
41 }
42 db.get(e.value, function (err, value) {
43 if (err) return cb(err)
44 // this looks funny, but it isn't
45 value = JSON.parse(value)
46 cb(null, {key: e.value, value: tryToParse(value)})
47 })
48 }
49
50 function write(key, msgString, branch, revisionRoot, revisionBranch, cb) {
51 let value = {
52 revisionRoot,
53 revisionBranch,
54 branch,
55 msgString
56 }
57 let json = JSON.stringify(value)
58 db.batch()
59 .put(key, json)
60 .put(`~BRANCH~${branch || ''}~${key}`, key)
61 .put(`~REVROOT~${revisionRoot || ''}~${key}`, key)
62 .write( (err)=>{
63 value.draft = true
64 cb(err, key, value)
65 })
66 }
67
68 return {
69 get: (key, cb) => {
70 db.get(key, (err, value) => {
71 if (err) return cb(err)
72 // this looks funny, but it isn't
73 value = JSON.parse(value)
74 value = tryToParse(value)
75 cb(null, value)
76 })
77 },
78 update: (key, msgString, cb) => {
79 db.get(key, (err, value) => {
80 if (err) return cb(err)
81 value = JSON.parse(value)
82 let {
83 revisionRoot,
84 revisionBranch,
85 branch
86 } = value
87 console.log('draft update', key, value)
88 write(key, msgString, branch, revisionRoot, revisionBranch, cb)
89 })
90 },
91 remove: (key, cb) => {
92 db.get(key, (err, value) => {
93 if (err) return cb(err)
94 value = JSON.parse(value)
95 let {branch, revisionRoot} = value
96 db.batch()
97 .del(key)
98 .del(`~BRANCH~${branch || ''}~${key}`)
99 .del(`~REVROOT~${revisionRoot || ''}~${key}`)
100 .write(cb)
101 })
102 },
103 create: function(msgString, branch, revisionRoot, revisionBranch, cb) {
104 const key = 'draft-' + crypto.randomBytes(16).toString('base64')
105 write(key, msgString, branch, revisionRoot, revisionBranch, cb)
106 },
107 publish: (ssb, key, cb) => {
108 db.get(key, (err, value) => {
109 if (err) return cb(err)
110 value = JSON.parse(value)
111 let msg
112 try {
113 msg = JSON.parse(value.msgString)
114 } catch(e) {
115 return cb(e)
116 }
117 if (!msg.content) return cb(new Error('message has no content'))
118 // NOTE: we ignore everything but the msg.content and overwrite
119 // branch, revisionRoot, and revisionBranch!
120 msg.content.root = root
121 if (value.branch) msg.content.branch = value.branch
122 if (value.revisionRoot) msg.content.revisionRoot = value.revisionRoot
123 if (value.revisionBranch) msg.content.revisionBranch = value.revisionBranch
124 msg.content['from-draft'] = key
125 ssb.publish(msg.content, cb)
126 })
127 },
128
129 byBranch: function(branch, opts) {
130 opts = opts || {}
131 return pull(
132 pl.read(db, Object.assign({}, opts, {min: `~BRANCH~${branch||""}`, max: `~BRANCH~${branch||""}~~`})),
133 pull.asyncMap(processEntry)
134 )
135 },
136
137 byRevisionRoot: function(root, opts) {
138 opts = opts || {}
139 return pull(
140 pl.read(db, Object.assign({}, opts, {min: `~REVROOT~${root||""}`, max: `~REVROOT~${root||""}~~`})),
141 pull.asyncMap(processEntry)
142 )
143 },
144
145 destroy: function(cb) {
146 require('level-js').destroy('drafts', cb)
147 },
148
149 all: function(opts) {
150 opts = opts || {}
151 return pull(
152 pl.read(db, Object.assign({keys: true, values: true}, opts)),
153 pull.filter( kv => !(kv.key && kv.key[0] === '~')),
154 pull.map( kv => {
155 if (kv.sync) return kv
156 if (kv.type && kv.type !== 'put') {
157 return {key: kv.key, value: null, type: kv.type}
158 }
159 let value = JSON.parse(kv.value)
160 let ret = Object.assign({}, value, {
161 key: kv.key,
162 value: tryToParse(value)
163 })
164 return ret
165 })
166 )
167 }
168 }
169}
170

Built with git-ssb-web