@tinacms/graphql 0.0.0-c852462-20250131014229 → 0.0.0-c965b5f-20250426163441

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
@@ -1847,7 +1847,7 @@ var Builder = class {
1847
1847
  * ```
1848
1848
  *
1849
1849
  * @public
1850
- * @param collection a Tina Cloud collection
1850
+ * @param collection a TinaCloud collection
1851
1851
  */
1852
1852
  this.collectionFragment = async (collection) => {
1853
1853
  const name = NAMER.dataTypeName(collection.namespace);
@@ -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.16",
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,37 @@ 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;
4777
- }
4778
- const parentPath = path7.replace(/\.[^.]+$/, "");
4779
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4780
- const parents = JSONPath2({ path: parentPath, json: obj, resultType: "value" });
4821
+ return { object: obj, updated };
4822
+ }
4823
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4824
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4825
+ const parents = JSONPath2({
4826
+ path: parentPath,
4827
+ json: obj,
4828
+ resultType: "value"
4829
+ });
4781
4830
  if (parents.length > 0) {
4782
4831
  parents.forEach((parent) => {
4783
4832
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4784
- parent[keyToUpdate] = newValue;
4833
+ if (parent[keyToUpdate] === oldValue) {
4834
+ parent[keyToUpdate] = newValue;
4835
+ updated = true;
4836
+ }
4785
4837
  }
4786
4838
  });
4787
4839
  }
4788
- return obj;
4840
+ return { object: obj, updated };
4789
4841
  };
4790
4842
  var Resolver = class {
4791
4843
  constructor(init) {
4792
4844
  this.init = init;
4793
- this.context = {};
4794
4845
  this.resolveCollection = async (args, collectionName, hasDocuments) => {
4795
4846
  const collection = this.tinaSchema.getCollection(collectionName);
4796
4847
  const extraFields = {};
@@ -4803,7 +4854,9 @@ var Resolver = class {
4803
4854
  };
4804
4855
  this.getRaw = async (fullPath) => {
4805
4856
  if (typeof fullPath !== "string") {
4806
- throw new Error(`fullPath must be of type string for getDocument request`);
4857
+ throw new Error(
4858
+ `fullPath must be of type string for getDocument request`
4859
+ );
4807
4860
  }
4808
4861
  return this.database.get(fullPath);
4809
4862
  };
@@ -4821,37 +4874,37 @@ var Resolver = class {
4821
4874
  path: rawData["__folderPath"]
4822
4875
  };
4823
4876
  } else {
4824
- this.context = { ...rawData };
4825
- return transformDocumentIntoPayload({
4877
+ return transformDocumentIntoPayload(
4826
4878
  fullPath,
4827
4879
  rawData,
4828
- tinaSchema: this.tinaSchema,
4829
- config: this.config,
4830
- isAudit: this.isAudit,
4831
- context: this.context
4832
- });
4880
+ this.tinaSchema,
4881
+ this.config,
4882
+ this.isAudit
4883
+ );
4833
4884
  }
4834
4885
  };
4835
4886
  this.getDocument = async (fullPath, opts = {}) => {
4836
4887
  if (typeof fullPath !== "string") {
4837
- throw new Error(`fullPath must be of type string for getDocument request`);
4888
+ throw new Error(
4889
+ `fullPath must be of type string for getDocument request`
4890
+ );
4838
4891
  }
4839
4892
  const rawData = await this.getRaw(fullPath);
4840
- this.context = { ...rawData };
4841
4893
  const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4842
- return transformDocumentIntoPayload({
4894
+ return transformDocumentIntoPayload(
4843
4895
  fullPath,
4844
4896
  rawData,
4845
- tinaSchema: this.tinaSchema,
4846
- config: this.config,
4847
- isAudit: this.isAudit,
4848
- context: this.context,
4897
+ this.tinaSchema,
4898
+ this.config,
4899
+ this.isAudit,
4849
4900
  hasReferences
4850
- });
4901
+ );
4851
4902
  };
4852
4903
  this.deleteDocument = async (fullPath) => {
4853
4904
  if (typeof fullPath !== "string") {
4854
- throw new Error(`fullPath must be of type string for getDocument request`);
4905
+ throw new Error(
4906
+ `fullPath must be of type string for getDocument request`
4907
+ );
4855
4908
  }
4856
4909
  await this.database.delete(fullPath);
4857
4910
  };
@@ -5006,31 +5059,34 @@ var Resolver = class {
5006
5059
  }) => {
5007
5060
  const doc = await this.getDocument(realPath);
5008
5061
  const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5009
- let values;
5010
5062
  if (isAddPendingDocument === true) {
5011
5063
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5012
- const params = this.buildParams(args);
5064
+ const params2 = this.buildParams(args);
5013
5065
  switch (templateInfo.type) {
5014
5066
  case "object":
5015
- if (params) {
5016
- const mutationValues = await this.buildFieldMutations(
5017
- params,
5067
+ if (params2) {
5068
+ const values = await this.buildFieldMutations(
5069
+ params2,
5018
5070
  templateInfo.template,
5019
5071
  doc?._rawData
5020
5072
  );
5021
- values = { ...oldDoc, ...mutationValues };
5073
+ await this.database.put(
5074
+ realPath,
5075
+ { ...oldDoc, ...values },
5076
+ collection.name
5077
+ );
5022
5078
  }
5023
5079
  break;
5024
- case "union": {
5080
+ case "union":
5025
5081
  await sequential(templateInfo.templates, async (template) => {
5026
- const templateParams = params[lastItem(template.namespace)];
5082
+ const templateParams = params2[lastItem(template.namespace)];
5027
5083
  if (templateParams) {
5028
5084
  if (typeof templateParams === "string") {
5029
5085
  throw new Error(
5030
5086
  `Expected to find an object for template params, but got string`
5031
5087
  );
5032
5088
  }
5033
- values = {
5089
+ const values = {
5034
5090
  ...oldDoc,
5035
5091
  ...await this.buildFieldMutations(
5036
5092
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
@@ -5040,23 +5096,21 @@ var Resolver = class {
5040
5096
  ),
5041
5097
  _template: lastItem(template.namespace)
5042
5098
  };
5099
+ await this.database.put(realPath, values, collection.name);
5043
5100
  }
5044
5101
  });
5045
- }
5046
5102
  }
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 };
5103
+ return this.getDocument(realPath);
5055
5104
  }
5056
- const _tinaEmbeds = this.context?._tinaEmbeds ? { _tinaEmbeds: this.context._tinaEmbeds } : {};
5105
+ const params = await this.buildObjectMutations(
5106
+ //@ts-ignore
5107
+ isCollectionSpecific ? args.params : args.params[collection.name],
5108
+ collection,
5109
+ doc?._rawData
5110
+ );
5057
5111
  await this.database.put(
5058
5112
  realPath,
5059
- { ...values, ..._tinaEmbeds },
5113
+ { ...oldDoc, ...params },
5060
5114
  collection.name
5061
5115
  );
5062
5116
  return this.getDocument(realPath);
@@ -5171,17 +5225,35 @@ var Resolver = class {
5171
5225
  await this.deleteDocument(realPath);
5172
5226
  if (await this.hasReferences(realPath, collection)) {
5173
5227
  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(
5228
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5229
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5230
+ docsWithRefs
5231
+ )) {
5232
+ let refDoc = await this.getRaw(pathToDocWithRef);
5233
+ let hasUpdate = false;
5234
+ for (const path7 of referencePaths) {
5235
+ const { object: object2, updated } = updateObjectWithJsonPath(
5179
5236
  refDoc,
5180
- ref.path.join("."),
5237
+ path7,
5238
+ realPath,
5181
5239
  null
5182
5240
  );
5241
+ refDoc = object2;
5242
+ hasUpdate = updated || hasUpdate;
5243
+ }
5244
+ if (hasUpdate) {
5245
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5246
+ if (!collectionWithRef) {
5247
+ throw new Error(
5248
+ `Unable to find collection for ${pathToDocWithRef}`
5249
+ );
5250
+ }
5251
+ await this.database.put(
5252
+ pathToDocWithRef,
5253
+ refDoc,
5254
+ collectionWithRef.name
5255
+ );
5183
5256
  }
5184
- await this.database.put(refPath, refDoc, collection2);
5185
5257
  }
5186
5258
  }
5187
5259
  }
@@ -5201,26 +5273,49 @@ var Resolver = class {
5201
5273
  collection?.path,
5202
5274
  args.params.relativePath
5203
5275
  );
5276
+ if (newRealPath === realPath) {
5277
+ return doc;
5278
+ }
5204
5279
  await this.database.put(newRealPath, doc._rawData, collection.name);
5205
5280
  await this.deleteDocument(realPath);
5206
5281
  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("."),
5282
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5283
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5284
+ docsWithRefs
5285
+ )) {
5286
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5287
+ let hasUpdate = false;
5288
+ for (const path7 of referencePaths) {
5289
+ const { object: object2, updated } = updateObjectWithJsonPath(
5290
+ docWithRef,
5291
+ path7,
5292
+ realPath,
5214
5293
  newRealPath
5215
5294
  );
5295
+ docWithRef = object2;
5296
+ hasUpdate = updated || hasUpdate;
5297
+ }
5298
+ if (hasUpdate) {
5299
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5300
+ if (!collectionWithRef) {
5301
+ throw new Error(
5302
+ `Unable to find collection for ${pathToDocWithRef}`
5303
+ );
5304
+ }
5305
+ await this.database.put(
5306
+ pathToDocWithRef,
5307
+ docWithRef,
5308
+ collectionWithRef.name
5309
+ );
5216
5310
  }
5217
- await this.database.put(refPath, refDoc, collection2);
5218
5311
  }
5219
5312
  }
5220
5313
  return this.getDocument(newRealPath);
5221
5314
  }
5222
5315
  if (alreadyExists === false) {
5223
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5316
+ throw new Error(
5317
+ `Unable to update document, ${realPath} does not exist`
5318
+ );
5224
5319
  }
5225
5320
  return this.updateResolveDocument({
5226
5321
  collection,
@@ -5346,35 +5441,30 @@ var Resolver = class {
5346
5441
  */
5347
5442
  this.hasReferences = async (id, c) => {
5348
5443
  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
- }
5444
+ await this.database.query(
5445
+ {
5446
+ collection: c.name,
5447
+ filterChain: makeFilterChain({
5448
+ conditions: [
5449
+ {
5450
+ filterPath: REFS_REFERENCE_FIELD,
5451
+ filterExpression: {
5452
+ _type: "string",
5453
+ _list: false,
5454
+ eq: id
5455
+ }
5456
+ }
5457
+ ]
5458
+ }),
5459
+ sort: REFS_COLLECTIONS_SORT_KEY
5460
+ },
5461
+ (refId) => {
5462
+ count++;
5463
+ return refId;
5377
5464
  }
5465
+ );
5466
+ if (count) {
5467
+ return true;
5378
5468
  }
5379
5469
  return false;
5380
5470
  };
@@ -5382,46 +5472,41 @@ var Resolver = class {
5382
5472
  * Finds references to a document
5383
5473
  * @param id the id of the document to find references to
5384
5474
  * @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
5475
+ * @returns a map of references to the document
5386
5476
  */
5387
5477
  this.findReferences = async (id, c) => {
5388
5478
  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] = [];
5479
+ await this.database.query(
5480
+ {
5481
+ collection: c.name,
5482
+ filterChain: makeFilterChain({
5483
+ conditions: [
5484
+ {
5485
+ filterPath: REFS_REFERENCE_FIELD,
5486
+ filterExpression: {
5487
+ _type: "string",
5488
+ _list: false,
5489
+ eq: id
5490
+ }
5415
5491
  }
5416
- references[collection][refId].push({
5417
- path: ref.path,
5418
- field: ref.field
5419
- });
5420
- return refId;
5421
- }
5422
- );
5492
+ ]
5493
+ }),
5494
+ sort: REFS_COLLECTIONS_SORT_KEY
5495
+ },
5496
+ (refId, rawItem) => {
5497
+ if (!references[c.name]) {
5498
+ references[c.name] = {};
5499
+ }
5500
+ if (!references[c.name][refId]) {
5501
+ references[c.name][refId] = [];
5502
+ }
5503
+ const referencePath = rawItem?.[REFS_PATH_FIELD];
5504
+ if (referencePath) {
5505
+ references[c.name][refId].push(referencePath);
5506
+ }
5507
+ return refId;
5423
5508
  }
5424
- }
5509
+ );
5425
5510
  return references;
5426
5511
  };
5427
5512
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
@@ -5492,15 +5577,13 @@ var Resolver = class {
5492
5577
  break;
5493
5578
  case "rich-text":
5494
5579
  accum[fieldName] = stringifyMDX(
5495
- // @ts-ignore
5496
5580
  fieldValue,
5497
5581
  field,
5498
5582
  (fieldValue2) => resolveMediaCloudToRelative(
5499
5583
  fieldValue2,
5500
5584
  this.config,
5501
5585
  this.tinaSchema.schema
5502
- ),
5503
- this.context
5586
+ )
5504
5587
  );
5505
5588
  break;
5506
5589
  case "reference":
@@ -6167,6 +6250,7 @@ var Database = class {
6167
6250
  );
6168
6251
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6169
6252
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6253
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6170
6254
  const normalizedPath = normalizePath(filepath);
6171
6255
  if (!collection?.isDetached) {
6172
6256
  if (this.bridge) {
@@ -6195,6 +6279,14 @@ var Database = class {
6195
6279
  let delOps = [];
6196
6280
  if (!isGitKeep(normalizedPath, collection)) {
6197
6281
  putOps = [
6282
+ ...makeRefOpsForDocument(
6283
+ normalizedPath,
6284
+ collection?.name,
6285
+ collectionReferences,
6286
+ dataFields,
6287
+ "put",
6288
+ level
6289
+ ),
6198
6290
  ...makeIndexOpsForDocument(
6199
6291
  normalizedPath,
6200
6292
  collection?.name,
@@ -6218,6 +6310,14 @@ var Database = class {
6218
6310
  SUBLEVEL_OPTIONS
6219
6311
  ).get(normalizedPath);
6220
6312
  delOps = existingItem ? [
6313
+ ...makeRefOpsForDocument(
6314
+ normalizedPath,
6315
+ collection?.name,
6316
+ collectionReferences,
6317
+ existingItem,
6318
+ "del",
6319
+ level
6320
+ ),
6221
6321
  ...makeIndexOpsForDocument(
6222
6322
  normalizedPath,
6223
6323
  collection?.name,
@@ -6265,6 +6365,7 @@ var Database = class {
6265
6365
  );
6266
6366
  collectionIndexDefinitions = indexDefinitions?.[collectionName];
6267
6367
  }
6368
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6268
6369
  const normalizedPath = normalizePath(filepath);
6269
6370
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6270
6371
  const collection = await this.collectionForPath(filepath);
@@ -6312,6 +6413,14 @@ var Database = class {
6312
6413
  let delOps = [];
6313
6414
  if (!isGitKeep(normalizedPath, collection)) {
6314
6415
  putOps = [
6416
+ ...makeRefOpsForDocument(
6417
+ normalizedPath,
6418
+ collectionName,
6419
+ collectionReferences,
6420
+ dataFields,
6421
+ "put",
6422
+ level
6423
+ ),
6315
6424
  ...makeIndexOpsForDocument(
6316
6425
  normalizedPath,
6317
6426
  collectionName,
@@ -6335,6 +6444,14 @@ var Database = class {
6335
6444
  SUBLEVEL_OPTIONS
6336
6445
  ).get(normalizedPath);
6337
6446
  delOps = existingItem ? [
6447
+ ...makeRefOpsForDocument(
6448
+ normalizedPath,
6449
+ collectionName,
6450
+ collectionReferences,
6451
+ existingItem,
6452
+ "del",
6453
+ level
6454
+ ),
6338
6455
  ...makeIndexOpsForDocument(
6339
6456
  normalizedPath,
6340
6457
  collectionName,
@@ -6497,6 +6614,22 @@ var Database = class {
6497
6614
  this.tinaSchema = await createSchema({ schema });
6498
6615
  return this.tinaSchema;
6499
6616
  };
6617
+ this.getCollectionReferences = async (level) => {
6618
+ if (this.collectionReferences) {
6619
+ return this.collectionReferences;
6620
+ }
6621
+ const result = {};
6622
+ const schema = await this.getSchema(level || this.contentLevel);
6623
+ const collections = schema.getCollections();
6624
+ for (const collection of collections) {
6625
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6626
+ collection.name
6627
+ );
6628
+ result[collection.name] = collectionReferences;
6629
+ }
6630
+ this.collectionReferences = result;
6631
+ return result;
6632
+ };
6500
6633
  this.getIndexDefinitions = async (level) => {
6501
6634
  if (!this.collectionIndexDefinitions) {
6502
6635
  await new Promise(async (resolve2, reject) => {
@@ -6506,11 +6639,53 @@ var Database = class {
6506
6639
  const collections = schema.getCollections();
6507
6640
  for (const collection of collections) {
6508
6641
  const indexDefinitions = {
6509
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6642
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6510
6643
  // provide a default sort key which is the file sort
6644
+ // pseudo-index for the collection's references
6645
+ [REFS_COLLECTIONS_SORT_KEY]: {
6646
+ fields: [
6647
+ {
6648
+ name: REFS_REFERENCE_FIELD,
6649
+ type: "string",
6650
+ list: false
6651
+ },
6652
+ {
6653
+ name: REFS_PATH_FIELD,
6654
+ type: "string",
6655
+ list: false
6656
+ }
6657
+ ]
6658
+ }
6511
6659
  };
6512
- if (collection.fields) {
6513
- for (const field of collection.fields) {
6660
+ let fields = [];
6661
+ if (collection.templates) {
6662
+ const templateFieldMap = {};
6663
+ const conflictedFields = /* @__PURE__ */ new Set();
6664
+ for (const template of collection.templates) {
6665
+ for (const field of template.fields) {
6666
+ if (!templateFieldMap[field.name]) {
6667
+ templateFieldMap[field.name] = field;
6668
+ } else {
6669
+ if (templateFieldMap[field.name].type !== field.type) {
6670
+ console.warn(
6671
+ `Field ${field.name} has conflicting types in templates - skipping index`
6672
+ );
6673
+ conflictedFields.add(field.name);
6674
+ }
6675
+ }
6676
+ }
6677
+ }
6678
+ for (const conflictedField in conflictedFields) {
6679
+ delete templateFieldMap[conflictedField];
6680
+ }
6681
+ for (const field of Object.values(templateFieldMap)) {
6682
+ fields.push(field);
6683
+ }
6684
+ } else if (collection.fields) {
6685
+ fields = collection.fields;
6686
+ }
6687
+ if (fields) {
6688
+ for (const field of fields) {
6514
6689
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6515
6690
  continue;
6516
6691
  }
@@ -6658,29 +6833,36 @@ var Database = class {
6658
6833
  }
6659
6834
  startKey = startKey || key || "";
6660
6835
  endKey = key || "";
6661
- edges = [...edges, { cursor: key, path: filepath }];
6836
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6662
6837
  }
6663
6838
  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
- });
6839
+ edges: await sequential(
6840
+ edges,
6841
+ async ({
6842
+ cursor,
6843
+ path: path7,
6844
+ value
6845
+ }) => {
6846
+ try {
6847
+ const node = await hydrator(path7, value);
6848
+ return {
6849
+ node,
6850
+ cursor: btoa(cursor)
6851
+ };
6852
+ } catch (error) {
6853
+ console.log(error);
6854
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6855
+ throw new TinaQueryError({
6856
+ originalError: error,
6857
+ file: path7,
6858
+ collection: collection.name,
6859
+ stack: error.stack
6860
+ });
6861
+ }
6862
+ throw error;
6680
6863
  }
6681
- throw error;
6682
6864
  }
6683
- }),
6865
+ ),
6684
6866
  pageInfo: {
6685
6867
  hasPreviousPage,
6686
6868
  hasNextPage,
@@ -6826,6 +7008,7 @@ var Database = class {
6826
7008
  throw new Error(`No collection found for path: ${filepath}`);
6827
7009
  }
6828
7010
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
7011
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6829
7012
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6830
7013
  let level = this.contentLevel;
6831
7014
  if (collection?.isDetached) {
@@ -6844,6 +7027,14 @@ var Database = class {
6844
7027
  collection.path || ""
6845
7028
  );
6846
7029
  await this.contentLevel.batch([
7030
+ ...makeRefOpsForDocument(
7031
+ normalizedPath,
7032
+ collection.name,
7033
+ collectionReferences,
7034
+ item,
7035
+ "del",
7036
+ level
7037
+ ),
6847
7038
  ...makeIndexOpsForDocument(
6848
7039
  normalizedPath,
6849
7040
  collection.name,
@@ -6921,7 +7112,13 @@ var Database = class {
6921
7112
  );
6922
7113
  }
6923
7114
  } else {
6924
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7115
+ await _indexContent(
7116
+ this,
7117
+ level,
7118
+ contentPaths,
7119
+ enqueueOps,
7120
+ collection
7121
+ );
6925
7122
  }
6926
7123
  }
6927
7124
  );
@@ -7071,6 +7268,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7071
7268
  }
7072
7269
  collectionPath = collection.path;
7073
7270
  }
7271
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7074
7272
  const tinaSchema = await database.getSchema();
7075
7273
  let templateInfo = null;
7076
7274
  if (collection) {
@@ -7092,12 +7290,59 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7092
7290
  await hashPasswordValues(aliasedData, passwordFields);
7093
7291
  }
7094
7292
  const normalizedPath = normalizePath(filepath);
7293
+ const rootSublevel = level.sublevel(
7294
+ CONTENT_ROOT_PREFIX,
7295
+ SUBLEVEL_OPTIONS
7296
+ );
7095
7297
  const folderKey = folderTreeBuilder.update(
7096
7298
  normalizedPath,
7097
7299
  collectionPath || ""
7098
7300
  );
7301
+ const item = await rootSublevel.get(normalizedPath);
7302
+ if (item) {
7303
+ await database.contentLevel.batch([
7304
+ ...makeRefOpsForDocument(
7305
+ normalizedPath,
7306
+ collection?.name,
7307
+ collectionReferences,
7308
+ item,
7309
+ "del",
7310
+ level
7311
+ ),
7312
+ ...makeIndexOpsForDocument(
7313
+ normalizedPath,
7314
+ collection.name,
7315
+ collectionIndexDefinitions,
7316
+ item,
7317
+ "del",
7318
+ level
7319
+ ),
7320
+ // folder indices
7321
+ ...makeIndexOpsForDocument(
7322
+ normalizedPath,
7323
+ `${collection.name}_${folderKey}`,
7324
+ collectionIndexDefinitions,
7325
+ item,
7326
+ "del",
7327
+ level
7328
+ ),
7329
+ {
7330
+ type: "del",
7331
+ key: normalizedPath,
7332
+ sublevel: rootSublevel
7333
+ }
7334
+ ]);
7335
+ }
7099
7336
  if (!isGitKeep(filepath, collection)) {
7100
7337
  await enqueueOps([
7338
+ ...makeRefOpsForDocument(
7339
+ normalizedPath,
7340
+ collection?.name,
7341
+ collectionReferences,
7342
+ aliasedData,
7343
+ "put",
7344
+ level
7345
+ ),
7101
7346
  ...makeIndexOpsForDocument(
7102
7347
  normalizedPath,
7103
7348
  collection?.name,
@@ -7161,6 +7406,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7161
7406
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7162
7407
  }
7163
7408
  }
7409
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7164
7410
  const tinaSchema = await database.getSchema();
7165
7411
  let templateInfo = null;
7166
7412
  if (collection) {
@@ -7184,6 +7430,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7184
7430
  item
7185
7431
  ) : item;
7186
7432
  await enqueueOps([
7433
+ ...makeRefOpsForDocument(
7434
+ itemKey,
7435
+ collection?.name,
7436
+ collectionReferences,
7437
+ aliasedData,
7438
+ "del",
7439
+ database.contentLevel
7440
+ ),
7187
7441
  ...makeIndexOpsForDocument(
7188
7442
  itemKey,
7189
7443
  collection.name,