@tinacms/datalayer 0.0.2 → 0.2.0

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/dist/index.js CHANGED
@@ -55,10 +55,22 @@ var __toModule = (module2) => {
55
55
  __export(exports, {
56
56
  AuditFileSystemBridge: () => AuditFileSystemBridge,
57
57
  AuditFilesystemStore: () => AuditFilesystemStore,
58
+ DEFAULT_COLLECTION_SORT_KEY: () => DEFAULT_COLLECTION_SORT_KEY,
59
+ DEFAULT_NUMERIC_LPAD: () => DEFAULT_NUMERIC_LPAD,
58
60
  FilesystemBridge: () => FilesystemBridge,
59
61
  FilesystemStore: () => FilesystemStore,
62
+ INDEX_KEY_FIELD_SEPARATOR: () => INDEX_KEY_FIELD_SEPARATOR,
63
+ IsomorphicBridge: () => IsomorphicBridge,
60
64
  LevelStore: () => LevelStore,
61
- MemoryStore: () => MemoryStore
65
+ OP: () => OP,
66
+ atob: () => atob,
67
+ btoa: () => btoa,
68
+ coerceFilterChainOperands: () => coerceFilterChainOperands,
69
+ makeFilter: () => makeFilter,
70
+ makeFilterChain: () => makeFilterChain,
71
+ makeFilterSuffixes: () => makeFilterSuffixes,
72
+ makeKeyForField: () => makeKeyForField,
73
+ makeStringEscaper: () => makeStringEscaper
62
74
  });
63
75
 
64
76
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/bridge/filesystem.ts
@@ -70,9 +82,9 @@ var FilesystemBridge = class {
70
82
  constructor(rootPath) {
71
83
  this.rootPath = rootPath || "";
72
84
  }
73
- async glob(pattern) {
85
+ async glob(pattern, extension) {
74
86
  const basePath = import_path.default.join(this.rootPath, ...pattern.split("/"));
75
- const items = await (0, import_fast_glob.default)(import_path.default.join(basePath, "**", "/*").replace(/\\/g, "/"), {
87
+ const items = await (0, import_fast_glob.default)(import_path.default.join(basePath, "**", `/*${extension}`).replace(/\\/g, "/"), {
76
88
  dot: true
77
89
  });
78
90
  const posixRootPath = (0, import_normalize_path.default)(this.rootPath);
@@ -83,6 +95,9 @@ var FilesystemBridge = class {
83
95
  supportsBuilding() {
84
96
  return true;
85
97
  }
98
+ async delete(filepath) {
99
+ await import_fs_extra.default.remove(import_path.default.join(this.rootPath, filepath));
100
+ }
86
101
  async get(filepath) {
87
102
  return import_fs_extra.default.readFileSync(import_path.default.join(this.rootPath, filepath)).toString();
88
103
  }
@@ -99,18 +114,335 @@ var AuditFileSystemBridge = class extends FilesystemBridge {
99
114
  }
100
115
  };
101
116
 
102
- // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/filesystem.ts
117
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/bridge/isomorphic.ts
118
+ var import_isomorphic_git = __toModule(require("isomorphic-git"));
103
119
  var import_fs_extra2 = __toModule(require("fs-extra"));
120
+ var import_glob_parent = __toModule(require("glob-parent"));
121
+ var import_normalize_path2 = __toModule(require("normalize-path"));
122
+ var import_graphql = __toModule(require("graphql"));
123
+ var flat = typeof Array.prototype.flat === "undefined" ? (entries) => entries.reduce((acc, x) => acc.concat(x), []) : (entries) => entries.flat();
124
+ var toUint8Array = (buf) => {
125
+ const ab = new ArrayBuffer(buf.length);
126
+ const view = new Uint8Array(ab);
127
+ for (let i = 0; i < buf.length; ++i) {
128
+ view[i] = buf[i];
129
+ }
130
+ return view;
131
+ };
132
+ var IsomorphicBridge = class {
133
+ constructor(rootPath, {
134
+ gitRoot,
135
+ author,
136
+ committer,
137
+ fsModule = import_fs_extra2.default,
138
+ commitMessage = "Update from GraphQL client",
139
+ ref,
140
+ onPut,
141
+ onDelete
142
+ }) {
143
+ this.cache = {};
144
+ this.rootPath = rootPath;
145
+ this.gitRoot = gitRoot;
146
+ this.relativePath = rootPath.slice(this.gitRoot.length).replace(/\\/g, "/");
147
+ if (this.relativePath.startsWith("/")) {
148
+ this.relativePath = this.relativePath.slice(1);
149
+ }
150
+ this.fsModule = fsModule;
151
+ this.author = author;
152
+ this.committer = committer || author;
153
+ this.isomorphicConfig = {
154
+ dir: (0, import_normalize_path2.default)(this.gitRoot),
155
+ fs: this.fsModule
156
+ };
157
+ this.ref = ref;
158
+ this.commitMessage = commitMessage;
159
+ this.onPut = onPut || (() => {
160
+ });
161
+ this.onDelete = onDelete || (() => {
162
+ });
163
+ }
164
+ getAuthor() {
165
+ return __spreadProps(__spreadValues({}, this.author), {
166
+ timestamp: Math.round(new Date().getTime() / 1e3),
167
+ timezoneOffset: 0
168
+ });
169
+ }
170
+ getCommitter() {
171
+ return __spreadProps(__spreadValues({}, this.committer), {
172
+ timestamp: Math.round(new Date().getTime() / 1e3),
173
+ timezoneOffset: 0
174
+ });
175
+ }
176
+ async listEntries({
177
+ pattern,
178
+ entry,
179
+ path: path4,
180
+ results
181
+ }) {
182
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
183
+ oid: entry.oid,
184
+ cache: this.cache
185
+ }));
186
+ const children = [];
187
+ for (const childEntry of treeResult.tree) {
188
+ const childPath = path4 ? `${path4}/${childEntry.path}` : childEntry.path;
189
+ if (childEntry.type === "tree") {
190
+ children.push(childEntry);
191
+ } else {
192
+ if (childPath.startsWith(pattern)) {
193
+ results.push(childPath);
194
+ }
195
+ }
196
+ }
197
+ for (const childEntry of children) {
198
+ const childPath = path4 ? `${path4}/${childEntry.path}` : childEntry.path;
199
+ await this.listEntries({
200
+ pattern,
201
+ entry: childEntry,
202
+ path: childPath,
203
+ results
204
+ });
205
+ }
206
+ }
207
+ async resolvePathEntries(path4, ref) {
208
+ let pathParts = path4.split("/");
209
+ const result = await import_isomorphic_git.default.walk(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
210
+ map: async (filepath, [head]) => {
211
+ if (head._fullpath === "." || path4.startsWith(filepath)) {
212
+ return head;
213
+ }
214
+ },
215
+ cache: this.cache,
216
+ trees: [import_isomorphic_git.default.TREE({ ref })]
217
+ }));
218
+ const pathEntries = flat(result);
219
+ if (pathParts.indexOf(".") === -1) {
220
+ pathParts = [".", ...pathParts];
221
+ }
222
+ while (pathParts.length > pathEntries.length) {
223
+ pathEntries.push(null);
224
+ }
225
+ return { pathParts, pathEntries };
226
+ }
227
+ async updateTreeHierarchy(existingOid, updatedOid, path4, type, pathEntries, pathParts) {
228
+ const lastIdx = pathEntries.length - 1;
229
+ const parentEntry = pathEntries[lastIdx];
230
+ const parentPath = pathParts[lastIdx];
231
+ let parentOid;
232
+ let tree;
233
+ const mode = type === "blob" ? "100644" : "040000";
234
+ if (parentEntry) {
235
+ parentOid = await parentEntry.oid();
236
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
237
+ oid: parentOid,
238
+ cache: this.cache
239
+ }));
240
+ tree = existingOid ? treeResult.tree.map((entry) => {
241
+ if (entry.path === path4) {
242
+ entry.oid = updatedOid;
243
+ }
244
+ return entry;
245
+ }) : [
246
+ ...treeResult.tree,
247
+ {
248
+ oid: updatedOid,
249
+ type,
250
+ path: path4,
251
+ mode
252
+ }
253
+ ];
254
+ } else {
255
+ tree = [
256
+ {
257
+ oid: updatedOid,
258
+ type,
259
+ path: path4,
260
+ mode
261
+ }
262
+ ];
263
+ }
264
+ const updatedParentOid = await import_isomorphic_git.default.writeTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
265
+ tree
266
+ }));
267
+ if (lastIdx === 0) {
268
+ return updatedParentOid;
269
+ } else {
270
+ return await this.updateTreeHierarchy(parentOid, updatedParentOid, parentPath, "tree", pathEntries.slice(0, lastIdx), pathParts.slice(0, lastIdx));
271
+ }
272
+ }
273
+ async commitTree(treeSha, ref) {
274
+ const commitSha = await import_isomorphic_git.default.writeCommit(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
275
+ commit: {
276
+ tree: treeSha,
277
+ parent: [
278
+ await import_isomorphic_git.default.resolveRef(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
279
+ ref
280
+ }))
281
+ ],
282
+ message: this.commitMessage,
283
+ author: this.getAuthor(),
284
+ committer: this.getCommitter()
285
+ }
286
+ }));
287
+ await import_isomorphic_git.default.writeRef(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
288
+ ref,
289
+ value: commitSha,
290
+ force: true
291
+ }));
292
+ }
293
+ async getRef() {
294
+ if (this.ref) {
295
+ return this.ref;
296
+ }
297
+ const ref = await import_isomorphic_git.default.currentBranch(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
298
+ fullname: true
299
+ }));
300
+ if (!ref) {
301
+ throw new import_graphql.GraphQLError(`Unable to determine current branch from HEAD`, null, null, null, null, null, {});
302
+ }
303
+ this.ref = ref;
304
+ return ref;
305
+ }
306
+ async glob(pattern, extension) {
307
+ const ref = await this.getRef();
308
+ const parent = (0, import_glob_parent.default)(this.qualifyPath(pattern));
309
+ const { pathParts, pathEntries } = await this.resolvePathEntries(parent, ref);
310
+ const leafEntry = pathEntries[pathEntries.length - 1];
311
+ const entryPath = pathParts[pathParts.length - 1];
312
+ const parentEntry = pathEntries[pathEntries.length - 2];
313
+ let treeEntry;
314
+ let parentPath;
315
+ if (parentEntry) {
316
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
317
+ oid: await parentEntry.oid(),
318
+ cache: this.cache
319
+ }));
320
+ treeEntry = treeResult.tree.find((entry) => entry.path === entryPath);
321
+ parentPath = pathParts.slice(1, pathParts.length).join("/");
322
+ } else {
323
+ treeEntry = {
324
+ type: "tree",
325
+ oid: await leafEntry.oid()
326
+ };
327
+ parentPath = "";
328
+ }
329
+ const results = [];
330
+ await this.listEntries({
331
+ pattern: this.qualifyPath(pattern),
332
+ entry: treeEntry,
333
+ path: parentPath,
334
+ results
335
+ });
336
+ return results.map((path4) => this.unqualifyPath(path4)).filter((path4) => path4.endsWith(extension));
337
+ }
338
+ supportsBuilding() {
339
+ return true;
340
+ }
341
+ async delete(filepath) {
342
+ const ref = await this.getRef();
343
+ const { pathParts, pathEntries } = await this.resolvePathEntries(this.qualifyPath(filepath), ref);
344
+ let oidToRemove;
345
+ let ptr = pathEntries.length - 1;
346
+ while (ptr >= 1) {
347
+ const leafEntry = pathEntries[ptr];
348
+ const nodePath = pathParts[ptr];
349
+ if (leafEntry) {
350
+ oidToRemove = oidToRemove || await leafEntry.oid();
351
+ const parentEntry = pathEntries[ptr - 1];
352
+ const existingOid = await parentEntry.oid();
353
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
354
+ oid: existingOid,
355
+ cache: this.cache
356
+ }));
357
+ const updatedTree = treeResult.tree.filter((value) => value.path !== nodePath);
358
+ if (updatedTree.length === 0) {
359
+ ptr -= 1;
360
+ continue;
361
+ }
362
+ const updatedTreeOid = await import_isomorphic_git.default.writeTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
363
+ tree: updatedTree
364
+ }));
365
+ const updatedRootTreeOid = await this.updateTreeHierarchy(existingOid, updatedTreeOid, pathParts[ptr - 1], "tree", pathEntries.slice(0, ptr - 1), pathParts.slice(0, ptr - 1));
366
+ await this.commitTree(updatedRootTreeOid, ref);
367
+ break;
368
+ } else {
369
+ throw new import_graphql.GraphQLError(`Unable to resolve path: ${filepath}`, null, null, null, null, null, { status: 404 });
370
+ }
371
+ }
372
+ if (oidToRemove) {
373
+ await import_isomorphic_git.default.updateIndex(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
374
+ filepath: this.qualifyPath(filepath),
375
+ force: true,
376
+ remove: true,
377
+ oid: oidToRemove,
378
+ cache: this.cache
379
+ }));
380
+ }
381
+ await this.onDelete(filepath);
382
+ }
383
+ qualifyPath(filepath) {
384
+ return this.relativePath ? `${this.relativePath}/${filepath}` : filepath;
385
+ }
386
+ unqualifyPath(filepath) {
387
+ return this.relativePath ? filepath.slice(this.relativePath.length + 1) : filepath;
388
+ }
389
+ async get(filepath) {
390
+ const ref = await this.getRef();
391
+ const oid = await import_isomorphic_git.default.resolveRef(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
392
+ ref
393
+ }));
394
+ const { blob } = await import_isomorphic_git.default.readBlob(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
395
+ oid,
396
+ filepath: this.qualifyPath(filepath),
397
+ cache: this.cache
398
+ }));
399
+ return Buffer.from(blob).toString("utf8");
400
+ }
401
+ async putConfig(filepath, data) {
402
+ await this.put(filepath, data);
403
+ }
404
+ async put(filepath, data) {
405
+ const ref = await this.getRef();
406
+ const { pathParts, pathEntries } = await this.resolvePathEntries(this.qualifyPath(filepath), ref);
407
+ const blobUpdate = toUint8Array(Buffer.from(data));
408
+ let existingOid;
409
+ const leafEntry = pathEntries[pathEntries.length - 1];
410
+ const nodePath = pathParts[pathParts.length - 1];
411
+ if (leafEntry) {
412
+ existingOid = await leafEntry.oid();
413
+ const hash = await import_isomorphic_git.default.hashBlob({ object: blobUpdate });
414
+ if (hash.oid === existingOid) {
415
+ await this.onPut(filepath, data);
416
+ return;
417
+ }
418
+ }
419
+ const updatedOid = await import_isomorphic_git.default.writeBlob(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
420
+ blob: blobUpdate
421
+ }));
422
+ const updatedRootSha = await this.updateTreeHierarchy(existingOid, updatedOid, nodePath, "blob", pathEntries.slice(0, pathEntries.length - 1), pathParts.slice(0, pathParts.length - 1));
423
+ await this.commitTree(updatedRootSha, ref);
424
+ await import_isomorphic_git.default.updateIndex(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
425
+ filepath: this.qualifyPath(filepath),
426
+ add: true,
427
+ oid: updatedOid,
428
+ cache: this.cache
429
+ }));
430
+ await this.onPut(filepath, data);
431
+ }
432
+ };
433
+
434
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/filesystem.ts
435
+ var import_fs_extra3 = __toModule(require("fs-extra"));
104
436
  var import_fast_glob2 = __toModule(require("fast-glob"));
105
437
  var import_path2 = __toModule(require("path"));
106
- var import_normalize_path2 = __toModule(require("normalize-path"));
438
+ var import_normalize_path3 = __toModule(require("normalize-path"));
107
439
 
108
440
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/util.ts
109
441
  var import_gray_matter = __toModule(require("gray-matter"));
110
442
 
111
443
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/util.ts
112
444
  var yup = __toModule(require("yup"));
113
- var import_graphql = __toModule(require("graphql"));
445
+ var import_graphql2 = __toModule(require("graphql"));
114
446
  var sequential = async (items, callback) => {
115
447
  const accum = [];
116
448
  if (!items) {
@@ -135,11 +467,17 @@ function assertShape(value, yupSchema, errorMessage) {
135
467
  shape.validateSync(value);
136
468
  } catch (e) {
137
469
  const message = errorMessage || `Failed to assertShape - ${e.message}`;
138
- throw new import_graphql.GraphQLError(message, null, null, null, null, null, {
470
+ throw new import_graphql2.GraphQLError(message, null, null, null, null, null, {
139
471
  stack: e.stack
140
472
  });
141
473
  }
142
474
  }
475
+ var atob = (b64Encoded) => {
476
+ return Buffer.from(b64Encoded, "base64").toString();
477
+ };
478
+ var btoa = (string) => {
479
+ return Buffer.from(string).toString("base64");
480
+ };
143
481
 
144
482
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/util.ts
145
483
  var stringifyFile = (content, format, keepTemplateKey) => {
@@ -205,14 +543,14 @@ var FilesystemStore = class {
205
543
  constructor({ rootPath }) {
206
544
  this.rootPath = rootPath || "";
207
545
  }
208
- async query(queryStrings) {
546
+ async query(_queryOptions) {
209
547
  throw new Error(`Unable to perform query for Filesystem store`);
210
548
  }
211
549
  async seed() {
212
550
  throw new Error(`Seeding data is not possible for Filesystem store`);
213
551
  }
214
552
  async get(filepath) {
215
- return parseFile(await import_fs_extra2.default.readFileSync(import_path2.default.join(this.rootPath, filepath)).toString(), import_path2.default.extname(filepath), (yup2) => yup2.object());
553
+ return parseFile(await import_fs_extra3.default.readFileSync(import_path2.default.join(this.rootPath, filepath)).toString(), import_path2.default.extname(filepath), (yup2) => yup2.object());
216
554
  }
217
555
  supportsSeeding() {
218
556
  return false;
@@ -220,12 +558,12 @@ var FilesystemStore = class {
220
558
  supportsIndexing() {
221
559
  return false;
222
560
  }
223
- async glob(pattern, callback) {
561
+ async glob(pattern, callback, extension) {
224
562
  const basePath = import_path2.default.join(this.rootPath, ...pattern.split("/"));
225
- const itemsRaw = await (0, import_fast_glob2.default)(import_path2.default.join(basePath, "**", "/*").replace(/\\/g, "/"), {
563
+ const itemsRaw = await (0, import_fast_glob2.default)(import_path2.default.join(basePath, "**", `/*${extension}`).replace(/\\/g, "/"), {
226
564
  dot: true
227
565
  });
228
- const posixRootPath = (0, import_normalize_path2.default)(this.rootPath);
566
+ const posixRootPath = (0, import_normalize_path3.default)(this.rootPath);
229
567
  const items = itemsRaw.map((item) => {
230
568
  return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
231
569
  });
@@ -237,8 +575,15 @@ var FilesystemStore = class {
237
575
  return items;
238
576
  }
239
577
  }
240
- async put(filepath, data, keepTemplateKey) {
241
- await import_fs_extra2.default.outputFileSync(import_path2.default.join(this.rootPath, filepath), stringifyFile(data, import_path2.default.extname(filepath), keepTemplateKey));
578
+ async put(filepath, data, options) {
579
+ await import_fs_extra3.default.outputFileSync(import_path2.default.join(this.rootPath, filepath), stringifyFile(data, import_path2.default.extname(filepath), options.keepTemplateKey));
580
+ }
581
+ async open() {
582
+ }
583
+ async close() {
584
+ }
585
+ async delete(filepath) {
586
+ await import_fs_extra3.default.remove(import_path2.default.join(this.rootPath, filepath));
242
587
  }
243
588
  };
244
589
  var AuditFilesystemStore = class extends FilesystemStore {
@@ -247,71 +592,346 @@ var AuditFilesystemStore = class extends FilesystemStore {
247
592
  }
248
593
  };
249
594
 
250
- // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/memory.ts
251
- var MemoryStore = class {
252
- constructor(rootPath, object = {}) {
253
- this.map = object;
254
- this.rootPath = rootPath || "";
255
- this.db = {
256
- get: async (filepath) => {
257
- return this.map[filepath];
258
- },
259
- put: async (filepath, content) => {
260
- this.map[filepath] = content;
261
- await this.print();
262
- }
263
- };
264
- }
265
- async query(queryStrings, hydrator) {
266
- const resultSets = await sequential(queryStrings, async (queryString) => {
267
- const res = await this.get(queryString);
268
- return res || [];
269
- });
270
- let items = [];
271
- if (resultSets.length > 0) {
272
- items = resultSets.reduce((p, c) => p.filter((e) => c.includes(e)));
273
- }
274
- return sequential(items, async (documentString) => {
275
- return hydrator(documentString);
276
- });
277
- }
278
- async seed(filepath, data) {
279
- await this.put(filepath, data);
280
- }
281
- supportsSeeding() {
282
- return true;
283
- }
284
- supportsIndexing() {
285
- return true;
595
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/index.ts
596
+ var import_jsonpath_plus = __toModule(require("jsonpath-plus"));
597
+ var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
598
+ var INDEX_KEY_FIELD_SEPARATOR = "#";
599
+ var DEFAULT_NUMERIC_LPAD = 4;
600
+ var OP;
601
+ (function(OP2) {
602
+ OP2["EQ"] = "eq";
603
+ OP2["GT"] = "gt";
604
+ OP2["LT"] = "lt";
605
+ OP2["GTE"] = "gte";
606
+ OP2["LTE"] = "lte";
607
+ OP2["STARTS_WITH"] = "startsWith";
608
+ OP2["IN"] = "in";
609
+ })(OP || (OP = {}));
610
+ var inferOperatorFromFilter = (filterOperator) => {
611
+ switch (filterOperator) {
612
+ case "after":
613
+ return OP.GT;
614
+ case "before":
615
+ return OP.LT;
616
+ case "eq":
617
+ return OP.EQ;
618
+ case "startsWith":
619
+ return OP.STARTS_WITH;
620
+ case "lt":
621
+ return OP.LT;
622
+ case "lte":
623
+ return OP.LTE;
624
+ case "gt":
625
+ return OP.GT;
626
+ case "gte":
627
+ return OP.GTE;
628
+ case "in":
629
+ return OP.IN;
630
+ default:
631
+ throw new Error(`unsupported filter condition: '${filterOperator}'`);
286
632
  }
287
- async print() {
633
+ };
634
+ var getFilterOperator = (expression, operand) => {
635
+ return (expression[operand] || expression[operand] === 0) && operand;
636
+ };
637
+ var makeFilterChain = ({
638
+ conditions
639
+ }) => {
640
+ const filterChain = [];
641
+ if (!conditions) {
642
+ return filterChain;
288
643
  }
289
- async clear() {
290
- this.map = {};
644
+ for (const condition of conditions) {
645
+ const { filterPath, filterExpression } = condition;
646
+ const _a = filterExpression, { _type } = _a, keys = __objRest(_a, ["_type"]);
647
+ const [key1, key2, ...extraKeys] = Object.keys(keys);
648
+ if (extraKeys.length) {
649
+ throw new Error(`Unexpected keys: [${extraKeys.join(",")}] in filter expression`);
650
+ }
651
+ if (key1 && !key2) {
652
+ filterChain.push({
653
+ pathExpression: filterPath,
654
+ rightOperand: filterExpression[key1],
655
+ operator: inferOperatorFromFilter(key1),
656
+ type: _type,
657
+ pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
658
+ });
659
+ } else if (key1 && key2) {
660
+ const leftFilterOperator = getFilterOperator(filterExpression, "gt") || getFilterOperator(filterExpression, "gte") || getFilterOperator(filterExpression, "after") || void 0;
661
+ const rightFilterOperator = getFilterOperator(filterExpression, "lt") || getFilterOperator(filterExpression, "lte") || getFilterOperator(filterExpression, "before") || void 0;
662
+ let leftOperand;
663
+ let rightOperand;
664
+ if (rightFilterOperator && leftFilterOperator) {
665
+ if (key1 === leftFilterOperator) {
666
+ leftOperand = filterExpression[key1];
667
+ rightOperand = filterExpression[key2];
668
+ } else {
669
+ rightOperand = filterExpression[key1];
670
+ leftOperand = filterExpression[key2];
671
+ }
672
+ filterChain.push({
673
+ pathExpression: filterPath,
674
+ rightOperand,
675
+ leftOperand,
676
+ leftOperator: inferOperatorFromFilter(leftFilterOperator),
677
+ rightOperator: inferOperatorFromFilter(rightFilterOperator),
678
+ type: _type,
679
+ pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
680
+ });
681
+ } else {
682
+ throw new Error(`Filter on field '${filterPath}' has invalid combination of conditions: '${key1}, ${key2}'`);
683
+ }
684
+ }
291
685
  }
292
- async glob(pattern, callback) {
293
- const strings = Object.keys(this.map).filter((key) => {
294
- if (key.startsWith(pattern)) {
295
- return true;
686
+ return filterChain;
687
+ };
688
+ var makeFilter = ({
689
+ filterChain
690
+ }) => {
691
+ return (values) => {
692
+ for (const filter of filterChain) {
693
+ const dataType = filter.type;
694
+ const resolvedValues = (0, import_jsonpath_plus.JSONPath)({
695
+ path: filter.pathExpression,
696
+ json: values
697
+ });
698
+ if (!resolvedValues || !resolvedValues.length) {
699
+ return false;
700
+ }
701
+ let operands;
702
+ if (dataType === "string" || dataType === "reference") {
703
+ operands = resolvedValues;
704
+ } else if (dataType === "number") {
705
+ operands = resolvedValues.map((resolvedValue) => Number(resolvedValue));
706
+ } else if (dataType === "datetime") {
707
+ operands = resolvedValues.map((resolvedValue) => {
708
+ const coerced = new Date(resolvedValue).getTime();
709
+ return isNaN(coerced) ? Number(resolvedValue) : coerced;
710
+ });
711
+ } else if (dataType === "boolean") {
712
+ operands = resolvedValues.map((resolvedValue) => typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1");
296
713
  } else {
714
+ throw new Error(`Unexpected datatype ${dataType}`);
715
+ }
716
+ const { operator } = filter;
717
+ let matches = false;
718
+ if (operator) {
719
+ switch (operator) {
720
+ case OP.EQ:
721
+ if (operands.findIndex((operand) => operand === filter.rightOperand) >= 0) {
722
+ matches = true;
723
+ }
724
+ break;
725
+ case OP.GT:
726
+ for (const operand of operands) {
727
+ if (operand > filter.rightOperand) {
728
+ matches = true;
729
+ break;
730
+ }
731
+ }
732
+ break;
733
+ case OP.LT:
734
+ for (const operand of operands) {
735
+ if (operand < filter.rightOperand) {
736
+ matches = true;
737
+ break;
738
+ }
739
+ }
740
+ break;
741
+ case OP.GTE:
742
+ for (const operand of operands) {
743
+ if (operand >= filter.rightOperand) {
744
+ matches = true;
745
+ break;
746
+ }
747
+ }
748
+ break;
749
+ case OP.LTE:
750
+ for (const operand of operands) {
751
+ if (operand <= filter.rightOperand) {
752
+ matches = true;
753
+ break;
754
+ }
755
+ }
756
+ break;
757
+ case OP.IN:
758
+ for (const operand of operands) {
759
+ if (filter.rightOperand.indexOf(operand) >= 0) {
760
+ matches = true;
761
+ break;
762
+ }
763
+ }
764
+ break;
765
+ case OP.STARTS_WITH:
766
+ for (const operand of operands) {
767
+ if (operand.startsWith(filter.rightOperand)) {
768
+ matches = true;
769
+ break;
770
+ }
771
+ }
772
+ break;
773
+ default:
774
+ throw new Error(`unexpected operator ${operator}`);
775
+ }
776
+ } else {
777
+ const { rightOperator, leftOperator, rightOperand, leftOperand } = filter;
778
+ for (const operand of operands) {
779
+ let rightMatches = false;
780
+ let leftMatches = false;
781
+ if (rightOperator === OP.LTE && operand <= rightOperand) {
782
+ rightMatches = true;
783
+ } else if (rightOperator === OP.LT && operand < rightOperand) {
784
+ rightMatches = true;
785
+ }
786
+ if (leftOperator === OP.GTE && operand >= leftOperand) {
787
+ leftMatches = true;
788
+ } else if (leftOperator === OP.GT && operand > leftOperand) {
789
+ leftMatches = true;
790
+ }
791
+ if (rightMatches && leftMatches) {
792
+ matches = true;
793
+ break;
794
+ }
795
+ }
796
+ }
797
+ if (!matches) {
297
798
  return false;
298
799
  }
299
- });
300
- if (callback) {
301
- return sequential(strings, async (item) => {
302
- return callback(item);
303
- });
800
+ }
801
+ return true;
802
+ };
803
+ };
804
+ var makeStringEscaper = (regex, replacement) => {
805
+ return (input) => {
806
+ if (Array.isArray(input)) {
807
+ return input.map((val) => val.replace(regex, replacement));
304
808
  } else {
305
- return strings;
809
+ return input.replace(regex, replacement);
810
+ }
811
+ };
812
+ };
813
+ var applyPadding = (input, pad) => {
814
+ if (pad) {
815
+ if (Array.isArray(input)) {
816
+ return input.map((val) => String(val).padStart(pad.maxLength, pad.fillString));
817
+ } else {
818
+ return String(input).padStart(pad.maxLength, pad.fillString);
306
819
  }
307
820
  }
308
- async get(filepath) {
309
- const content = await this.db.get(filepath);
310
- return content;
821
+ return input;
822
+ };
823
+ var coerceFilterChainOperands = (filterChain, stringEscaper) => {
824
+ const result = [];
825
+ if (filterChain.length) {
826
+ for (const filter of filterChain) {
827
+ const dataType = filter.type;
828
+ if (dataType === "datetime") {
829
+ if (filter.leftOperand !== void 0) {
830
+ result.push(__spreadProps(__spreadValues({}, filter), {
831
+ rightOperand: new Date(filter.rightOperand).getTime(),
832
+ leftOperand: new Date(filter.leftOperand).getTime()
833
+ }));
834
+ } else {
835
+ if (Array.isArray(filter.rightOperand)) {
836
+ result.push(__spreadProps(__spreadValues({}, filter), {
837
+ rightOperand: filter.rightOperand.map((operand) => new Date(operand).getTime())
838
+ }));
839
+ } else {
840
+ result.push(__spreadProps(__spreadValues({}, filter), {
841
+ rightOperand: new Date(filter.rightOperand).getTime()
842
+ }));
843
+ }
844
+ }
845
+ } else if (dataType === "string") {
846
+ if (filter.leftOperand !== void 0) {
847
+ result.push(__spreadProps(__spreadValues({}, filter), {
848
+ rightOperand: applyPadding(stringEscaper(filter.rightOperand), filter.pad),
849
+ leftOperand: applyPadding(stringEscaper(filter.leftOperand), filter.pad)
850
+ }));
851
+ } else {
852
+ result.push(__spreadProps(__spreadValues({}, filter), {
853
+ rightOperand: applyPadding(stringEscaper(filter.rightOperand), filter.pad)
854
+ }));
855
+ }
856
+ } else {
857
+ result.push(__spreadValues({}, filter));
858
+ }
859
+ }
311
860
  }
312
- async put(filepath, data) {
313
- await this.db.put(filepath, data);
861
+ return result;
862
+ };
863
+ var makeFilterSuffixes = (filterChain, index) => {
864
+ if (filterChain && filterChain.length) {
865
+ const indexFields = index.fields.map((field) => field.name);
866
+ const orderedFilterChain = [];
867
+ for (const filter of filterChain) {
868
+ const idx = indexFields.indexOf(filter.pathExpression);
869
+ if (idx === -1) {
870
+ return;
871
+ }
872
+ if (filter.operator && filter.operator === OP.IN) {
873
+ return;
874
+ }
875
+ orderedFilterChain[idx] = filter;
876
+ }
877
+ const baseFragments = [];
878
+ let rightSuffix;
879
+ let leftSuffix;
880
+ let ternaryFilter = false;
881
+ if (orderedFilterChain[filterChain.length - 1] && !orderedFilterChain[filterChain.length - 1].operator) {
882
+ ternaryFilter = true;
883
+ }
884
+ for (let i = 0; i < orderedFilterChain.length; i++) {
885
+ const filter = orderedFilterChain[i];
886
+ if (!filter) {
887
+ return;
888
+ }
889
+ if (Number(i) < indexFields.length - 1) {
890
+ if (!filter.operator) {
891
+ return;
892
+ }
893
+ const binaryFilter = filter;
894
+ if (binaryFilter.operator !== OP.EQ) {
895
+ return;
896
+ }
897
+ baseFragments.push(applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad));
898
+ } else {
899
+ if (ternaryFilter) {
900
+ leftSuffix = applyPadding(orderedFilterChain[i].leftOperand, orderedFilterChain[i].pad);
901
+ rightSuffix = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
902
+ } else {
903
+ const op = orderedFilterChain[i].operator;
904
+ const operand = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
905
+ if (op === OP.LT || op === OP.LTE) {
906
+ rightSuffix = operand;
907
+ } else if (op === OP.GT || op === OP.GTE) {
908
+ leftSuffix = operand;
909
+ } else {
910
+ rightSuffix = operand;
911
+ leftSuffix = operand;
912
+ }
913
+ }
914
+ }
915
+ }
916
+ return {
917
+ left: leftSuffix && [...baseFragments, leftSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0,
918
+ right: rightSuffix && [...baseFragments, rightSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0
919
+ };
920
+ } else {
921
+ return {};
922
+ }
923
+ };
924
+ var makeKeyForField = (definition, data, stringEscaper) => {
925
+ const valueParts = [];
926
+ for (const field of definition.fields) {
927
+ if (field.name in data) {
928
+ const resolvedValue = String(field.type === "datetime" ? new Date(data[field.name]).getTime() : field.type === "string" ? stringEscaper(data[field.name]) : data[field.name]);
929
+ valueParts.push(applyPadding(resolvedValue, field.pad));
930
+ } else {
931
+ return null;
932
+ }
314
933
  }
934
+ return valueParts.join(INDEX_KEY_FIELD_SEPARATOR);
315
935
  };
316
936
 
317
937
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/level.ts
@@ -320,47 +940,89 @@ var import_level = __toModule(require("level"));
320
940
  var import_levelup = __toModule(require("levelup"));
321
941
  var import_memdown = __toModule(require("memdown"));
322
942
  var import_encoding_down = __toModule(require("encoding-down"));
943
+ var defaultPrefix = "_ROOT_";
944
+ var escapeStr = makeStringEscaper(new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"), encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR));
323
945
  var LevelStore = class {
324
946
  constructor(rootPath, useMemory = false) {
325
947
  this.rootPath = rootPath || "";
948
+ this.useMemory = useMemory;
326
949
  if (useMemory) {
327
- const db = (0, import_levelup.default)((0, import_encoding_down.default)((0, import_memdown.default)(), { valueEncoding: "json" }));
328
- this.db = db;
950
+ this.db = (0, import_levelup.default)((0, import_encoding_down.default)((0, import_memdown.default)(), { valueEncoding: "json" }));
329
951
  } else {
330
- const db = (0, import_level.default)(import_path3.default.join(rootPath, ".tina/__generated__/db"), {
952
+ this.db = (0, import_level.default)(import_path3.default.join(rootPath, ".tina/__generated__/db"), {
331
953
  valueEncoding: "json"
332
954
  });
333
- this.db = db;
334
- }
335
- }
336
- async query(queryStrings, hydrator) {
337
- const resultSets = await sequential(queryStrings, async (queryString) => {
338
- let strings = [];
339
- const p = new Promise((resolve, reject) => {
340
- this.db.createReadStream({
341
- gte: queryString,
342
- lte: queryString + "\xFF"
343
- }).on("data", (data) => {
344
- strings = [...strings, ...data.value];
345
- }).on("error", (message) => {
346
- reject(message);
347
- }).on("end", function() {
348
- resolve();
349
- });
350
- });
351
- await p;
352
- return strings || [];
353
- });
354
- let items = [];
355
- if (resultSets.length > 0) {
356
- items = resultSets.reduce((p, c) => p.filter((e) => c.includes(e)));
357
955
  }
358
- return sequential(items, async (documentString) => {
359
- return hydrator(documentString);
360
- });
361
956
  }
362
- async seed(filepath, data) {
363
- await this.put(filepath, data);
957
+ async query(queryOptions) {
958
+ var _b;
959
+ const _a = queryOptions, {
960
+ filterChain: rawFilterChain,
961
+ sort = DEFAULT_COLLECTION_SORT_KEY,
962
+ collection,
963
+ indexDefinitions,
964
+ limit = 10
965
+ } = _a, query = __objRest(_a, [
966
+ "filterChain",
967
+ "sort",
968
+ "collection",
969
+ "indexDefinitions",
970
+ "limit"
971
+ ]);
972
+ const filterChain = coerceFilterChainOperands(rawFilterChain, escapeStr);
973
+ const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
974
+ const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
975
+ const indexPrefix = indexDefinition ? `${collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}` : `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}`;
976
+ if (!query.gt && !query.gte) {
977
+ query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? `${indexPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filterSuffixes.left}` : indexPrefix;
978
+ }
979
+ if (!query.lt && !query.lte) {
980
+ query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${indexPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filterSuffixes.right}\xFF` : `${indexPrefix}\xFF`;
981
+ }
982
+ let edges = [];
983
+ let startKey = "";
984
+ let endKey = "";
985
+ let hasPreviousPage = false;
986
+ let hasNextPage = false;
987
+ const fieldsPattern = ((_b = indexDefinition == null ? void 0 : indexDefinition.fields) == null ? void 0 : _b.length) ? `${indexDefinition.fields.map((p) => `${INDEX_KEY_FIELD_SEPARATOR}(?<${p.name}>.+)`).join("")}${INDEX_KEY_FIELD_SEPARATOR}` : INDEX_KEY_FIELD_SEPARATOR;
988
+ const valuesRegex = indexDefinition ? new RegExp(`^${indexPrefix}${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^${indexPrefix}(?<_filepath_>.+)`);
989
+ const itemFilter = makeFilter({ filterChain });
990
+ for await (const [key, value] of this.db.iterator(query)) {
991
+ const matcher = valuesRegex.exec(key);
992
+ if (!matcher || indexDefinition && matcher.length !== indexDefinition.fields.length + 2) {
993
+ continue;
994
+ }
995
+ const filepath = matcher.groups["_filepath_"];
996
+ if (!itemFilter(filterSuffixes ? matcher.groups : indexDefinition ? await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`) : value)) {
997
+ continue;
998
+ }
999
+ if (limit !== -1 && edges.length >= limit) {
1000
+ if (query.reverse) {
1001
+ hasPreviousPage = true;
1002
+ } else {
1003
+ hasNextPage = true;
1004
+ }
1005
+ break;
1006
+ }
1007
+ startKey = startKey || key || "";
1008
+ endKey = key || "";
1009
+ edges = [...edges, { cursor: key, path: filepath }];
1010
+ }
1011
+ return {
1012
+ edges,
1013
+ pageInfo: {
1014
+ hasPreviousPage,
1015
+ hasNextPage,
1016
+ startCursor: startKey,
1017
+ endCursor: endKey
1018
+ }
1019
+ };
1020
+ }
1021
+ async seed(filepath, data, options) {
1022
+ await this.put(filepath, data, __spreadValues({
1023
+ keepTemplateKey: false,
1024
+ seed: true
1025
+ }, options));
364
1026
  }
365
1027
  supportsSeeding() {
366
1028
  return true;
@@ -368,6 +1030,27 @@ var LevelStore = class {
368
1030
  supportsIndexing() {
369
1031
  return true;
370
1032
  }
1033
+ async delete(filepath, options) {
1034
+ const data = await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`);
1035
+ if (!data) {
1036
+ return;
1037
+ }
1038
+ if (options == null ? void 0 : options.indexDefinitions) {
1039
+ for (const [sort, definition] of Object.entries(options.indexDefinitions)) {
1040
+ const indexedValue = makeKeyForField(definition, data, escapeStr);
1041
+ let indexKey;
1042
+ if (sort === DEFAULT_COLLECTION_SORT_KEY) {
1043
+ indexKey = `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`;
1044
+ } else {
1045
+ indexKey = indexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${indexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
1046
+ }
1047
+ if (indexKey) {
1048
+ await this.db.del(indexKey);
1049
+ }
1050
+ }
1051
+ }
1052
+ await this.db.del(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`);
1053
+ }
371
1054
  async print() {
372
1055
  this.db.createReadStream().on("data", function(data) {
373
1056
  console.log(data.key, "=", data.value);
@@ -389,10 +1072,10 @@ var LevelStore = class {
389
1072
  const strings = [];
390
1073
  const p = new Promise((resolve, reject) => {
391
1074
  this.db.createKeyStream({
392
- gte: pattern,
393
- lte: pattern + "\xFF"
1075
+ gte: `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${pattern}`,
1076
+ lte: `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${pattern}\xFF`
394
1077
  }).on("data", (data) => {
395
- strings.push(data);
1078
+ strings.push(data.split(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}`)[1]);
396
1079
  }).on("error", (message) => {
397
1080
  reject(message);
398
1081
  }).on("end", function() {
@@ -410,22 +1093,65 @@ var LevelStore = class {
410
1093
  }
411
1094
  async get(filepath) {
412
1095
  try {
413
- const content = await this.db.get(filepath);
414
- return content;
1096
+ return await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`);
415
1097
  } catch (e) {
416
1098
  return void 0;
417
1099
  }
418
1100
  }
419
- async put(filepath, data) {
420
- await this.db.put(filepath, data);
1101
+ async close() {
1102
+ await this.db.close();
1103
+ }
1104
+ async put(filepath, data, options) {
1105
+ let existingData;
1106
+ try {
1107
+ existingData = options && !options.seed ? await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`) : null;
1108
+ } catch (err) {
1109
+ if (!err.notFound) {
1110
+ throw err;
1111
+ }
1112
+ }
1113
+ await this.db.put(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`, data);
1114
+ if (options == null ? void 0 : options.indexDefinitions) {
1115
+ for (const [sort, definition] of Object.entries(options.indexDefinitions)) {
1116
+ const indexedValue = makeKeyForField(definition, data, escapeStr);
1117
+ const existingIndexedValue = existingData ? makeKeyForField(definition, existingData, escapeStr) : null;
1118
+ let indexKey;
1119
+ let existingIndexKey = null;
1120
+ if (sort === DEFAULT_COLLECTION_SORT_KEY) {
1121
+ indexKey = `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`;
1122
+ existingIndexKey = indexKey;
1123
+ } else {
1124
+ indexKey = indexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${indexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
1125
+ existingIndexKey = existingIndexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${existingIndexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
1126
+ }
1127
+ if (indexKey) {
1128
+ if (existingIndexKey && indexKey != existingIndexKey) {
1129
+ await this.db.del(existingIndexKey);
1130
+ }
1131
+ await this.db.put(indexKey, "");
1132
+ }
1133
+ }
1134
+ }
421
1135
  }
422
1136
  };
423
1137
  // Annotate the CommonJS export names for ESM import in node:
424
1138
  0 && (module.exports = {
425
1139
  AuditFileSystemBridge,
426
1140
  AuditFilesystemStore,
1141
+ DEFAULT_COLLECTION_SORT_KEY,
1142
+ DEFAULT_NUMERIC_LPAD,
427
1143
  FilesystemBridge,
428
1144
  FilesystemStore,
1145
+ INDEX_KEY_FIELD_SEPARATOR,
1146
+ IsomorphicBridge,
429
1147
  LevelStore,
430
- MemoryStore
1148
+ OP,
1149
+ atob,
1150
+ btoa,
1151
+ coerceFilterChainOperands,
1152
+ makeFilter,
1153
+ makeFilterChain,
1154
+ makeFilterSuffixes,
1155
+ makeKeyForField,
1156
+ makeStringEscaper
431
1157
  });