@tinacms/graphql 1.4.11 → 1.4.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.
@@ -18,6 +18,7 @@ export declare type BinaryFilter = {
18
18
  operator: OP.EQ | OP.GT | OP.LT | OP.GTE | OP.LTE | OP.STARTS_WITH | OP.IN;
19
19
  type: string;
20
20
  pad?: PadDefinition;
21
+ list: boolean;
21
22
  };
22
23
  export declare type TernaryFilter = {
23
24
  pathExpression: string;
@@ -27,12 +28,14 @@ export declare type TernaryFilter = {
27
28
  rightOperator: OP.LT | OP.LTE;
28
29
  type: string;
29
30
  pad?: PadDefinition;
31
+ list: boolean;
30
32
  };
31
33
  export declare type IndexDefinition = {
32
34
  fields: {
33
35
  name: string;
34
36
  type?: string;
35
37
  pad?: PadDefinition;
38
+ list: boolean;
36
39
  }[];
37
40
  };
38
41
  export declare type PadDefinition = {
@@ -16,6 +16,7 @@ export declare type DelOp = {
16
16
  sublevel?: AbstractSublevel<Level, Buffer | Uint8Array | string, string, Record<string, Record<string, any>>>;
17
17
  };
18
18
  export declare type BatchOp = PutOp | DelOp;
19
+ export declare const ARRAY_ITEM_VALUE_SEPARATOR = ",";
19
20
  export declare const INDEX_KEY_FIELD_SEPARATOR = "\u001D";
20
21
  export declare const CONTENT_ROOT_PREFIX = "~";
21
22
  export declare const SUBLEVEL_OPTIONS: AbstractSublevelOptions<string, Record<string, any>>;
package/dist/index.es.js CHANGED
@@ -2525,7 +2525,7 @@ var validateField = async (field) => {
2525
2525
  // package.json
2526
2526
  var package_default = {
2527
2527
  name: "@tinacms/graphql",
2528
- version: "1.4.11",
2528
+ version: "1.4.13",
2529
2529
  main: "dist/index.js",
2530
2530
  module: "dist/index.es.js",
2531
2531
  typings: "dist/index.d.ts",
@@ -3001,6 +3001,7 @@ var collectConditionsForField = (fieldName, field, filterNode, pathExpression, c
3001
3001
  filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
3002
3002
  filterExpression: {
3003
3003
  _type: field.type,
3004
+ _list: !!field.list,
3004
3005
  ...filterNode
3005
3006
  }
3006
3007
  });
@@ -3087,6 +3088,7 @@ import { JSONPath } from "jsonpath-plus";
3087
3088
  import sha from "js-sha1";
3088
3089
 
3089
3090
  // src/database/level.ts
3091
+ var ARRAY_ITEM_VALUE_SEPARATOR = ",";
3090
3092
  var INDEX_KEY_FIELD_SEPARATOR = "";
3091
3093
  var CONTENT_ROOT_PREFIX = "~";
3092
3094
  var SUBLEVEL_OPTIONS = {
@@ -3133,6 +3135,97 @@ var LevelProxy = class {
3133
3135
 
3134
3136
  // src/database/datalayer.ts
3135
3137
  import path from "path";
3138
+
3139
+ // src/database/util.ts
3140
+ import toml from "@iarna/toml";
3141
+ import yaml from "js-yaml";
3142
+ import matter from "gray-matter";
3143
+ import { normalizePath } from "@tinacms/schema-tools";
3144
+ var matterEngines = {
3145
+ toml: {
3146
+ parse: (val) => toml.parse(val),
3147
+ stringify: (val) => toml.stringify(val)
3148
+ }
3149
+ };
3150
+ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3151
+ const {
3152
+ _relativePath,
3153
+ _keepTemplateKey,
3154
+ _id,
3155
+ _template,
3156
+ _collection,
3157
+ $_body,
3158
+ ...rest
3159
+ } = content;
3160
+ const extra = {};
3161
+ if (keepTemplateKey) {
3162
+ extra["_template"] = _template;
3163
+ }
3164
+ const strippedContent = { ...rest, ...extra };
3165
+ switch (format) {
3166
+ case ".markdown":
3167
+ case ".mdx":
3168
+ case ".md":
3169
+ const ok = matter.stringify(
3170
+ typeof $_body === "undefined" ? "" : `
3171
+ ${$_body}`,
3172
+ strippedContent,
3173
+ {
3174
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3175
+ engines: matterEngines,
3176
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
3177
+ }
3178
+ );
3179
+ return ok;
3180
+ case ".json":
3181
+ return JSON.stringify(strippedContent, null, 2);
3182
+ case ".yaml":
3183
+ case ".yml":
3184
+ return yaml.safeDump(strippedContent);
3185
+ case ".toml":
3186
+ return toml.stringify(strippedContent);
3187
+ default:
3188
+ throw new Error(`Must specify a valid format, got ${format}`);
3189
+ }
3190
+ };
3191
+ var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3192
+ switch (format) {
3193
+ case ".markdown":
3194
+ case ".mdx":
3195
+ case ".md":
3196
+ const contentJSON = matter(content || "", {
3197
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3198
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
3199
+ engines: matterEngines
3200
+ });
3201
+ const markdownData = {
3202
+ ...contentJSON.data,
3203
+ $_body: contentJSON.content
3204
+ };
3205
+ assertShape(markdownData, yupSchema);
3206
+ return markdownData;
3207
+ case ".json":
3208
+ if (!content) {
3209
+ return {};
3210
+ }
3211
+ return JSON.parse(content);
3212
+ case ".toml":
3213
+ if (!content) {
3214
+ return {};
3215
+ }
3216
+ return toml.parse(content);
3217
+ case ".yaml":
3218
+ case ".yml":
3219
+ if (!content) {
3220
+ return {};
3221
+ }
3222
+ return yaml.safeLoad(content);
3223
+ default:
3224
+ throw new Error(`Must specify a valid format, got ${format}`);
3225
+ }
3226
+ };
3227
+
3228
+ // src/database/datalayer.ts
3136
3229
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
3137
3230
  var DEFAULT_NUMERIC_LPAD = 4;
3138
3231
  var applyPadding = (input, pad) => {
@@ -3179,10 +3272,24 @@ var makeKeyForField = (definition, data, stringEscaper2, maxStringLength = 100)
3179
3272
  for (const field of definition.fields) {
3180
3273
  if (field.name in data && data[field.name] !== void 0 && data[field.name] !== null) {
3181
3274
  const rawValue = data[field.name];
3182
- const resolvedValue = String(
3183
- field.type === "datetime" ? new Date(rawValue).getTime() : field.type === "string" ? stringEscaper2(rawValue) : rawValue
3184
- ).substring(0, maxStringLength);
3185
- valueParts.push(applyPadding(resolvedValue, field.pad));
3275
+ let resolvedValue;
3276
+ if (field.type === "datetime") {
3277
+ resolvedValue = String(new Date(rawValue).getTime());
3278
+ } else {
3279
+ if (field.type === "string") {
3280
+ const escapedString = stringEscaper2(rawValue);
3281
+ if (Array.isArray(escapedString)) {
3282
+ resolvedValue = escapedString.sort().join(ARRAY_ITEM_VALUE_SEPARATOR);
3283
+ } else {
3284
+ resolvedValue = escapedString;
3285
+ }
3286
+ } else {
3287
+ resolvedValue = String(rawValue);
3288
+ }
3289
+ }
3290
+ valueParts.push(
3291
+ applyPadding(resolvedValue.substring(0, maxStringLength), field.pad)
3292
+ );
3186
3293
  } else {
3187
3294
  return null;
3188
3295
  }
@@ -3249,12 +3356,96 @@ var coerceFilterChainOperands = (filterChain, escapeString = stringEscaper) => {
3249
3356
  }
3250
3357
  return result;
3251
3358
  };
3359
+ function operatorMatchesBinaryFilter(operator, operands, filter) {
3360
+ let matches = false;
3361
+ switch (operator) {
3362
+ case "eq" /* EQ */:
3363
+ if (operands.findIndex((operand) => operand === filter.rightOperand) >= 0) {
3364
+ matches = true;
3365
+ }
3366
+ break;
3367
+ case "gt" /* GT */:
3368
+ for (const operand of operands) {
3369
+ if (operand > filter.rightOperand) {
3370
+ matches = true;
3371
+ break;
3372
+ }
3373
+ }
3374
+ break;
3375
+ case "lt" /* LT */:
3376
+ for (const operand of operands) {
3377
+ if (operand < filter.rightOperand) {
3378
+ matches = true;
3379
+ break;
3380
+ }
3381
+ }
3382
+ break;
3383
+ case "gte" /* GTE */:
3384
+ for (const operand of operands) {
3385
+ if (operand >= filter.rightOperand) {
3386
+ matches = true;
3387
+ break;
3388
+ }
3389
+ }
3390
+ break;
3391
+ case "lte" /* LTE */:
3392
+ for (const operand of operands) {
3393
+ if (operand <= filter.rightOperand) {
3394
+ matches = true;
3395
+ break;
3396
+ }
3397
+ }
3398
+ break;
3399
+ case "in" /* IN */:
3400
+ for (const operand of operands) {
3401
+ if (filter.rightOperand.indexOf(operand) >= 0) {
3402
+ matches = true;
3403
+ break;
3404
+ }
3405
+ }
3406
+ break;
3407
+ case "startsWith" /* STARTS_WITH */:
3408
+ for (const operand of operands) {
3409
+ if (operand.startsWith(filter.rightOperand)) {
3410
+ matches = true;
3411
+ break;
3412
+ }
3413
+ }
3414
+ break;
3415
+ default:
3416
+ throw new Error(`unexpected operator ${operator}`);
3417
+ }
3418
+ return matches;
3419
+ }
3420
+ function operatorMatchesTernaryFilter(operands, rightOperator, rightOperand, leftOperator, leftOperand) {
3421
+ let matches = false;
3422
+ for (const operand of operands) {
3423
+ let rightMatches = false;
3424
+ let leftMatches = false;
3425
+ if (rightOperator === "lte" /* LTE */ && operand <= rightOperand) {
3426
+ rightMatches = true;
3427
+ } else if (rightOperator === "lt" /* LT */ && operand < rightOperand) {
3428
+ rightMatches = true;
3429
+ }
3430
+ if (leftOperator === "gte" /* GTE */ && operand >= leftOperand) {
3431
+ leftMatches = true;
3432
+ } else if (leftOperator === "gt" /* GT */ && operand > leftOperand) {
3433
+ leftMatches = true;
3434
+ }
3435
+ if (rightMatches && leftMatches) {
3436
+ matches = true;
3437
+ break;
3438
+ }
3439
+ }
3440
+ return matches;
3441
+ }
3252
3442
  var makeFilter = ({
3253
3443
  filterChain
3254
3444
  }) => {
3255
3445
  return (values) => {
3256
3446
  for (const filter of filterChain) {
3257
3447
  const dataType = filter.type;
3448
+ const isList = filter.list;
3258
3449
  const resolvedValues = JSONPath({
3259
3450
  path: filter.pathExpression,
3260
3451
  json: values
@@ -3266,99 +3457,74 @@ var makeFilter = ({
3266
3457
  if (dataType === "string" || dataType === "reference") {
3267
3458
  operands = resolvedValues;
3268
3459
  } else if (dataType === "number") {
3269
- operands = resolvedValues.map((resolvedValue) => Number(resolvedValue));
3460
+ operands = resolvedValues.map((resolvedValue) => {
3461
+ if (isList) {
3462
+ return resolvedValue.map((listValue) => Number(listValue));
3463
+ }
3464
+ return Number(resolvedValue);
3465
+ });
3270
3466
  } else if (dataType === "datetime") {
3271
3467
  operands = resolvedValues.map((resolvedValue) => {
3468
+ if (isList) {
3469
+ return resolvedValue.map((listValue) => {
3470
+ const coerced2 = new Date(listValue).getTime();
3471
+ return isNaN(coerced2) ? Number(listValue) : coerced2;
3472
+ });
3473
+ }
3272
3474
  const coerced = new Date(resolvedValue).getTime();
3273
3475
  return isNaN(coerced) ? Number(resolvedValue) : coerced;
3274
3476
  });
3275
3477
  } else if (dataType === "boolean") {
3276
- operands = resolvedValues.map(
3277
- (resolvedValue) => typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1"
3278
- );
3478
+ operands = resolvedValues.map((resolvedValue) => {
3479
+ if (isList) {
3480
+ return resolvedValue.map((listValue) => {
3481
+ return typeof listValue === "boolean" && listValue || listValue === "true" || listValue === "1";
3482
+ });
3483
+ }
3484
+ return typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1";
3485
+ });
3279
3486
  } else {
3280
3487
  throw new Error(`Unexpected datatype ${dataType}`);
3281
3488
  }
3282
3489
  const { operator } = filter;
3283
3490
  let matches = false;
3284
3491
  if (operator) {
3285
- switch (operator) {
3286
- case "eq" /* EQ */:
3287
- if (operands.findIndex(
3288
- (operand) => operand === filter.rightOperand
3289
- ) >= 0) {
3492
+ if (isList) {
3493
+ for (const operand of operands) {
3494
+ if (operatorMatchesBinaryFilter(operator, operand, filter)) {
3290
3495
  matches = true;
3496
+ break;
3291
3497
  }
3292
- break;
3293
- case "gt" /* GT */:
3294
- for (const operand of operands) {
3295
- if (operand > filter.rightOperand) {
3296
- matches = true;
3297
- break;
3298
- }
3299
- }
3300
- break;
3301
- case "lt" /* LT */:
3302
- for (const operand of operands) {
3303
- if (operand < filter.rightOperand) {
3304
- matches = true;
3305
- break;
3306
- }
3307
- }
3308
- break;
3309
- case "gte" /* GTE */:
3310
- for (const operand of operands) {
3311
- if (operand >= filter.rightOperand) {
3312
- matches = true;
3313
- break;
3314
- }
3315
- }
3316
- break;
3317
- case "lte" /* LTE */:
3318
- for (const operand of operands) {
3319
- if (operand <= filter.rightOperand) {
3320
- matches = true;
3321
- break;
3322
- }
3323
- }
3324
- break;
3325
- case "in" /* IN */:
3326
- for (const operand of operands) {
3327
- if (filter.rightOperand.indexOf(operand) >= 0) {
3328
- matches = true;
3329
- break;
3330
- }
3331
- }
3332
- break;
3333
- case "startsWith" /* STARTS_WITH */:
3334
- for (const operand of operands) {
3335
- if (operand.startsWith(filter.rightOperand)) {
3336
- matches = true;
3337
- break;
3338
- }
3339
- }
3340
- break;
3341
- default:
3342
- throw new Error(`unexpected operator ${operator}`);
3498
+ }
3499
+ } else {
3500
+ if (operatorMatchesBinaryFilter(operator, operands, filter)) {
3501
+ matches = true;
3502
+ }
3343
3503
  }
3344
3504
  } else {
3345
3505
  const { rightOperator, leftOperator, rightOperand, leftOperand } = filter;
3346
- for (const operand of operands) {
3347
- let rightMatches = false;
3348
- let leftMatches = false;
3349
- if (rightOperator === "lte" /* LTE */ && operand <= rightOperand) {
3350
- rightMatches = true;
3351
- } else if (rightOperator === "lt" /* LT */ && operand < rightOperand) {
3352
- rightMatches = true;
3353
- }
3354
- if (leftOperator === "gte" /* GTE */ && operand >= leftOperand) {
3355
- leftMatches = true;
3356
- } else if (leftOperator === "gt" /* GT */ && operand > leftOperand) {
3357
- leftMatches = true;
3506
+ if (isList) {
3507
+ for (const operand of operands) {
3508
+ if (operatorMatchesTernaryFilter(
3509
+ operand,
3510
+ rightOperator,
3511
+ rightOperand,
3512
+ leftOperator,
3513
+ leftOperand
3514
+ )) {
3515
+ matches = true;
3516
+ break;
3517
+ }
3358
3518
  }
3359
- if (rightMatches && leftMatches) {
3519
+ } else {
3520
+ if (operatorMatchesTernaryFilter(
3521
+ operands,
3522
+ rightOperator,
3523
+ rightOperand,
3524
+ leftOperator,
3525
+ leftOperand
3526
+ )) {
3360
3527
  matches = true;
3361
- break;
3362
3528
  }
3363
3529
  }
3364
3530
  }
@@ -3378,7 +3544,7 @@ var makeFilterChain = ({
3378
3544
  }
3379
3545
  for (const condition of conditions) {
3380
3546
  const { filterPath, filterExpression } = condition;
3381
- const { _type, ...keys } = filterExpression;
3547
+ const { _type, _list, ...keys } = filterExpression;
3382
3548
  const [key1, key2, ...extraKeys] = Object.keys(keys);
3383
3549
  if (extraKeys.length) {
3384
3550
  throw new Error(
@@ -3387,6 +3553,7 @@ var makeFilterChain = ({
3387
3553
  }
3388
3554
  if (key1 && !key2) {
3389
3555
  filterChain.push({
3556
+ list: _list,
3390
3557
  pathExpression: filterPath,
3391
3558
  rightOperand: filterExpression[key1],
3392
3559
  operator: inferOperatorFromFilter(key1),
@@ -3407,6 +3574,7 @@ var makeFilterChain = ({
3407
3574
  leftOperand = filterExpression[key2];
3408
3575
  }
3409
3576
  filterChain.push({
3577
+ list: _list,
3410
3578
  pathExpression: filterPath,
3411
3579
  rightOperand,
3412
3580
  leftOperand,
@@ -3516,7 +3684,7 @@ var FolderTreeBuilder = class {
3516
3684
  return this._tree;
3517
3685
  }
3518
3686
  update(documentPath, collectionPath) {
3519
- let folderPath = path.dirname(documentPath);
3687
+ let folderPath = path.dirname(normalizePath(documentPath));
3520
3688
  if (folderPath === ".") {
3521
3689
  folderPath = "";
3522
3690
  }
@@ -3529,7 +3697,7 @@ var FolderTreeBuilder = class {
3529
3697
  if (!this._tree[current2]) {
3530
3698
  this._tree[current2] = /* @__PURE__ */ new Set();
3531
3699
  }
3532
- this._tree[current2].add(path.join(current2, part));
3700
+ this._tree[current2].add(normalizePath(path.join(current2, part)));
3533
3701
  parent.push(part);
3534
3702
  });
3535
3703
  const current = parent.join("/");
@@ -4185,7 +4353,9 @@ var Resolver = class {
4185
4353
  case "boolean":
4186
4354
  case "number":
4187
4355
  case "reference":
4188
- accumulator[field.name] = value;
4356
+ if (value) {
4357
+ accumulator[field.name] = value;
4358
+ }
4189
4359
  break;
4190
4360
  case "image":
4191
4361
  accumulator[field.name] = resolveMediaRelativeToCloud(
@@ -4451,7 +4621,7 @@ var resolve = async ({
4451
4621
  );
4452
4622
  return resolver.getDocument(args.id);
4453
4623
  case "multiCollectionDocument":
4454
- if (typeof value === "string") {
4624
+ if (typeof value === "string" && value !== "") {
4455
4625
  return resolver.getDocument(value);
4456
4626
  }
4457
4627
  if (args && args.collection && info.fieldName === "addPendingDocument") {
@@ -4581,95 +4751,6 @@ import path3 from "path";
4581
4751
  import { GraphQLError as GraphQLError4 } from "graphql";
4582
4752
  import micromatch from "micromatch";
4583
4753
 
4584
- // src/database/util.ts
4585
- import toml from "@iarna/toml";
4586
- import yaml from "js-yaml";
4587
- import matter from "gray-matter";
4588
- import { normalizePath } from "@tinacms/schema-tools";
4589
- var matterEngines = {
4590
- toml: {
4591
- parse: (val) => toml.parse(val),
4592
- stringify: (val) => toml.stringify(val)
4593
- }
4594
- };
4595
- var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
4596
- const {
4597
- _relativePath,
4598
- _keepTemplateKey,
4599
- _id,
4600
- _template,
4601
- _collection,
4602
- $_body,
4603
- ...rest
4604
- } = content;
4605
- const extra = {};
4606
- if (keepTemplateKey) {
4607
- extra["_template"] = _template;
4608
- }
4609
- const strippedContent = { ...rest, ...extra };
4610
- switch (format) {
4611
- case ".markdown":
4612
- case ".mdx":
4613
- case ".md":
4614
- const ok = matter.stringify(
4615
- typeof $_body === "undefined" ? "" : `
4616
- ${$_body}`,
4617
- strippedContent,
4618
- {
4619
- language: markdownParseConfig?.frontmatterFormat ?? "yaml",
4620
- engines: matterEngines,
4621
- delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
4622
- }
4623
- );
4624
- return ok;
4625
- case ".json":
4626
- return JSON.stringify(strippedContent, null, 2);
4627
- case ".yaml":
4628
- case ".yml":
4629
- return yaml.safeDump(strippedContent);
4630
- case ".toml":
4631
- return toml.stringify(strippedContent);
4632
- default:
4633
- throw new Error(`Must specify a valid format, got ${format}`);
4634
- }
4635
- };
4636
- var parseFile = (content, format, yupSchema, markdownParseConfig) => {
4637
- switch (format) {
4638
- case ".markdown":
4639
- case ".mdx":
4640
- case ".md":
4641
- const contentJSON = matter(content || "", {
4642
- language: markdownParseConfig?.frontmatterFormat ?? "yaml",
4643
- delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
4644
- engines: matterEngines
4645
- });
4646
- const markdownData = {
4647
- ...contentJSON.data,
4648
- $_body: contentJSON.content
4649
- };
4650
- assertShape(markdownData, yupSchema);
4651
- return markdownData;
4652
- case ".json":
4653
- if (!content) {
4654
- return {};
4655
- }
4656
- return JSON.parse(content);
4657
- case ".toml":
4658
- if (!content) {
4659
- return {};
4660
- }
4661
- return toml.parse(content);
4662
- case ".yaml":
4663
- case ".yml":
4664
- if (!content) {
4665
- return {};
4666
- }
4667
- return yaml.safeLoad(content);
4668
- default:
4669
- throw new Error(`Must specify a valid format, got ${format}`);
4670
- }
4671
- };
4672
-
4673
4754
  // src/database/alias-utils.ts
4674
4755
  var replaceBlockAliases = (template, item) => {
4675
4756
  const output = { ...item };
@@ -5169,6 +5250,7 @@ var Database = class {
5169
5250
  {
5170
5251
  name: field.name,
5171
5252
  type: field.type,
5253
+ list: !!field.list,
5172
5254
  pad: field.type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
5173
5255
  }
5174
5256
  ]
@@ -5178,12 +5260,16 @@ var Database = class {
5178
5260
  if (collection.indexes) {
5179
5261
  for (const index of collection.indexes) {
5180
5262
  indexDefinitions[index.name] = {
5181
- fields: index.fields.map((indexField) => ({
5182
- name: indexField.name,
5183
- type: collection.fields.find(
5184
- (field) => indexField.name === field.name
5185
- )?.type
5186
- }))
5263
+ fields: index.fields.map((indexField) => {
5264
+ const field = collection.fields.find(
5265
+ (field2) => indexField.name === field2.name
5266
+ );
5267
+ return {
5268
+ name: indexField.name,
5269
+ type: field?.type,
5270
+ list: !!field?.list
5271
+ };
5272
+ })
5187
5273
  };
5188
5274
  }
5189
5275
  }
@@ -5268,10 +5354,27 @@ var Database = class {
5268
5354
  if (!matcher || indexDefinition && matcher.length !== indexDefinition.fields.length + 2) {
5269
5355
  continue;
5270
5356
  }
5271
- const filepath = matcher.groups["_filepath_"];
5272
- if (!itemFilter(
5273
- filterSuffixes ? matcher.groups : indexDefinition ? await rootLevel.get(filepath) : value
5274
- )) {
5357
+ let filepath = matcher.groups["_filepath_"];
5358
+ let itemRecord;
5359
+ if (filterSuffixes) {
5360
+ itemRecord = matcher.groups;
5361
+ for (const field of indexDefinition.fields) {
5362
+ if (itemRecord[field.name]) {
5363
+ if (field.list) {
5364
+ itemRecord[field.name] = itemRecord[field.name].split(
5365
+ ARRAY_ITEM_VALUE_SEPARATOR
5366
+ );
5367
+ }
5368
+ }
5369
+ }
5370
+ } else {
5371
+ if (indexDefinition) {
5372
+ itemRecord = await rootLevel.get(filepath);
5373
+ } else {
5374
+ itemRecord = value;
5375
+ }
5376
+ }
5377
+ if (!itemFilter(itemRecord)) {
5275
5378
  continue;
5276
5379
  }
5277
5380
  if (limit !== -1 && edges.length >= limit) {
@@ -5328,13 +5431,24 @@ var Database = class {
5328
5431
  let nextLevel;
5329
5432
  return await this.indexStatusCallbackWrapper(
5330
5433
  async () => {
5331
- const lookup = lookupFromLockFile || JSON.parse(
5332
- await this.bridge.get(
5333
- normalizePath(
5334
- path3.join(this.getGeneratedFolder(), "_lookup.json")
5434
+ let lookup;
5435
+ try {
5436
+ lookup = lookupFromLockFile || JSON.parse(
5437
+ await this.bridge.get(
5438
+ normalizePath(
5439
+ path3.join(this.getGeneratedFolder(), "_lookup.json")
5440
+ )
5335
5441
  )
5336
- )
5337
- );
5442
+ );
5443
+ } catch (error) {
5444
+ console.error("Error: Unable to find generated lookup file");
5445
+ if (this.tinaDirectory === "tina") {
5446
+ console.error(
5447
+ 'If you are using the .tina folder. Please set {tinaDirectory: ".tina"} in your createDatabase options or migrate to the new tina folder: https://tina.io/blog/tina-config-rearrangements/'
5448
+ );
5449
+ }
5450
+ throw error;
5451
+ }
5338
5452
  let nextVersion;
5339
5453
  if (!this.config.version) {
5340
5454
  await this.level.clear();
@@ -5525,7 +5639,7 @@ This will be an error in the future. See https://tina.io/docs/errors/file-in-mut
5525
5639
  }
5526
5640
  return { warnings };
5527
5641
  };
5528
- this.tinaDirectory = config.tinaDirectory || ".tina";
5642
+ this.tinaDirectory = config.tinaDirectory || "tina";
5529
5643
  this.bridge = config.bridge;
5530
5644
  this.rootLevel = config.level && new LevelProxy(config.level);
5531
5645
  this.indexStatusCallback = config.indexStatusCallback || defaultStatusCallback;
package/dist/index.js CHANGED
@@ -2577,7 +2577,7 @@ var validateField = async (field) => {
2577
2577
  // package.json
2578
2578
  var package_default = {
2579
2579
  name: "@tinacms/graphql",
2580
- version: "1.4.11",
2580
+ version: "1.4.13",
2581
2581
  main: "dist/index.js",
2582
2582
  module: "dist/index.es.js",
2583
2583
  typings: "dist/index.d.ts",
@@ -3047,6 +3047,7 @@ var collectConditionsForField = (fieldName, field, filterNode, pathExpression, c
3047
3047
  filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
3048
3048
  filterExpression: {
3049
3049
  _type: field.type,
3050
+ _list: !!field.list,
3050
3051
  ...filterNode
3051
3052
  }
3052
3053
  });
@@ -3134,6 +3135,7 @@ var import_jsonpath_plus = require("jsonpath-plus");
3134
3135
  var import_js_sha1 = __toESM(require("js-sha1"));
3135
3136
 
3136
3137
  // src/database/level.ts
3138
+ var ARRAY_ITEM_VALUE_SEPARATOR = ",";
3137
3139
  var INDEX_KEY_FIELD_SEPARATOR = "";
3138
3140
  var CONTENT_ROOT_PREFIX = "~";
3139
3141
  var SUBLEVEL_OPTIONS = {
@@ -3180,6 +3182,99 @@ var LevelProxy = class {
3180
3182
 
3181
3183
  // src/database/datalayer.ts
3182
3184
  var import_path = __toESM(require("path"));
3185
+
3186
+ // src/database/util.ts
3187
+ var import_toml = __toESM(require("@iarna/toml"));
3188
+ var import_js_yaml = __toESM(require("js-yaml"));
3189
+ var import_gray_matter = __toESM(require("gray-matter"));
3190
+ var import_schema_tools3 = require("@tinacms/schema-tools");
3191
+ var matterEngines = {
3192
+ toml: {
3193
+ parse: (val) => import_toml.default.parse(val),
3194
+ stringify: (val) => import_toml.default.stringify(val)
3195
+ }
3196
+ };
3197
+ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3198
+ var _a, _b;
3199
+ const {
3200
+ _relativePath,
3201
+ _keepTemplateKey,
3202
+ _id,
3203
+ _template,
3204
+ _collection,
3205
+ $_body,
3206
+ ...rest
3207
+ } = content;
3208
+ const extra = {};
3209
+ if (keepTemplateKey) {
3210
+ extra["_template"] = _template;
3211
+ }
3212
+ const strippedContent = { ...rest, ...extra };
3213
+ switch (format) {
3214
+ case ".markdown":
3215
+ case ".mdx":
3216
+ case ".md":
3217
+ const ok = import_gray_matter.default.stringify(
3218
+ typeof $_body === "undefined" ? "" : `
3219
+ ${$_body}`,
3220
+ strippedContent,
3221
+ {
3222
+ language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3223
+ engines: matterEngines,
3224
+ delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
3225
+ }
3226
+ );
3227
+ return ok;
3228
+ case ".json":
3229
+ return JSON.stringify(strippedContent, null, 2);
3230
+ case ".yaml":
3231
+ case ".yml":
3232
+ return import_js_yaml.default.safeDump(strippedContent);
3233
+ case ".toml":
3234
+ return import_toml.default.stringify(strippedContent);
3235
+ default:
3236
+ throw new Error(`Must specify a valid format, got ${format}`);
3237
+ }
3238
+ };
3239
+ var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3240
+ var _a, _b;
3241
+ switch (format) {
3242
+ case ".markdown":
3243
+ case ".mdx":
3244
+ case ".md":
3245
+ const contentJSON = (0, import_gray_matter.default)(content || "", {
3246
+ language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3247
+ delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---",
3248
+ engines: matterEngines
3249
+ });
3250
+ const markdownData = {
3251
+ ...contentJSON.data,
3252
+ $_body: contentJSON.content
3253
+ };
3254
+ assertShape(markdownData, yupSchema);
3255
+ return markdownData;
3256
+ case ".json":
3257
+ if (!content) {
3258
+ return {};
3259
+ }
3260
+ return JSON.parse(content);
3261
+ case ".toml":
3262
+ if (!content) {
3263
+ return {};
3264
+ }
3265
+ return import_toml.default.parse(content);
3266
+ case ".yaml":
3267
+ case ".yml":
3268
+ if (!content) {
3269
+ return {};
3270
+ }
3271
+ return import_js_yaml.default.safeLoad(content);
3272
+ default:
3273
+ throw new Error(`Must specify a valid format, got ${format}`);
3274
+ }
3275
+ };
3276
+
3277
+ // src/database/datalayer.ts
3183
3278
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
3184
3279
  var DEFAULT_NUMERIC_LPAD = 4;
3185
3280
  var applyPadding = (input, pad) => {
@@ -3226,10 +3321,24 @@ var makeKeyForField = (definition, data, stringEscaper2, maxStringLength = 100)
3226
3321
  for (const field of definition.fields) {
3227
3322
  if (field.name in data && data[field.name] !== void 0 && data[field.name] !== null) {
3228
3323
  const rawValue = data[field.name];
3229
- const resolvedValue = String(
3230
- field.type === "datetime" ? new Date(rawValue).getTime() : field.type === "string" ? stringEscaper2(rawValue) : rawValue
3231
- ).substring(0, maxStringLength);
3232
- valueParts.push(applyPadding(resolvedValue, field.pad));
3324
+ let resolvedValue;
3325
+ if (field.type === "datetime") {
3326
+ resolvedValue = String(new Date(rawValue).getTime());
3327
+ } else {
3328
+ if (field.type === "string") {
3329
+ const escapedString = stringEscaper2(rawValue);
3330
+ if (Array.isArray(escapedString)) {
3331
+ resolvedValue = escapedString.sort().join(ARRAY_ITEM_VALUE_SEPARATOR);
3332
+ } else {
3333
+ resolvedValue = escapedString;
3334
+ }
3335
+ } else {
3336
+ resolvedValue = String(rawValue);
3337
+ }
3338
+ }
3339
+ valueParts.push(
3340
+ applyPadding(resolvedValue.substring(0, maxStringLength), field.pad)
3341
+ );
3233
3342
  } else {
3234
3343
  return null;
3235
3344
  }
@@ -3296,12 +3405,96 @@ var coerceFilterChainOperands = (filterChain, escapeString = stringEscaper) => {
3296
3405
  }
3297
3406
  return result;
3298
3407
  };
3408
+ function operatorMatchesBinaryFilter(operator, operands, filter) {
3409
+ let matches = false;
3410
+ switch (operator) {
3411
+ case "eq" /* EQ */:
3412
+ if (operands.findIndex((operand) => operand === filter.rightOperand) >= 0) {
3413
+ matches = true;
3414
+ }
3415
+ break;
3416
+ case "gt" /* GT */:
3417
+ for (const operand of operands) {
3418
+ if (operand > filter.rightOperand) {
3419
+ matches = true;
3420
+ break;
3421
+ }
3422
+ }
3423
+ break;
3424
+ case "lt" /* LT */:
3425
+ for (const operand of operands) {
3426
+ if (operand < filter.rightOperand) {
3427
+ matches = true;
3428
+ break;
3429
+ }
3430
+ }
3431
+ break;
3432
+ case "gte" /* GTE */:
3433
+ for (const operand of operands) {
3434
+ if (operand >= filter.rightOperand) {
3435
+ matches = true;
3436
+ break;
3437
+ }
3438
+ }
3439
+ break;
3440
+ case "lte" /* LTE */:
3441
+ for (const operand of operands) {
3442
+ if (operand <= filter.rightOperand) {
3443
+ matches = true;
3444
+ break;
3445
+ }
3446
+ }
3447
+ break;
3448
+ case "in" /* IN */:
3449
+ for (const operand of operands) {
3450
+ if (filter.rightOperand.indexOf(operand) >= 0) {
3451
+ matches = true;
3452
+ break;
3453
+ }
3454
+ }
3455
+ break;
3456
+ case "startsWith" /* STARTS_WITH */:
3457
+ for (const operand of operands) {
3458
+ if (operand.startsWith(filter.rightOperand)) {
3459
+ matches = true;
3460
+ break;
3461
+ }
3462
+ }
3463
+ break;
3464
+ default:
3465
+ throw new Error(`unexpected operator ${operator}`);
3466
+ }
3467
+ return matches;
3468
+ }
3469
+ function operatorMatchesTernaryFilter(operands, rightOperator, rightOperand, leftOperator, leftOperand) {
3470
+ let matches = false;
3471
+ for (const operand of operands) {
3472
+ let rightMatches = false;
3473
+ let leftMatches = false;
3474
+ if (rightOperator === "lte" /* LTE */ && operand <= rightOperand) {
3475
+ rightMatches = true;
3476
+ } else if (rightOperator === "lt" /* LT */ && operand < rightOperand) {
3477
+ rightMatches = true;
3478
+ }
3479
+ if (leftOperator === "gte" /* GTE */ && operand >= leftOperand) {
3480
+ leftMatches = true;
3481
+ } else if (leftOperator === "gt" /* GT */ && operand > leftOperand) {
3482
+ leftMatches = true;
3483
+ }
3484
+ if (rightMatches && leftMatches) {
3485
+ matches = true;
3486
+ break;
3487
+ }
3488
+ }
3489
+ return matches;
3490
+ }
3299
3491
  var makeFilter = ({
3300
3492
  filterChain
3301
3493
  }) => {
3302
3494
  return (values) => {
3303
3495
  for (const filter of filterChain) {
3304
3496
  const dataType = filter.type;
3497
+ const isList = filter.list;
3305
3498
  const resolvedValues = (0, import_jsonpath_plus.JSONPath)({
3306
3499
  path: filter.pathExpression,
3307
3500
  json: values
@@ -3313,99 +3506,74 @@ var makeFilter = ({
3313
3506
  if (dataType === "string" || dataType === "reference") {
3314
3507
  operands = resolvedValues;
3315
3508
  } else if (dataType === "number") {
3316
- operands = resolvedValues.map((resolvedValue) => Number(resolvedValue));
3509
+ operands = resolvedValues.map((resolvedValue) => {
3510
+ if (isList) {
3511
+ return resolvedValue.map((listValue) => Number(listValue));
3512
+ }
3513
+ return Number(resolvedValue);
3514
+ });
3317
3515
  } else if (dataType === "datetime") {
3318
3516
  operands = resolvedValues.map((resolvedValue) => {
3517
+ if (isList) {
3518
+ return resolvedValue.map((listValue) => {
3519
+ const coerced2 = new Date(listValue).getTime();
3520
+ return isNaN(coerced2) ? Number(listValue) : coerced2;
3521
+ });
3522
+ }
3319
3523
  const coerced = new Date(resolvedValue).getTime();
3320
3524
  return isNaN(coerced) ? Number(resolvedValue) : coerced;
3321
3525
  });
3322
3526
  } else if (dataType === "boolean") {
3323
- operands = resolvedValues.map(
3324
- (resolvedValue) => typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1"
3325
- );
3527
+ operands = resolvedValues.map((resolvedValue) => {
3528
+ if (isList) {
3529
+ return resolvedValue.map((listValue) => {
3530
+ return typeof listValue === "boolean" && listValue || listValue === "true" || listValue === "1";
3531
+ });
3532
+ }
3533
+ return typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1";
3534
+ });
3326
3535
  } else {
3327
3536
  throw new Error(`Unexpected datatype ${dataType}`);
3328
3537
  }
3329
3538
  const { operator } = filter;
3330
3539
  let matches = false;
3331
3540
  if (operator) {
3332
- switch (operator) {
3333
- case "eq" /* EQ */:
3334
- if (operands.findIndex(
3335
- (operand) => operand === filter.rightOperand
3336
- ) >= 0) {
3541
+ if (isList) {
3542
+ for (const operand of operands) {
3543
+ if (operatorMatchesBinaryFilter(operator, operand, filter)) {
3337
3544
  matches = true;
3545
+ break;
3338
3546
  }
3339
- break;
3340
- case "gt" /* GT */:
3341
- for (const operand of operands) {
3342
- if (operand > filter.rightOperand) {
3343
- matches = true;
3344
- break;
3345
- }
3346
- }
3347
- break;
3348
- case "lt" /* LT */:
3349
- for (const operand of operands) {
3350
- if (operand < filter.rightOperand) {
3351
- matches = true;
3352
- break;
3353
- }
3354
- }
3355
- break;
3356
- case "gte" /* GTE */:
3357
- for (const operand of operands) {
3358
- if (operand >= filter.rightOperand) {
3359
- matches = true;
3360
- break;
3361
- }
3362
- }
3363
- break;
3364
- case "lte" /* LTE */:
3365
- for (const operand of operands) {
3366
- if (operand <= filter.rightOperand) {
3367
- matches = true;
3368
- break;
3369
- }
3370
- }
3371
- break;
3372
- case "in" /* IN */:
3373
- for (const operand of operands) {
3374
- if (filter.rightOperand.indexOf(operand) >= 0) {
3375
- matches = true;
3376
- break;
3377
- }
3378
- }
3379
- break;
3380
- case "startsWith" /* STARTS_WITH */:
3381
- for (const operand of operands) {
3382
- if (operand.startsWith(filter.rightOperand)) {
3383
- matches = true;
3384
- break;
3385
- }
3386
- }
3387
- break;
3388
- default:
3389
- throw new Error(`unexpected operator ${operator}`);
3547
+ }
3548
+ } else {
3549
+ if (operatorMatchesBinaryFilter(operator, operands, filter)) {
3550
+ matches = true;
3551
+ }
3390
3552
  }
3391
3553
  } else {
3392
3554
  const { rightOperator, leftOperator, rightOperand, leftOperand } = filter;
3393
- for (const operand of operands) {
3394
- let rightMatches = false;
3395
- let leftMatches = false;
3396
- if (rightOperator === "lte" /* LTE */ && operand <= rightOperand) {
3397
- rightMatches = true;
3398
- } else if (rightOperator === "lt" /* LT */ && operand < rightOperand) {
3399
- rightMatches = true;
3400
- }
3401
- if (leftOperator === "gte" /* GTE */ && operand >= leftOperand) {
3402
- leftMatches = true;
3403
- } else if (leftOperator === "gt" /* GT */ && operand > leftOperand) {
3404
- leftMatches = true;
3555
+ if (isList) {
3556
+ for (const operand of operands) {
3557
+ if (operatorMatchesTernaryFilter(
3558
+ operand,
3559
+ rightOperator,
3560
+ rightOperand,
3561
+ leftOperator,
3562
+ leftOperand
3563
+ )) {
3564
+ matches = true;
3565
+ break;
3566
+ }
3405
3567
  }
3406
- if (rightMatches && leftMatches) {
3568
+ } else {
3569
+ if (operatorMatchesTernaryFilter(
3570
+ operands,
3571
+ rightOperator,
3572
+ rightOperand,
3573
+ leftOperator,
3574
+ leftOperand
3575
+ )) {
3407
3576
  matches = true;
3408
- break;
3409
3577
  }
3410
3578
  }
3411
3579
  }
@@ -3425,7 +3593,7 @@ var makeFilterChain = ({
3425
3593
  }
3426
3594
  for (const condition of conditions) {
3427
3595
  const { filterPath, filterExpression } = condition;
3428
- const { _type, ...keys } = filterExpression;
3596
+ const { _type, _list, ...keys } = filterExpression;
3429
3597
  const [key1, key2, ...extraKeys] = Object.keys(keys);
3430
3598
  if (extraKeys.length) {
3431
3599
  throw new Error(
@@ -3434,6 +3602,7 @@ var makeFilterChain = ({
3434
3602
  }
3435
3603
  if (key1 && !key2) {
3436
3604
  filterChain.push({
3605
+ list: _list,
3437
3606
  pathExpression: filterPath,
3438
3607
  rightOperand: filterExpression[key1],
3439
3608
  operator: inferOperatorFromFilter(key1),
@@ -3454,6 +3623,7 @@ var makeFilterChain = ({
3454
3623
  leftOperand = filterExpression[key2];
3455
3624
  }
3456
3625
  filterChain.push({
3626
+ list: _list,
3457
3627
  pathExpression: filterPath,
3458
3628
  rightOperand,
3459
3629
  leftOperand,
@@ -3563,7 +3733,7 @@ var FolderTreeBuilder = class {
3563
3733
  return this._tree;
3564
3734
  }
3565
3735
  update(documentPath, collectionPath) {
3566
- let folderPath = import_path.default.dirname(documentPath);
3736
+ let folderPath = import_path.default.dirname((0, import_schema_tools3.normalizePath)(documentPath));
3567
3737
  if (folderPath === ".") {
3568
3738
  folderPath = "";
3569
3739
  }
@@ -3576,7 +3746,7 @@ var FolderTreeBuilder = class {
3576
3746
  if (!this._tree[current2]) {
3577
3747
  this._tree[current2] = /* @__PURE__ */ new Set();
3578
3748
  }
3579
- this._tree[current2].add(import_path.default.join(current2, part));
3749
+ this._tree[current2].add((0, import_schema_tools3.normalizePath)(import_path.default.join(current2, part)));
3580
3750
  parent.push(part);
3581
3751
  });
3582
3752
  const current = parent.join("/");
@@ -4233,7 +4403,9 @@ var Resolver = class {
4233
4403
  case "boolean":
4234
4404
  case "number":
4235
4405
  case "reference":
4236
- accumulator[field.name] = value;
4406
+ if (value) {
4407
+ accumulator[field.name] = value;
4408
+ }
4237
4409
  break;
4238
4410
  case "image":
4239
4411
  accumulator[field.name] = resolveMediaRelativeToCloud(
@@ -4503,7 +4675,7 @@ var resolve = async ({
4503
4675
  );
4504
4676
  return resolver.getDocument(args.id);
4505
4677
  case "multiCollectionDocument":
4506
- if (typeof value === "string") {
4678
+ if (typeof value === "string" && value !== "") {
4507
4679
  return resolver.getDocument(value);
4508
4680
  }
4509
4681
  if (args && args.collection && info.fieldName === "addPendingDocument") {
@@ -4633,97 +4805,6 @@ var import_path3 = __toESM(require("path"));
4633
4805
  var import_graphql5 = require("graphql");
4634
4806
  var import_micromatch = __toESM(require("micromatch"));
4635
4807
 
4636
- // src/database/util.ts
4637
- var import_toml = __toESM(require("@iarna/toml"));
4638
- var import_js_yaml = __toESM(require("js-yaml"));
4639
- var import_gray_matter = __toESM(require("gray-matter"));
4640
- var import_schema_tools3 = require("@tinacms/schema-tools");
4641
- var matterEngines = {
4642
- toml: {
4643
- parse: (val) => import_toml.default.parse(val),
4644
- stringify: (val) => import_toml.default.stringify(val)
4645
- }
4646
- };
4647
- var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
4648
- var _a, _b;
4649
- const {
4650
- _relativePath,
4651
- _keepTemplateKey,
4652
- _id,
4653
- _template,
4654
- _collection,
4655
- $_body,
4656
- ...rest
4657
- } = content;
4658
- const extra = {};
4659
- if (keepTemplateKey) {
4660
- extra["_template"] = _template;
4661
- }
4662
- const strippedContent = { ...rest, ...extra };
4663
- switch (format) {
4664
- case ".markdown":
4665
- case ".mdx":
4666
- case ".md":
4667
- const ok = import_gray_matter.default.stringify(
4668
- typeof $_body === "undefined" ? "" : `
4669
- ${$_body}`,
4670
- strippedContent,
4671
- {
4672
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
4673
- engines: matterEngines,
4674
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
4675
- }
4676
- );
4677
- return ok;
4678
- case ".json":
4679
- return JSON.stringify(strippedContent, null, 2);
4680
- case ".yaml":
4681
- case ".yml":
4682
- return import_js_yaml.default.safeDump(strippedContent);
4683
- case ".toml":
4684
- return import_toml.default.stringify(strippedContent);
4685
- default:
4686
- throw new Error(`Must specify a valid format, got ${format}`);
4687
- }
4688
- };
4689
- var parseFile = (content, format, yupSchema, markdownParseConfig) => {
4690
- var _a, _b;
4691
- switch (format) {
4692
- case ".markdown":
4693
- case ".mdx":
4694
- case ".md":
4695
- const contentJSON = (0, import_gray_matter.default)(content || "", {
4696
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
4697
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---",
4698
- engines: matterEngines
4699
- });
4700
- const markdownData = {
4701
- ...contentJSON.data,
4702
- $_body: contentJSON.content
4703
- };
4704
- assertShape(markdownData, yupSchema);
4705
- return markdownData;
4706
- case ".json":
4707
- if (!content) {
4708
- return {};
4709
- }
4710
- return JSON.parse(content);
4711
- case ".toml":
4712
- if (!content) {
4713
- return {};
4714
- }
4715
- return import_toml.default.parse(content);
4716
- case ".yaml":
4717
- case ".yml":
4718
- if (!content) {
4719
- return {};
4720
- }
4721
- return import_js_yaml.default.safeLoad(content);
4722
- default:
4723
- throw new Error(`Must specify a valid format, got ${format}`);
4724
- }
4725
- };
4726
-
4727
4808
  // src/database/alias-utils.ts
4728
4809
  var replaceBlockAliases = (template, item) => {
4729
4810
  const output = { ...item };
@@ -5226,6 +5307,7 @@ var Database = class {
5226
5307
  {
5227
5308
  name: field.name,
5228
5309
  type: field.type,
5310
+ list: !!field.list,
5229
5311
  pad: field.type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
5230
5312
  }
5231
5313
  ]
@@ -5236,12 +5318,13 @@ var Database = class {
5236
5318
  for (const index of collection.indexes) {
5237
5319
  indexDefinitions[index.name] = {
5238
5320
  fields: index.fields.map((indexField) => {
5239
- var _a;
5321
+ const field = collection.fields.find(
5322
+ (field2) => indexField.name === field2.name
5323
+ );
5240
5324
  return {
5241
5325
  name: indexField.name,
5242
- type: (_a = collection.fields.find(
5243
- (field) => indexField.name === field.name
5244
- )) == null ? void 0 : _a.type
5326
+ type: field == null ? void 0 : field.type,
5327
+ list: !!(field == null ? void 0 : field.list)
5245
5328
  };
5246
5329
  })
5247
5330
  };
@@ -5329,10 +5412,27 @@ var Database = class {
5329
5412
  if (!matcher || indexDefinition && matcher.length !== indexDefinition.fields.length + 2) {
5330
5413
  continue;
5331
5414
  }
5332
- const filepath = matcher.groups["_filepath_"];
5333
- if (!itemFilter(
5334
- filterSuffixes ? matcher.groups : indexDefinition ? await rootLevel.get(filepath) : value
5335
- )) {
5415
+ let filepath = matcher.groups["_filepath_"];
5416
+ let itemRecord;
5417
+ if (filterSuffixes) {
5418
+ itemRecord = matcher.groups;
5419
+ for (const field of indexDefinition.fields) {
5420
+ if (itemRecord[field.name]) {
5421
+ if (field.list) {
5422
+ itemRecord[field.name] = itemRecord[field.name].split(
5423
+ ARRAY_ITEM_VALUE_SEPARATOR
5424
+ );
5425
+ }
5426
+ }
5427
+ }
5428
+ } else {
5429
+ if (indexDefinition) {
5430
+ itemRecord = await rootLevel.get(filepath);
5431
+ } else {
5432
+ itemRecord = value;
5433
+ }
5434
+ }
5435
+ if (!itemFilter(itemRecord)) {
5336
5436
  continue;
5337
5437
  }
5338
5438
  if (limit !== -1 && edges.length >= limit) {
@@ -5389,13 +5489,24 @@ var Database = class {
5389
5489
  let nextLevel;
5390
5490
  return await this.indexStatusCallbackWrapper(
5391
5491
  async () => {
5392
- const lookup = lookupFromLockFile || JSON.parse(
5393
- await this.bridge.get(
5394
- (0, import_schema_tools3.normalizePath)(
5395
- import_path3.default.join(this.getGeneratedFolder(), "_lookup.json")
5492
+ let lookup;
5493
+ try {
5494
+ lookup = lookupFromLockFile || JSON.parse(
5495
+ await this.bridge.get(
5496
+ (0, import_schema_tools3.normalizePath)(
5497
+ import_path3.default.join(this.getGeneratedFolder(), "_lookup.json")
5498
+ )
5396
5499
  )
5397
- )
5398
- );
5500
+ );
5501
+ } catch (error) {
5502
+ console.error("Error: Unable to find generated lookup file");
5503
+ if (this.tinaDirectory === "tina") {
5504
+ console.error(
5505
+ 'If you are using the .tina folder. Please set {tinaDirectory: ".tina"} in your createDatabase options or migrate to the new tina folder: https://tina.io/blog/tina-config-rearrangements/'
5506
+ );
5507
+ }
5508
+ throw error;
5509
+ }
5399
5510
  let nextVersion;
5400
5511
  if (!this.config.version) {
5401
5512
  await this.level.clear();
@@ -5586,7 +5697,7 @@ This will be an error in the future. See https://tina.io/docs/errors/file-in-mut
5586
5697
  }
5587
5698
  return { warnings };
5588
5699
  };
5589
- this.tinaDirectory = config.tinaDirectory || ".tina";
5700
+ this.tinaDirectory = config.tinaDirectory || "tina";
5590
5701
  this.bridge = config.bridge;
5591
5702
  this.rootLevel = config.level && new LevelProxy(config.level);
5592
5703
  this.indexStatusCallback = config.indexStatusCallback || defaultStatusCallback;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/graphql",
3
- "version": "1.4.11",
3
+ "version": "1.4.13",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.es.js",
6
6
  "typings": "dist/index.d.ts",
@@ -25,8 +25,8 @@
25
25
  "dependencies": {
26
26
  "@graphql-tools/relay-operation-optimizer": "^6.4.1",
27
27
  "@iarna/toml": "^2.2.5",
28
- "@tinacms/mdx": "1.3.9",
29
- "@tinacms/schema-tools": "1.4.3",
28
+ "@tinacms/mdx": "1.3.10",
29
+ "@tinacms/schema-tools": "1.4.4",
30
30
  "abstract-level": "^1.0.3",
31
31
  "body-parser": "^1.19.0",
32
32
  "cors": "^2.8.5",
@@ -84,7 +84,7 @@
84
84
  "directory": "packages/tina-graphql"
85
85
  },
86
86
  "devDependencies": {
87
- "@tinacms/schema-tools": "1.4.3",
87
+ "@tinacms/schema-tools": "1.4.4",
88
88
  "@tinacms/scripts": "1.1.0",
89
89
  "@types/cors": "^2.8.7",
90
90
  "@types/estree": "^0.0.50",