@tinacms/graphql 0.0.0-c852462-20250131014229 → 0.0.0-cacbd0e-20250306051805

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.mjs CHANGED
@@ -3019,7 +3019,7 @@ var validateField = async (field) => {
3019
3019
  // package.json
3020
3020
  var package_default = {
3021
3021
  name: "@tinacms/graphql",
3022
- version: "1.5.11",
3022
+ version: "1.5.14",
3023
3023
  main: "dist/index.js",
3024
3024
  module: "dist/index.mjs",
3025
3025
  typings: "dist/index.d.ts",
@@ -3055,12 +3055,12 @@ var package_default = {
3055
3055
  "@tinacms/schema-tools": "workspace:*",
3056
3056
  "abstract-level": "^1.0.4",
3057
3057
  "date-fns": "^2.30.0",
3058
- "fast-glob": "^3.3.2",
3059
- "fs-extra": "^11.2.0",
3058
+ "fast-glob": "^3.3.3",
3059
+ "fs-extra": "^11.3.0",
3060
3060
  "glob-parent": "^6.0.2",
3061
3061
  graphql: "15.8.0",
3062
3062
  "gray-matter": "^4.0.3",
3063
- "isomorphic-git": "^1.27.1",
3063
+ "isomorphic-git": "^1.29.0",
3064
3064
  "js-sha1": "^0.6.0",
3065
3065
  "js-yaml": "^3.14.1",
3066
3066
  "jsonpath-plus": "10.1.0",
@@ -3070,7 +3070,7 @@ var package_default = {
3070
3070
  "many-level": "^2.0.0",
3071
3071
  micromatch: "4.0.8",
3072
3072
  "normalize-path": "^3.0.0",
3073
- "readable-stream": "^4.5.2",
3073
+ "readable-stream": "^4.7.0",
3074
3074
  scmp: "^2.1.0",
3075
3075
  yup: "^0.32.11"
3076
3076
  },
@@ -3094,17 +3094,17 @@ var package_default = {
3094
3094
  "@types/lru-cache": "^5.1.1",
3095
3095
  "@types/mdast": "^3.0.15",
3096
3096
  "@types/micromatch": "^4.0.9",
3097
- "@types/node": "^22.9.0",
3097
+ "@types/node": "^22.13.1",
3098
3098
  "@types/normalize-path": "^3.0.2",
3099
3099
  "@types/ws": "^7.4.7",
3100
3100
  "@types/yup": "^0.29.14",
3101
3101
  "jest-file-snapshot": "^0.5.0",
3102
3102
  "memory-level": "^1.0.0",
3103
3103
  nodemon: "3.1.4",
3104
- typescript: "^5.6.3",
3105
- vite: "^4.3.9",
3106
- vitest: "^0.32.2",
3107
- zod: "^3.23.8"
3104
+ typescript: "^5.7.3",
3105
+ vite: "^4.5.9",
3106
+ vitest: "^0.32.4",
3107
+ zod: "^3.24.2"
3108
3108
  }
3109
3109
  };
3110
3110
 
@@ -3260,7 +3260,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3260
3260
  await builder.buildCreateCollectionFolderMutation()
3261
3261
  );
3262
3262
  await sequential(collections, async (collection) => {
3263
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3263
+ queryTypeDefinitionFields.push(
3264
+ await builder.collectionDocument(collection)
3265
+ );
3264
3266
  if (collection.isAuthCollection) {
3265
3267
  queryTypeDefinitionFields.push(
3266
3268
  await builder.authenticationCollectionDocument(collection)
@@ -3575,7 +3577,9 @@ var LevelProxyHandler = {
3575
3577
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3576
3578
  }
3577
3579
  if (typeof target[property] !== "function") {
3578
- throw new Error(`The property, ${property.toString()}, is not a function`);
3580
+ throw new Error(
3581
+ `The property, ${property.toString()}, is not a function`
3582
+ );
3579
3583
  }
3580
3584
  if (property === "get") {
3581
3585
  return async (...args) => {
@@ -3960,6 +3964,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3960
3964
 
3961
3965
  // src/database/datalayer.ts
3962
3966
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
3967
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
3968
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
3969
+ var REFS_PATH_FIELD = "__tina_ref_path__";
3963
3970
  var DEFAULT_NUMERIC_LPAD = 4;
3964
3971
  var applyPadding = (input, pad) => {
3965
3972
  if (pad) {
@@ -4533,6 +4540,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4533
4540
  }
4534
4541
  return result;
4535
4542
  };
4543
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4544
+ const result = [];
4545
+ if (collection) {
4546
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4547
+ if (!referencePaths.length) {
4548
+ continue;
4549
+ }
4550
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4551
+ const refSublevel = collectionSublevel.sublevel(
4552
+ REFS_COLLECTIONS_SORT_KEY,
4553
+ SUBLEVEL_OPTIONS
4554
+ );
4555
+ const references2 = {};
4556
+ for (const path7 of referencePaths) {
4557
+ const ref = JSONPath({ path: path7, json: data });
4558
+ if (!ref) {
4559
+ continue;
4560
+ }
4561
+ if (Array.isArray(ref)) {
4562
+ for (const r of ref) {
4563
+ if (!r) {
4564
+ continue;
4565
+ }
4566
+ if (references2[r]) {
4567
+ references2[r].push(path7);
4568
+ } else {
4569
+ references2[r] = [path7];
4570
+ }
4571
+ }
4572
+ } else {
4573
+ if (references2[ref]) {
4574
+ references2[ref].push(path7);
4575
+ } else {
4576
+ references2[ref] = [path7];
4577
+ }
4578
+ }
4579
+ }
4580
+ for (const ref of Object.keys(references2)) {
4581
+ for (const path7 of references2[ref]) {
4582
+ result.push({
4583
+ type: opType,
4584
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4585
+ sublevel: refSublevel,
4586
+ value: opType === "put" ? {} : void 0
4587
+ });
4588
+ }
4589
+ }
4590
+ }
4591
+ }
4592
+ return result;
4593
+ };
4536
4594
  var makeStringEscaper = (regex, replacement) => {
4537
4595
  return (input) => {
4538
4596
  if (Array.isArray(input)) {
@@ -4557,16 +4615,7 @@ var stringEscaper = makeStringEscaper(
4557
4615
  var createResolver = (args) => {
4558
4616
  return new Resolver(args);
4559
4617
  };
4560
- var resolveFieldData = async (args) => {
4561
- const {
4562
- field: { namespace, ...field },
4563
- rawData,
4564
- accumulator,
4565
- tinaSchema,
4566
- config,
4567
- isAudit,
4568
- context
4569
- } = args;
4618
+ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4570
4619
  if (!rawData) {
4571
4620
  return void 0;
4572
4621
  }
@@ -4606,11 +4655,9 @@ var resolveFieldData = async (args) => {
4606
4655
  break;
4607
4656
  case "rich-text":
4608
4657
  const tree = parseMDX(
4609
- // @ts-ignore value is unknown
4610
4658
  value,
4611
4659
  field,
4612
- (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema),
4613
- context
4660
+ (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4614
4661
  );
4615
4662
  if (tree?.children[0]?.type === "invalid_markdown") {
4616
4663
  if (isAudit) {
@@ -4641,15 +4688,14 @@ var resolveFieldData = async (args) => {
4641
4688
  });
4642
4689
  const payload = {};
4643
4690
  await sequential(template.fields, async (field2) => {
4644
- await resolveFieldData({
4645
- field: field2,
4646
- rawData: item,
4647
- accumulator: payload,
4691
+ await resolveFieldData(
4692
+ field2,
4693
+ item,
4694
+ payload,
4648
4695
  tinaSchema,
4649
4696
  config,
4650
- isAudit,
4651
- context
4652
- });
4697
+ isAudit
4698
+ );
4653
4699
  });
4654
4700
  const isUnion = !!field.templates;
4655
4701
  return isUnion ? {
@@ -4670,15 +4716,14 @@ var resolveFieldData = async (args) => {
4670
4716
  });
4671
4717
  const payload = {};
4672
4718
  await sequential(template.fields, async (field2) => {
4673
- await resolveFieldData({
4674
- field: field2,
4675
- rawData: value,
4676
- accumulator: payload,
4719
+ await resolveFieldData(
4720
+ field2,
4721
+ value,
4722
+ payload,
4677
4723
  tinaSchema,
4678
4724
  config,
4679
- isAudit,
4680
- context
4681
- });
4725
+ isAudit
4726
+ );
4682
4727
  });
4683
4728
  const isUnion = !!field.templates;
4684
4729
  accumulator[field.name] = isUnion ? {
@@ -4692,8 +4737,7 @@ var resolveFieldData = async (args) => {
4692
4737
  }
4693
4738
  return accumulator;
4694
4739
  };
4695
- var transformDocumentIntoPayload = async (args) => {
4696
- const { fullPath, rawData, tinaSchema, config, isAudit, context } = args;
4740
+ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit, hasReferences) => {
4697
4741
  const collection = tinaSchema.getCollection(rawData._collection);
4698
4742
  try {
4699
4743
  const template = tinaSchema.getTemplateForData({
@@ -4713,15 +4757,14 @@ var transformDocumentIntoPayload = async (args) => {
4713
4757
  };
4714
4758
  try {
4715
4759
  await sequential(template.fields, async (field) => {
4716
- return resolveFieldData({
4760
+ return resolveFieldData(
4717
4761
  field,
4718
4762
  rawData,
4719
- accumulator: data,
4763
+ data,
4720
4764
  tinaSchema,
4721
4765
  config,
4722
- isAudit,
4723
- context
4724
- });
4766
+ isAudit
4767
+ );
4725
4768
  });
4726
4769
  } catch (e) {
4727
4770
  throw new TinaParseDocumentError({
@@ -4748,7 +4791,7 @@ var transformDocumentIntoPayload = async (args) => {
4748
4791
  basename,
4749
4792
  filename,
4750
4793
  extension,
4751
- hasReferences: args.hasReferences,
4794
+ hasReferences,
4752
4795
  path: fullPath,
4753
4796
  relativePath,
4754
4797
  breadcrumbs,
@@ -4768,29 +4811,33 @@ var transformDocumentIntoPayload = async (args) => {
4768
4811
  throw e;
4769
4812
  }
4770
4813
  };
4771
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4814
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4815
+ let updated = false;
4772
4816
  if (!path7.includes(".") && !path7.includes("[")) {
4773
- if (path7 in obj) {
4817
+ if (path7 in obj && obj[path7] === oldValue) {
4774
4818
  obj[path7] = newValue;
4819
+ updated = true;
4775
4820
  }
4776
- return obj;
4821
+ return { object: obj, updated };
4777
4822
  }
4778
- const parentPath = path7.replace(/\.[^.]+$/, "");
4779
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4823
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4824
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4780
4825
  const parents = JSONPath2({ path: parentPath, json: obj, resultType: "value" });
4781
4826
  if (parents.length > 0) {
4782
4827
  parents.forEach((parent) => {
4783
4828
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4784
- parent[keyToUpdate] = newValue;
4829
+ if (parent[keyToUpdate] === oldValue) {
4830
+ parent[keyToUpdate] = newValue;
4831
+ updated = true;
4832
+ }
4785
4833
  }
4786
4834
  });
4787
4835
  }
4788
- return obj;
4836
+ return { object: obj, updated };
4789
4837
  };
4790
4838
  var Resolver = class {
4791
4839
  constructor(init) {
4792
4840
  this.init = init;
4793
- this.context = {};
4794
4841
  this.resolveCollection = async (args, collectionName, hasDocuments) => {
4795
4842
  const collection = this.tinaSchema.getCollection(collectionName);
4796
4843
  const extraFields = {};
@@ -4803,7 +4850,9 @@ var Resolver = class {
4803
4850
  };
4804
4851
  this.getRaw = async (fullPath) => {
4805
4852
  if (typeof fullPath !== "string") {
4806
- throw new Error(`fullPath must be of type string for getDocument request`);
4853
+ throw new Error(
4854
+ `fullPath must be of type string for getDocument request`
4855
+ );
4807
4856
  }
4808
4857
  return this.database.get(fullPath);
4809
4858
  };
@@ -4821,37 +4870,37 @@ var Resolver = class {
4821
4870
  path: rawData["__folderPath"]
4822
4871
  };
4823
4872
  } else {
4824
- this.context = { ...rawData };
4825
- return transformDocumentIntoPayload({
4873
+ return transformDocumentIntoPayload(
4826
4874
  fullPath,
4827
4875
  rawData,
4828
- tinaSchema: this.tinaSchema,
4829
- config: this.config,
4830
- isAudit: this.isAudit,
4831
- context: this.context
4832
- });
4876
+ this.tinaSchema,
4877
+ this.config,
4878
+ this.isAudit
4879
+ );
4833
4880
  }
4834
4881
  };
4835
4882
  this.getDocument = async (fullPath, opts = {}) => {
4836
4883
  if (typeof fullPath !== "string") {
4837
- throw new Error(`fullPath must be of type string for getDocument request`);
4884
+ throw new Error(
4885
+ `fullPath must be of type string for getDocument request`
4886
+ );
4838
4887
  }
4839
4888
  const rawData = await this.getRaw(fullPath);
4840
- this.context = { ...rawData };
4841
4889
  const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4842
- return transformDocumentIntoPayload({
4890
+ return transformDocumentIntoPayload(
4843
4891
  fullPath,
4844
4892
  rawData,
4845
- tinaSchema: this.tinaSchema,
4846
- config: this.config,
4847
- isAudit: this.isAudit,
4848
- context: this.context,
4893
+ this.tinaSchema,
4894
+ this.config,
4895
+ this.isAudit,
4849
4896
  hasReferences
4850
- });
4897
+ );
4851
4898
  };
4852
4899
  this.deleteDocument = async (fullPath) => {
4853
4900
  if (typeof fullPath !== "string") {
4854
- throw new Error(`fullPath must be of type string for getDocument request`);
4901
+ throw new Error(
4902
+ `fullPath must be of type string for getDocument request`
4903
+ );
4855
4904
  }
4856
4905
  await this.database.delete(fullPath);
4857
4906
  };
@@ -5006,31 +5055,34 @@ var Resolver = class {
5006
5055
  }) => {
5007
5056
  const doc = await this.getDocument(realPath);
5008
5057
  const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5009
- let values;
5010
5058
  if (isAddPendingDocument === true) {
5011
5059
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5012
- const params = this.buildParams(args);
5060
+ const params2 = this.buildParams(args);
5013
5061
  switch (templateInfo.type) {
5014
5062
  case "object":
5015
- if (params) {
5016
- const mutationValues = await this.buildFieldMutations(
5017
- params,
5063
+ if (params2) {
5064
+ const values = await this.buildFieldMutations(
5065
+ params2,
5018
5066
  templateInfo.template,
5019
5067
  doc?._rawData
5020
5068
  );
5021
- values = { ...oldDoc, ...mutationValues };
5069
+ await this.database.put(
5070
+ realPath,
5071
+ { ...oldDoc, ...values },
5072
+ collection.name
5073
+ );
5022
5074
  }
5023
5075
  break;
5024
- case "union": {
5076
+ case "union":
5025
5077
  await sequential(templateInfo.templates, async (template) => {
5026
- const templateParams = params[lastItem(template.namespace)];
5078
+ const templateParams = params2[lastItem(template.namespace)];
5027
5079
  if (templateParams) {
5028
5080
  if (typeof templateParams === "string") {
5029
5081
  throw new Error(
5030
5082
  `Expected to find an object for template params, but got string`
5031
5083
  );
5032
5084
  }
5033
- values = {
5085
+ const values = {
5034
5086
  ...oldDoc,
5035
5087
  ...await this.buildFieldMutations(
5036
5088
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
@@ -5040,23 +5092,21 @@ var Resolver = class {
5040
5092
  ),
5041
5093
  _template: lastItem(template.namespace)
5042
5094
  };
5095
+ await this.database.put(realPath, values, collection.name);
5043
5096
  }
5044
5097
  });
5045
- }
5046
5098
  }
5047
- } else {
5048
- const params = await this.buildObjectMutations(
5049
- //@ts-expect-error FIXME: Argument of type 'unknown' is not assignable to parameter of type 'FieldParams'
5050
- isCollectionSpecific ? args.params : args.params[collection.name],
5051
- collection,
5052
- doc?._rawData
5053
- );
5054
- values = { ...oldDoc, ...params };
5099
+ return this.getDocument(realPath);
5055
5100
  }
5056
- const _tinaEmbeds = this.context?._tinaEmbeds ? { _tinaEmbeds: this.context._tinaEmbeds } : {};
5101
+ const params = await this.buildObjectMutations(
5102
+ //@ts-ignore
5103
+ isCollectionSpecific ? args.params : args.params[collection.name],
5104
+ collection,
5105
+ doc?._rawData
5106
+ );
5057
5107
  await this.database.put(
5058
5108
  realPath,
5059
- { ...values, ..._tinaEmbeds },
5109
+ { ...oldDoc, ...params },
5060
5110
  collection.name
5061
5111
  );
5062
5112
  return this.getDocument(realPath);
@@ -5171,17 +5221,35 @@ var Resolver = class {
5171
5221
  await this.deleteDocument(realPath);
5172
5222
  if (await this.hasReferences(realPath, collection)) {
5173
5223
  const collRefs = await this.findReferences(realPath, collection);
5174
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5175
- for (const [refPath, refs] of Object.entries(refFields)) {
5176
- let refDoc = await this.getRaw(refPath);
5177
- for (const ref of refs) {
5178
- refDoc = updateObjectWithJsonPath(
5224
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5225
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5226
+ docsWithRefs
5227
+ )) {
5228
+ let refDoc = await this.getRaw(pathToDocWithRef);
5229
+ let hasUpdate = false;
5230
+ for (const path7 of referencePaths) {
5231
+ const { object: object2, updated } = updateObjectWithJsonPath(
5179
5232
  refDoc,
5180
- ref.path.join("."),
5233
+ path7,
5234
+ realPath,
5181
5235
  null
5182
5236
  );
5237
+ refDoc = object2;
5238
+ hasUpdate = updated || hasUpdate;
5239
+ }
5240
+ if (hasUpdate) {
5241
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5242
+ if (!collectionWithRef) {
5243
+ throw new Error(
5244
+ `Unable to find collection for ${pathToDocWithRef}`
5245
+ );
5246
+ }
5247
+ await this.database.put(
5248
+ pathToDocWithRef,
5249
+ refDoc,
5250
+ collectionWithRef.name
5251
+ );
5183
5252
  }
5184
- await this.database.put(refPath, refDoc, collection2);
5185
5253
  }
5186
5254
  }
5187
5255
  }
@@ -5201,26 +5269,49 @@ var Resolver = class {
5201
5269
  collection?.path,
5202
5270
  args.params.relativePath
5203
5271
  );
5272
+ if (newRealPath === realPath) {
5273
+ return doc;
5274
+ }
5204
5275
  await this.database.put(newRealPath, doc._rawData, collection.name);
5205
5276
  await this.deleteDocument(realPath);
5206
5277
  const collRefs = await this.findReferences(realPath, collection);
5207
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5208
- for (const [refPath, refs] of Object.entries(refFields)) {
5209
- let refDoc = await this.getRaw(refPath);
5210
- for (const ref of refs) {
5211
- refDoc = updateObjectWithJsonPath(
5212
- refDoc,
5213
- ref.path.join("."),
5278
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5279
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5280
+ docsWithRefs
5281
+ )) {
5282
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5283
+ let hasUpdate = false;
5284
+ for (const path7 of referencePaths) {
5285
+ const { object: object2, updated } = updateObjectWithJsonPath(
5286
+ docWithRef,
5287
+ path7,
5288
+ realPath,
5214
5289
  newRealPath
5215
5290
  );
5291
+ docWithRef = object2;
5292
+ hasUpdate = updated || hasUpdate;
5293
+ }
5294
+ if (hasUpdate) {
5295
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5296
+ if (!collectionWithRef) {
5297
+ throw new Error(
5298
+ `Unable to find collection for ${pathToDocWithRef}`
5299
+ );
5300
+ }
5301
+ await this.database.put(
5302
+ pathToDocWithRef,
5303
+ docWithRef,
5304
+ collectionWithRef.name
5305
+ );
5216
5306
  }
5217
- await this.database.put(refPath, refDoc, collection2);
5218
5307
  }
5219
5308
  }
5220
5309
  return this.getDocument(newRealPath);
5221
5310
  }
5222
5311
  if (alreadyExists === false) {
5223
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5312
+ throw new Error(
5313
+ `Unable to update document, ${realPath} does not exist`
5314
+ );
5224
5315
  }
5225
5316
  return this.updateResolveDocument({
5226
5317
  collection,
@@ -5346,35 +5437,30 @@ var Resolver = class {
5346
5437
  */
5347
5438
  this.hasReferences = async (id, c) => {
5348
5439
  let count = 0;
5349
- const deepRefs = this.tinaSchema.findReferences(c.name);
5350
- for (const [collection, refs] of Object.entries(deepRefs)) {
5351
- for (const ref of refs) {
5352
- await this.database.query(
5353
- {
5354
- collection,
5355
- filterChain: makeFilterChain({
5356
- conditions: [
5357
- {
5358
- filterPath: ref.path.join("."),
5359
- filterExpression: {
5360
- _type: "reference",
5361
- _list: false,
5362
- eq: id
5363
- }
5364
- }
5365
- ]
5366
- }),
5367
- sort: ref.field.name
5368
- },
5369
- (refId) => {
5370
- count++;
5371
- return refId;
5372
- }
5373
- );
5374
- if (count) {
5375
- return true;
5376
- }
5440
+ await this.database.query(
5441
+ {
5442
+ collection: c.name,
5443
+ filterChain: makeFilterChain({
5444
+ conditions: [
5445
+ {
5446
+ filterPath: REFS_REFERENCE_FIELD,
5447
+ filterExpression: {
5448
+ _type: "string",
5449
+ _list: false,
5450
+ eq: id
5451
+ }
5452
+ }
5453
+ ]
5454
+ }),
5455
+ sort: REFS_COLLECTIONS_SORT_KEY
5456
+ },
5457
+ (refId) => {
5458
+ count++;
5459
+ return refId;
5377
5460
  }
5461
+ );
5462
+ if (count) {
5463
+ return true;
5378
5464
  }
5379
5465
  return false;
5380
5466
  };
@@ -5382,46 +5468,41 @@ var Resolver = class {
5382
5468
  * Finds references to a document
5383
5469
  * @param id the id of the document to find references to
5384
5470
  * @param c the collection to find references in
5385
- * @returns references to the document in the form of a map of collection names to a list of fields that reference the document
5471
+ * @returns a map of references to the document
5386
5472
  */
5387
5473
  this.findReferences = async (id, c) => {
5388
5474
  const references = {};
5389
- const deepRefs = this.tinaSchema.findReferences(c.name);
5390
- for (const [collection, refs] of Object.entries(deepRefs)) {
5391
- for (const ref of refs) {
5392
- await this.database.query(
5393
- {
5394
- collection,
5395
- filterChain: makeFilterChain({
5396
- conditions: [
5397
- {
5398
- filterPath: ref.path.join("."),
5399
- filterExpression: {
5400
- _type: "reference",
5401
- _list: false,
5402
- eq: id
5403
- }
5404
- }
5405
- ]
5406
- }),
5407
- sort: ref.field.name
5408
- },
5409
- (refId) => {
5410
- if (!references[collection]) {
5411
- references[collection] = {};
5412
- }
5413
- if (!references[collection][refId]) {
5414
- references[collection][refId] = [];
5475
+ await this.database.query(
5476
+ {
5477
+ collection: c.name,
5478
+ filterChain: makeFilterChain({
5479
+ conditions: [
5480
+ {
5481
+ filterPath: REFS_REFERENCE_FIELD,
5482
+ filterExpression: {
5483
+ _type: "string",
5484
+ _list: false,
5485
+ eq: id
5486
+ }
5415
5487
  }
5416
- references[collection][refId].push({
5417
- path: ref.path,
5418
- field: ref.field
5419
- });
5420
- return refId;
5421
- }
5422
- );
5488
+ ]
5489
+ }),
5490
+ sort: REFS_COLLECTIONS_SORT_KEY
5491
+ },
5492
+ (refId, rawItem) => {
5493
+ if (!references[c.name]) {
5494
+ references[c.name] = {};
5495
+ }
5496
+ if (!references[c.name][refId]) {
5497
+ references[c.name][refId] = [];
5498
+ }
5499
+ const referencePath = rawItem?.[REFS_PATH_FIELD];
5500
+ if (referencePath) {
5501
+ references[c.name][refId].push(referencePath);
5502
+ }
5503
+ return refId;
5423
5504
  }
5424
- }
5505
+ );
5425
5506
  return references;
5426
5507
  };
5427
5508
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
@@ -5492,15 +5573,13 @@ var Resolver = class {
5492
5573
  break;
5493
5574
  case "rich-text":
5494
5575
  accum[fieldName] = stringifyMDX(
5495
- // @ts-ignore
5496
5576
  fieldValue,
5497
5577
  field,
5498
5578
  (fieldValue2) => resolveMediaCloudToRelative(
5499
5579
  fieldValue2,
5500
5580
  this.config,
5501
5581
  this.tinaSchema.schema
5502
- ),
5503
- this.context
5582
+ )
5504
5583
  );
5505
5584
  break;
5506
5585
  case "reference":
@@ -6167,6 +6246,7 @@ var Database = class {
6167
6246
  );
6168
6247
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6169
6248
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6249
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6170
6250
  const normalizedPath = normalizePath(filepath);
6171
6251
  if (!collection?.isDetached) {
6172
6252
  if (this.bridge) {
@@ -6195,6 +6275,14 @@ var Database = class {
6195
6275
  let delOps = [];
6196
6276
  if (!isGitKeep(normalizedPath, collection)) {
6197
6277
  putOps = [
6278
+ ...makeRefOpsForDocument(
6279
+ normalizedPath,
6280
+ collection?.name,
6281
+ collectionReferences,
6282
+ dataFields,
6283
+ "put",
6284
+ level
6285
+ ),
6198
6286
  ...makeIndexOpsForDocument(
6199
6287
  normalizedPath,
6200
6288
  collection?.name,
@@ -6218,6 +6306,14 @@ var Database = class {
6218
6306
  SUBLEVEL_OPTIONS
6219
6307
  ).get(normalizedPath);
6220
6308
  delOps = existingItem ? [
6309
+ ...makeRefOpsForDocument(
6310
+ normalizedPath,
6311
+ collection?.name,
6312
+ collectionReferences,
6313
+ existingItem,
6314
+ "del",
6315
+ level
6316
+ ),
6221
6317
  ...makeIndexOpsForDocument(
6222
6318
  normalizedPath,
6223
6319
  collection?.name,
@@ -6265,6 +6361,7 @@ var Database = class {
6265
6361
  );
6266
6362
  collectionIndexDefinitions = indexDefinitions?.[collectionName];
6267
6363
  }
6364
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6268
6365
  const normalizedPath = normalizePath(filepath);
6269
6366
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6270
6367
  const collection = await this.collectionForPath(filepath);
@@ -6312,6 +6409,14 @@ var Database = class {
6312
6409
  let delOps = [];
6313
6410
  if (!isGitKeep(normalizedPath, collection)) {
6314
6411
  putOps = [
6412
+ ...makeRefOpsForDocument(
6413
+ normalizedPath,
6414
+ collectionName,
6415
+ collectionReferences,
6416
+ dataFields,
6417
+ "put",
6418
+ level
6419
+ ),
6315
6420
  ...makeIndexOpsForDocument(
6316
6421
  normalizedPath,
6317
6422
  collectionName,
@@ -6335,6 +6440,14 @@ var Database = class {
6335
6440
  SUBLEVEL_OPTIONS
6336
6441
  ).get(normalizedPath);
6337
6442
  delOps = existingItem ? [
6443
+ ...makeRefOpsForDocument(
6444
+ normalizedPath,
6445
+ collectionName,
6446
+ collectionReferences,
6447
+ existingItem,
6448
+ "del",
6449
+ level
6450
+ ),
6338
6451
  ...makeIndexOpsForDocument(
6339
6452
  normalizedPath,
6340
6453
  collectionName,
@@ -6497,6 +6610,22 @@ var Database = class {
6497
6610
  this.tinaSchema = await createSchema({ schema });
6498
6611
  return this.tinaSchema;
6499
6612
  };
6613
+ this.getCollectionReferences = async (level) => {
6614
+ if (this.collectionReferences) {
6615
+ return this.collectionReferences;
6616
+ }
6617
+ const result = {};
6618
+ const schema = await this.getSchema(level || this.contentLevel);
6619
+ const collections = schema.getCollections();
6620
+ for (const collection of collections) {
6621
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6622
+ collection.name
6623
+ );
6624
+ result[collection.name] = collectionReferences;
6625
+ }
6626
+ this.collectionReferences = result;
6627
+ return result;
6628
+ };
6500
6629
  this.getIndexDefinitions = async (level) => {
6501
6630
  if (!this.collectionIndexDefinitions) {
6502
6631
  await new Promise(async (resolve2, reject) => {
@@ -6506,8 +6635,23 @@ var Database = class {
6506
6635
  const collections = schema.getCollections();
6507
6636
  for (const collection of collections) {
6508
6637
  const indexDefinitions = {
6509
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6638
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6510
6639
  // provide a default sort key which is the file sort
6640
+ // pseudo-index for the collection's references
6641
+ [REFS_COLLECTIONS_SORT_KEY]: {
6642
+ fields: [
6643
+ {
6644
+ name: REFS_REFERENCE_FIELD,
6645
+ type: "string",
6646
+ list: false
6647
+ },
6648
+ {
6649
+ name: REFS_PATH_FIELD,
6650
+ type: "string",
6651
+ list: false
6652
+ }
6653
+ ]
6654
+ }
6511
6655
  };
6512
6656
  if (collection.fields) {
6513
6657
  for (const field of collection.fields) {
@@ -6658,29 +6802,36 @@ var Database = class {
6658
6802
  }
6659
6803
  startKey = startKey || key || "";
6660
6804
  endKey = key || "";
6661
- edges = [...edges, { cursor: key, path: filepath }];
6805
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6662
6806
  }
6663
6807
  return {
6664
- edges: await sequential(edges, async (edge) => {
6665
- try {
6666
- const node = await hydrator(edge.path);
6667
- return {
6668
- node,
6669
- cursor: btoa(edge.cursor)
6670
- };
6671
- } catch (error) {
6672
- console.log(error);
6673
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6674
- throw new TinaQueryError({
6675
- originalError: error,
6676
- file: edge.path,
6677
- collection: collection.name,
6678
- stack: error.stack
6679
- });
6808
+ edges: await sequential(
6809
+ edges,
6810
+ async ({
6811
+ cursor,
6812
+ path: path7,
6813
+ value
6814
+ }) => {
6815
+ try {
6816
+ const node = await hydrator(path7, value);
6817
+ return {
6818
+ node,
6819
+ cursor: btoa(cursor)
6820
+ };
6821
+ } catch (error) {
6822
+ console.log(error);
6823
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6824
+ throw new TinaQueryError({
6825
+ originalError: error,
6826
+ file: path7,
6827
+ collection: collection.name,
6828
+ stack: error.stack
6829
+ });
6830
+ }
6831
+ throw error;
6680
6832
  }
6681
- throw error;
6682
6833
  }
6683
- }),
6834
+ ),
6684
6835
  pageInfo: {
6685
6836
  hasPreviousPage,
6686
6837
  hasNextPage,
@@ -6826,6 +6977,7 @@ var Database = class {
6826
6977
  throw new Error(`No collection found for path: ${filepath}`);
6827
6978
  }
6828
6979
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6980
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6829
6981
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6830
6982
  let level = this.contentLevel;
6831
6983
  if (collection?.isDetached) {
@@ -6844,6 +6996,14 @@ var Database = class {
6844
6996
  collection.path || ""
6845
6997
  );
6846
6998
  await this.contentLevel.batch([
6999
+ ...makeRefOpsForDocument(
7000
+ normalizedPath,
7001
+ collection.name,
7002
+ collectionReferences,
7003
+ item,
7004
+ "del",
7005
+ level
7006
+ ),
6847
7007
  ...makeIndexOpsForDocument(
6848
7008
  normalizedPath,
6849
7009
  collection.name,
@@ -6921,7 +7081,13 @@ var Database = class {
6921
7081
  );
6922
7082
  }
6923
7083
  } else {
6924
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7084
+ await _indexContent(
7085
+ this,
7086
+ level,
7087
+ contentPaths,
7088
+ enqueueOps,
7089
+ collection
7090
+ );
6925
7091
  }
6926
7092
  }
6927
7093
  );
@@ -7071,14 +7237,16 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7071
7237
  }
7072
7238
  collectionPath = collection.path;
7073
7239
  }
7240
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7074
7241
  const tinaSchema = await database.getSchema();
7075
7242
  let templateInfo = null;
7076
7243
  if (collection) {
7077
7244
  templateInfo = tinaSchema.getTemplatesForCollectable(collection);
7078
7245
  }
7079
7246
  const folderTreeBuilder = new FolderTreeBuilder();
7080
- await sequential(documentPaths, async (filepath) => {
7247
+ async function processFile(filepath) {
7081
7248
  try {
7249
+ console.log(`Preloading ${filepath}`);
7082
7250
  const aliasedData = await loadAndParseWithAliases(
7083
7251
  database.bridge,
7084
7252
  filepath,
@@ -7092,12 +7260,62 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7092
7260
  await hashPasswordValues(aliasedData, passwordFields);
7093
7261
  }
7094
7262
  const normalizedPath = normalizePath(filepath);
7263
+ const rootSublevel = level.sublevel(
7264
+ CONTENT_ROOT_PREFIX,
7265
+ SUBLEVEL_OPTIONS
7266
+ );
7095
7267
  const folderKey = folderTreeBuilder.update(
7096
7268
  normalizedPath,
7097
7269
  collectionPath || ""
7098
7270
  );
7271
+ const item = await rootSublevel.get(normalizedPath);
7272
+ await new Promise((res) => setTimeout(res, 5e3));
7273
+ console.log("Ceasing preload");
7274
+ if (item) {
7275
+ console.log("Running deletion operations");
7276
+ await database.contentLevel.batch([
7277
+ ...makeRefOpsForDocument(
7278
+ normalizedPath,
7279
+ collection?.name,
7280
+ collectionReferences,
7281
+ item,
7282
+ "del",
7283
+ level
7284
+ ),
7285
+ ...makeIndexOpsForDocument(
7286
+ normalizedPath,
7287
+ collection.name,
7288
+ collectionIndexDefinitions,
7289
+ item,
7290
+ "del",
7291
+ level
7292
+ ),
7293
+ // folder indices
7294
+ ...makeIndexOpsForDocument(
7295
+ normalizedPath,
7296
+ `${collection.name}_${folderKey}`,
7297
+ collectionIndexDefinitions,
7298
+ item,
7299
+ "del",
7300
+ level
7301
+ ),
7302
+ {
7303
+ type: "del",
7304
+ key: normalizedPath,
7305
+ sublevel: rootSublevel
7306
+ }
7307
+ ]);
7308
+ }
7099
7309
  if (!isGitKeep(filepath, collection)) {
7100
7310
  await enqueueOps([
7311
+ ...makeRefOpsForDocument(
7312
+ normalizedPath,
7313
+ collection?.name,
7314
+ collectionReferences,
7315
+ aliasedData,
7316
+ "put",
7317
+ level
7318
+ ),
7101
7319
  ...makeIndexOpsForDocument(
7102
7320
  normalizedPath,
7103
7321
  collection?.name,
@@ -7134,7 +7352,10 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7134
7352
  stack: error.stack
7135
7353
  });
7136
7354
  }
7137
- });
7355
+ }
7356
+ ;
7357
+ const filePromises = documentPaths.map(processFile);
7358
+ await Promise.all(filePromises);
7138
7359
  if (collection) {
7139
7360
  await enqueueOps(
7140
7361
  makeFolderOpsForCollection(
@@ -7161,6 +7382,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7161
7382
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7162
7383
  }
7163
7384
  }
7385
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7164
7386
  const tinaSchema = await database.getSchema();
7165
7387
  let templateInfo = null;
7166
7388
  if (collection) {
@@ -7184,6 +7406,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7184
7406
  item
7185
7407
  ) : item;
7186
7408
  await enqueueOps([
7409
+ ...makeRefOpsForDocument(
7410
+ itemKey,
7411
+ collection?.name,
7412
+ collectionReferences,
7413
+ aliasedData,
7414
+ "del",
7415
+ database.contentLevel
7416
+ ),
7187
7417
  ...makeIndexOpsForDocument(
7188
7418
  itemKey,
7189
7419
  collection.name,