gip-remote 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -5,7 +5,7 @@ const z32 = require('z32')
5
5
  const def = require('./schema/hyperdb/index')
6
6
  const RemoteDrive = require('./lib/drive')
7
7
  const GitPearLink = require('./lib/link')
8
- const { parseCommit, walkTree } = require('./lib/git')
8
+ const { parseCommit, parseTag, walkTree } = require('./lib/git')
9
9
 
10
10
  class Remote extends ReadyResource {
11
11
  _swarm = null
@@ -22,7 +22,7 @@ class Remote extends ReadyResource {
22
22
  let config
23
23
  if (typeof this._link === 'string') {
24
24
  this._name = this._link
25
- config = {}
25
+ config = { core: store.get({ name: this._link }) }
26
26
  } else if (this._link.drive) {
27
27
  this._name = this._link.pathname?.split('/').slice(1)[0]
28
28
  config = { key: this._link.drive.key }
@@ -91,13 +91,18 @@ class Remote extends ReadyResource {
91
91
  }
92
92
 
93
93
  async getAllRefs() {
94
- const branches = this._db.find('@gip/branches')
95
94
  const refs = []
96
95
 
96
+ const branches = this._db.find('@gip/branches')
97
97
  for await (const b of branches) {
98
98
  refs.push({ ref: `refs/heads/${b.name}`, oid: b.commitOid })
99
99
  }
100
100
 
101
+ const tags = this._db.find('@gip/tags')
102
+ for await (const t of tags) {
103
+ refs.push({ ref: `refs/tags/${t.name}`, oid: t.oid })
104
+ }
105
+
101
106
  const headBranch = await this.getHead()
102
107
  if (headBranch) {
103
108
  const head = refs.find((r) => r.ref === `refs/heads/${headBranch}`)
@@ -129,28 +134,58 @@ class Remote extends ReadyResource {
129
134
  return true
130
135
  }
131
136
 
132
- // --- Push: store objects + index branch + files ---
137
+ async deleteTag(tagName) {
138
+ const tag = await this._db.get('@gip/tags', { name: tagName })
139
+ if (!tag) return false
140
+
141
+ await this._db.delete('@gip/tags', { name: tagName })
133
142
 
134
- async push(branchName, commitOid, objects) {
143
+ // Remove file records for this tag
144
+ const filesBranch = 'tags/' + tagName
145
+ const files = this._db.find('@gip/files', { branch: filesBranch })
146
+ for await (const file of files) {
147
+ await this._db.delete('@gip/files', { branch: filesBranch, path: file.path })
148
+ }
149
+
150
+ await this._db.flush()
151
+ return true
152
+ }
153
+
154
+ // --- Push: store objects + index branch/tag + files ---
155
+
156
+ async push(refName, oid, objects) {
135
157
  // 1. Store all git objects
136
- for (const [oid, obj] of objects) {
137
- const existing = await this.getObject(oid)
158
+ for (const [objOid, obj] of objects) {
159
+ const existing = await this.getObject(objOid)
138
160
  if (existing) continue
139
161
 
140
162
  await this._db.insert('@gip/objects', {
141
- oid,
163
+ oid: objOid,
142
164
  type: obj.type,
143
165
  size: obj.size,
144
166
  data: obj.data
145
167
  })
146
168
  }
147
169
 
148
- // 2. Parse commit metadata
149
- const commitObj = objects.get(commitOid)
150
- if (!commitObj) throw new Error('Commit object not found: ' + commitOid)
170
+ // 2. Dereference tag objects to find the commit
171
+ let resolvedOid = oid
172
+ let obj = objects.get(resolvedOid)
173
+ if (!obj) throw new Error('Object not found: ' + resolvedOid)
174
+
175
+ let tagMeta = null
176
+ while (obj.type === 'tag') {
177
+ const tag = parseTag(obj.data)
178
+ if (!tagMeta) tagMeta = tag
179
+ if (!tag.object) throw new Error('Tag has no object: ' + resolvedOid)
180
+ resolvedOid = tag.object
181
+ obj = objects.get(resolvedOid)
182
+ if (!obj) throw new Error('Object not found: ' + resolvedOid)
183
+ }
184
+
185
+ if (obj.type !== 'commit') throw new Error('Expected commit, got ' + obj.type + ': ' + resolvedOid)
151
186
 
152
- const commit = parseCommit(commitObj.data)
153
- if (!commit.tree) throw new Error('Commit has no tree: ' + commitOid)
187
+ const commit = parseCommit(obj.data)
188
+ if (!commit.tree) throw new Error('Commit has no tree: ' + resolvedOid)
154
189
 
155
190
  // 3. Walk tree to enumerate files
156
191
  const files = walkTree(objects, commit.tree, '')
@@ -158,7 +193,7 @@ class Remote extends ReadyResource {
158
193
  // 4. Insert file records
159
194
  for (const file of files) {
160
195
  await this._db.insert('@gip/files', {
161
- branch: branchName,
196
+ branch: refName,
162
197
  path: file.path,
163
198
  oid: file.oid,
164
199
  mode: file.mode,
@@ -169,21 +204,38 @@ class Remote extends ReadyResource {
169
204
  })
170
205
  }
171
206
 
172
- // 5. Insert branch record
173
- await this._db.insert('@gip/branches', {
174
- name: branchName,
175
- commitOid,
176
- treeOid: commit.tree,
177
- author: commit.author,
178
- message: commit.message,
179
- timestamp: commit.timestamp,
180
- objects: [...objects.keys()]
181
- })
207
+ const isTag = refName.startsWith('tags/')
182
208
 
183
- // 6. Set HEAD to first branch pushed (like git init)
184
- const currentHead = await this.getHead()
185
- if (!currentHead) {
186
- await this._db.insert('@gip/head', { branch: branchName })
209
+ if (isTag) {
210
+ // 5a. Insert tag record
211
+ const tagName = refName.slice(5) // strip 'tags/'
212
+ await this._db.insert('@gip/tags', {
213
+ name: tagName,
214
+ oid,
215
+ commitOid: resolvedOid,
216
+ treeOid: commit.tree,
217
+ tagger: tagMeta ? tagMeta.tagger : null,
218
+ message: tagMeta ? tagMeta.message : null,
219
+ timestamp: tagMeta ? tagMeta.timestamp : 0,
220
+ objects: [...objects.keys()]
221
+ })
222
+ } else {
223
+ // 5b. Insert branch record
224
+ await this._db.insert('@gip/branches', {
225
+ name: refName,
226
+ commitOid: oid,
227
+ treeOid: commit.tree,
228
+ author: commit.author,
229
+ message: commit.message,
230
+ timestamp: commit.timestamp,
231
+ objects: [...objects.keys()]
232
+ })
233
+
234
+ // 6. Set HEAD to first branch pushed (like git init)
235
+ const currentHead = await this.getHead()
236
+ if (!currentHead) {
237
+ await this._db.insert('@gip/head', { branch: refName })
238
+ }
187
239
  }
188
240
 
189
241
  // 7. Flush
@@ -192,29 +244,41 @@ class Remote extends ReadyResource {
192
244
 
193
245
  // --- Fetch support ---
194
246
 
195
- async getRefObjects(commitOid, onLoad) {
196
- const branches = this._db.find('@gip/branches')
197
- let branch = null
247
+ async getRefObjects(oid, onLoad) {
248
+ let record = null
198
249
 
250
+ // Check branches first
251
+ const branches = this._db.find('@gip/branches')
199
252
  for await (const b of branches) {
200
- if (b.commitOid === commitOid) {
201
- branch = b
253
+ if (b.commitOid === oid) {
254
+ record = b
202
255
  break
203
256
  }
204
257
  }
205
258
 
206
- if (!branch) return []
259
+ // Then check tags
260
+ if (!record) {
261
+ const tags = this._db.find('@gip/tags')
262
+ for await (const t of tags) {
263
+ if (t.oid === oid) {
264
+ record = t
265
+ break
266
+ }
267
+ }
268
+ }
269
+
270
+ if (!record) return []
207
271
 
208
272
  const results = []
209
- for (const oid of branch.objects) {
210
- const obj = await this.getObject(oid)
273
+ for (const objOid of record.objects) {
274
+ const obj = await this.getObject(objOid)
211
275
  if (!obj) continue
212
276
 
213
277
  // Empty blobs have null data after round-tripping through compact-encoding
214
278
  const data = obj.data || Buffer.alloc(0)
215
279
 
216
280
  if (onLoad) onLoad(obj.size)
217
- results.push({ ...obj, data, id: oid })
281
+ results.push({ ...obj, data, id: objOid })
218
282
  }
219
283
 
220
284
  return results
@@ -223,8 +287,16 @@ class Remote extends ReadyResource {
223
287
  // --- Drive ---
224
288
 
225
289
  async toDrive(branch) {
290
+ // Check branches first, then tags
226
291
  const b = await this._db.get('@gip/branches', { name: branch })
227
- if (!b) return null
292
+ if (!b) {
293
+ const t = await this._db.get('@gip/tags', { name: branch })
294
+ if (!t) return null
295
+ // For tags, files are stored under 'tags/<name>'
296
+ const drive = new RemoteDrive(this._db, { branch: 'tags/' + branch })
297
+ await drive.ready()
298
+ return drive
299
+ }
228
300
 
229
301
  const drive = new RemoteDrive(this._db, { branch })
230
302
  await drive.ready()
package/lib/git.js CHANGED
@@ -35,6 +35,37 @@ function parseCommit(data) {
35
35
  return result
36
36
  }
37
37
 
38
+ // --- Git tag parser ---
39
+
40
+ function parseTag(data) {
41
+ const text = data.toString('utf8')
42
+ const lines = text.split('\n')
43
+ const result = { object: null, type: null, tag: null, tagger: null, timestamp: 0, message: '' }
44
+
45
+ let i = 0
46
+ for (; i < lines.length; i++) {
47
+ const line = lines[i]
48
+ if (line === '') {
49
+ i++
50
+ break
51
+ }
52
+
53
+ if (line.startsWith('object ')) result.object = line.slice(7)
54
+ else if (line.startsWith('type ')) result.type = line.slice(5)
55
+ else if (line.startsWith('tag ')) result.tag = line.slice(4)
56
+ else if (line.startsWith('tagger ')) {
57
+ const match = line.match(/^tagger (.+) <.+> (\d+) [+-]\d+$/)
58
+ if (match) {
59
+ result.tagger = match[1]
60
+ result.timestamp = parseInt(match[2])
61
+ }
62
+ }
63
+ }
64
+
65
+ result.message = lines.slice(i).join('\n').trim()
66
+ return result
67
+ }
68
+
38
69
  // --- Tree walker: extracts all file paths from git tree objects ---
39
70
 
40
71
  function walkTree(objects, treeOid, prefix) {
@@ -136,4 +167,4 @@ async function toDisk(opts) {
136
167
  }
137
168
  }
138
169
 
139
- module.exports = { parseCommit, walkTree, toDisk }
170
+ module.exports = { parseCommit, parseTag, walkTree, toDisk }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gip-remote",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "Git+Pear remote DB for handling git data",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 2,
2
+ "version": 3,
3
3
  "offset": 0,
4
4
  "schema": [
5
5
  {
@@ -12,7 +12,9 @@
12
12
  "indexes": [],
13
13
  "schema": "@gip/repos",
14
14
  "derived": false,
15
- "key": ["name"],
15
+ "key": [
16
+ "name"
17
+ ],
16
18
  "trigger": null
17
19
  },
18
20
  {
@@ -25,7 +27,9 @@
25
27
  "indexes": [],
26
28
  "schema": "@gip/branches",
27
29
  "derived": false,
28
- "key": ["name"],
30
+ "key": [
31
+ "name"
32
+ ],
29
33
  "trigger": null
30
34
  },
31
35
  {
@@ -35,10 +39,15 @@
35
39
  "type": 1,
36
40
  "version": 1,
37
41
  "versionField": null,
38
- "indexes": ["@gip/files-by-branch"],
42
+ "indexes": [
43
+ "@gip/files-by-branch"
44
+ ],
39
45
  "schema": "@gip/files",
40
46
  "derived": false,
41
- "key": ["branch", "path"],
47
+ "key": [
48
+ "branch",
49
+ "path"
50
+ ],
42
51
  "trigger": null
43
52
  },
44
53
  {
@@ -51,7 +60,9 @@
51
60
  "indexes": [],
52
61
  "schema": "@gip/objects",
53
62
  "derived": false,
54
- "key": ["oid"],
63
+ "key": [
64
+ "oid"
65
+ ],
55
66
  "trigger": null
56
67
  },
57
68
  {
@@ -63,7 +74,9 @@
63
74
  "collection": "@gip/files",
64
75
  "unique": false,
65
76
  "deprecated": false,
66
- "key": ["branch"]
77
+ "key": [
78
+ "branch"
79
+ ]
67
80
  },
68
81
  {
69
82
  "name": "head",
@@ -77,6 +90,21 @@
77
90
  "derived": false,
78
91
  "key": [],
79
92
  "trigger": null
93
+ },
94
+ {
95
+ "name": "tags",
96
+ "namespace": "gip",
97
+ "id": 6,
98
+ "type": 1,
99
+ "version": 3,
100
+ "versionField": null,
101
+ "indexes": [],
102
+ "schema": "@gip/tags",
103
+ "derived": false,
104
+ "key": [
105
+ "name"
106
+ ],
107
+ "trigger": null
80
108
  }
81
109
  ]
82
- }
110
+ }
@@ -4,12 +4,14 @@
4
4
  const { IndexEncoder, c, b4a } = require('hyperdb/runtime')
5
5
  const { version, getEncoding, setVersion } = require('./messages.js')
6
6
 
7
- const versions = { schema: version, db: 2 }
7
+ const versions = { schema: version, db: 3 }
8
8
 
9
9
  // '@gip/repos' collection key
10
- const collection0_key = new IndexEncoder([IndexEncoder.STRING], { prefix: 0 })
10
+ const collection0_key = new IndexEncoder([
11
+ IndexEncoder.STRING
12
+ ], { prefix: 0 })
11
13
 
12
- function collection0_indexify(record) {
14
+ function collection0_indexify (record) {
13
15
  const a = record.name
14
16
  return a === undefined ? [] : [a]
15
17
  }
@@ -18,7 +20,7 @@ function collection0_indexify(record) {
18
20
  const collection0_enc = getEncoding('@gip/repos/hyperdb#0')
19
21
 
20
22
  // '@gip/repos' reconstruction function
21
- function collection0_reconstruct(schemaVersion, keyBuf, valueBuf) {
23
+ function collection0_reconstruct (schemaVersion, keyBuf, valueBuf) {
22
24
  const key = collection0_key.decode(keyBuf)
23
25
  setVersion(schemaVersion)
24
26
  const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
@@ -30,7 +32,7 @@ function collection0_reconstruct(schemaVersion, keyBuf, valueBuf) {
30
32
  return record
31
33
  }
32
34
  // '@gip/repos' key reconstruction function
33
- function collection0_reconstruct_key(keyBuf) {
35
+ function collection0_reconstruct_key (keyBuf) {
34
36
  const key = collection0_key.decode(keyBuf)
35
37
  return {
36
38
  name: key[0]
@@ -42,11 +44,11 @@ const collection0 = {
42
44
  name: '@gip/repos',
43
45
  id: 0,
44
46
  version: 1,
45
- encodeKey(record) {
47
+ encodeKey (record) {
46
48
  const key = [record.name]
47
49
  return collection0_key.encode(key)
48
50
  },
49
- encodeKeyRange({ gt, lt, gte, lte } = {}) {
51
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
50
52
  return collection0_key.encodeRange({
51
53
  gt: gt ? collection0_indexify(gt) : null,
52
54
  lt: lt ? collection0_indexify(lt) : null,
@@ -54,7 +56,7 @@ const collection0 = {
54
56
  lte: lte ? collection0_indexify(lte) : null
55
57
  })
56
58
  },
57
- encodeValue(schemaVersion, collectionVersion, record) {
59
+ encodeValue (schemaVersion, collectionVersion, record) {
58
60
  setVersion(schemaVersion)
59
61
  const state = { start: 0, end: 2, buffer: null }
60
62
  collection0_enc.preencode(state, record)
@@ -72,9 +74,11 @@ const collection0 = {
72
74
  }
73
75
 
74
76
  // '@gip/branches' collection key
75
- const collection1_key = new IndexEncoder([IndexEncoder.STRING], { prefix: 1 })
77
+ const collection1_key = new IndexEncoder([
78
+ IndexEncoder.STRING
79
+ ], { prefix: 1 })
76
80
 
77
- function collection1_indexify(record) {
81
+ function collection1_indexify (record) {
78
82
  const a = record.name
79
83
  return a === undefined ? [] : [a]
80
84
  }
@@ -83,7 +87,7 @@ function collection1_indexify(record) {
83
87
  const collection1_enc = getEncoding('@gip/branches/hyperdb#1')
84
88
 
85
89
  // '@gip/branches' reconstruction function
86
- function collection1_reconstruct(schemaVersion, keyBuf, valueBuf) {
90
+ function collection1_reconstruct (schemaVersion, keyBuf, valueBuf) {
87
91
  const key = collection1_key.decode(keyBuf)
88
92
  setVersion(schemaVersion)
89
93
  const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
@@ -95,7 +99,7 @@ function collection1_reconstruct(schemaVersion, keyBuf, valueBuf) {
95
99
  return record
96
100
  }
97
101
  // '@gip/branches' key reconstruction function
98
- function collection1_reconstruct_key(keyBuf) {
102
+ function collection1_reconstruct_key (keyBuf) {
99
103
  const key = collection1_key.decode(keyBuf)
100
104
  return {
101
105
  name: key[0]
@@ -107,11 +111,11 @@ const collection1 = {
107
111
  name: '@gip/branches',
108
112
  id: 1,
109
113
  version: 1,
110
- encodeKey(record) {
114
+ encodeKey (record) {
111
115
  const key = [record.name]
112
116
  return collection1_key.encode(key)
113
117
  },
114
- encodeKeyRange({ gt, lt, gte, lte } = {}) {
118
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
115
119
  return collection1_key.encodeRange({
116
120
  gt: gt ? collection1_indexify(gt) : null,
117
121
  lt: lt ? collection1_indexify(lt) : null,
@@ -119,7 +123,7 @@ const collection1 = {
119
123
  lte: lte ? collection1_indexify(lte) : null
120
124
  })
121
125
  },
122
- encodeValue(schemaVersion, collectionVersion, record) {
126
+ encodeValue (schemaVersion, collectionVersion, record) {
123
127
  setVersion(schemaVersion)
124
128
  const state = { start: 0, end: 2, buffer: null }
125
129
  collection1_enc.preencode(state, record)
@@ -137,9 +141,12 @@ const collection1 = {
137
141
  }
138
142
 
139
143
  // '@gip/files' collection key
140
- const collection2_key = new IndexEncoder([IndexEncoder.STRING, IndexEncoder.STRING], { prefix: 2 })
144
+ const collection2_key = new IndexEncoder([
145
+ IndexEncoder.STRING,
146
+ IndexEncoder.STRING
147
+ ], { prefix: 2 })
141
148
 
142
- function collection2_indexify(record) {
149
+ function collection2_indexify (record) {
143
150
  const arr = []
144
151
 
145
152
  const a0 = record.branch
@@ -157,7 +164,7 @@ function collection2_indexify(record) {
157
164
  const collection2_enc = getEncoding('@gip/files/hyperdb#2')
158
165
 
159
166
  // '@gip/files' reconstruction function
160
- function collection2_reconstruct(schemaVersion, keyBuf, valueBuf) {
167
+ function collection2_reconstruct (schemaVersion, keyBuf, valueBuf) {
161
168
  const key = collection2_key.decode(keyBuf)
162
169
  setVersion(schemaVersion)
163
170
  const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
@@ -170,7 +177,7 @@ function collection2_reconstruct(schemaVersion, keyBuf, valueBuf) {
170
177
  return record
171
178
  }
172
179
  // '@gip/files' key reconstruction function
173
- function collection2_reconstruct_key(keyBuf) {
180
+ function collection2_reconstruct_key (keyBuf) {
174
181
  const key = collection2_key.decode(keyBuf)
175
182
  return {
176
183
  branch: key[0],
@@ -183,11 +190,11 @@ const collection2 = {
183
190
  name: '@gip/files',
184
191
  id: 2,
185
192
  version: 1,
186
- encodeKey(record) {
193
+ encodeKey (record) {
187
194
  const key = [record.branch, record.path]
188
195
  return collection2_key.encode(key)
189
196
  },
190
- encodeKeyRange({ gt, lt, gte, lte } = {}) {
197
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
191
198
  return collection2_key.encodeRange({
192
199
  gt: gt ? collection2_indexify(gt) : null,
193
200
  lt: lt ? collection2_indexify(lt) : null,
@@ -195,7 +202,7 @@ const collection2 = {
195
202
  lte: lte ? collection2_indexify(lte) : null
196
203
  })
197
204
  },
198
- encodeValue(schemaVersion, collectionVersion, record) {
205
+ encodeValue (schemaVersion, collectionVersion, record) {
199
206
  setVersion(schemaVersion)
200
207
  const state = { start: 0, end: 2, buffer: null }
201
208
  collection2_enc.preencode(state, record)
@@ -213,9 +220,11 @@ const collection2 = {
213
220
  }
214
221
 
215
222
  // '@gip/objects' collection key
216
- const collection3_key = new IndexEncoder([IndexEncoder.STRING], { prefix: 3 })
223
+ const collection3_key = new IndexEncoder([
224
+ IndexEncoder.STRING
225
+ ], { prefix: 3 })
217
226
 
218
- function collection3_indexify(record) {
227
+ function collection3_indexify (record) {
219
228
  const a = record.oid
220
229
  return a === undefined ? [] : [a]
221
230
  }
@@ -224,7 +233,7 @@ function collection3_indexify(record) {
224
233
  const collection3_enc = getEncoding('@gip/objects/hyperdb#3')
225
234
 
226
235
  // '@gip/objects' reconstruction function
227
- function collection3_reconstruct(schemaVersion, keyBuf, valueBuf) {
236
+ function collection3_reconstruct (schemaVersion, keyBuf, valueBuf) {
228
237
  const key = collection3_key.decode(keyBuf)
229
238
  setVersion(schemaVersion)
230
239
  const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
@@ -236,7 +245,7 @@ function collection3_reconstruct(schemaVersion, keyBuf, valueBuf) {
236
245
  return record
237
246
  }
238
247
  // '@gip/objects' key reconstruction function
239
- function collection3_reconstruct_key(keyBuf) {
248
+ function collection3_reconstruct_key (keyBuf) {
240
249
  const key = collection3_key.decode(keyBuf)
241
250
  return {
242
251
  oid: key[0]
@@ -248,11 +257,11 @@ const collection3 = {
248
257
  name: '@gip/objects',
249
258
  id: 3,
250
259
  version: 1,
251
- encodeKey(record) {
260
+ encodeKey (record) {
252
261
  const key = [record.oid]
253
262
  return collection3_key.encode(key)
254
263
  },
255
- encodeKeyRange({ gt, lt, gte, lte } = {}) {
264
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
256
265
  return collection3_key.encodeRange({
257
266
  gt: gt ? collection3_indexify(gt) : null,
258
267
  lt: lt ? collection3_indexify(lt) : null,
@@ -260,7 +269,7 @@ const collection3 = {
260
269
  lte: lte ? collection3_indexify(lte) : null
261
270
  })
262
271
  },
263
- encodeValue(schemaVersion, collectionVersion, record) {
272
+ encodeValue (schemaVersion, collectionVersion, record) {
264
273
  setVersion(schemaVersion)
265
274
  const state = { start: 0, end: 2, buffer: null }
266
275
  collection3_enc.preencode(state, record)
@@ -278,12 +287,13 @@ const collection3 = {
278
287
  }
279
288
 
280
289
  // '@gip/files-by-branch' collection key
281
- const index4_key = new IndexEncoder(
282
- [IndexEncoder.STRING, IndexEncoder.STRING, IndexEncoder.STRING],
283
- { prefix: 4 }
284
- )
290
+ const index4_key = new IndexEncoder([
291
+ IndexEncoder.STRING,
292
+ IndexEncoder.STRING,
293
+ IndexEncoder.STRING
294
+ ], { prefix: 4 })
285
295
 
286
- function index4_indexify(record) {
296
+ function index4_indexify (record) {
287
297
  const arr = []
288
298
 
289
299
  const a0 = record.branch
@@ -306,10 +316,10 @@ const index4 = {
306
316
  name: '@gip/files-by-branch',
307
317
  version: 1,
308
318
  id: 4,
309
- encodeKey(record) {
319
+ encodeKey (record) {
310
320
  return index4_key.encode(index4_indexify(record))
311
321
  },
312
- encodeKeyRange({ gt, lt, gte, lte } = {}) {
322
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
313
323
  return index4_key.encodeRange({
314
324
  gt: gt ? index4_indexify(gt) : null,
315
325
  lt: lt ? index4_indexify(lt) : null,
@@ -318,7 +328,7 @@ const index4 = {
318
328
  })
319
329
  },
320
330
  encodeValue: (record) => index4.collection.encodeKey(record),
321
- encodeIndexKeys(record, context) {
331
+ encodeIndexKeys (record, context) {
322
332
  return [index4_key.encode([record.branch, record.branch, record.path])]
323
333
  },
324
334
  reconstruct: (keyBuf, valueBuf) => valueBuf,
@@ -328,9 +338,10 @@ const index4 = {
328
338
  collection2.indexes.push(index4)
329
339
 
330
340
  // '@gip/head' collection key
331
- const collection5_key = new IndexEncoder([], { prefix: 5 })
341
+ const collection5_key = new IndexEncoder([
342
+ ], { prefix: 5 })
332
343
 
333
- function collection5_indexify(record) {
344
+ function collection5_indexify (record) {
334
345
  return []
335
346
  }
336
347
 
@@ -338,7 +349,7 @@ function collection5_indexify(record) {
338
349
  const collection5_enc = getEncoding('@gip/head')
339
350
 
340
351
  // '@gip/head' reconstruction function
341
- function collection5_reconstruct(schemaVersion, keyBuf, valueBuf) {
352
+ function collection5_reconstruct (schemaVersion, keyBuf, valueBuf) {
342
353
  setVersion(schemaVersion)
343
354
  const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
344
355
  const type = c.uint.decode(state)
@@ -348,7 +359,7 @@ function collection5_reconstruct(schemaVersion, keyBuf, valueBuf) {
348
359
  return record
349
360
  }
350
361
  // '@gip/head' key reconstruction function
351
- function collection5_reconstruct_key(keyBuf) {
362
+ function collection5_reconstruct_key (keyBuf) {
352
363
  return {}
353
364
  }
354
365
 
@@ -357,11 +368,11 @@ const collection5 = {
357
368
  name: '@gip/head',
358
369
  id: 5,
359
370
  version: 2,
360
- encodeKey(record) {
371
+ encodeKey (record) {
361
372
  const key = []
362
373
  return collection5_key.encode(key)
363
374
  },
364
- encodeKeyRange({ gt, lt, gte, lte } = {}) {
375
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
365
376
  return collection5_key.encodeRange({
366
377
  gt: gt ? collection5_indexify(gt) : null,
367
378
  lt: lt ? collection5_indexify(lt) : null,
@@ -369,7 +380,7 @@ const collection5 = {
369
380
  lte: lte ? collection5_indexify(lte) : null
370
381
  })
371
382
  },
372
- encodeValue(schemaVersion, collectionVersion, record) {
383
+ encodeValue (schemaVersion, collectionVersion, record) {
373
384
  setVersion(schemaVersion)
374
385
  const state = { start: 0, end: 2, buffer: null }
375
386
  collection5_enc.preencode(state, record)
@@ -386,34 +397,103 @@ const collection5 = {
386
397
  decodedVersion: 0
387
398
  }
388
399
 
389
- const collections = [collection0, collection1, collection2, collection3, collection5]
400
+ // '@gip/tags' collection key
401
+ const collection6_key = new IndexEncoder([
402
+ IndexEncoder.STRING
403
+ ], { prefix: 6 })
390
404
 
391
- const indexes = [index4]
405
+ function collection6_indexify (record) {
406
+ const a = record.name
407
+ return a === undefined ? [] : [a]
408
+ }
409
+
410
+ // '@gip/tags' value encoding
411
+ const collection6_enc = getEncoding('@gip/tags/hyperdb#6')
412
+
413
+ // '@gip/tags' reconstruction function
414
+ function collection6_reconstruct (schemaVersion, keyBuf, valueBuf) {
415
+ const key = collection6_key.decode(keyBuf)
416
+ setVersion(schemaVersion)
417
+ const state = { start: 0, end: valueBuf.byteLength, buffer: valueBuf }
418
+ const type = c.uint.decode(state)
419
+ if (type !== 0) throw new Error('Unknown collection type: ' + type)
420
+ collection6.decodedVersion = c.uint.decode(state)
421
+ const record = collection6_enc.decode(state)
422
+ record.name = key[0]
423
+ return record
424
+ }
425
+ // '@gip/tags' key reconstruction function
426
+ function collection6_reconstruct_key (keyBuf) {
427
+ const key = collection6_key.decode(keyBuf)
428
+ return {
429
+ name: key[0]
430
+ }
431
+ }
432
+
433
+ // '@gip/tags'
434
+ const collection6 = {
435
+ name: '@gip/tags',
436
+ id: 6,
437
+ version: 3,
438
+ encodeKey (record) {
439
+ const key = [record.name]
440
+ return collection6_key.encode(key)
441
+ },
442
+ encodeKeyRange ({ gt, lt, gte, lte } = {}) {
443
+ return collection6_key.encodeRange({
444
+ gt: gt ? collection6_indexify(gt) : null,
445
+ lt: lt ? collection6_indexify(lt) : null,
446
+ gte: gte ? collection6_indexify(gte) : null,
447
+ lte: lte ? collection6_indexify(lte) : null
448
+ })
449
+ },
450
+ encodeValue (schemaVersion, collectionVersion, record) {
451
+ setVersion(schemaVersion)
452
+ const state = { start: 0, end: 2, buffer: null }
453
+ collection6_enc.preencode(state, record)
454
+ state.buffer = b4a.allocUnsafe(state.end)
455
+ state.buffer[state.start++] = 0
456
+ state.buffer[state.start++] = collectionVersion
457
+ collection6_enc.encode(state, record)
458
+ return state.buffer
459
+ },
460
+ trigger: null,
461
+ reconstruct: collection6_reconstruct,
462
+ reconstructKey: collection6_reconstruct_key,
463
+ indexes: [],
464
+ decodedVersion: 0
465
+ }
466
+
467
+ const collections = [
468
+ collection0,
469
+ collection1,
470
+ collection2,
471
+ collection3,
472
+ collection5,
473
+ collection6
474
+ ]
475
+
476
+ const indexes = [
477
+ index4
478
+ ]
392
479
 
393
480
  module.exports = { versions, collections, indexes, resolveCollection, resolveIndex }
394
481
 
395
- function resolveCollection(name) {
482
+ function resolveCollection (name) {
396
483
  switch (name) {
397
- case '@gip/repos':
398
- return collection0
399
- case '@gip/branches':
400
- return collection1
401
- case '@gip/files':
402
- return collection2
403
- case '@gip/objects':
404
- return collection3
405
- case '@gip/head':
406
- return collection5
407
- default:
408
- return null
484
+ case '@gip/repos': return collection0
485
+ case '@gip/branches': return collection1
486
+ case '@gip/files': return collection2
487
+ case '@gip/objects': return collection3
488
+ case '@gip/head': return collection5
489
+ case '@gip/tags': return collection6
490
+ default: return null
409
491
  }
410
492
  }
411
493
 
412
- function resolveIndex(name) {
494
+ function resolveIndex (name) {
413
495
  switch (name) {
414
- case '@gip/files-by-branch':
415
- return index4
416
- default:
417
- return null
496
+ case '@gip/files-by-branch': return index4
497
+ default: return null
418
498
  }
419
499
  }
@@ -1,12 +1,12 @@
1
1
  // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 2
2
+ // Schema Version: 3
3
3
  /* eslint-disable camelcase */
4
4
  /* eslint-disable quotes */
5
5
  /* eslint-disable space-before-function-paren */
6
6
 
7
7
  const { c } = require('hyperschema/runtime')
8
8
 
9
- const VERSION = 2
9
+ const VERSION = 3
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  let version = VERSION
@@ -151,10 +151,10 @@ const encoding3_enum = {
151
151
 
152
152
  // @gip/object-type enum
153
153
  const encoding3 = {
154
- preencode(state, m) {
154
+ preencode (state, m) {
155
155
  state.end++ // max enum is 4 so always one byte
156
156
  },
157
- encode(state, m) {
157
+ encode (state, m) {
158
158
  switch (m) {
159
159
  case 'blob':
160
160
  c.uint.encode(state, 1)
@@ -172,7 +172,7 @@ const encoding3 = {
172
172
  throw new Error('Unknown enum')
173
173
  }
174
174
  },
175
- decode(state) {
175
+ decode (state) {
176
176
  switch (c.uint.decode(state)) {
177
177
  case 1:
178
178
  return 'blob'
@@ -182,8 +182,7 @@ const encoding3 = {
182
182
  return 'commit'
183
183
  case 4:
184
184
  return 'tag'
185
- default:
186
- return null
185
+ default: return null
187
186
  }
188
187
  }
189
188
  }
@@ -234,8 +233,63 @@ const encoding5 = {
234
233
  }
235
234
  }
236
235
 
237
- // @gip/repos/hyperdb#0
236
+ // @gip/tags.objects
237
+ const encoding6_7 = encoding1_6
238
+
239
+ // @gip/tags
238
240
  const encoding6 = {
241
+ preencode(state, m) {
242
+ c.string.preencode(state, m.name)
243
+ c.string.preencode(state, m.oid)
244
+ c.string.preencode(state, m.commitOid)
245
+ c.string.preencode(state, m.treeOid)
246
+ state.end++ // flags are fixed size
247
+
248
+ if (version >= 3 && m.tagger) c.string.preencode(state, m.tagger)
249
+ if (version >= 3 && m.message) c.string.preencode(state, m.message)
250
+ if (version >= 3 && m.timestamp) c.uint.preencode(state, m.timestamp)
251
+ if (version >= 3 && m.objects) encoding6_7.preencode(state, m.objects)
252
+ },
253
+ encode(state, m) {
254
+ const flags =
255
+ ((version >= 3 && m.tagger) ? 1 : 0) |
256
+ ((version >= 3 && m.message) ? 2 : 0) |
257
+ ((version >= 3 && m.timestamp) ? 4 : 0) |
258
+ ((version >= 3 && m.objects) ? 8 : 0)
259
+
260
+ c.string.encode(state, m.name)
261
+ c.string.encode(state, m.oid)
262
+ c.string.encode(state, m.commitOid)
263
+ c.string.encode(state, m.treeOid)
264
+ c.uint8.encode(state, flags)
265
+
266
+ if (version >= 3 && m.tagger) c.string.encode(state, m.tagger)
267
+ if (version >= 3 && m.message) c.string.encode(state, m.message)
268
+ if (version >= 3 && m.timestamp) c.uint.encode(state, m.timestamp)
269
+ if (version >= 3 && m.objects) encoding6_7.encode(state, m.objects)
270
+ },
271
+ decode(state) {
272
+ const r0 = c.string.decode(state)
273
+ const r1 = c.string.decode(state)
274
+ const r2 = c.string.decode(state)
275
+ const r3 = c.string.decode(state)
276
+ const flags = c.uint8.decode(state)
277
+
278
+ return {
279
+ name: r0,
280
+ oid: r1,
281
+ commitOid: r2,
282
+ treeOid: r3,
283
+ tagger: (version >= 3 && (flags & 1) !== 0) ? c.string.decode(state) : null,
284
+ message: (version >= 3 && (flags & 2) !== 0) ? c.string.decode(state) : null,
285
+ timestamp: (version >= 3 && (flags & 4) !== 0) ? c.uint.decode(state) : 0,
286
+ objects: (version >= 3 && (flags & 8) !== 0) ? encoding6_7.decode(state) : null
287
+ }
288
+ }
289
+ }
290
+
291
+ // @gip/repos/hyperdb#0
292
+ const encoding7 = {
239
293
  preencode(state, m) {
240
294
  c.buffer.preencode(state, m.key)
241
295
  state.end++ // flags are fixed size
@@ -266,10 +320,10 @@ const encoding6 = {
266
320
  }
267
321
 
268
322
  // @gip/branches/hyperdb#1.objects
269
- const encoding7_6 = encoding1_6
323
+ const encoding8_6 = encoding1_6
270
324
 
271
325
  // @gip/branches/hyperdb#1
272
- const encoding7 = {
326
+ const encoding8 = {
273
327
  preencode(state, m) {
274
328
  c.string.preencode(state, m.commitOid)
275
329
  c.string.preencode(state, m.treeOid)
@@ -278,7 +332,7 @@ const encoding7 = {
278
332
  if (m.author) c.string.preencode(state, m.author)
279
333
  if (m.message) c.string.preencode(state, m.message)
280
334
  if (m.timestamp) c.uint.preencode(state, m.timestamp)
281
- if (m.objects) encoding7_6.preencode(state, m.objects)
335
+ if (m.objects) encoding8_6.preencode(state, m.objects)
282
336
  },
283
337
  encode(state, m) {
284
338
  const flags =
@@ -291,7 +345,7 @@ const encoding7 = {
291
345
  if (m.author) c.string.encode(state, m.author)
292
346
  if (m.message) c.string.encode(state, m.message)
293
347
  if (m.timestamp) c.uint.encode(state, m.timestamp)
294
- if (m.objects) encoding7_6.encode(state, m.objects)
348
+ if (m.objects) encoding8_6.encode(state, m.objects)
295
349
  },
296
350
  decode(state) {
297
351
  const r1 = c.string.decode(state)
@@ -305,13 +359,13 @@ const encoding7 = {
305
359
  author: (flags & 1) !== 0 ? c.string.decode(state) : null,
306
360
  message: (flags & 2) !== 0 ? c.string.decode(state) : null,
307
361
  timestamp: (flags & 4) !== 0 ? c.uint.decode(state) : 0,
308
- objects: (flags & 8) !== 0 ? encoding7_6.decode(state) : null
362
+ objects: (flags & 8) !== 0 ? encoding8_6.decode(state) : null
309
363
  }
310
364
  }
311
365
  }
312
366
 
313
367
  // @gip/files/hyperdb#2
314
- const encoding8 = {
368
+ const encoding9 = {
315
369
  preencode(state, m) {
316
370
  c.string.preencode(state, m.oid)
317
371
  c.string.preencode(state, m.mode)
@@ -354,7 +408,7 @@ const encoding8 = {
354
408
  }
355
409
 
356
410
  // @gip/objects/hyperdb#3
357
- const encoding9 = {
411
+ const encoding10 = {
358
412
  preencode(state, m) {
359
413
  encoding3.preencode(state, m.type)
360
414
  c.uint.preencode(state, m.size)
@@ -379,6 +433,58 @@ const encoding9 = {
379
433
  }
380
434
  }
381
435
 
436
+ // @gip/tags/hyperdb#6.objects
437
+ const encoding11_7 = encoding1_6
438
+
439
+ // @gip/tags/hyperdb#6
440
+ const encoding11 = {
441
+ preencode(state, m) {
442
+ c.string.preencode(state, m.oid)
443
+ c.string.preencode(state, m.commitOid)
444
+ c.string.preencode(state, m.treeOid)
445
+ state.end++ // flags are fixed size
446
+
447
+ if (version >= 3 && m.tagger) c.string.preencode(state, m.tagger)
448
+ if (version >= 3 && m.message) c.string.preencode(state, m.message)
449
+ if (version >= 3 && m.timestamp) c.uint.preencode(state, m.timestamp)
450
+ if (version >= 3 && m.objects) encoding11_7.preencode(state, m.objects)
451
+ },
452
+ encode(state, m) {
453
+ const flags =
454
+ ((version >= 3 && m.tagger) ? 1 : 0) |
455
+ ((version >= 3 && m.message) ? 2 : 0) |
456
+ ((version >= 3 && m.timestamp) ? 4 : 0) |
457
+ ((version >= 3 && m.objects) ? 8 : 0)
458
+
459
+ c.string.encode(state, m.oid)
460
+ c.string.encode(state, m.commitOid)
461
+ c.string.encode(state, m.treeOid)
462
+ c.uint8.encode(state, flags)
463
+
464
+ if (version >= 3 && m.tagger) c.string.encode(state, m.tagger)
465
+ if (version >= 3 && m.message) c.string.encode(state, m.message)
466
+ if (version >= 3 && m.timestamp) c.uint.encode(state, m.timestamp)
467
+ if (version >= 3 && m.objects) encoding11_7.encode(state, m.objects)
468
+ },
469
+ decode(state) {
470
+ const r1 = c.string.decode(state)
471
+ const r2 = c.string.decode(state)
472
+ const r3 = c.string.decode(state)
473
+ const flags = c.uint8.decode(state)
474
+
475
+ return {
476
+ name: null,
477
+ oid: r1,
478
+ commitOid: r2,
479
+ treeOid: r3,
480
+ tagger: (version >= 3 && (flags & 1) !== 0) ? c.string.decode(state) : null,
481
+ message: (version >= 3 && (flags & 2) !== 0) ? c.string.decode(state) : null,
482
+ timestamp: (version >= 3 && (flags & 4) !== 0) ? c.uint.decode(state) : 0,
483
+ objects: (version >= 3 && (flags & 8) !== 0) ? encoding11_7.decode(state) : null
484
+ }
485
+ }
486
+ }
487
+
382
488
  function setVersion(v) {
383
489
  version = v
384
490
  }
@@ -416,14 +522,18 @@ function getEncoding(name) {
416
522
  return encoding4
417
523
  case '@gip/head':
418
524
  return encoding5
419
- case '@gip/repos/hyperdb#0':
525
+ case '@gip/tags':
420
526
  return encoding6
421
- case '@gip/branches/hyperdb#1':
527
+ case '@gip/repos/hyperdb#0':
422
528
  return encoding7
423
- case '@gip/files/hyperdb#2':
529
+ case '@gip/branches/hyperdb#1':
424
530
  return encoding8
425
- case '@gip/objects/hyperdb#3':
531
+ case '@gip/files/hyperdb#2':
426
532
  return encoding9
533
+ case '@gip/objects/hyperdb#3':
534
+ return encoding10
535
+ case '@gip/tags/hyperdb#6':
536
+ return encoding11
427
537
  default:
428
538
  throw new Error('Encoder not found ' + name)
429
539
  }
@@ -1,12 +1,12 @@
1
1
  // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 2
2
+ // Schema Version: 3
3
3
  /* eslint-disable camelcase */
4
4
  /* eslint-disable quotes */
5
5
  /* eslint-disable space-before-function-paren */
6
6
 
7
7
  const { c } = require('hyperschema/runtime')
8
8
 
9
- const VERSION = 2
9
+ const VERSION = 3
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  let version = VERSION
@@ -151,10 +151,10 @@ const encoding3_enum = {
151
151
 
152
152
  // @gip/object-type enum
153
153
  const encoding3 = {
154
- preencode(state, m) {
154
+ preencode (state, m) {
155
155
  state.end++ // max enum is 4 so always one byte
156
156
  },
157
- encode(state, m) {
157
+ encode (state, m) {
158
158
  switch (m) {
159
159
  case 'blob':
160
160
  c.uint.encode(state, 1)
@@ -172,7 +172,7 @@ const encoding3 = {
172
172
  throw new Error('Unknown enum')
173
173
  }
174
174
  },
175
- decode(state) {
175
+ decode (state) {
176
176
  switch (c.uint.decode(state)) {
177
177
  case 1:
178
178
  return 'blob'
@@ -182,8 +182,7 @@ const encoding3 = {
182
182
  return 'commit'
183
183
  case 4:
184
184
  return 'tag'
185
- default:
186
- return null
185
+ default: return null
187
186
  }
188
187
  }
189
188
  }
@@ -234,6 +233,61 @@ const encoding5 = {
234
233
  }
235
234
  }
236
235
 
236
+ // @gip/tags.objects
237
+ const encoding6_7 = encoding1_6
238
+
239
+ // @gip/tags
240
+ const encoding6 = {
241
+ preencode(state, m) {
242
+ c.string.preencode(state, m.name)
243
+ c.string.preencode(state, m.oid)
244
+ c.string.preencode(state, m.commitOid)
245
+ c.string.preencode(state, m.treeOid)
246
+ state.end++ // flags are fixed size
247
+
248
+ if (version >= 3 && m.tagger) c.string.preencode(state, m.tagger)
249
+ if (version >= 3 && m.message) c.string.preencode(state, m.message)
250
+ if (version >= 3 && m.timestamp) c.uint.preencode(state, m.timestamp)
251
+ if (version >= 3 && m.objects) encoding6_7.preencode(state, m.objects)
252
+ },
253
+ encode(state, m) {
254
+ const flags =
255
+ ((version >= 3 && m.tagger) ? 1 : 0) |
256
+ ((version >= 3 && m.message) ? 2 : 0) |
257
+ ((version >= 3 && m.timestamp) ? 4 : 0) |
258
+ ((version >= 3 && m.objects) ? 8 : 0)
259
+
260
+ c.string.encode(state, m.name)
261
+ c.string.encode(state, m.oid)
262
+ c.string.encode(state, m.commitOid)
263
+ c.string.encode(state, m.treeOid)
264
+ c.uint8.encode(state, flags)
265
+
266
+ if (version >= 3 && m.tagger) c.string.encode(state, m.tagger)
267
+ if (version >= 3 && m.message) c.string.encode(state, m.message)
268
+ if (version >= 3 && m.timestamp) c.uint.encode(state, m.timestamp)
269
+ if (version >= 3 && m.objects) encoding6_7.encode(state, m.objects)
270
+ },
271
+ decode(state) {
272
+ const r0 = c.string.decode(state)
273
+ const r1 = c.string.decode(state)
274
+ const r2 = c.string.decode(state)
275
+ const r3 = c.string.decode(state)
276
+ const flags = c.uint8.decode(state)
277
+
278
+ return {
279
+ name: r0,
280
+ oid: r1,
281
+ commitOid: r2,
282
+ treeOid: r3,
283
+ tagger: (version >= 3 && (flags & 1) !== 0) ? c.string.decode(state) : null,
284
+ message: (version >= 3 && (flags & 2) !== 0) ? c.string.decode(state) : null,
285
+ timestamp: (version >= 3 && (flags & 4) !== 0) ? c.uint.decode(state) : 0,
286
+ objects: (version >= 3 && (flags & 8) !== 0) ? encoding6_7.decode(state) : null
287
+ }
288
+ }
289
+ }
290
+
237
291
  function setVersion(v) {
238
292
  version = v
239
293
  }
@@ -271,6 +325,8 @@ function getEncoding(name) {
271
325
  return encoding4
272
326
  case '@gip/head':
273
327
  return encoding5
328
+ case '@gip/tags':
329
+ return encoding6
274
330
  default:
275
331
  throw new Error('Encoder not found ' + name)
276
332
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 2,
2
+ "version": 3,
3
3
  "schema": [
4
4
  {
5
5
  "name": "repos",
@@ -208,6 +208,62 @@
208
208
  "version": 2
209
209
  }
210
210
  ]
211
+ },
212
+ {
213
+ "name": "tags",
214
+ "namespace": "gip",
215
+ "compact": true,
216
+ "flagsPosition": 4,
217
+ "fields": [
218
+ {
219
+ "name": "name",
220
+ "required": true,
221
+ "type": "string",
222
+ "version": 3
223
+ },
224
+ {
225
+ "name": "oid",
226
+ "required": true,
227
+ "type": "string",
228
+ "version": 3
229
+ },
230
+ {
231
+ "name": "commitOid",
232
+ "required": true,
233
+ "type": "string",
234
+ "version": 3
235
+ },
236
+ {
237
+ "name": "treeOid",
238
+ "required": true,
239
+ "type": "string",
240
+ "version": 3
241
+ },
242
+ {
243
+ "name": "tagger",
244
+ "required": false,
245
+ "type": "string",
246
+ "version": 3
247
+ },
248
+ {
249
+ "name": "message",
250
+ "required": false,
251
+ "type": "string",
252
+ "version": 3
253
+ },
254
+ {
255
+ "name": "timestamp",
256
+ "required": false,
257
+ "type": "uint",
258
+ "version": 3
259
+ },
260
+ {
261
+ "name": "objects",
262
+ "array": true,
263
+ "type": "string",
264
+ "version": 3
265
+ }
266
+ ]
211
267
  }
212
268
  ]
213
269
  }