Browse Source

Merge branch 'remove-need-for-config' of CoBox/cobox-group-store into development

peg 2 years ago
parent
commit
28a2a2ad34
5 changed files with 2024 additions and 155 deletions
  1. 24
    61
      index.js
  2. 4
    2
      package.json
  3. 79
    22
      test/index.test.js
  4. 0
    21
      test/mocks.js
  5. 1917
    49
      yarn.lock

+ 24
- 61
index.js View File

@@ -8,20 +8,18 @@ const maybe = require('call-me-maybe')
8 8
 
9 9
 const { uniq, isString } = require('./util')
10 10
 
11
-module.exports = (createGroup, storage, opts) => new GroupStore(createGroup, storage, opts)
11
+module.exports = (storage, factory, collection, opts) => new GroupStore(storage, factory, collection, opts)
12 12
 
13 13
 class GroupStore {
14
-  constructor (createGroup, storage, opts = {}) {
14
+  constructor (storage, factory, collection, opts = {}) {
15 15
     this._id = crypto.randomBytes(16).toString('hex')
16
-    this.root = storage || constants.storage
17
-    this.storage = path.join(this.root, 'groups')
18
-    this.config = opts.config
16
+    this.storage = storage
19 17
     this.opts = opts
20
-    this.createGroup = createGroup
18
+    this.factory = factory
21 19
 
22
-    this.groups = {}
23
-    this.config.groups.list().forEach((groupOpts, i) => {
24
-      this._cacheGroup(this._buildGroup(groupOpts))
20
+    this.collection = {}
21
+    collection.forEach((_opts, i) => {
22
+      this._cache(this._build(_opts))
25 23
     })
26 24
 
27 25
     this._readyCallback = thunky(this._ready.bind(this))
@@ -38,7 +36,7 @@ class GroupStore {
38 36
 
39 37
   async all () {
40 38
     await this.ready()
41
-    return uniq(Object.values(this.groups))
39
+    return uniq(Object.values(this.collection))
42 40
   }
43 41
 
44 42
   async where (params = {}) {
@@ -63,34 +61,15 @@ class GroupStore {
63 61
   }
64 62
 
65 63
   async create (params = {}) {
66
-    var group = await this.findBy(params)
67
-    if (group) throw new Error('group already exists')
64
+    var entry = await this.findBy(params)
65
+    if (entry) throw new Error('entry already exists')
66
+    var entry = this._build(params)
68 67
 
69
-    var group = this._buildGroup(params)
68
+    await entry.ready()
70 69
 
71
-    await group.ready()
72
-
73
-    this._cacheGroup(group)
74
-    this._saveGroup(group)
75
-
76
-    return group
77
-  }
78
-
79
-  // TODO: this doesn't work currently, throws a level db error
80
-  async destroy (params = {}) {
81
-    var group = await this.findBy(params)
82
-    if (!group) throw new Error('no group exists')
83
-
84
-    this.config.groups.delete(group.address)
85
-    // TODO: delete group data
86
-
87
-    if (this.config.save()) {
88
-      delete this.groups[group.address.toString('hex')]
89
-      return true
90
-    } else {
91
-      this.config.groups.set(group.address, group)
92
-      throw new Error('failed to save config file')
93
-    }
70
+    this._cache(entry)
71
+    entry.save()
72
+    return entry
94 73
   }
95 74
 
96 75
   // ------------------------------------------------------------------
@@ -98,14 +77,14 @@ class GroupStore {
98 77
   _ready (callback) {
99 78
     var pending = 1
100 79
     var self = this
101
-    var groups = Object.values(self.groups)
80
+    var collection = Object.values(self.collection)
102 81
 
103 82
     function next (n) {
104
-      var group = groups[n]
105
-      if (!group) return done()
83
+      var entry = collection[n]
84
+      if (!entry) return done()
106 85
       ++pending
107 86
       process.nextTick(next, n + 1)
108
-      group.ready(done)
87
+      entry.ready(done)
109 88
     }
110 89
 
111 90
     function done (err) {
@@ -121,33 +100,17 @@ class GroupStore {
121 100
     next(0)
122 101
   }
123 102
 
124
-  _buildGroup (params = {}) {
125
-    return this.createGroup(
103
+  _build (params = {}) {
104
+    return this.factory(
126 105
       this.storage,
127 106
       params.address,
128 107
       Object.assign(this.opts, params)
129 108
     )
130 109
   }
131 110
 
132
-  _cacheGroup (group) {
133
-    this.groups[group.address.toString('hex')] = group
134
-    if (group.name) this.groups[group.name] = group
135
-    return true
136
-  }
137
-
138
-  _saveGroup (group) {
139
-    this.config.groups.set(group.address, group.toConfig())
140
-    var success = this.config.save()
141
-    if (!success) return false
111
+  _cache (entry) {
112
+    this.collection[entry.address.toString('hex')] = entry
113
+    if (entry.name) this.collection[entry.name] = entry
142 114
     return true
143 115
   }
144 116
 }
145
-
146
-// _validate (id) {
147
-//   if (crypto.isKey(id)) key = id
148
-//   if (!crypto.isKey(id) && isString(id)) name = id
149
-//   // Ensure we either have no key, or the key is a valid key
150
-//   if (!(!key || crypto.isKey(key))) throw new Error('invalid: key format')
151
-//   return { key, name }
152
-// }
153
-

+ 4
- 2
package.json View File

@@ -13,13 +13,15 @@
13 13
   "license": "AGPL-3.0-or-later",
14 14
   "dependencies": {
15 15
     "call-me-maybe": "^1.0.1",
16
-    "cobox-config": "git+https://ledger-git.dyne.org/cobox/cobox-config",
16
+    "cobox-config": "git+https://ledger-git.dyne.org/cobox/cobox-config#development",
17 17
     "cobox-constants": "^1.0.0",
18
-    "cobox-crypto": "git+https://ledger-git.dyne.org/cobox/cobox-crypto",
18
+    "cobox-crypto": "git+https://ledger-git.dyne.org/cobox/cobox-crypto#development",
19 19
     "debug": "^4.1.1",
20 20
     "thunky": "^1.1.0"
21 21
   },
22 22
   "devDependencies": {
23
+    "cobox-blind-replicator": "git+https://ledger-git.dyne.org/cobox/cobox-blind-replicator",
24
+    "cobox-group": "git+https://ledger-git.dyne.org/cobox/cobox-group#development",
23 25
     "mkdirp": "^0.5.1",
24 26
     "rimraf": "^3.0.0",
25 27
     "tap-spec": "^5.0.0",

+ 79
- 22
test/index.test.js View File

@@ -4,7 +4,8 @@ const crypto = require('cobox-crypto')
4 4
 const Store = require('../')
5 5
 
6 6
 const { tmp, cleanup } = require('./util')
7
-const { createGroup } = require('./mocks')
7
+const Group = require('cobox-group/test/mock')
8
+const BlindReplicator = require('cobox-blind-replicator/test/mock')
8 9
 
9 10
 describe('group store: basic', (context) => {
10 11
   context('ready()', async function (assert, next) {
@@ -14,12 +15,13 @@ describe('group store: basic', (context) => {
14 15
 
15 16
     config.groups.set(params.address, params)
16 17
 
17
-    const store = Store(createGroup, storage, { config })
18
+    const collection = config.groups.list()
19
+    const store = Store(storage, Group, collection, { config })
18 20
 
19 21
     try {
20 22
       await store.ready()
21
-      assert.same(Object.values(store.groups).length, 1, 'builds then caches groups from the config')
22
-      assert.ok(store.groups[params.address.toString('hex')], 'accessible using address hex string')
23
+      assert.same(Object.values(store.collection).length, 1, 'builds then caches groups from the config')
24
+      assert.ok(store.collection[params.address.toString('hex')], 'accessible using address hex string')
23 25
     } catch (err) {
24 26
       assert.error(err, 'no error')
25 27
     }
@@ -34,7 +36,8 @@ describe('group store: basic', (context) => {
34 36
 
35 37
     config.groups.set(params.address, params)
36 38
 
37
-    const store = Store(createGroup, storage, { config })
39
+    const collection = config.groups.list()
40
+    const store = Store(storage, Group, collection, { config })
38 41
 
39 42
     try {
40 43
       await store.ready()
@@ -56,7 +59,8 @@ describe('group store: basic', (context) => {
56 59
     seedConfig()
57 60
     config.groups.set(params.address, params)
58 61
 
59
-    const store = Store(createGroup, storage, { config })
62
+    const collection = config.groups.list()
63
+    const store = Store(storage, Group, collection, { config })
60 64
 
61 65
     try {
62 66
       await store.ready()
@@ -66,9 +70,9 @@ describe('group store: basic', (context) => {
66 70
       })
67 71
 
68 72
       assert.ok(Array.isArray(response), 'returns an array')
69
-      var group = response[0]
70
-      assert.ok(group, 'finds a group')
71
-      assert.same(group && group.address, params.address, 'finds the correct group')
73
+      var entry = response[0]
74
+      assert.ok(entry, 'finds a entry')
75
+      assert.same(entry && entry.address, params.address, 'finds the correct entry')
72 76
     } catch (err) {
73 77
       assert.error(err, 'no error')
74 78
     }
@@ -93,7 +97,8 @@ describe('group store: basic', (context) => {
93 97
 
94 98
     config.groups.set(params.address, params)
95 99
 
96
-    const store = Store(createGroup, storage, { config })
100
+    const collection = config.groups.list()
101
+    const store = Store(storage, Group, collection, { config })
97 102
 
98 103
     try {
99 104
       await store.ready()
@@ -103,7 +108,7 @@ describe('group store: basic', (context) => {
103 108
         address: null
104 109
       })
105 110
 
106
-      assert.same(response.length, 0, 'fails to find a group')
111
+      assert.same(response.length, 0, 'fails to find an entry')
107 112
     } catch (err) {
108 113
       assert.error(err, 'no error')
109 114
     }
@@ -118,7 +123,8 @@ describe('group store: basic', (context) => {
118 123
 
119 124
     config.groups.set(params.address, params)
120 125
 
121
-    const store = Store(createGroup, storage, { config })
126
+    const collection = config.groups.list()
127
+    const store = Store(storage, Group, collection, { config })
122 128
 
123 129
     try {
124 130
       await store.ready()
@@ -128,7 +134,7 @@ describe('group store: basic', (context) => {
128 134
         address: params.address
129 135
       })
130 136
 
131
-      assert.same(response.length, 0, 'fails to find a group')
137
+      assert.same(response.length, 0, 'fails to find an entry')
132 138
     } catch (err) {
133 139
       assert.error(err, 'no error')
134 140
     }
@@ -143,7 +149,8 @@ describe('group store: basic', (context) => {
143 149
 
144 150
     config.groups.set(params.address, params)
145 151
 
146
-    const store = Store(createGroup, storage, { config })
152
+    const collection = config.groups.list()
153
+    const store = Store(storage, Group, collection, { config })
147 154
 
148 155
     try {
149 156
       await store.ready()
@@ -153,7 +160,7 @@ describe('group store: basic', (context) => {
153 160
         address: crypto.randomBytes(32).toString('hex')
154 161
       })
155 162
 
156
-      assert.same(response.length, 0, 'fails to find a group')
163
+      assert.same(response.length, 0, 'fails to find an entry')
157 164
     } catch (err) {
158 165
       assert.error(err, 'no error')
159 166
     }
@@ -168,7 +175,8 @@ describe('group store: basic', (context) => {
168 175
 
169 176
     config.groups.set(params.address, params)
170 177
 
171
-    const store = Store(createGroup, storage, { config })
178
+    const collection = config.groups.list()
179
+    const store = Store(storage, Group, collection, { config })
172 180
 
173 181
     try {
174 182
       await store.ready()
@@ -178,7 +186,7 @@ describe('group store: basic', (context) => {
178 186
         address: params.address
179 187
       })
180 188
 
181
-      assert.same(response.length, 0, 'fails to find a group')
189
+      assert.same(response.length, 0, 'fails to find an entry')
182 190
     } catch (err) {
183 191
       assert.error(err, 'no error')
184 192
     }
@@ -193,7 +201,8 @@ describe('group store: basic', (context) => {
193 201
 
194 202
     config.groups.set(params.address, params)
195 203
 
196
-    const store = Store(createGroup, storage, { config })
204
+    const collection = config.groups.list()
205
+    const store = Store(storage, Group, collection, { config })
197 206
 
198 207
     try {
199 208
       await store.ready()
@@ -217,7 +226,8 @@ describe('group store: basic', (context) => {
217 226
 
218 227
     config.groups.set(params.address, params)
219 228
 
220
-    const store = Store(createGroup, storage, { config })
229
+    const collection = config.groups.list()
230
+    const store = Store(storage, Group, collection, { config })
221 231
 
222 232
     try {
223 233
       await store.ready()
@@ -241,7 +251,8 @@ describe('group store: basic', (context) => {
241 251
 
242 252
     config.groups.set(params.address, params)
243 253
 
244
-    const store = Store(createGroup, storage, { config })
254
+    const collection = config.groups.list()
255
+    const store = Store(storage, Group, collection, { config })
245 256
 
246 257
     try {
247 258
       await store.ready()
@@ -261,7 +272,8 @@ describe('group store: basic', (context) => {
261 272
       config = Config(storage),
262 273
       params = Object.assign(crypto.keySet(), { name: 'magma' })
263 274
 
264
-    const store = Store(createGroup, storage, { config })
275
+    const collection = config.groups.list()
276
+    const store = Store(storage, Group, collection, { config })
265 277
 
266 278
     try {
267 279
       var group = await store.create(params)
@@ -278,7 +290,7 @@ describe('group store: basic', (context) => {
278 290
   //     params = crypto.keySet()
279 291
 
280 292
   //   config.groups.set(params.address, params)
281
-  //   const store = Store(createGroup, storage, { config })
293
+  //   const store = Store(Group, storage, { config })
282 294
 
283 295
   //   var groups = await store.all()
284 296
   //   console.log(groups.map((group) => group.address.toString('hex')))
@@ -288,3 +300,48 @@ describe('group store: basic', (context) => {
288 300
   //   cleanup(storage, next)
289 301
   // })
290 302
 })
303
+
304
+describe('multiple', (context) => {
305
+  context('factory', async (assert, next) => {
306
+    let storage = tmp(),
307
+      config = Config(storage),
308
+      group = crypto.keySet(),
309
+      replicator = { address: crypto.address() }
310
+
311
+    config.groups.set(group.address, group)
312
+    config.replicators.set(replicator.address, replicator)
313
+
314
+    const groups = config.groups.list()
315
+    const replicators = config.replicators.list()
316
+
317
+    const api = {
318
+      groups: {
319
+        store: Store(
320
+          storage,
321
+          Group,
322
+          groups,
323
+          { config }
324
+        )
325
+      },
326
+      replicators: {
327
+        store: Store(
328
+          storage,
329
+          BlindReplicator,
330
+          replicators,
331
+          { config }
332
+        )
333
+      }
334
+    }
335
+
336
+    await api.groups.store.ready()
337
+    await api.replicators.store.ready()
338
+
339
+    assert.same(Object.values(api.groups.store.collection).length, 1, 'builds then caches groups')
340
+    assert.same(Object.values(api.replicators.store.collection).length, 1, 'builds then caches replicators')
341
+
342
+    assert.ok(api.groups.store.collection[group.address.toString('hex')], 'accessible using address hex string')
343
+    assert.ok(api.replicators.store.collection[replicator.address.toString('hex')], 'accessible using address hex string')
344
+
345
+    cleanup(storage, next)
346
+  })
347
+})

+ 0
- 21
test/mocks.js View File

@@ -1,21 +0,0 @@
1
-const maybe = require('call-me-maybe')
2
-
3
-function createGroup (storage, address, opts = {}) {
4
-  this.storage = storage
5
-  this.address = Buffer.from(address, 'hex')
6
-  this.encryptionKey = Buffer.from(opts.encryptionKey, 'hex')
7
-  this.name = opts.name
8
-}
9
-
10
-createGroup.prototype.ready = (callback) => maybe(callback, new Promise((resolve, reject) => resolve(true)))
11
-createGroup.prototype.toConfig = function () {
12
-  return {
13
-    name: this.name,
14
-    address: this.address,
15
-    encryptionKey: this.encryptionKey
16
-  }
17
-}
18
-
19
-module.exports = {
20
-  createGroup: (storage, address, opts) => new createGroup(storage, address, opts)
21
-}

+ 1917
- 49
yarn.lock
File diff suppressed because it is too large
View File