proskomma-core 0.9.10 → 0.9.13

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.
Files changed (136) hide show
  1. package/.eslintrc.json +79 -0
  2. package/.gitattributes +2 -0
  3. package/docs/_config.yml +1 -0
  4. package/docs/index.md +3 -0
  5. package/docs/pk_edit_0_9.odt +0 -0
  6. package/docs/pk_edit_0_9.pdf +0 -0
  7. package/docs/proskomma_101_slideshow.odp +0 -0
  8. package/docs/proskomma_101_slideshow.pdf +0 -0
  9. package/docs/proskomma_edit_html.png +0 -0
  10. package/docs/proskomma_edit_html.svg +451 -0
  11. package/docs/proskomma_edit_reference.png +0 -0
  12. package/docs/proskomma_edit_reference.svg +349 -0
  13. package/docs/repo_logo.png +0 -0
  14. package/esm/package.json +3 -0
  15. package/esm/wrapper.mjs +5 -0
  16. package/index.cjs +6 -0
  17. package/package.json +18 -15
  18. package/src/graph/index.cjs +201 -0
  19. package/src/graph/lib/do_cv.cjs +249 -0
  20. package/src/graph/lib/dump.cjs +40 -0
  21. package/src/graph/lib/remake_blocks.cjs +57 -0
  22. package/src/graph/lib/sequence_chars.cjs +84 -0
  23. package/src/graph/lib/sort.cjs +39 -0
  24. package/src/graph/lib/tribos.cjs +97 -0
  25. package/src/graph/lib/tribos_expression.cjs +556 -0
  26. package/src/graph/lib/tribos_ohm_UNUSED.cjs +37 -0
  27. package/src/graph/lib/tribos_step.cjs +434 -0
  28. package/src/graph/mutations/add.cjs +91 -0
  29. package/src/graph/mutations/delete.cjs +61 -0
  30. package/src/graph/mutations/index.cjs +54 -0
  31. package/src/graph/mutations/rehash.cjs +17 -0
  32. package/src/graph/mutations/tags.cjs +120 -0
  33. package/src/graph/mutations/update.cjs +210 -0
  34. package/src/graph/mutations/versification.cjs +96 -0
  35. package/src/graph/queries/block.cjs +228 -0
  36. package/src/graph/queries/cIndex.cjs +87 -0
  37. package/src/graph/queries/cell.cjs +42 -0
  38. package/src/graph/queries/cv.cjs +19 -0
  39. package/src/graph/queries/cvBook.cjs +16 -0
  40. package/src/graph/queries/cvChapter.cjs +16 -0
  41. package/src/graph/queries/cvIndex.cjs +47 -0
  42. package/src/graph/queries/cvNavigation.cjs +116 -0
  43. package/src/graph/queries/cvVerseElement.cjs +84 -0
  44. package/src/graph/queries/cvVerses.cjs +14 -0
  45. package/src/graph/queries/doc_set.cjs +220 -0
  46. package/src/graph/queries/document.cjs +555 -0
  47. package/src/graph/queries/idParts.cjs +30 -0
  48. package/src/graph/queries/index.cjs +151 -0
  49. package/src/graph/queries/inputBlockSpec.cjs +17 -0
  50. package/src/graph/queries/inputItemObject.cjs +12 -0
  51. package/src/graph/queries/input_att_spec.cjs +14 -0
  52. package/src/graph/queries/input_key_matches.cjs +11 -0
  53. package/src/graph/queries/input_key_value.cjs +11 -0
  54. package/src/graph/queries/input_key_values.cjs +11 -0
  55. package/src/graph/queries/input_selector_spec.cjs +19 -0
  56. package/src/graph/queries/item.cjs +71 -0
  57. package/src/graph/queries/itemGroup.cjs +75 -0
  58. package/src/graph/queries/key_value.cjs +18 -0
  59. package/src/graph/queries/kv_entry.cjs +21 -0
  60. package/src/graph/queries/kv_sequence.cjs +151 -0
  61. package/src/graph/queries/node.cjs +44 -0
  62. package/src/graph/queries/orig.cjs +11 -0
  63. package/src/graph/queries/regex_index.cjs +18 -0
  64. package/src/graph/queries/row_equals_spec.cjs +11 -0
  65. package/src/graph/queries/row_match_spec.cjs +11 -0
  66. package/src/graph/queries/selector_spec.cjs +29 -0
  67. package/src/graph/queries/sequence.cjs +314 -0
  68. package/src/graph/queries/table_sequence.cjs +192 -0
  69. package/src/graph/queries/tree_sequence.cjs +58 -0
  70. package/src/graph/queries/verseNumber.cjs +44 -0
  71. package/src/graph/queries/verseRange.cjs +11 -0
  72. package/src/graph/queries/versification.cjs +25 -0
  73. package/src/index.cjs +583 -0
  74. package/src/model/doc_set.cjs +389 -0
  75. package/src/model/doc_set_helpers/block.cjs +232 -0
  76. package/src/model/doc_set_helpers/enum.cjs +87 -0
  77. package/src/model/doc_set_helpers/item.cjs +198 -0
  78. package/src/model/doc_set_helpers/rehash.cjs +53 -0
  79. package/src/model/doc_set_helpers/selectors.cjs +58 -0
  80. package/src/model/doc_set_helpers/serialize.cjs +22 -0
  81. package/src/model/doc_set_helpers/unsuccinctify.cjs +288 -0
  82. package/src/model/doc_set_helpers/update.cjs +290 -0
  83. package/src/model/document.cjs +369 -0
  84. package/src/model/document_helpers/blocks.cjs +135 -0
  85. package/src/model/document_helpers/chapter_verse.cjs +291 -0
  86. package/src/model/document_helpers/pre_enums.cjs +67 -0
  87. package/src/model/document_helpers/sequences.cjs +205 -0
  88. package/src/model/document_helpers/serialize_succinct.cjs +55 -0
  89. package/src/model/document_helpers/succinct_filter.cjs +102 -0
  90. package/src/model/versifications/eng_vrs.cjs +455 -0
  91. package/src/model/versifications/index.cjs +38 -0
  92. package/src/model/versifications/lxx_vrs.cjs +950 -0
  93. package/src/model/versifications/org_vrs.cjs +155 -0
  94. package/src/model/versifications/rsc_vrs.cjs +342 -0
  95. package/src/model/versifications/rso_vrs.cjs +541 -0
  96. package/src/model/versifications/vul_vrs.cjs +835 -0
  97. package/src/parser/index.cjs +506 -0
  98. package/src/parser/lexers/index.cjs +11 -0
  99. package/src/parser/lexers/lexingRegexes.cjs +45 -0
  100. package/src/parser/lexers/nodes.cjs +123 -0
  101. package/src/parser/lexers/object_for_fragment.cjs +123 -0
  102. package/src/parser/lexers/tsv.cjs +45 -0
  103. package/src/parser/lexers/usfm.cjs +17 -0
  104. package/src/parser/lexers/usx/index.cjs +7 -0
  105. package/src/parser/lexers/usx/usx_lexer.cjs +321 -0
  106. package/src/parser/lib/tokenize.cjs +37 -0
  107. package/src/parser/model/index.cjs +637 -0
  108. package/src/parser/parser_specs.cjs +781 -0
  109. package/src/pipelines/perf2x/index.cjs +7 -0
  110. package/src/pipelines/perf2x/perf2PkJsonPipeline.json +41 -0
  111. package/src/pipelines/perf2x/perf2usfmPipeline.json +65 -0
  112. package/src/transforms/calculateUsfmChapterPositions.cjs +106 -0
  113. package/src/transforms/index.cjs +9 -0
  114. package/src/transforms/perf2PkJson.cjs +534 -0
  115. package/src/transforms/perf2usfm.cjs +294 -0
  116. package/src/util/byteArray.cjs +251 -0
  117. package/src/util/canons.cjs +117 -0
  118. package/src/util/enums.cjs +41 -0
  119. package/src/util/generateId.cjs +6 -0
  120. package/src/util/graftDefs.cjs +15 -0
  121. package/src/util/index.cjs +29 -0
  122. package/src/util/inspectSuccinct.cjs +59 -0
  123. package/src/util/itemDefs.cjs +33 -0
  124. package/src/util/parserConstantDefs.cjs +30 -0
  125. package/src/util/scopeDefs.cjs +173 -0
  126. package/src/util/scriptlike/blocksSpec.cjs +192 -0
  127. package/src/util/scriptlike/dodson_lexicon.xsl +19 -0
  128. package/src/util/scriptlike/dodson_lexicon_to_entries.cjs +85 -0
  129. package/src/util/scriptlike/open_scriptures_hebrew_lexicon.xsl +28 -0
  130. package/src/util/scriptlike/open_scriptures_hebrew_lexicon_to_entries.cjs +85 -0
  131. package/src/util/succinct.cjs +159 -0
  132. package/src/util/tags.cjs +28 -0
  133. package/src/util/tokenDefs.cjs +27 -0
  134. package/src/util/versification.cjs +364 -0
  135. package/dist/index.js +0 -8
  136. package/dist/index.js.LICENSE.txt +0 -23
package/src/index.cjs ADDED
@@ -0,0 +1,583 @@
1
+ const xre = require('xregexp');
2
+ const { makeExecutableSchema } = require('@graphql-tools/schema');
3
+
4
+ const { Mutex } =require('async-mutex');
5
+ const checksum = require('checksum');
6
+ const {
7
+ graphql,
8
+ graphqlSync,
9
+ } = require('graphql');
10
+ const BitSet = require('bitset');
11
+
12
+ const packageJson = require('../package.json');
13
+ const utils = require('./util/index.cjs');
14
+ const { DocSet } = require('./model/doc_set.cjs');
15
+ const { Document } = require('./model/document.cjs');
16
+ const {
17
+ typeDefs,
18
+ resolvers,
19
+ } = require('./graph/index.cjs');
20
+
21
+ const { lexingRegexes } = require('./parser/lexers/lexingRegexes.cjs');
22
+ const blocksSpecUtils = require('./util/scriptlike/blocksSpec.cjs');
23
+ const {
24
+ flattenNodes,
25
+ numberNodes,
26
+ } = require('./parser/lexers/nodes.cjs');
27
+
28
+ const tree2nodes = tree => flattenNodes(numberNodes(tree));
29
+
30
+ const executableSchema =
31
+ makeExecutableSchema({
32
+ typeDefs,
33
+ resolvers,
34
+ });
35
+
36
+ class Proskomma {
37
+ constructor(selectors) {
38
+ this.processorId = utils.generateId();
39
+ this.documents = {};
40
+ this.docSetsBySelector = {};
41
+ this.docSets = {};
42
+ this.filters = {};
43
+ this.customTags = {
44
+ heading: [],
45
+ paragraph: [],
46
+ char: [],
47
+ word: [],
48
+ intro: [],
49
+ introHeading: [],
50
+ };
51
+ this.emptyBlocks = [];
52
+ this.selectors = selectors || [
53
+ {
54
+ name: 'lang',
55
+ type: 'string',
56
+ regex: '[a-z]{3}',
57
+ },
58
+ {
59
+ name: 'abbr',
60
+ type: 'string',
61
+ },
62
+ ];
63
+ this.validateSelectorSpec(this.selectors);
64
+ this.mutex = new Mutex();
65
+ this.nextPeriph = 0;
66
+ this.nextTable = 0;
67
+ this.nextNodes = 0;
68
+ }
69
+
70
+ validateSelectors() {
71
+ if (this.selectors.length === 0) {
72
+ throw new Error('No selectors found');
73
+ }
74
+
75
+ for (const [n, selector] of this.selectors.entries()) {
76
+ if (!('name' in selector)) {
77
+ throw new Error(`Selector ${n} has no name`);
78
+ }
79
+
80
+ if (!('type' in selector)) {
81
+ throw new Error(`Selector ${n} has no type`);
82
+ }
83
+
84
+ if (!['string', 'integer'].includes(selector.type)) {
85
+ throw new Error(`Type for selector ${n} must be string or number, not ${selector.type}`);
86
+ }
87
+
88
+ if (selector.type === 'string') {
89
+ if ('min' in selector) {
90
+ throw new Error('String selector should not include \'min\'');
91
+ }
92
+
93
+ if ('max' in selector) {
94
+ throw new Error('String selector should not include \'max\'');
95
+ }
96
+
97
+ if ('regex' in selector) {
98
+ try {
99
+ xre(selector.regex);
100
+ } catch (err) {
101
+ throw new Error(`Regex '${selector.regex}' is not valid: ${err}`);
102
+ }
103
+ }
104
+
105
+ if ('enum' in selector) {
106
+ for (const enumElement of selector.enum) {
107
+ if (typeof enumElement !== 'string') {
108
+ throw new Error(`Enum values for selector ${selector.name} should be strings, not '${enumElement}'`);
109
+ }
110
+ }
111
+ }
112
+ } else {
113
+ if ('regex' in selector) {
114
+ throw new Error('Integer selector should not include \'regex\'');
115
+ }
116
+
117
+ if ('min' in selector && typeof selector.min !== 'number') {
118
+ throw new Error(`'min' must be a number, not '${selector.min}'`);
119
+ }
120
+
121
+ if ('max' in selector && typeof selector.max !== 'number') {
122
+ throw new Error(`'max' must be a number, not '${selector.max}'`);
123
+ }
124
+
125
+ if ('min' in selector && 'max' in selector && selector.min > selector.max) {
126
+ throw new Error(`'min' cannot be greater than 'max' (${selector.min} > ${selector.max})`);
127
+ }
128
+
129
+ if ('enum' in selector) {
130
+ for (const enumElement of selector.enum) {
131
+ if (typeof enumElement !== 'number') {
132
+ throw new Error(`Enum values for selector ${selector.name} should be numbers, not '${enumElement}'`);
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ for (const selectorKey of Object.keys(selector)) {
139
+ if (!['name', 'type', 'regex', 'min', 'max', 'enum'].includes(selectorKey)) {
140
+ throw new Error(`Unexpected key '${selectorKey}' in selector ${n}`);
141
+ }
142
+ }
143
+ }
144
+ }
145
+
146
+ validateSelectorSpec(spec) {
147
+ for (const specElement of spec) {
148
+ if (!specElement['name']) {
149
+ throw new Error(`name not found in selector spec element '${JSON.stringify(specElement)}'`);
150
+ }
151
+
152
+ if (!specElement['type']) {
153
+ throw new Error(`type not found in selector spec element '${JSON.stringify(specElement)}'`);
154
+ }
155
+
156
+ if (!['string', 'integer'].includes(specElement.type)) {
157
+ throw new Error(`Type for spec element must be string or number, not ${specElement.type}`);
158
+ }
159
+
160
+ for (const selectorKey of Object.keys(specElement)) {
161
+ if (!['name', 'type', 'regex', 'min', 'max', 'enum'].includes(selectorKey)) {
162
+ throw new Error(`Unexpected key '${selectorKey}' in selectorSpec`);
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ selectorString(docSetSelectors) {
169
+ // In root so it can be easily subclassed
170
+ return this.selectors.map(s => s.name).map(n => `${docSetSelectors[n]}`).join('_');
171
+ }
172
+
173
+ processor() {
174
+ return 'Proskomma JS';
175
+ }
176
+
177
+ packageVersion() {
178
+ return packageJson.version;
179
+ }
180
+
181
+ docSetList() {
182
+ return Object.values(this.docSets);
183
+ }
184
+
185
+ docSetsById(ids) {
186
+ return Object.values(this.docSets).filter(ds => ids.includes(ds.id));
187
+ }
188
+
189
+ docSetById(id) {
190
+ return this.docSets[id];
191
+ }
192
+
193
+ docSetsWithBook(bookCode) {
194
+ const docIdsWithBook = Object.values(this.documents)
195
+ .filter(doc => 'bookCode' in doc.headers && doc.headers['bookCode'] === bookCode)
196
+ .map(doc => doc.id);
197
+
198
+ const docIdWithBookInDocSet = (ds) => {
199
+ for (const docId of docIdsWithBook) {
200
+ if (ds.docIds.includes(docId)) {
201
+ return true;
202
+ }
203
+ }
204
+ return false;
205
+ };
206
+ return Object.values(this.docSets).filter(ds => docIdWithBookInDocSet(ds));
207
+ }
208
+
209
+ nDocSets() {
210
+ return this.docSetList().length;
211
+ }
212
+
213
+ nDocuments() {
214
+ return this.documentList().length;
215
+ }
216
+
217
+ documentList() {
218
+ return Object.values(this.documents);
219
+ }
220
+
221
+ documentById(id) {
222
+ return this.documents[id];
223
+ }
224
+
225
+ documentsById(ids) {
226
+ return Object.values(this.documents).filter(doc => ids.includes(doc.id));
227
+ }
228
+
229
+ documentsWithBook(bookCode) {
230
+ return Object.values(this.documents).filter(doc => 'bookCode' in doc.headers && doc.headers['bookCode'] === bookCode);
231
+ }
232
+
233
+ importDocument(selectors, contentType, contentString, filterOptions, customTags, emptyBlocks, tags) {
234
+ return this.importDocuments(selectors, contentType, [contentString], filterOptions, customTags, emptyBlocks, tags)[0];
235
+ }
236
+
237
+ importDocuments(selectors, contentType, contentStrings, filterOptions, customTags, emptyBlocks, tags) {
238
+ if (!filterOptions) {
239
+ filterOptions = this.filters;
240
+ }
241
+
242
+ if (!customTags) {
243
+ customTags = this.customTags;
244
+ }
245
+
246
+ if (!emptyBlocks) {
247
+ emptyBlocks = this.emptyBlocks;
248
+ }
249
+
250
+ if (!tags) {
251
+ tags = [];
252
+ }
253
+
254
+ const docSetId = this.findOrMakeDocSet(selectors);
255
+ const docSet = this.docSets[docSetId];
256
+ docSet.buildPreEnums();
257
+ const docs = [];
258
+
259
+ for (const contentString of contentStrings) {
260
+ let doc = new Document(this, docSetId, contentType, contentString, filterOptions, customTags, emptyBlocks, tags);
261
+ const bookCode = doc.headers.bookCode;
262
+ const existingBookCodes = Object.values(this.documents)
263
+ .filter(d => docSet.docIds.includes(d.id))
264
+ .map(d => d.headers.bookCode);
265
+
266
+ if (existingBookCodes.includes(bookCode)) {
267
+ throw new Error(`Attempt to import document with bookCode '${bookCode}' which already exists in docSet ${docSetId}`);
268
+ }
269
+ this.addDocument(doc, docSetId);
270
+ docs.push(doc);
271
+ }
272
+ docSet.preEnums = {};
273
+ return docs;
274
+ }
275
+
276
+ importUsfmPeriph(selectors, contentString, filterOptions, customTags, emptyBlocks, tags) {
277
+ const lines = contentString.toString().split(/[\n\r]+/);
278
+ const bookCode = lines[0].substring(4, 7);
279
+
280
+ if (!['FRT', 'BAK', 'INT'].includes(bookCode)) {
281
+ throw new Error(`importUsfmInt() expected bookCode of FRT, BAK or INT, not '${bookCode}'`);
282
+ }
283
+
284
+ let periphs = [];
285
+
286
+ for (const line of lines) {
287
+ if (line.substring(0, 7) === '\\periph') {
288
+ let matchedBits = xre.exec(line, xre('^\\\\periph (.*)\\|\\s*id\\s*=\\s*"([^"]+)"\\s*$'));
289
+
290
+ if (!matchedBits) {
291
+ throw new Error(`Unable to parse periph line '${line}'`);
292
+ }
293
+
294
+ const periphDesc = matchedBits[1];
295
+ const periphId = matchedBits[2];
296
+ const periphBookCode = `\\id P${this.nextPeriph > 9 ? this.nextPeriph : '0' + this.nextPeriph}`;
297
+ periphs.push([`${periphBookCode} INT ${periphId} - ${periphDesc}`]);
298
+ this.nextPeriph++;
299
+ } else if (periphs.length > 0 && line.substring(0, 3) !== '\\id') {
300
+ periphs[periphs.length - 1].push(line);
301
+ }
302
+ }
303
+ this.importDocuments(
304
+ selectors,
305
+ 'usfm',
306
+ periphs.map(p => p.join('\n')),
307
+ filterOptions,
308
+ customTags,
309
+ emptyBlocks,
310
+ tags,
311
+ );
312
+ }
313
+
314
+ cleanUsfm(usfm, options) {
315
+ options = options || {};
316
+ const lines = usfm.toString().split(/[\n\r]+/);
317
+ const ret = [];
318
+ let inHeaders = true;
319
+ const headers = ['\\id', '\\ide', '\\usfm', '\\sts', '\\rem', '\\h', '\\toc'];
320
+
321
+ for (const line of lines) {
322
+ const firstWord = line.split(' ')[0]
323
+ .replace(/[0-9]+/g, '');
324
+
325
+ if ('remove' in options && options.remove.includes(firstWord)) {
326
+ continue;
327
+ }
328
+
329
+ const isHeaderLine = headers.includes(firstWord);
330
+
331
+ if (inHeaders && !isHeaderLine && firstWord !== '\\mt') {
332
+ ret.push('\\mt1 USFM');
333
+ }
334
+ ret.push(line);
335
+
336
+ if (!isHeaderLine) {
337
+ inHeaders = false;
338
+ }
339
+ }
340
+ return ret.join('\n');
341
+ }
342
+
343
+ deleteDocSet(docSetId) {
344
+ if (!(docSetId in this.docSets)) {
345
+ return false;
346
+ }
347
+
348
+ for (const docId of Object.entries(this.documents).filter(tup => tup[1].docSetId === docSetId).map(tup => tup[0])) {
349
+ this.deleteDocument(docSetId, docId, false, false);
350
+ }
351
+
352
+ let selected = this.docSetsBySelector;
353
+ const parentSelectors = this.selectors.slice(0, this.selectors.length - 1);
354
+
355
+ for (const selector of parentSelectors) {
356
+ selected = selected[this.docSets[docSetId].selectors[selector.name]];
357
+ }
358
+
359
+ const lastSelectorName = this.selectors[this.selectors.length - 1].name;
360
+ const lastSelectorValue = this.docSets[docSetId].selectors[lastSelectorName];
361
+
362
+ if (!selected[lastSelectorValue]) {
363
+ throw new Error(`Could not find docSetId '${docSetId}' in docSetsBySelector in deleteDocSet`);
364
+ }
365
+ delete selected[lastSelectorValue];
366
+ delete this.docSets[docSetId];
367
+ return true;
368
+ }
369
+
370
+ deleteDocument(docSetId, documentId, maybeDeleteDocSet, maybeRehashDocSet) {
371
+ maybeDeleteDocSet = maybeDeleteDocSet === undefined ? true : maybeDeleteDocSet;
372
+ maybeRehashDocSet = maybeRehashDocSet === undefined ? true : maybeRehashDocSet;
373
+
374
+ if (!(docSetId in this.docSets)) {
375
+ return false;
376
+ }
377
+
378
+ if (!(documentId in this.documents)) {
379
+ return false;
380
+ }
381
+
382
+ delete this.documents[documentId];
383
+
384
+ if (this.docSets[docSetId].docIds.length > 1) {
385
+ this.docSets[docSetId].docIds = this.docSets[docSetId].docIds.filter(i => i !== documentId);
386
+
387
+ if (maybeRehashDocSet) {
388
+ this.rehashDocSet(docSetId);
389
+ }
390
+ } else if (maybeDeleteDocSet) {
391
+ this.deleteDocSet(docSetId);
392
+ }
393
+ return true;
394
+ }
395
+
396
+ rehashDocSet(docSetId) {
397
+ if (!(docSetId in this.docSets)) {
398
+ return false;
399
+ }
400
+
401
+ const docSet = this.docSets[docSetId];
402
+ return docSet.rehash();
403
+ }
404
+
405
+ addDocument(doc, docSetId) {
406
+ this.documents[doc.id] = doc;
407
+ this.docSets[docSetId].docIds.push(doc.id);
408
+ this.docSets[docSetId].buildEnumIndexes();
409
+ }
410
+
411
+ loadSuccinctDocSet(succinctOb) {
412
+ const succinctId = succinctOb.id;
413
+
414
+ if (succinctId in this.docSets) {
415
+ throw new Error(`Attempting to succinct load docSet ${succinctId} which is already loaded`);
416
+ }
417
+
418
+ const docSet = new DocSet(this, null, null, succinctOb);
419
+ const docSetId = docSet.id;
420
+ this.docSets[docSetId] = docSet;
421
+ let selectorTree = this.docSetsBySelector;
422
+ const selectors = succinctOb.metadata.selectors;
423
+
424
+ for (const selector of this.selectors) {
425
+ if (selector.name === this.selectors[this.selectors.length - 1].name) {
426
+ if (!(selectors[selector.name] in selectorTree)) {
427
+ selectorTree[selectors[selector.name]] = docSet;
428
+ this.docSets[docSet.id] = docSet;
429
+ }
430
+ } else {
431
+ if (!(selectors[selector.name] in selectorTree)) {
432
+ selectorTree[selectors[selector.name]] = {};
433
+ }
434
+ selectorTree = selectorTree[selectors[selector.name]];
435
+ }
436
+ }
437
+ docSet.buildPreEnums();
438
+ const docs = [];
439
+
440
+ for (const docId of Object.keys(succinctOb.docs)) {
441
+ let doc = this.newDocumentFromSuccinct(docId, succinctOb);
442
+ docs.push(doc);
443
+ }
444
+ docSet.preEnums = {};
445
+ return docs;
446
+ }
447
+
448
+ newDocumentFromSuccinct(docId, succinctOb) {
449
+ const doc = new Document(this, succinctOb.id);
450
+ doc.id = docId;
451
+ const succinctDocOb = succinctOb.docs[docId];
452
+ doc.filterOptions = {};
453
+ doc.customTags = [];
454
+ doc.emptyBlocks = [];
455
+ doc.tags = new Set(succinctDocOb.tags);
456
+ doc.headers = succinctDocOb.headers;
457
+ doc.mainId = succinctDocOb.mainId;
458
+ doc.sequences = {};
459
+
460
+ for (const [seqId, seq] of Object.entries(succinctDocOb.sequences)) {
461
+ doc.sequences[seqId] = {
462
+ id: seqId,
463
+ type: seq.type,
464
+ tags: new Set(seq.tags),
465
+ blocks: [],
466
+ };
467
+
468
+ if (seq.type === 'main') {
469
+ doc.sequences[seqId].chapters = {};
470
+
471
+ if (!('chapters' in seq)) {
472
+ throw new Error('chapters not found in main sequence');
473
+ }
474
+
475
+ for (const [chK, chV] of Object.entries(seq.chapters)) {
476
+ const bA = new utils.ByteArray();
477
+ bA.fromBase64(chV);
478
+ doc.sequences[seqId].chapters[chK] = bA;
479
+ }
480
+ doc.sequences[seqId].chapterVerses = {};
481
+
482
+ if (!('chapterVerses' in seq)) {
483
+ throw new Error('chapterVerses not found in main sequence');
484
+ }
485
+
486
+ for (const [chvK, chvV] of Object.entries(seq.chapterVerses)) {
487
+ const bA = new utils.ByteArray();
488
+ bA.fromBase64(chvV);
489
+ doc.sequences[seqId].chapterVerses[chvK] = bA;
490
+ }
491
+
492
+ if (!('tokensPresent' in seq)) {
493
+ throw new Error('tokensPresent not found in main sequence');
494
+ }
495
+
496
+ doc.sequences[seqId].tokensPresent = new BitSet(seq.tokensPresent);
497
+ }
498
+
499
+ for (const succinctBlock of seq.blocks) {
500
+ const block = {};
501
+
502
+ for (const [blockField, blockSuccinct] of Object.entries(succinctBlock)) {
503
+ const ba = new utils.ByteArray(256);
504
+ ba.fromBase64(blockSuccinct);
505
+ block[blockField] = ba;
506
+ }
507
+ doc.sequences[seqId].blocks.push(block);
508
+ }
509
+ }
510
+ this.addDocument(doc, succinctOb.id);
511
+ return doc;
512
+ }
513
+
514
+ findOrMakeDocSet(selectors) {
515
+ let selectorTree = this.docSetsBySelector;
516
+ let docSet;
517
+
518
+ for (const selector of this.selectors) {
519
+ if (selector.name === this.selectors[this.selectors.length - 1].name) {
520
+ if (selectors[selector.name] in selectorTree) {
521
+ docSet = selectorTree[selectors[selector.name]];
522
+ } else {
523
+ docSet = new DocSet(this, selectors);
524
+ selectorTree[selectors[selector.name]] = docSet;
525
+ this.docSets[docSet.id] = docSet;
526
+ }
527
+ } else {
528
+ if (!(selectors[selector.name] in selectorTree)) {
529
+ selectorTree[selectors[selector.name]] = {};
530
+ }
531
+ selectorTree = selectorTree[selectors[selector.name]];
532
+ }
533
+ }
534
+ return docSet.id;
535
+ }
536
+
537
+ async gqlQuery(query, callback) {
538
+ const release = await this.mutex.acquire();
539
+
540
+ try {
541
+ const result = await graphql({
542
+ schema: executableSchema, source: query, rootValue:this, contextValue:{},
543
+ });
544
+
545
+ if (callback) {
546
+ callback(result);
547
+ }
548
+ return result;
549
+ } finally {
550
+ release();
551
+ }
552
+ }
553
+
554
+ gqlQuerySync(query, callback) {
555
+ const result = graphqlSync({
556
+ schema: executableSchema, source: query, rootValue:this, contextValue:{},
557
+ });
558
+
559
+ if (callback) {
560
+ callback(result);
561
+ }
562
+ return result;
563
+ }
564
+
565
+ serializeSuccinct(docSetId) {
566
+ return this.docSets[docSetId].serializeSuccinct();
567
+ }
568
+
569
+ checksum() {
570
+ const dsChecksums = Object.values(this.docSets).map(ds => ds.checksum()).sort().join(' ');
571
+ return checksum(dsChecksums);
572
+ }
573
+ }
574
+
575
+ module.exports = {
576
+ Proskomma,
577
+ typeDefs,
578
+ resolvers,
579
+ lexingRegexes,
580
+ blocksSpecUtils,
581
+ tree2nodes,
582
+ utils,
583
+ };