@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.js CHANGED
@@ -27,8 +27,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/index.ts
30
- var src_exports = {};
31
- __export(src_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  AuditFileSystemBridge: () => AuditFileSystemBridge,
33
33
  Database: () => Database,
34
34
  FilesystemBridge: () => FilesystemBridge,
@@ -62,7 +62,7 @@ __export(src_exports, {
62
62
  transformDocument: () => transformDocument,
63
63
  transformDocumentIntoPayload: () => transformDocumentIntoPayload
64
64
  });
65
- module.exports = __toCommonJS(src_exports);
65
+ module.exports = __toCommonJS(index_exports);
66
66
 
67
67
  // src/build.ts
68
68
  var import_graphql2 = require("graphql");
@@ -1914,7 +1914,7 @@ var Builder = class {
1914
1914
  * ```
1915
1915
  *
1916
1916
  * @public
1917
- * @param collection a Tina Cloud collection
1917
+ * @param collection a TinaCloud collection
1918
1918
  */
1919
1919
  this.collectionFragment = async (collection) => {
1920
1920
  const name = NAMER.dataTypeName(collection.namespace);
@@ -3090,7 +3090,7 @@ var validateField = async (field) => {
3090
3090
  // package.json
3091
3091
  var package_default = {
3092
3092
  name: "@tinacms/graphql",
3093
- version: "1.5.11",
3093
+ version: "1.5.16",
3094
3094
  main: "dist/index.js",
3095
3095
  module: "dist/index.mjs",
3096
3096
  typings: "dist/index.d.ts",
@@ -3126,12 +3126,12 @@ var package_default = {
3126
3126
  "@tinacms/schema-tools": "workspace:*",
3127
3127
  "abstract-level": "^1.0.4",
3128
3128
  "date-fns": "^2.30.0",
3129
- "fast-glob": "^3.3.2",
3130
- "fs-extra": "^11.2.0",
3129
+ "fast-glob": "^3.3.3",
3130
+ "fs-extra": "^11.3.0",
3131
3131
  "glob-parent": "^6.0.2",
3132
3132
  graphql: "15.8.0",
3133
3133
  "gray-matter": "^4.0.3",
3134
- "isomorphic-git": "^1.27.1",
3134
+ "isomorphic-git": "^1.29.0",
3135
3135
  "js-sha1": "^0.6.0",
3136
3136
  "js-yaml": "^3.14.1",
3137
3137
  "jsonpath-plus": "10.1.0",
@@ -3141,7 +3141,7 @@ var package_default = {
3141
3141
  "many-level": "^2.0.0",
3142
3142
  micromatch: "4.0.8",
3143
3143
  "normalize-path": "^3.0.0",
3144
- "readable-stream": "^4.5.2",
3144
+ "readable-stream": "^4.7.0",
3145
3145
  scmp: "^2.1.0",
3146
3146
  yup: "^0.32.11"
3147
3147
  },
@@ -3165,17 +3165,17 @@ var package_default = {
3165
3165
  "@types/lru-cache": "^5.1.1",
3166
3166
  "@types/mdast": "^3.0.15",
3167
3167
  "@types/micromatch": "^4.0.9",
3168
- "@types/node": "^22.9.0",
3168
+ "@types/node": "^22.13.1",
3169
3169
  "@types/normalize-path": "^3.0.2",
3170
3170
  "@types/ws": "^7.4.7",
3171
3171
  "@types/yup": "^0.29.14",
3172
3172
  "jest-file-snapshot": "^0.5.0",
3173
3173
  "memory-level": "^1.0.0",
3174
3174
  nodemon: "3.1.4",
3175
- typescript: "^5.6.3",
3176
- vite: "^4.3.9",
3177
- vitest: "^0.32.2",
3178
- zod: "^3.23.8"
3175
+ typescript: "^5.7.3",
3176
+ vite: "^4.5.9",
3177
+ vitest: "^0.32.4",
3178
+ zod: "^3.24.2"
3179
3179
  }
3180
3180
  };
3181
3181
 
@@ -3332,7 +3332,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3332
3332
  await builder.buildCreateCollectionFolderMutation()
3333
3333
  );
3334
3334
  await sequential(collections, async (collection) => {
3335
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3335
+ queryTypeDefinitionFields.push(
3336
+ await builder.collectionDocument(collection)
3337
+ );
3336
3338
  if (collection.isAuthCollection) {
3337
3339
  queryTypeDefinitionFields.push(
3338
3340
  await builder.authenticationCollectionDocument(collection)
@@ -3648,7 +3650,9 @@ var LevelProxyHandler = {
3648
3650
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3649
3651
  }
3650
3652
  if (typeof target[property] !== "function") {
3651
- throw new Error(`The property, ${property.toString()}, is not a function`);
3653
+ throw new Error(
3654
+ `The property, ${property.toString()}, is not a function`
3655
+ );
3652
3656
  }
3653
3657
  if (property === "get") {
3654
3658
  return async (...args) => {
@@ -4035,6 +4039,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
4035
4039
 
4036
4040
  // src/database/datalayer.ts
4037
4041
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
4042
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
4043
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
4044
+ var REFS_PATH_FIELD = "__tina_ref_path__";
4038
4045
  var DEFAULT_NUMERIC_LPAD = 4;
4039
4046
  var applyPadding = (input, pad) => {
4040
4047
  if (pad) {
@@ -4608,6 +4615,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4608
4615
  }
4609
4616
  return result;
4610
4617
  };
4618
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4619
+ const result = [];
4620
+ if (collection) {
4621
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4622
+ if (!referencePaths.length) {
4623
+ continue;
4624
+ }
4625
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4626
+ const refSublevel = collectionSublevel.sublevel(
4627
+ REFS_COLLECTIONS_SORT_KEY,
4628
+ SUBLEVEL_OPTIONS
4629
+ );
4630
+ const references2 = {};
4631
+ for (const path7 of referencePaths) {
4632
+ const ref = (0, import_jsonpath_plus.JSONPath)({ path: path7, json: data });
4633
+ if (!ref) {
4634
+ continue;
4635
+ }
4636
+ if (Array.isArray(ref)) {
4637
+ for (const r of ref) {
4638
+ if (!r) {
4639
+ continue;
4640
+ }
4641
+ if (references2[r]) {
4642
+ references2[r].push(path7);
4643
+ } else {
4644
+ references2[r] = [path7];
4645
+ }
4646
+ }
4647
+ } else {
4648
+ if (references2[ref]) {
4649
+ references2[ref].push(path7);
4650
+ } else {
4651
+ references2[ref] = [path7];
4652
+ }
4653
+ }
4654
+ }
4655
+ for (const ref of Object.keys(references2)) {
4656
+ for (const path7 of references2[ref]) {
4657
+ result.push({
4658
+ type: opType,
4659
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4660
+ sublevel: refSublevel,
4661
+ value: opType === "put" ? {} : void 0
4662
+ });
4663
+ }
4664
+ }
4665
+ }
4666
+ }
4667
+ return result;
4668
+ };
4611
4669
  var makeStringEscaper = (regex, replacement) => {
4612
4670
  return (input) => {
4613
4671
  if (Array.isArray(input)) {
@@ -4632,17 +4690,8 @@ var stringEscaper = makeStringEscaper(
4632
4690
  var createResolver = (args) => {
4633
4691
  return new Resolver(args);
4634
4692
  };
4635
- var resolveFieldData = async (args) => {
4693
+ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4636
4694
  var _a, _b;
4637
- const {
4638
- field: { namespace, ...field },
4639
- rawData,
4640
- accumulator,
4641
- tinaSchema,
4642
- config,
4643
- isAudit,
4644
- context
4645
- } = args;
4646
4695
  if (!rawData) {
4647
4696
  return void 0;
4648
4697
  }
@@ -4682,11 +4731,9 @@ var resolveFieldData = async (args) => {
4682
4731
  break;
4683
4732
  case "rich-text":
4684
4733
  const tree = (0, import_mdx.parseMDX)(
4685
- // @ts-ignore value is unknown
4686
4734
  value,
4687
4735
  field,
4688
- (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema),
4689
- context
4736
+ (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4690
4737
  );
4691
4738
  if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4692
4739
  if (isAudit) {
@@ -4717,15 +4764,14 @@ var resolveFieldData = async (args) => {
4717
4764
  });
4718
4765
  const payload = {};
4719
4766
  await sequential(template.fields, async (field2) => {
4720
- await resolveFieldData({
4721
- field: field2,
4722
- rawData: item,
4723
- accumulator: payload,
4767
+ await resolveFieldData(
4768
+ field2,
4769
+ item,
4770
+ payload,
4724
4771
  tinaSchema,
4725
4772
  config,
4726
- isAudit,
4727
- context
4728
- });
4773
+ isAudit
4774
+ );
4729
4775
  });
4730
4776
  const isUnion = !!field.templates;
4731
4777
  return isUnion ? {
@@ -4746,15 +4792,14 @@ var resolveFieldData = async (args) => {
4746
4792
  });
4747
4793
  const payload = {};
4748
4794
  await sequential(template.fields, async (field2) => {
4749
- await resolveFieldData({
4750
- field: field2,
4751
- rawData: value,
4752
- accumulator: payload,
4795
+ await resolveFieldData(
4796
+ field2,
4797
+ value,
4798
+ payload,
4753
4799
  tinaSchema,
4754
4800
  config,
4755
- isAudit,
4756
- context
4757
- });
4801
+ isAudit
4802
+ );
4758
4803
  });
4759
4804
  const isUnion = !!field.templates;
4760
4805
  accumulator[field.name] = isUnion ? {
@@ -4768,8 +4813,7 @@ var resolveFieldData = async (args) => {
4768
4813
  }
4769
4814
  return accumulator;
4770
4815
  };
4771
- var transformDocumentIntoPayload = async (args) => {
4772
- const { fullPath, rawData, tinaSchema, config, isAudit, context } = args;
4816
+ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit, hasReferences) => {
4773
4817
  const collection = tinaSchema.getCollection(rawData._collection);
4774
4818
  try {
4775
4819
  const template = tinaSchema.getTemplateForData({
@@ -4789,15 +4833,14 @@ var transformDocumentIntoPayload = async (args) => {
4789
4833
  };
4790
4834
  try {
4791
4835
  await sequential(template.fields, async (field) => {
4792
- return resolveFieldData({
4836
+ return resolveFieldData(
4793
4837
  field,
4794
4838
  rawData,
4795
- accumulator: data,
4839
+ data,
4796
4840
  tinaSchema,
4797
4841
  config,
4798
- isAudit,
4799
- context
4800
- });
4842
+ isAudit
4843
+ );
4801
4844
  });
4802
4845
  } catch (e) {
4803
4846
  throw new TinaParseDocumentError({
@@ -4824,7 +4867,7 @@ var transformDocumentIntoPayload = async (args) => {
4824
4867
  basename,
4825
4868
  filename,
4826
4869
  extension,
4827
- hasReferences: args.hasReferences,
4870
+ hasReferences,
4828
4871
  path: fullPath,
4829
4872
  relativePath,
4830
4873
  breadcrumbs,
@@ -4844,29 +4887,37 @@ var transformDocumentIntoPayload = async (args) => {
4844
4887
  throw e;
4845
4888
  }
4846
4889
  };
4847
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4890
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4891
+ let updated = false;
4848
4892
  if (!path7.includes(".") && !path7.includes("[")) {
4849
- if (path7 in obj) {
4893
+ if (path7 in obj && obj[path7] === oldValue) {
4850
4894
  obj[path7] = newValue;
4895
+ updated = true;
4851
4896
  }
4852
- return obj;
4853
- }
4854
- const parentPath = path7.replace(/\.[^.]+$/, "");
4855
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4856
- const parents = (0, import_jsonpath_plus2.JSONPath)({ path: parentPath, json: obj, resultType: "value" });
4897
+ return { object: obj, updated };
4898
+ }
4899
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4900
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4901
+ const parents = (0, import_jsonpath_plus2.JSONPath)({
4902
+ path: parentPath,
4903
+ json: obj,
4904
+ resultType: "value"
4905
+ });
4857
4906
  if (parents.length > 0) {
4858
4907
  parents.forEach((parent) => {
4859
4908
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4860
- parent[keyToUpdate] = newValue;
4909
+ if (parent[keyToUpdate] === oldValue) {
4910
+ parent[keyToUpdate] = newValue;
4911
+ updated = true;
4912
+ }
4861
4913
  }
4862
4914
  });
4863
4915
  }
4864
- return obj;
4916
+ return { object: obj, updated };
4865
4917
  };
4866
4918
  var Resolver = class {
4867
4919
  constructor(init) {
4868
4920
  this.init = init;
4869
- this.context = {};
4870
4921
  this.resolveCollection = async (args, collectionName, hasDocuments) => {
4871
4922
  const collection = this.tinaSchema.getCollection(collectionName);
4872
4923
  const extraFields = {};
@@ -4879,7 +4930,9 @@ var Resolver = class {
4879
4930
  };
4880
4931
  this.getRaw = async (fullPath) => {
4881
4932
  if (typeof fullPath !== "string") {
4882
- throw new Error(`fullPath must be of type string for getDocument request`);
4933
+ throw new Error(
4934
+ `fullPath must be of type string for getDocument request`
4935
+ );
4883
4936
  }
4884
4937
  return this.database.get(fullPath);
4885
4938
  };
@@ -4897,37 +4950,37 @@ var Resolver = class {
4897
4950
  path: rawData["__folderPath"]
4898
4951
  };
4899
4952
  } else {
4900
- this.context = { ...rawData };
4901
- return transformDocumentIntoPayload({
4953
+ return transformDocumentIntoPayload(
4902
4954
  fullPath,
4903
4955
  rawData,
4904
- tinaSchema: this.tinaSchema,
4905
- config: this.config,
4906
- isAudit: this.isAudit,
4907
- context: this.context
4908
- });
4956
+ this.tinaSchema,
4957
+ this.config,
4958
+ this.isAudit
4959
+ );
4909
4960
  }
4910
4961
  };
4911
4962
  this.getDocument = async (fullPath, opts = {}) => {
4912
4963
  if (typeof fullPath !== "string") {
4913
- throw new Error(`fullPath must be of type string for getDocument request`);
4964
+ throw new Error(
4965
+ `fullPath must be of type string for getDocument request`
4966
+ );
4914
4967
  }
4915
4968
  const rawData = await this.getRaw(fullPath);
4916
- this.context = { ...rawData };
4917
4969
  const hasReferences = (opts == null ? void 0 : opts.checkReferences) ? await this.hasReferences(fullPath, opts.collection) : void 0;
4918
- return transformDocumentIntoPayload({
4970
+ return transformDocumentIntoPayload(
4919
4971
  fullPath,
4920
4972
  rawData,
4921
- tinaSchema: this.tinaSchema,
4922
- config: this.config,
4923
- isAudit: this.isAudit,
4924
- context: this.context,
4973
+ this.tinaSchema,
4974
+ this.config,
4975
+ this.isAudit,
4925
4976
  hasReferences
4926
- });
4977
+ );
4927
4978
  };
4928
4979
  this.deleteDocument = async (fullPath) => {
4929
4980
  if (typeof fullPath !== "string") {
4930
- throw new Error(`fullPath must be of type string for getDocument request`);
4981
+ throw new Error(
4982
+ `fullPath must be of type string for getDocument request`
4983
+ );
4931
4984
  }
4932
4985
  await this.database.delete(fullPath);
4933
4986
  };
@@ -5080,34 +5133,36 @@ var Resolver = class {
5080
5133
  isAddPendingDocument,
5081
5134
  isCollectionSpecific
5082
5135
  }) => {
5083
- var _a;
5084
5136
  const doc = await this.getDocument(realPath);
5085
5137
  const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5086
- let values;
5087
5138
  if (isAddPendingDocument === true) {
5088
5139
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5089
- const params = this.buildParams(args);
5140
+ const params2 = this.buildParams(args);
5090
5141
  switch (templateInfo.type) {
5091
5142
  case "object":
5092
- if (params) {
5093
- const mutationValues = await this.buildFieldMutations(
5094
- params,
5143
+ if (params2) {
5144
+ const values = await this.buildFieldMutations(
5145
+ params2,
5095
5146
  templateInfo.template,
5096
5147
  doc == null ? void 0 : doc._rawData
5097
5148
  );
5098
- values = { ...oldDoc, ...mutationValues };
5149
+ await this.database.put(
5150
+ realPath,
5151
+ { ...oldDoc, ...values },
5152
+ collection.name
5153
+ );
5099
5154
  }
5100
5155
  break;
5101
- case "union": {
5156
+ case "union":
5102
5157
  await sequential(templateInfo.templates, async (template) => {
5103
- const templateParams = params[lastItem(template.namespace)];
5158
+ const templateParams = params2[lastItem(template.namespace)];
5104
5159
  if (templateParams) {
5105
5160
  if (typeof templateParams === "string") {
5106
5161
  throw new Error(
5107
5162
  `Expected to find an object for template params, but got string`
5108
5163
  );
5109
5164
  }
5110
- values = {
5165
+ const values = {
5111
5166
  ...oldDoc,
5112
5167
  ...await this.buildFieldMutations(
5113
5168
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
@@ -5117,23 +5172,21 @@ var Resolver = class {
5117
5172
  ),
5118
5173
  _template: lastItem(template.namespace)
5119
5174
  };
5175
+ await this.database.put(realPath, values, collection.name);
5120
5176
  }
5121
5177
  });
5122
- }
5123
5178
  }
5124
- } else {
5125
- const params = await this.buildObjectMutations(
5126
- //@ts-expect-error FIXME: Argument of type 'unknown' is not assignable to parameter of type 'FieldParams'
5127
- isCollectionSpecific ? args.params : args.params[collection.name],
5128
- collection,
5129
- doc == null ? void 0 : doc._rawData
5130
- );
5131
- values = { ...oldDoc, ...params };
5179
+ return this.getDocument(realPath);
5132
5180
  }
5133
- const _tinaEmbeds = ((_a = this.context) == null ? void 0 : _a._tinaEmbeds) ? { _tinaEmbeds: this.context._tinaEmbeds } : {};
5181
+ const params = await this.buildObjectMutations(
5182
+ //@ts-ignore
5183
+ isCollectionSpecific ? args.params : args.params[collection.name],
5184
+ collection,
5185
+ doc == null ? void 0 : doc._rawData
5186
+ );
5134
5187
  await this.database.put(
5135
5188
  realPath,
5136
- { ...values, ..._tinaEmbeds },
5189
+ { ...oldDoc, ...params },
5137
5190
  collection.name
5138
5191
  );
5139
5192
  return this.getDocument(realPath);
@@ -5249,17 +5302,35 @@ var Resolver = class {
5249
5302
  await this.deleteDocument(realPath);
5250
5303
  if (await this.hasReferences(realPath, collection)) {
5251
5304
  const collRefs = await this.findReferences(realPath, collection);
5252
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5253
- for (const [refPath, refs] of Object.entries(refFields)) {
5254
- let refDoc = await this.getRaw(refPath);
5255
- for (const ref of refs) {
5256
- refDoc = updateObjectWithJsonPath(
5305
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5306
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5307
+ docsWithRefs
5308
+ )) {
5309
+ let refDoc = await this.getRaw(pathToDocWithRef);
5310
+ let hasUpdate = false;
5311
+ for (const path7 of referencePaths) {
5312
+ const { object: object2, updated } = updateObjectWithJsonPath(
5257
5313
  refDoc,
5258
- ref.path.join("."),
5314
+ path7,
5315
+ realPath,
5259
5316
  null
5260
5317
  );
5318
+ refDoc = object2;
5319
+ hasUpdate = updated || hasUpdate;
5320
+ }
5321
+ if (hasUpdate) {
5322
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5323
+ if (!collectionWithRef) {
5324
+ throw new Error(
5325
+ `Unable to find collection for ${pathToDocWithRef}`
5326
+ );
5327
+ }
5328
+ await this.database.put(
5329
+ pathToDocWithRef,
5330
+ refDoc,
5331
+ collectionWithRef.name
5332
+ );
5261
5333
  }
5262
- await this.database.put(refPath, refDoc, collection2);
5263
5334
  }
5264
5335
  }
5265
5336
  }
@@ -5279,26 +5350,49 @@ var Resolver = class {
5279
5350
  collection == null ? void 0 : collection.path,
5280
5351
  args.params.relativePath
5281
5352
  );
5353
+ if (newRealPath === realPath) {
5354
+ return doc;
5355
+ }
5282
5356
  await this.database.put(newRealPath, doc._rawData, collection.name);
5283
5357
  await this.deleteDocument(realPath);
5284
5358
  const collRefs = await this.findReferences(realPath, collection);
5285
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5286
- for (const [refPath, refs] of Object.entries(refFields)) {
5287
- let refDoc = await this.getRaw(refPath);
5288
- for (const ref of refs) {
5289
- refDoc = updateObjectWithJsonPath(
5290
- refDoc,
5291
- ref.path.join("."),
5359
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5360
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5361
+ docsWithRefs
5362
+ )) {
5363
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5364
+ let hasUpdate = false;
5365
+ for (const path7 of referencePaths) {
5366
+ const { object: object2, updated } = updateObjectWithJsonPath(
5367
+ docWithRef,
5368
+ path7,
5369
+ realPath,
5292
5370
  newRealPath
5293
5371
  );
5372
+ docWithRef = object2;
5373
+ hasUpdate = updated || hasUpdate;
5374
+ }
5375
+ if (hasUpdate) {
5376
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5377
+ if (!collectionWithRef) {
5378
+ throw new Error(
5379
+ `Unable to find collection for ${pathToDocWithRef}`
5380
+ );
5381
+ }
5382
+ await this.database.put(
5383
+ pathToDocWithRef,
5384
+ docWithRef,
5385
+ collectionWithRef.name
5386
+ );
5294
5387
  }
5295
- await this.database.put(refPath, refDoc, collection2);
5296
5388
  }
5297
5389
  }
5298
5390
  return this.getDocument(newRealPath);
5299
5391
  }
5300
5392
  if (alreadyExists === false) {
5301
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5393
+ throw new Error(
5394
+ `Unable to update document, ${realPath} does not exist`
5395
+ );
5302
5396
  }
5303
5397
  return this.updateResolveDocument({
5304
5398
  collection,
@@ -5424,35 +5518,30 @@ var Resolver = class {
5424
5518
  */
5425
5519
  this.hasReferences = async (id, c) => {
5426
5520
  let count = 0;
5427
- const deepRefs = this.tinaSchema.findReferences(c.name);
5428
- for (const [collection, refs] of Object.entries(deepRefs)) {
5429
- for (const ref of refs) {
5430
- await this.database.query(
5431
- {
5432
- collection,
5433
- filterChain: makeFilterChain({
5434
- conditions: [
5435
- {
5436
- filterPath: ref.path.join("."),
5437
- filterExpression: {
5438
- _type: "reference",
5439
- _list: false,
5440
- eq: id
5441
- }
5442
- }
5443
- ]
5444
- }),
5445
- sort: ref.field.name
5446
- },
5447
- (refId) => {
5448
- count++;
5449
- return refId;
5450
- }
5451
- );
5452
- if (count) {
5453
- return true;
5454
- }
5521
+ await this.database.query(
5522
+ {
5523
+ collection: c.name,
5524
+ filterChain: makeFilterChain({
5525
+ conditions: [
5526
+ {
5527
+ filterPath: REFS_REFERENCE_FIELD,
5528
+ filterExpression: {
5529
+ _type: "string",
5530
+ _list: false,
5531
+ eq: id
5532
+ }
5533
+ }
5534
+ ]
5535
+ }),
5536
+ sort: REFS_COLLECTIONS_SORT_KEY
5537
+ },
5538
+ (refId) => {
5539
+ count++;
5540
+ return refId;
5455
5541
  }
5542
+ );
5543
+ if (count) {
5544
+ return true;
5456
5545
  }
5457
5546
  return false;
5458
5547
  };
@@ -5460,46 +5549,41 @@ var Resolver = class {
5460
5549
  * Finds references to a document
5461
5550
  * @param id the id of the document to find references to
5462
5551
  * @param c the collection to find references in
5463
- * @returns references to the document in the form of a map of collection names to a list of fields that reference the document
5552
+ * @returns a map of references to the document
5464
5553
  */
5465
5554
  this.findReferences = async (id, c) => {
5466
5555
  const references = {};
5467
- const deepRefs = this.tinaSchema.findReferences(c.name);
5468
- for (const [collection, refs] of Object.entries(deepRefs)) {
5469
- for (const ref of refs) {
5470
- await this.database.query(
5471
- {
5472
- collection,
5473
- filterChain: makeFilterChain({
5474
- conditions: [
5475
- {
5476
- filterPath: ref.path.join("."),
5477
- filterExpression: {
5478
- _type: "reference",
5479
- _list: false,
5480
- eq: id
5481
- }
5482
- }
5483
- ]
5484
- }),
5485
- sort: ref.field.name
5486
- },
5487
- (refId) => {
5488
- if (!references[collection]) {
5489
- references[collection] = {};
5490
- }
5491
- if (!references[collection][refId]) {
5492
- references[collection][refId] = [];
5556
+ await this.database.query(
5557
+ {
5558
+ collection: c.name,
5559
+ filterChain: makeFilterChain({
5560
+ conditions: [
5561
+ {
5562
+ filterPath: REFS_REFERENCE_FIELD,
5563
+ filterExpression: {
5564
+ _type: "string",
5565
+ _list: false,
5566
+ eq: id
5567
+ }
5493
5568
  }
5494
- references[collection][refId].push({
5495
- path: ref.path,
5496
- field: ref.field
5497
- });
5498
- return refId;
5499
- }
5500
- );
5569
+ ]
5570
+ }),
5571
+ sort: REFS_COLLECTIONS_SORT_KEY
5572
+ },
5573
+ (refId, rawItem) => {
5574
+ if (!references[c.name]) {
5575
+ references[c.name] = {};
5576
+ }
5577
+ if (!references[c.name][refId]) {
5578
+ references[c.name][refId] = [];
5579
+ }
5580
+ const referencePath = rawItem == null ? void 0 : rawItem[REFS_PATH_FIELD];
5581
+ if (referencePath) {
5582
+ references[c.name][refId].push(referencePath);
5583
+ }
5584
+ return refId;
5501
5585
  }
5502
- }
5586
+ );
5503
5587
  return references;
5504
5588
  };
5505
5589
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
@@ -5571,15 +5655,13 @@ var Resolver = class {
5571
5655
  break;
5572
5656
  case "rich-text":
5573
5657
  accum[fieldName] = (0, import_mdx.stringifyMDX)(
5574
- // @ts-ignore
5575
5658
  fieldValue,
5576
5659
  field,
5577
5660
  (fieldValue2) => resolveMediaCloudToRelative(
5578
5661
  fieldValue2,
5579
5662
  this.config,
5580
5663
  this.tinaSchema.schema
5581
- ),
5582
- this.context
5664
+ )
5583
5665
  );
5584
5666
  break;
5585
5667
  case "reference":
@@ -6237,6 +6319,7 @@ var Database = class {
6237
6319
  }
6238
6320
  };
6239
6321
  this.addPendingDocument = async (filepath, data) => {
6322
+ var _a;
6240
6323
  await this.initLevel();
6241
6324
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6242
6325
  const collection = await this.collectionForPath(filepath);
@@ -6250,6 +6333,7 @@ var Database = class {
6250
6333
  );
6251
6334
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6252
6335
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6336
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collection.name];
6253
6337
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6254
6338
  if (!(collection == null ? void 0 : collection.isDetached)) {
6255
6339
  if (this.bridge) {
@@ -6278,6 +6362,14 @@ var Database = class {
6278
6362
  let delOps = [];
6279
6363
  if (!isGitKeep(normalizedPath, collection)) {
6280
6364
  putOps = [
6365
+ ...makeRefOpsForDocument(
6366
+ normalizedPath,
6367
+ collection == null ? void 0 : collection.name,
6368
+ collectionReferences,
6369
+ dataFields,
6370
+ "put",
6371
+ level
6372
+ ),
6281
6373
  ...makeIndexOpsForDocument(
6282
6374
  normalizedPath,
6283
6375
  collection == null ? void 0 : collection.name,
@@ -6301,6 +6393,14 @@ var Database = class {
6301
6393
  SUBLEVEL_OPTIONS
6302
6394
  ).get(normalizedPath);
6303
6395
  delOps = existingItem ? [
6396
+ ...makeRefOpsForDocument(
6397
+ normalizedPath,
6398
+ collection == null ? void 0 : collection.name,
6399
+ collectionReferences,
6400
+ existingItem,
6401
+ "del",
6402
+ level
6403
+ ),
6304
6404
  ...makeIndexOpsForDocument(
6305
6405
  normalizedPath,
6306
6406
  collection == null ? void 0 : collection.name,
@@ -6336,7 +6436,7 @@ var Database = class {
6336
6436
  await level.batch(ops);
6337
6437
  };
6338
6438
  this.put = async (filepath, data, collectionName) => {
6339
- var _a, _b;
6439
+ var _a, _b, _c;
6340
6440
  await this.initLevel();
6341
6441
  try {
6342
6442
  if (SYSTEM_FILES.includes(filepath)) {
@@ -6349,13 +6449,14 @@ var Database = class {
6349
6449
  );
6350
6450
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6351
6451
  }
6452
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collectionName];
6352
6453
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6353
6454
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6354
6455
  const collection = await this.collectionForPath(filepath);
6355
6456
  if (!collection) {
6356
6457
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
6357
6458
  }
6358
- if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
6459
+ if (((_b = collection.match) == null ? void 0 : _b.exclude) || ((_c = collection.match) == null ? void 0 : _c.include)) {
6359
6460
  const matches = this.tinaSchema.getMatches({ collection });
6360
6461
  const match = import_micromatch2.default.isMatch(filepath, matches);
6361
6462
  if (!match) {
@@ -6396,6 +6497,14 @@ var Database = class {
6396
6497
  let delOps = [];
6397
6498
  if (!isGitKeep(normalizedPath, collection)) {
6398
6499
  putOps = [
6500
+ ...makeRefOpsForDocument(
6501
+ normalizedPath,
6502
+ collectionName,
6503
+ collectionReferences,
6504
+ dataFields,
6505
+ "put",
6506
+ level
6507
+ ),
6399
6508
  ...makeIndexOpsForDocument(
6400
6509
  normalizedPath,
6401
6510
  collectionName,
@@ -6419,6 +6528,14 @@ var Database = class {
6419
6528
  SUBLEVEL_OPTIONS
6420
6529
  ).get(normalizedPath);
6421
6530
  delOps = existingItem ? [
6531
+ ...makeRefOpsForDocument(
6532
+ normalizedPath,
6533
+ collectionName,
6534
+ collectionReferences,
6535
+ existingItem,
6536
+ "del",
6537
+ level
6538
+ ),
6422
6539
  ...makeIndexOpsForDocument(
6423
6540
  normalizedPath,
6424
6541
  collectionName,
@@ -6581,6 +6698,22 @@ var Database = class {
6581
6698
  this.tinaSchema = await createSchema({ schema });
6582
6699
  return this.tinaSchema;
6583
6700
  };
6701
+ this.getCollectionReferences = async (level) => {
6702
+ if (this.collectionReferences) {
6703
+ return this.collectionReferences;
6704
+ }
6705
+ const result = {};
6706
+ const schema = await this.getSchema(level || this.contentLevel);
6707
+ const collections = schema.getCollections();
6708
+ for (const collection of collections) {
6709
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6710
+ collection.name
6711
+ );
6712
+ result[collection.name] = collectionReferences;
6713
+ }
6714
+ this.collectionReferences = result;
6715
+ return result;
6716
+ };
6584
6717
  this.getIndexDefinitions = async (level) => {
6585
6718
  if (!this.collectionIndexDefinitions) {
6586
6719
  await new Promise(async (resolve2, reject) => {
@@ -6590,11 +6723,53 @@ var Database = class {
6590
6723
  const collections = schema.getCollections();
6591
6724
  for (const collection of collections) {
6592
6725
  const indexDefinitions = {
6593
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6726
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6594
6727
  // provide a default sort key which is the file sort
6728
+ // pseudo-index for the collection's references
6729
+ [REFS_COLLECTIONS_SORT_KEY]: {
6730
+ fields: [
6731
+ {
6732
+ name: REFS_REFERENCE_FIELD,
6733
+ type: "string",
6734
+ list: false
6735
+ },
6736
+ {
6737
+ name: REFS_PATH_FIELD,
6738
+ type: "string",
6739
+ list: false
6740
+ }
6741
+ ]
6742
+ }
6595
6743
  };
6596
- if (collection.fields) {
6597
- for (const field of collection.fields) {
6744
+ let fields = [];
6745
+ if (collection.templates) {
6746
+ const templateFieldMap = {};
6747
+ const conflictedFields = /* @__PURE__ */ new Set();
6748
+ for (const template of collection.templates) {
6749
+ for (const field of template.fields) {
6750
+ if (!templateFieldMap[field.name]) {
6751
+ templateFieldMap[field.name] = field;
6752
+ } else {
6753
+ if (templateFieldMap[field.name].type !== field.type) {
6754
+ console.warn(
6755
+ `Field ${field.name} has conflicting types in templates - skipping index`
6756
+ );
6757
+ conflictedFields.add(field.name);
6758
+ }
6759
+ }
6760
+ }
6761
+ }
6762
+ for (const conflictedField in conflictedFields) {
6763
+ delete templateFieldMap[conflictedField];
6764
+ }
6765
+ for (const field of Object.values(templateFieldMap)) {
6766
+ fields.push(field);
6767
+ }
6768
+ } else if (collection.fields) {
6769
+ fields = collection.fields;
6770
+ }
6771
+ if (fields) {
6772
+ for (const field of fields) {
6598
6773
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6599
6774
  continue;
6600
6775
  }
@@ -6743,29 +6918,36 @@ var Database = class {
6743
6918
  }
6744
6919
  startKey = startKey || key || "";
6745
6920
  endKey = key || "";
6746
- edges = [...edges, { cursor: key, path: filepath }];
6921
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6747
6922
  }
6748
6923
  return {
6749
- edges: await sequential(edges, async (edge) => {
6750
- try {
6751
- const node = await hydrator(edge.path);
6752
- return {
6753
- node,
6754
- cursor: btoa(edge.cursor)
6755
- };
6756
- } catch (error) {
6757
- console.log(error);
6758
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6759
- throw new TinaQueryError({
6760
- originalError: error,
6761
- file: edge.path,
6762
- collection: collection.name,
6763
- stack: error.stack
6764
- });
6924
+ edges: await sequential(
6925
+ edges,
6926
+ async ({
6927
+ cursor,
6928
+ path: path7,
6929
+ value
6930
+ }) => {
6931
+ try {
6932
+ const node = await hydrator(path7, value);
6933
+ return {
6934
+ node,
6935
+ cursor: btoa(cursor)
6936
+ };
6937
+ } catch (error) {
6938
+ console.log(error);
6939
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6940
+ throw new TinaQueryError({
6941
+ originalError: error,
6942
+ file: path7,
6943
+ collection: collection.name,
6944
+ stack: error.stack
6945
+ });
6946
+ }
6947
+ throw error;
6765
6948
  }
6766
- throw error;
6767
6949
  }
6768
- }),
6950
+ ),
6769
6951
  pageInfo: {
6770
6952
  hasPreviousPage,
6771
6953
  hasNextPage,
@@ -6905,12 +7087,14 @@ var Database = class {
6905
7087
  }
6906
7088
  };
6907
7089
  this.delete = async (filepath) => {
7090
+ var _a;
6908
7091
  await this.initLevel();
6909
7092
  const collection = await this.collectionForPath(filepath);
6910
7093
  if (!collection) {
6911
7094
  throw new Error(`No collection found for path: ${filepath}`);
6912
7095
  }
6913
7096
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
7097
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collection.name];
6914
7098
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6915
7099
  let level = this.contentLevel;
6916
7100
  if (collection == null ? void 0 : collection.isDetached) {
@@ -6929,6 +7113,14 @@ var Database = class {
6929
7113
  collection.path || ""
6930
7114
  );
6931
7115
  await this.contentLevel.batch([
7116
+ ...makeRefOpsForDocument(
7117
+ normalizedPath,
7118
+ collection.name,
7119
+ collectionReferences,
7120
+ item,
7121
+ "del",
7122
+ level
7123
+ ),
6932
7124
  ...makeIndexOpsForDocument(
6933
7125
  normalizedPath,
6934
7126
  collection.name,
@@ -7006,7 +7198,13 @@ var Database = class {
7006
7198
  );
7007
7199
  }
7008
7200
  } else {
7009
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7201
+ await _indexContent(
7202
+ this,
7203
+ level,
7204
+ contentPaths,
7205
+ enqueueOps,
7206
+ collection
7207
+ );
7010
7208
  }
7011
7209
  }
7012
7210
  );
@@ -7146,6 +7344,7 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
7146
7344
  );
7147
7345
  var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
7148
7346
  var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7347
+ var _a;
7149
7348
  let collectionIndexDefinitions;
7150
7349
  let collectionPath;
7151
7350
  if (collection) {
@@ -7156,6 +7355,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7156
7355
  }
7157
7356
  collectionPath = collection.path;
7158
7357
  }
7358
+ const collectionReferences = (_a = await database.getCollectionReferences()) == null ? void 0 : _a[collection == null ? void 0 : collection.name];
7159
7359
  const tinaSchema = await database.getSchema();
7160
7360
  let templateInfo = null;
7161
7361
  if (collection) {
@@ -7177,12 +7377,59 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7177
7377
  await hashPasswordValues(aliasedData, passwordFields);
7178
7378
  }
7179
7379
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
7380
+ const rootSublevel = level.sublevel(
7381
+ CONTENT_ROOT_PREFIX,
7382
+ SUBLEVEL_OPTIONS
7383
+ );
7180
7384
  const folderKey = folderTreeBuilder.update(
7181
7385
  normalizedPath,
7182
7386
  collectionPath || ""
7183
7387
  );
7388
+ const item = await rootSublevel.get(normalizedPath);
7389
+ if (item) {
7390
+ await database.contentLevel.batch([
7391
+ ...makeRefOpsForDocument(
7392
+ normalizedPath,
7393
+ collection == null ? void 0 : collection.name,
7394
+ collectionReferences,
7395
+ item,
7396
+ "del",
7397
+ level
7398
+ ),
7399
+ ...makeIndexOpsForDocument(
7400
+ normalizedPath,
7401
+ collection.name,
7402
+ collectionIndexDefinitions,
7403
+ item,
7404
+ "del",
7405
+ level
7406
+ ),
7407
+ // folder indices
7408
+ ...makeIndexOpsForDocument(
7409
+ normalizedPath,
7410
+ `${collection.name}_${folderKey}`,
7411
+ collectionIndexDefinitions,
7412
+ item,
7413
+ "del",
7414
+ level
7415
+ ),
7416
+ {
7417
+ type: "del",
7418
+ key: normalizedPath,
7419
+ sublevel: rootSublevel
7420
+ }
7421
+ ]);
7422
+ }
7184
7423
  if (!isGitKeep(filepath, collection)) {
7185
7424
  await enqueueOps([
7425
+ ...makeRefOpsForDocument(
7426
+ normalizedPath,
7427
+ collection == null ? void 0 : collection.name,
7428
+ collectionReferences,
7429
+ aliasedData,
7430
+ "put",
7431
+ level
7432
+ ),
7186
7433
  ...makeIndexOpsForDocument(
7187
7434
  normalizedPath,
7188
7435
  collection == null ? void 0 : collection.name,
@@ -7233,6 +7480,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7233
7480
  }
7234
7481
  };
7235
7482
  var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection) => {
7483
+ var _a;
7236
7484
  if (!documentPaths.length) {
7237
7485
  return;
7238
7486
  }
@@ -7246,6 +7494,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7246
7494
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7247
7495
  }
7248
7496
  }
7497
+ const collectionReferences = (_a = await database.getCollectionReferences()) == null ? void 0 : _a[collection == null ? void 0 : collection.name];
7249
7498
  const tinaSchema = await database.getSchema();
7250
7499
  let templateInfo = null;
7251
7500
  if (collection) {
@@ -7269,6 +7518,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7269
7518
  item
7270
7519
  ) : item;
7271
7520
  await enqueueOps([
7521
+ ...makeRefOpsForDocument(
7522
+ itemKey,
7523
+ collection == null ? void 0 : collection.name,
7524
+ collectionReferences,
7525
+ aliasedData,
7526
+ "del",
7527
+ database.contentLevel
7528
+ ),
7272
7529
  ...makeIndexOpsForDocument(
7273
7530
  itemKey,
7274
7531
  collection.name,