@tinacms/datalayer 0.0.0 → 0.1.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
@@ -51,112 +51,77 @@ var __toModule = (module2) => {
51
51
  return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
52
52
  };
53
53
 
54
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/index.ts
54
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/index.ts
55
55
  __export(exports, {
56
+ AuditFileSystemBridge: () => AuditFileSystemBridge,
57
+ AuditFilesystemStore: () => AuditFilesystemStore,
58
+ DEFAULT_COLLECTION_SORT_KEY: () => DEFAULT_COLLECTION_SORT_KEY,
59
+ DEFAULT_NUMERIC_LPAD: () => DEFAULT_NUMERIC_LPAD,
56
60
  FilesystemBridge: () => FilesystemBridge,
57
61
  FilesystemStore: () => FilesystemStore,
58
- GithubBridge: () => GithubBridge,
59
- GithubStore: () => GithubStore,
62
+ INDEX_KEY_FIELD_SEPARATOR: () => INDEX_KEY_FIELD_SEPARATOR,
60
63
  LevelStore: () => LevelStore,
61
- MemoryStore: () => MemoryStore
64
+ OP: () => OP,
65
+ atob: () => atob,
66
+ btoa: () => btoa,
67
+ coerceFilterChainOperands: () => coerceFilterChainOperands,
68
+ makeFilter: () => makeFilter,
69
+ makeFilterChain: () => makeFilterChain,
70
+ makeFilterSuffixes: () => makeFilterSuffixes,
71
+ makeKeyForField: () => makeKeyForField,
72
+ makeStringEscaper: () => makeStringEscaper
62
73
  });
63
74
 
64
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/bridge/github.ts
65
- var import_lodash = __toModule(require("lodash"));
75
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/bridge/filesystem.ts
76
+ var import_fs_extra = __toModule(require("fs-extra"));
77
+ var import_fast_glob = __toModule(require("fast-glob"));
66
78
  var import_path = __toModule(require("path"));
67
- var import_rest = __toModule(require("@octokit/rest"));
68
- var import_graphql = __toModule(require("graphql"));
69
- var GithubBridge = class {
70
- constructor({ rootPath, accessToken, owner, repo, ref }) {
71
- this.rootPath = rootPath;
72
- this.repoConfig = {
73
- owner,
74
- repo,
75
- ref
76
- };
77
- this.appOctoKit = new import_rest.Octokit({
78
- auth: accessToken
79
- });
79
+ var import_normalize_path = __toModule(require("normalize-path"));
80
+ var FilesystemBridge = class {
81
+ constructor(rootPath) {
82
+ this.rootPath = rootPath || "";
80
83
  }
81
- async readDir(filepath) {
82
- const fullPath = import_path.default.join(this.rootPath, filepath);
83
- const repos = await this.appOctoKit.repos.getContent(__spreadProps(__spreadValues({}, this.repoConfig), {
84
- path: fullPath
85
- })).then(async (response) => {
86
- if (Array.isArray(response.data)) {
87
- return await Promise.all(await response.data.map(async (d) => {
88
- if (d.type === "dir") {
89
- const nestedItems = await this.readDir(d.path);
90
- if (Array.isArray(nestedItems)) {
91
- return nestedItems.map((nestedItem) => {
92
- return import_path.default.join(d.path, nestedItem);
93
- });
94
- } else {
95
- throw new Error(`Expected items to be an array of strings for readDir at ${d.path}`);
96
- }
97
- }
98
- return d.path;
99
- }));
100
- }
101
- throw new Error(`Expected to return an array from Github directory ${import_path.default}`);
84
+ async glob(pattern) {
85
+ const basePath = import_path.default.join(this.rootPath, ...pattern.split("/"));
86
+ const items = await (0, import_fast_glob.default)(import_path.default.join(basePath, "**", "/*").replace(/\\/g, "/"), {
87
+ dot: true
88
+ });
89
+ const posixRootPath = (0, import_normalize_path.default)(this.rootPath);
90
+ return items.map((item) => {
91
+ return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
102
92
  });
103
- return import_lodash.default.flatten(repos);
104
93
  }
105
94
  supportsBuilding() {
106
- return false;
107
- }
108
- async glob(pattern) {
109
- const results = await this.readDir(pattern);
110
- return results.map((item) => item.replace(this.rootPath, "").replace(/^\/|\/$/g, ""));
95
+ return true;
111
96
  }
112
97
  async get(filepath) {
113
- const realpath = import_path.default.join(this.rootPath, filepath);
114
- return this.appOctoKit.repos.getContent(__spreadProps(__spreadValues({}, this.repoConfig), {
115
- path: realpath
116
- })).then((response) => {
117
- return Buffer.from(response.data.content, "base64").toString();
118
- }).catch((e) => {
119
- if (e.status === 401) {
120
- throw new import_graphql.GraphQLError(`Unauthorized request to Github Repository: '${this.repoConfig.owner}/${this.repoConfig.repo}', please ensure your access token is valid.`, null, null, null, null, e, { status: e.status });
121
- }
122
- throw new import_graphql.GraphQLError(`Unable to find record '${filepath}' in Github Repository: '${this.repoConfig.owner}/${this.repoConfig.repo}', Ref: '${this.repoConfig.ref}'`, null, null, null, null, e, { status: e.status });
123
- });
98
+ return import_fs_extra.default.readFileSync(import_path.default.join(this.rootPath, filepath)).toString();
124
99
  }
125
100
  async putConfig(filepath, data) {
126
- throw new Error(`Config files cannot be changed by the Github bridge`);
101
+ await this.put(filepath, data);
127
102
  }
128
103
  async put(filepath, data) {
129
- const realpath = import_path.default.join(this.rootPath, filepath);
130
- let fileSha = void 0;
131
- try {
132
- const fileContent = await this.appOctoKit.repos.getContent(__spreadProps(__spreadValues({}, this.repoConfig), {
133
- path: realpath
134
- }));
135
- fileSha = fileContent.data.sha;
136
- } catch (e) {
137
- console.log("No file exists, creating new one");
138
- }
139
- await this.appOctoKit.repos.createOrUpdateFileContents(__spreadProps(__spreadValues({}, this.repoConfig), {
140
- branch: this.repoConfig.ref,
141
- path: realpath,
142
- message: "Update from GraphQL client",
143
- content: new Buffer(data).toString("base64"),
144
- sha: fileSha
145
- }));
104
+ await import_fs_extra.default.outputFileSync(import_path.default.join(this.rootPath, filepath), data);
105
+ }
106
+ };
107
+ var AuditFileSystemBridge = class extends FilesystemBridge {
108
+ async put(_filepath, _data) {
109
+ return;
146
110
  }
147
111
  };
148
112
 
149
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/store/github.ts
150
- var import_lodash2 = __toModule(require("lodash"));
113
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/filesystem.ts
114
+ var import_fs_extra2 = __toModule(require("fs-extra"));
115
+ var import_fast_glob2 = __toModule(require("fast-glob"));
151
116
  var import_path2 = __toModule(require("path"));
152
- var import_rest2 = __toModule(require("@octokit/rest"));
117
+ var import_normalize_path2 = __toModule(require("normalize-path"));
153
118
 
154
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/util.ts
119
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/util.ts
155
120
  var import_gray_matter = __toModule(require("gray-matter"));
156
121
 
157
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/util.ts
122
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/util.ts
158
123
  var yup = __toModule(require("yup"));
159
- var import_graphql2 = __toModule(require("graphql"));
124
+ var import_graphql = __toModule(require("graphql"));
160
125
  var sequential = async (items, callback) => {
161
126
  const accum = [];
162
127
  if (!items) {
@@ -181,13 +146,19 @@ function assertShape(value, yupSchema, errorMessage) {
181
146
  shape.validateSync(value);
182
147
  } catch (e) {
183
148
  const message = errorMessage || `Failed to assertShape - ${e.message}`;
184
- throw new import_graphql2.GraphQLError(message, null, null, null, null, null, {
149
+ throw new import_graphql.GraphQLError(message, null, null, null, null, null, {
185
150
  stack: e.stack
186
151
  });
187
152
  }
188
153
  }
154
+ var atob = (b64Encoded) => {
155
+ return Buffer.from(b64Encoded, "base64").toString();
156
+ };
157
+ var btoa = (string) => {
158
+ return Buffer.from(string).toString("base64");
159
+ };
189
160
 
190
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/util.ts
161
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/util.ts
191
162
  var stringifyFile = (content, format, keepTemplateKey) => {
192
163
  switch (format) {
193
164
  case ".markdown":
@@ -242,144 +213,7 @@ var parseFile = (content, format, yupSchema) => {
242
213
  }
243
214
  };
244
215
 
245
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/store/github.ts
246
- var import_graphql3 = __toModule(require("graphql"));
247
- var GithubStore = class {
248
- async clear() {
249
- }
250
- async print() {
251
- }
252
- constructor({ rootPath, accessToken, owner, repo, ref }) {
253
- this.rootPath = rootPath;
254
- this.repoConfig = {
255
- owner,
256
- repo,
257
- ref
258
- };
259
- this.appOctoKit = new import_rest2.Octokit({
260
- auth: accessToken
261
- });
262
- }
263
- async query(queryStrings) {
264
- throw new Error(`Unable to perform query for GithubStore`);
265
- }
266
- supportsSeeding() {
267
- return false;
268
- }
269
- async seed() {
270
- throw new Error(`Seeding data is not possible for Github data store`);
271
- }
272
- async readDir(filepath) {
273
- const fullPath = import_path2.default.join(this.rootPath, filepath);
274
- const repos = await this.appOctoKit.repos.getContent(__spreadProps(__spreadValues({}, this.repoConfig), {
275
- path: fullPath
276
- })).then(async (response) => {
277
- if (Array.isArray(response.data)) {
278
- return await Promise.all(await response.data.map(async (d) => {
279
- if (d.type === "dir") {
280
- const nestedItems = await this.readDir(d.path);
281
- if (Array.isArray(nestedItems)) {
282
- return nestedItems.map((nestedItem) => {
283
- return import_path2.default.join(d.path, nestedItem);
284
- });
285
- } else {
286
- throw new Error(`Expected items to be an array of strings for readDir at ${d.path}`);
287
- }
288
- }
289
- return d.path;
290
- }));
291
- }
292
- throw new Error(`Expected to return an array from Github directory ${import_path2.default}`);
293
- });
294
- return import_lodash2.default.flatten(repos);
295
- }
296
- async glob(pattern, callback) {
297
- const results = await this.readDir(pattern);
298
- const items = results.map((item) => item.replace(this.rootPath, "").replace(/^\/|\/$/g, ""));
299
- if (callback) {
300
- return sequential(items, async (item) => {
301
- return callback(item);
302
- });
303
- } else {
304
- return items;
305
- }
306
- }
307
- async get(filepath) {
308
- const realpath = import_path2.default.join(this.rootPath, filepath);
309
- return this.appOctoKit.repos.getContent(__spreadProps(__spreadValues({}, this.repoConfig), {
310
- path: realpath
311
- })).then((response) => {
312
- const responseString = Buffer.from(response.data.content, "base64").toString();
313
- return parseFile(responseString, import_path2.default.extname(filepath), (yup2) => yup2.object());
314
- }).catch((e) => {
315
- if (e.status === 401) {
316
- throw new import_graphql3.GraphQLError(`Unauthorized request to Github Repository: '${this.repoConfig.owner}/${this.repoConfig.repo}', please ensure your access token is valid.`, null, null, null, null, e, { status: e.status });
317
- }
318
- throw new import_graphql3.GraphQLError(`Unable to find record '${filepath}' in Github Repository: '${this.repoConfig.owner}/${this.repoConfig.repo}', Ref: '${this.repoConfig.ref}'`, null, null, null, null, e, { status: e.status });
319
- });
320
- }
321
- supportsIndexing() {
322
- return false;
323
- }
324
- async put(filepath, data) {
325
- const realpath = import_path2.default.join(this.rootPath, filepath);
326
- let fileSha = void 0;
327
- try {
328
- const fileContent = await this.appOctoKit.repos.getContent(__spreadProps(__spreadValues({}, this.repoConfig), {
329
- path: realpath
330
- }));
331
- fileSha = fileContent.data.sha;
332
- } catch (e) {
333
- console.log("No file exists, creating new one");
334
- }
335
- await this.appOctoKit.repos.createOrUpdateFileContents(__spreadProps(__spreadValues({}, this.repoConfig), {
336
- branch: this.repoConfig.ref,
337
- path: realpath,
338
- message: "Update from GraphQL client",
339
- content: new Buffer(stringifyFile(data, import_path2.default.extname(filepath), false)).toString("base64"),
340
- sha: fileSha
341
- }));
342
- }
343
- };
344
-
345
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/bridge/filesystem.ts
346
- var import_fs_extra = __toModule(require("fs-extra"));
347
- var import_fast_glob = __toModule(require("fast-glob"));
348
- var import_path3 = __toModule(require("path"));
349
- var import_normalize_path = __toModule(require("normalize-path"));
350
- var FilesystemBridge = class {
351
- constructor(rootPath) {
352
- this.rootPath = rootPath || "";
353
- }
354
- async glob(pattern) {
355
- const basePath = import_path3.default.join(this.rootPath, ...pattern.split("/"));
356
- const items = await (0, import_fast_glob.default)(import_path3.default.join(basePath, "**", "/*").replace(/\\/g, "/"), {
357
- dot: true
358
- });
359
- const posixRootPath = (0, import_normalize_path.default)(this.rootPath);
360
- return items.map((item) => {
361
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
362
- });
363
- }
364
- supportsBuilding() {
365
- return true;
366
- }
367
- async get(filepath) {
368
- return import_fs_extra.default.readFileSync(import_path3.default.join(this.rootPath, filepath)).toString();
369
- }
370
- async putConfig(filepath, data) {
371
- await this.put(filepath, data);
372
- }
373
- async put(filepath, data) {
374
- await import_fs_extra.default.outputFileSync(import_path3.default.join(this.rootPath, filepath), data);
375
- }
376
- };
377
-
378
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/store/filesystem.ts
379
- var import_fs_extra2 = __toModule(require("fs-extra"));
380
- var import_fast_glob2 = __toModule(require("fast-glob"));
381
- var import_path4 = __toModule(require("path"));
382
- var import_normalize_path2 = __toModule(require("normalize-path"));
216
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/filesystem.ts
383
217
  var FilesystemStore = class {
384
218
  async clear() {
385
219
  }
@@ -388,14 +222,14 @@ var FilesystemStore = class {
388
222
  constructor({ rootPath }) {
389
223
  this.rootPath = rootPath || "";
390
224
  }
391
- async query(queryStrings) {
225
+ async query(queryOptions) {
392
226
  throw new Error(`Unable to perform query for Filesystem store`);
393
227
  }
394
228
  async seed() {
395
229
  throw new Error(`Seeding data is not possible for Filesystem store`);
396
230
  }
397
231
  async get(filepath) {
398
- return parseFile(await import_fs_extra2.default.readFileSync(import_path4.default.join(this.rootPath, filepath)).toString(), import_path4.default.extname(filepath), (yup2) => yup2.object());
232
+ return parseFile(await import_fs_extra2.default.readFileSync(import_path2.default.join(this.rootPath, filepath)).toString(), import_path2.default.extname(filepath), (yup2) => yup2.object());
399
233
  }
400
234
  supportsSeeding() {
401
235
  return false;
@@ -404,8 +238,8 @@ var FilesystemStore = class {
404
238
  return false;
405
239
  }
406
240
  async glob(pattern, callback) {
407
- const basePath = import_path4.default.join(this.rootPath, ...pattern.split("/"));
408
- const itemsRaw = await (0, import_fast_glob2.default)(import_path4.default.join(basePath, "**", "/*").replace(/\\/g, "/"), {
241
+ const basePath = import_path2.default.join(this.rootPath, ...pattern.split("/"));
242
+ const itemsRaw = await (0, import_fast_glob2.default)(import_path2.default.join(basePath, "**", "/*").replace(/\\/g, "/"), {
409
243
  dot: true
410
244
  });
411
245
  const posixRootPath = (0, import_normalize_path2.default)(this.rootPath);
@@ -420,125 +254,446 @@ var FilesystemStore = class {
420
254
  return items;
421
255
  }
422
256
  }
423
- async put(filepath, data) {
424
- await import_fs_extra2.default.outputFileSync(import_path4.default.join(this.rootPath, filepath), stringifyFile(data, import_path4.default.extname(filepath), false));
425
- }
426
- };
427
-
428
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/store/memory.ts
429
- var MemoryStore = class {
430
- constructor(rootPath, object = {}) {
431
- this.map = object;
432
- this.rootPath = rootPath || "";
433
- this.db = {
434
- get: async (filepath) => {
435
- return this.map[filepath];
436
- },
437
- put: async (filepath, content) => {
438
- this.map[filepath] = content;
439
- await this.print();
440
- }
441
- };
257
+ async put(filepath, data, options) {
258
+ await import_fs_extra2.default.outputFileSync(import_path2.default.join(this.rootPath, filepath), stringifyFile(data, import_path2.default.extname(filepath), options.keepTemplateKey));
442
259
  }
443
- async query(queryStrings, hydrator) {
444
- const resultSets = await sequential(queryStrings, async (queryString) => {
445
- const res = await this.get(queryString);
446
- return res || [];
447
- });
448
- let items = [];
449
- if (resultSets.length > 0) {
450
- items = resultSets.reduce((p, c) => p.filter((e) => c.includes(e)));
451
- }
452
- return sequential(items, async (documentString) => {
453
- return hydrator(documentString);
454
- });
260
+ async open() {
455
261
  }
456
- async seed(filepath, data) {
457
- await this.put(filepath, data);
262
+ async close() {
458
263
  }
459
- supportsSeeding() {
460
- return true;
461
- }
462
- supportsIndexing() {
463
- return true;
264
+ };
265
+ var AuditFilesystemStore = class extends FilesystemStore {
266
+ async put(_filepath, _data) {
267
+ return;
464
268
  }
465
- async print() {
269
+ };
270
+
271
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/index.ts
272
+ var import_jsonpath_plus = __toModule(require("jsonpath-plus"));
273
+ var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
274
+ var INDEX_KEY_FIELD_SEPARATOR = "#";
275
+ var DEFAULT_NUMERIC_LPAD = 4;
276
+ var OP;
277
+ (function(OP2) {
278
+ OP2["EQ"] = "eq";
279
+ OP2["GT"] = "gt";
280
+ OP2["LT"] = "lt";
281
+ OP2["GTE"] = "gte";
282
+ OP2["LTE"] = "lte";
283
+ OP2["STARTS_WITH"] = "startsWith";
284
+ OP2["IN"] = "in";
285
+ })(OP || (OP = {}));
286
+ var inferOperatorFromFilter = (filterOperator) => {
287
+ switch (filterOperator) {
288
+ case "after":
289
+ return OP.GT;
290
+ case "before":
291
+ return OP.LT;
292
+ case "eq":
293
+ return OP.EQ;
294
+ case "startsWith":
295
+ return OP.STARTS_WITH;
296
+ case "lt":
297
+ return OP.LT;
298
+ case "lte":
299
+ return OP.LTE;
300
+ case "gt":
301
+ return OP.GT;
302
+ case "gte":
303
+ return OP.GTE;
304
+ case "in":
305
+ return OP.IN;
306
+ default:
307
+ throw new Error(`unsupported filter condition: '${filterOperator}'`);
466
308
  }
467
- async clear() {
468
- this.map = {};
309
+ };
310
+ var getFilterOperator = (expression, operand) => {
311
+ return (expression[operand] || expression[operand] === 0) && operand;
312
+ };
313
+ var makeFilterChain = ({
314
+ conditions
315
+ }) => {
316
+ const filterChain = [];
317
+ if (!conditions) {
318
+ return filterChain;
319
+ }
320
+ for (const condition of conditions) {
321
+ const { filterPath, filterExpression } = condition;
322
+ const _a = filterExpression, { _type } = _a, keys = __objRest(_a, ["_type"]);
323
+ const [key1, key2, ...extraKeys] = Object.keys(keys);
324
+ if (extraKeys.length) {
325
+ throw new Error(`Unexpected keys: [${extraKeys.join(",")}] in filter expression`);
326
+ }
327
+ if (key1 && !key2) {
328
+ filterChain.push({
329
+ pathExpression: filterPath,
330
+ rightOperand: filterExpression[key1],
331
+ operator: inferOperatorFromFilter(key1),
332
+ type: _type,
333
+ pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
334
+ });
335
+ } else if (key1 && key2) {
336
+ const leftFilterOperator = getFilterOperator(filterExpression, "gt") || getFilterOperator(filterExpression, "gte") || getFilterOperator(filterExpression, "after") || void 0;
337
+ const rightFilterOperator = getFilterOperator(filterExpression, "lt") || getFilterOperator(filterExpression, "lte") || getFilterOperator(filterExpression, "before") || void 0;
338
+ let leftOperand;
339
+ let rightOperand;
340
+ if (rightFilterOperator && leftFilterOperator) {
341
+ if (key1 === leftFilterOperator) {
342
+ leftOperand = filterExpression[key1];
343
+ rightOperand = filterExpression[key2];
344
+ } else {
345
+ rightOperand = filterExpression[key1];
346
+ leftOperand = filterExpression[key2];
347
+ }
348
+ filterChain.push({
349
+ pathExpression: filterPath,
350
+ rightOperand,
351
+ leftOperand,
352
+ leftOperator: inferOperatorFromFilter(leftFilterOperator),
353
+ rightOperator: inferOperatorFromFilter(rightFilterOperator),
354
+ type: _type,
355
+ pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
356
+ });
357
+ } else {
358
+ throw new Error(`Filter on field '${filterPath}' has invalid combination of conditions: '${key1}, ${key2}'`);
359
+ }
360
+ }
469
361
  }
470
- async glob(pattern, callback) {
471
- const strings = Object.keys(this.map).filter((key) => {
472
- if (key.startsWith(pattern)) {
473
- return true;
362
+ return filterChain;
363
+ };
364
+ var makeFilter = ({
365
+ filterChain
366
+ }) => {
367
+ return (values) => {
368
+ for (const filter of filterChain) {
369
+ const dataType = filter.type;
370
+ const resolvedValues = (0, import_jsonpath_plus.JSONPath)({
371
+ path: filter.pathExpression,
372
+ json: values
373
+ });
374
+ if (!resolvedValues || !resolvedValues.length) {
375
+ return false;
376
+ }
377
+ let operands;
378
+ if (dataType === "string" || dataType === "reference") {
379
+ operands = resolvedValues;
380
+ } else if (dataType === "number" || dataType === "datetime") {
381
+ operands = resolvedValues.map((resolvedValue) => Number(resolvedValue));
382
+ } else if (dataType === "boolean") {
383
+ operands = resolvedValues.map((resolvedValue) => typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1");
384
+ } else {
385
+ throw new Error(`Unexpected datatype ${dataType}`);
386
+ }
387
+ const { operator } = filter;
388
+ let matches = false;
389
+ if (operator) {
390
+ switch (operator) {
391
+ case OP.EQ:
392
+ if (operands.findIndex((operand) => operand === filter.rightOperand) >= 0) {
393
+ matches = true;
394
+ }
395
+ break;
396
+ case OP.GT:
397
+ for (const operand of operands) {
398
+ if (operand > filter.rightOperand) {
399
+ matches = true;
400
+ break;
401
+ }
402
+ }
403
+ break;
404
+ case OP.LT:
405
+ for (const operand of operands) {
406
+ if (operand < filter.rightOperand) {
407
+ matches = true;
408
+ break;
409
+ }
410
+ }
411
+ break;
412
+ case OP.GTE:
413
+ for (const operand of operands) {
414
+ if (operand >= filter.rightOperand) {
415
+ matches = true;
416
+ break;
417
+ }
418
+ }
419
+ break;
420
+ case OP.LTE:
421
+ for (const operand of operands) {
422
+ if (operand <= filter.rightOperand) {
423
+ matches = true;
424
+ break;
425
+ }
426
+ }
427
+ break;
428
+ case OP.IN:
429
+ for (const operand of operands) {
430
+ if (filter.rightOperand.indexOf(operand) >= 0) {
431
+ matches = true;
432
+ break;
433
+ }
434
+ }
435
+ break;
436
+ case OP.STARTS_WITH:
437
+ for (const operand of operands) {
438
+ if (operand.startsWith(filter.rightOperand)) {
439
+ matches = true;
440
+ break;
441
+ }
442
+ }
443
+ break;
444
+ default:
445
+ throw new Error(`unexpected operator ${operator}`);
446
+ }
474
447
  } else {
448
+ const { rightOperator, leftOperator, rightOperand, leftOperand } = filter;
449
+ for (const operand of operands) {
450
+ let rightMatches = false;
451
+ let leftMatches = false;
452
+ if (rightOperator === OP.LTE && operand <= rightOperand) {
453
+ rightMatches = true;
454
+ } else if (rightOperator === OP.LT && operand < rightOperand) {
455
+ rightMatches = true;
456
+ }
457
+ if (leftOperator === OP.GTE && operand >= leftOperand) {
458
+ leftMatches = true;
459
+ } else if (leftOperator === OP.GT && operand > leftOperand) {
460
+ leftMatches = true;
461
+ }
462
+ if (rightMatches && leftMatches) {
463
+ matches = true;
464
+ break;
465
+ }
466
+ }
467
+ }
468
+ if (!matches) {
475
469
  return false;
476
470
  }
477
- });
478
- if (callback) {
479
- return sequential(strings, async (item) => {
480
- return callback(item);
481
- });
471
+ }
472
+ return true;
473
+ };
474
+ };
475
+ var makeStringEscaper = (regex, replacement) => {
476
+ return (input) => {
477
+ if (Array.isArray(input)) {
478
+ return input.map((val) => val.replace(regex, replacement));
482
479
  } else {
483
- return strings;
480
+ return input.replace(regex, replacement);
481
+ }
482
+ };
483
+ };
484
+ var applyPadding = (input, pad) => {
485
+ if (pad) {
486
+ if (Array.isArray(input)) {
487
+ return input.map((val) => String(val).padStart(pad.maxLength, pad.fillString));
488
+ } else {
489
+ return String(input).padStart(pad.maxLength, pad.fillString);
484
490
  }
485
491
  }
486
- async get(filepath) {
487
- const content = await this.db.get(filepath);
488
- return content;
492
+ return input;
493
+ };
494
+ var coerceFilterChainOperands = (filterChain, stringEscaper) => {
495
+ const result = [];
496
+ if (filterChain.length) {
497
+ for (const filter of filterChain) {
498
+ const dataType = filter.type;
499
+ if (dataType === "datetime") {
500
+ if (filter.leftOperand !== void 0) {
501
+ result.push(__spreadProps(__spreadValues({}, filter), {
502
+ rightOperand: new Date(filter.rightOperand).getTime(),
503
+ leftOperand: new Date(filter.leftOperand).getTime()
504
+ }));
505
+ } else {
506
+ if (Array.isArray(filter.rightOperand)) {
507
+ result.push(__spreadProps(__spreadValues({}, filter), {
508
+ rightOperand: filter.rightOperand.map((operand) => new Date(operand).getTime())
509
+ }));
510
+ } else {
511
+ result.push(__spreadProps(__spreadValues({}, filter), {
512
+ rightOperand: new Date(filter.rightOperand).getTime()
513
+ }));
514
+ }
515
+ }
516
+ } else if (dataType === "string") {
517
+ if (filter.leftOperand !== void 0) {
518
+ result.push(__spreadProps(__spreadValues({}, filter), {
519
+ rightOperand: applyPadding(stringEscaper(filter.rightOperand), filter.pad),
520
+ leftOperand: applyPadding(stringEscaper(filter.leftOperand), filter.pad)
521
+ }));
522
+ } else {
523
+ result.push(__spreadProps(__spreadValues({}, filter), {
524
+ rightOperand: applyPadding(stringEscaper(filter.rightOperand), filter.pad)
525
+ }));
526
+ }
527
+ } else {
528
+ result.push(__spreadValues({}, filter));
529
+ }
530
+ }
489
531
  }
490
- async put(filepath, data) {
491
- await this.db.put(filepath, data);
532
+ return result;
533
+ };
534
+ var makeFilterSuffixes = (filterChain, index) => {
535
+ if (filterChain && filterChain.length) {
536
+ const indexFields = index.fields.map((field) => field.name);
537
+ const orderedFilterChain = [];
538
+ for (const filter of filterChain) {
539
+ const idx = indexFields.indexOf(filter.pathExpression);
540
+ if (idx === -1) {
541
+ return;
542
+ }
543
+ if (filter.operator && filter.operator === OP.IN) {
544
+ return;
545
+ }
546
+ orderedFilterChain[idx] = filter;
547
+ }
548
+ const baseFragments = [];
549
+ let rightSuffix;
550
+ let leftSuffix;
551
+ let ternaryFilter = false;
552
+ if (orderedFilterChain[filterChain.length - 1] && !orderedFilterChain[filterChain.length - 1].operator) {
553
+ ternaryFilter = true;
554
+ }
555
+ for (let i = 0; i < orderedFilterChain.length; i++) {
556
+ const filter = orderedFilterChain[i];
557
+ if (!filter) {
558
+ return;
559
+ }
560
+ if (Number(i) < indexFields.length - 1) {
561
+ if (!filter.operator) {
562
+ return;
563
+ }
564
+ const binaryFilter = filter;
565
+ if (binaryFilter.operator !== OP.EQ) {
566
+ return;
567
+ }
568
+ baseFragments.push(applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad));
569
+ } else {
570
+ if (ternaryFilter) {
571
+ leftSuffix = applyPadding(orderedFilterChain[i].leftOperand, orderedFilterChain[i].pad);
572
+ rightSuffix = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
573
+ } else {
574
+ const op = orderedFilterChain[i].operator;
575
+ const operand = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
576
+ if (op === OP.LT || op === OP.LTE) {
577
+ rightSuffix = operand;
578
+ } else if (op === OP.GT || op === OP.GTE) {
579
+ leftSuffix = operand;
580
+ } else {
581
+ rightSuffix = operand;
582
+ leftSuffix = operand;
583
+ }
584
+ }
585
+ }
586
+ }
587
+ return {
588
+ left: leftSuffix && [...baseFragments, leftSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0,
589
+ right: rightSuffix && [...baseFragments, rightSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0
590
+ };
591
+ } else {
592
+ return {};
492
593
  }
493
594
  };
595
+ var makeKeyForField = (definition, data, stringEscaper) => {
596
+ const valueParts = [];
597
+ for (const field of definition.fields) {
598
+ if (field.name in data) {
599
+ const resolvedValue = String(field.type === "datetime" ? new Date(data[field.name]).getTime() : field.type === "string" ? stringEscaper(data[field.name]) : data[field.name]);
600
+ valueParts.push(applyPadding(resolvedValue, field.pad));
601
+ } else {
602
+ return null;
603
+ }
604
+ }
605
+ return valueParts.join(INDEX_KEY_FIELD_SEPARATOR);
606
+ };
494
607
 
495
- // pnp:/Users/jeffsee/code/tinacms2/packages/@tinacms/datalayer/src/database/store/level.ts
496
- var import_path5 = __toModule(require("path"));
608
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/level.ts
609
+ var import_path3 = __toModule(require("path"));
497
610
  var import_level = __toModule(require("level"));
498
611
  var import_levelup = __toModule(require("levelup"));
499
612
  var import_memdown = __toModule(require("memdown"));
500
613
  var import_encoding_down = __toModule(require("encoding-down"));
614
+ var defaultPrefix = "_ROOT_";
615
+ var escapeStr = makeStringEscaper(new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"), encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR));
501
616
  var LevelStore = class {
502
617
  constructor(rootPath, useMemory = false) {
503
618
  this.rootPath = rootPath || "";
619
+ this.useMemory = useMemory;
504
620
  if (useMemory) {
505
- const db = (0, import_levelup.default)((0, import_encoding_down.default)((0, import_memdown.default)(), { valueEncoding: "json" }));
506
- this.db = db;
621
+ this.db = (0, import_levelup.default)((0, import_encoding_down.default)((0, import_memdown.default)(), { valueEncoding: "json" }));
507
622
  } else {
508
- const db = (0, import_level.default)(import_path5.default.join(rootPath, ".tina/__generated__/db"), {
623
+ this.db = (0, import_level.default)(import_path3.default.join(rootPath, ".tina/__generated__/db"), {
509
624
  valueEncoding: "json"
510
625
  });
511
- this.db = db;
512
626
  }
513
627
  }
514
- async query(queryStrings, hydrator) {
515
- const resultSets = await sequential(queryStrings, async (queryString) => {
516
- let strings = [];
517
- const p = new Promise((resolve, reject) => {
518
- this.db.createReadStream({
519
- gte: queryString,
520
- lte: queryString + "\xFF"
521
- }).on("data", (data) => {
522
- strings = [...strings, ...data.value];
523
- }).on("error", (message) => {
524
- reject(message);
525
- }).on("end", function() {
526
- resolve();
527
- });
528
- });
529
- await p;
530
- return strings || [];
531
- });
532
- let items = [];
533
- if (resultSets.length > 0) {
534
- items = resultSets.reduce((p, c) => p.filter((e) => c.includes(e)));
628
+ async query(queryOptions) {
629
+ var _b;
630
+ const _a = queryOptions, {
631
+ filterChain: rawFilterChain,
632
+ sort = DEFAULT_COLLECTION_SORT_KEY,
633
+ collection,
634
+ indexDefinitions,
635
+ limit = 10
636
+ } = _a, query = __objRest(_a, [
637
+ "filterChain",
638
+ "sort",
639
+ "collection",
640
+ "indexDefinitions",
641
+ "limit"
642
+ ]);
643
+ const filterChain = coerceFilterChainOperands(rawFilterChain, escapeStr);
644
+ const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
645
+ const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
646
+ const indexPrefix = indexDefinition ? `${collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}` : `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}`;
647
+ if (!query.gt && !query.gte) {
648
+ query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? `${indexPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filterSuffixes.left}` : indexPrefix;
535
649
  }
536
- return sequential(items, async (documentString) => {
537
- return hydrator(documentString);
538
- });
650
+ if (!query.lt && !query.lte) {
651
+ query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${indexPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filterSuffixes.right}\xFF` : `${indexPrefix}\xFF`;
652
+ }
653
+ let edges = [];
654
+ let startKey = "";
655
+ let endKey = "";
656
+ let hasPreviousPage = false;
657
+ let hasNextPage = false;
658
+ 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;
659
+ const valuesRegex = indexDefinition ? new RegExp(`^${indexPrefix}${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^${indexPrefix}(?<_filepath_>.+)`);
660
+ const itemFilter = makeFilter({ filterChain });
661
+ for await (const [key, value] of this.db.iterator(query)) {
662
+ const matcher = valuesRegex.exec(key);
663
+ if (!matcher || indexDefinition && matcher.length !== indexDefinition.fields.length + 2) {
664
+ continue;
665
+ }
666
+ const filepath = matcher.groups["_filepath_"];
667
+ if (!itemFilter(filterSuffixes ? matcher.groups : indexDefinition ? await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`) : value)) {
668
+ continue;
669
+ }
670
+ if (limit !== -1 && edges.length >= limit) {
671
+ if (query.reverse) {
672
+ hasPreviousPage = true;
673
+ } else {
674
+ hasNextPage = true;
675
+ }
676
+ break;
677
+ }
678
+ startKey = startKey || key || "";
679
+ endKey = key || "";
680
+ edges = [...edges, { cursor: key, path: filepath }];
681
+ }
682
+ return {
683
+ edges,
684
+ pageInfo: {
685
+ hasPreviousPage,
686
+ hasNextPage,
687
+ startCursor: startKey,
688
+ endCursor: endKey
689
+ }
690
+ };
539
691
  }
540
- async seed(filepath, data) {
541
- await this.put(filepath, data);
692
+ async seed(filepath, data, options) {
693
+ await this.put(filepath, data, __spreadValues({
694
+ keepTemplateKey: false,
695
+ seed: true
696
+ }, options));
542
697
  }
543
698
  supportsSeeding() {
544
699
  return true;
@@ -567,10 +722,10 @@ var LevelStore = class {
567
722
  const strings = [];
568
723
  const p = new Promise((resolve, reject) => {
569
724
  this.db.createKeyStream({
570
- gte: pattern,
571
- lte: pattern + "\xFF"
725
+ gte: `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${pattern}`,
726
+ lte: `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${pattern}\xFF`
572
727
  }).on("data", (data) => {
573
- strings.push(data);
728
+ strings.push(data.split(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}`)[1]);
574
729
  }).on("error", (message) => {
575
730
  reject(message);
576
731
  }).on("end", function() {
@@ -588,22 +743,64 @@ var LevelStore = class {
588
743
  }
589
744
  async get(filepath) {
590
745
  try {
591
- const content = await this.db.get(filepath);
592
- return content;
746
+ return await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`);
593
747
  } catch (e) {
594
748
  return void 0;
595
749
  }
596
750
  }
597
- async put(filepath, data) {
598
- await this.db.put(filepath, data);
751
+ async close() {
752
+ await this.db.close();
753
+ }
754
+ async put(filepath, data, options) {
755
+ let existingData;
756
+ try {
757
+ existingData = options && !options.seed ? await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`) : null;
758
+ } catch (err) {
759
+ if (!err.notFound) {
760
+ throw err;
761
+ }
762
+ }
763
+ await this.db.put(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`, data);
764
+ if (options == null ? void 0 : options.indexDefinitions) {
765
+ for (const [sort, definition] of Object.entries(options.indexDefinitions)) {
766
+ const indexedValue = makeKeyForField(definition, data, escapeStr);
767
+ const existingIndexedValue = existingData ? makeKeyForField(definition, existingData, escapeStr) : null;
768
+ let indexKey;
769
+ let existingIndexKey = null;
770
+ if (sort === DEFAULT_COLLECTION_SORT_KEY) {
771
+ indexKey = `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`;
772
+ existingIndexKey = indexKey;
773
+ } else {
774
+ indexKey = indexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${indexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
775
+ existingIndexKey = existingIndexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${existingIndexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
776
+ }
777
+ if (indexKey) {
778
+ if (existingIndexKey && indexKey != existingIndexKey) {
779
+ await this.db.del(existingIndexKey);
780
+ }
781
+ await this.db.put(indexKey, "");
782
+ }
783
+ }
784
+ }
599
785
  }
600
786
  };
601
787
  // Annotate the CommonJS export names for ESM import in node:
602
788
  0 && (module.exports = {
789
+ AuditFileSystemBridge,
790
+ AuditFilesystemStore,
791
+ DEFAULT_COLLECTION_SORT_KEY,
792
+ DEFAULT_NUMERIC_LPAD,
603
793
  FilesystemBridge,
604
794
  FilesystemStore,
605
- GithubBridge,
606
- GithubStore,
795
+ INDEX_KEY_FIELD_SEPARATOR,
607
796
  LevelStore,
608
- MemoryStore
797
+ OP,
798
+ atob,
799
+ btoa,
800
+ coerceFilterChainOperands,
801
+ makeFilter,
802
+ makeFilterChain,
803
+ makeFilterSuffixes,
804
+ makeKeyForField,
805
+ makeStringEscaper
609
806
  });