@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.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");
@@ -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.14",
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,33 @@ 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;
4897
+ return { object: obj, updated };
4853
4898
  }
4854
- const parentPath = path7.replace(/\.[^.]+$/, "");
4855
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4899
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4900
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4856
4901
  const parents = (0, import_jsonpath_plus2.JSONPath)({ path: parentPath, json: obj, resultType: "value" });
4857
4902
  if (parents.length > 0) {
4858
4903
  parents.forEach((parent) => {
4859
4904
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4860
- parent[keyToUpdate] = newValue;
4905
+ if (parent[keyToUpdate] === oldValue) {
4906
+ parent[keyToUpdate] = newValue;
4907
+ updated = true;
4908
+ }
4861
4909
  }
4862
4910
  });
4863
4911
  }
4864
- return obj;
4912
+ return { object: obj, updated };
4865
4913
  };
4866
4914
  var Resolver = class {
4867
4915
  constructor(init) {
4868
4916
  this.init = init;
4869
- this.context = {};
4870
4917
  this.resolveCollection = async (args, collectionName, hasDocuments) => {
4871
4918
  const collection = this.tinaSchema.getCollection(collectionName);
4872
4919
  const extraFields = {};
@@ -4879,7 +4926,9 @@ var Resolver = class {
4879
4926
  };
4880
4927
  this.getRaw = async (fullPath) => {
4881
4928
  if (typeof fullPath !== "string") {
4882
- throw new Error(`fullPath must be of type string for getDocument request`);
4929
+ throw new Error(
4930
+ `fullPath must be of type string for getDocument request`
4931
+ );
4883
4932
  }
4884
4933
  return this.database.get(fullPath);
4885
4934
  };
@@ -4897,37 +4946,37 @@ var Resolver = class {
4897
4946
  path: rawData["__folderPath"]
4898
4947
  };
4899
4948
  } else {
4900
- this.context = { ...rawData };
4901
- return transformDocumentIntoPayload({
4949
+ return transformDocumentIntoPayload(
4902
4950
  fullPath,
4903
4951
  rawData,
4904
- tinaSchema: this.tinaSchema,
4905
- config: this.config,
4906
- isAudit: this.isAudit,
4907
- context: this.context
4908
- });
4952
+ this.tinaSchema,
4953
+ this.config,
4954
+ this.isAudit
4955
+ );
4909
4956
  }
4910
4957
  };
4911
4958
  this.getDocument = async (fullPath, opts = {}) => {
4912
4959
  if (typeof fullPath !== "string") {
4913
- throw new Error(`fullPath must be of type string for getDocument request`);
4960
+ throw new Error(
4961
+ `fullPath must be of type string for getDocument request`
4962
+ );
4914
4963
  }
4915
4964
  const rawData = await this.getRaw(fullPath);
4916
- this.context = { ...rawData };
4917
4965
  const hasReferences = (opts == null ? void 0 : opts.checkReferences) ? await this.hasReferences(fullPath, opts.collection) : void 0;
4918
- return transformDocumentIntoPayload({
4966
+ return transformDocumentIntoPayload(
4919
4967
  fullPath,
4920
4968
  rawData,
4921
- tinaSchema: this.tinaSchema,
4922
- config: this.config,
4923
- isAudit: this.isAudit,
4924
- context: this.context,
4969
+ this.tinaSchema,
4970
+ this.config,
4971
+ this.isAudit,
4925
4972
  hasReferences
4926
- });
4973
+ );
4927
4974
  };
4928
4975
  this.deleteDocument = async (fullPath) => {
4929
4976
  if (typeof fullPath !== "string") {
4930
- throw new Error(`fullPath must be of type string for getDocument request`);
4977
+ throw new Error(
4978
+ `fullPath must be of type string for getDocument request`
4979
+ );
4931
4980
  }
4932
4981
  await this.database.delete(fullPath);
4933
4982
  };
@@ -5080,34 +5129,36 @@ var Resolver = class {
5080
5129
  isAddPendingDocument,
5081
5130
  isCollectionSpecific
5082
5131
  }) => {
5083
- var _a;
5084
5132
  const doc = await this.getDocument(realPath);
5085
5133
  const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5086
- let values;
5087
5134
  if (isAddPendingDocument === true) {
5088
5135
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5089
- const params = this.buildParams(args);
5136
+ const params2 = this.buildParams(args);
5090
5137
  switch (templateInfo.type) {
5091
5138
  case "object":
5092
- if (params) {
5093
- const mutationValues = await this.buildFieldMutations(
5094
- params,
5139
+ if (params2) {
5140
+ const values = await this.buildFieldMutations(
5141
+ params2,
5095
5142
  templateInfo.template,
5096
5143
  doc == null ? void 0 : doc._rawData
5097
5144
  );
5098
- values = { ...oldDoc, ...mutationValues };
5145
+ await this.database.put(
5146
+ realPath,
5147
+ { ...oldDoc, ...values },
5148
+ collection.name
5149
+ );
5099
5150
  }
5100
5151
  break;
5101
- case "union": {
5152
+ case "union":
5102
5153
  await sequential(templateInfo.templates, async (template) => {
5103
- const templateParams = params[lastItem(template.namespace)];
5154
+ const templateParams = params2[lastItem(template.namespace)];
5104
5155
  if (templateParams) {
5105
5156
  if (typeof templateParams === "string") {
5106
5157
  throw new Error(
5107
5158
  `Expected to find an object for template params, but got string`
5108
5159
  );
5109
5160
  }
5110
- values = {
5161
+ const values = {
5111
5162
  ...oldDoc,
5112
5163
  ...await this.buildFieldMutations(
5113
5164
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
@@ -5117,23 +5168,21 @@ var Resolver = class {
5117
5168
  ),
5118
5169
  _template: lastItem(template.namespace)
5119
5170
  };
5171
+ await this.database.put(realPath, values, collection.name);
5120
5172
  }
5121
5173
  });
5122
- }
5123
5174
  }
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 };
5175
+ return this.getDocument(realPath);
5132
5176
  }
5133
- const _tinaEmbeds = ((_a = this.context) == null ? void 0 : _a._tinaEmbeds) ? { _tinaEmbeds: this.context._tinaEmbeds } : {};
5177
+ const params = await this.buildObjectMutations(
5178
+ //@ts-ignore
5179
+ isCollectionSpecific ? args.params : args.params[collection.name],
5180
+ collection,
5181
+ doc == null ? void 0 : doc._rawData
5182
+ );
5134
5183
  await this.database.put(
5135
5184
  realPath,
5136
- { ...values, ..._tinaEmbeds },
5185
+ { ...oldDoc, ...params },
5137
5186
  collection.name
5138
5187
  );
5139
5188
  return this.getDocument(realPath);
@@ -5249,17 +5298,35 @@ var Resolver = class {
5249
5298
  await this.deleteDocument(realPath);
5250
5299
  if (await this.hasReferences(realPath, collection)) {
5251
5300
  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(
5301
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5302
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5303
+ docsWithRefs
5304
+ )) {
5305
+ let refDoc = await this.getRaw(pathToDocWithRef);
5306
+ let hasUpdate = false;
5307
+ for (const path7 of referencePaths) {
5308
+ const { object: object2, updated } = updateObjectWithJsonPath(
5257
5309
  refDoc,
5258
- ref.path.join("."),
5310
+ path7,
5311
+ realPath,
5259
5312
  null
5260
5313
  );
5314
+ refDoc = object2;
5315
+ hasUpdate = updated || hasUpdate;
5316
+ }
5317
+ if (hasUpdate) {
5318
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5319
+ if (!collectionWithRef) {
5320
+ throw new Error(
5321
+ `Unable to find collection for ${pathToDocWithRef}`
5322
+ );
5323
+ }
5324
+ await this.database.put(
5325
+ pathToDocWithRef,
5326
+ refDoc,
5327
+ collectionWithRef.name
5328
+ );
5261
5329
  }
5262
- await this.database.put(refPath, refDoc, collection2);
5263
5330
  }
5264
5331
  }
5265
5332
  }
@@ -5279,26 +5346,49 @@ var Resolver = class {
5279
5346
  collection == null ? void 0 : collection.path,
5280
5347
  args.params.relativePath
5281
5348
  );
5349
+ if (newRealPath === realPath) {
5350
+ return doc;
5351
+ }
5282
5352
  await this.database.put(newRealPath, doc._rawData, collection.name);
5283
5353
  await this.deleteDocument(realPath);
5284
5354
  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("."),
5355
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5356
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5357
+ docsWithRefs
5358
+ )) {
5359
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5360
+ let hasUpdate = false;
5361
+ for (const path7 of referencePaths) {
5362
+ const { object: object2, updated } = updateObjectWithJsonPath(
5363
+ docWithRef,
5364
+ path7,
5365
+ realPath,
5292
5366
  newRealPath
5293
5367
  );
5368
+ docWithRef = object2;
5369
+ hasUpdate = updated || hasUpdate;
5370
+ }
5371
+ if (hasUpdate) {
5372
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5373
+ if (!collectionWithRef) {
5374
+ throw new Error(
5375
+ `Unable to find collection for ${pathToDocWithRef}`
5376
+ );
5377
+ }
5378
+ await this.database.put(
5379
+ pathToDocWithRef,
5380
+ docWithRef,
5381
+ collectionWithRef.name
5382
+ );
5294
5383
  }
5295
- await this.database.put(refPath, refDoc, collection2);
5296
5384
  }
5297
5385
  }
5298
5386
  return this.getDocument(newRealPath);
5299
5387
  }
5300
5388
  if (alreadyExists === false) {
5301
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5389
+ throw new Error(
5390
+ `Unable to update document, ${realPath} does not exist`
5391
+ );
5302
5392
  }
5303
5393
  return this.updateResolveDocument({
5304
5394
  collection,
@@ -5424,35 +5514,30 @@ var Resolver = class {
5424
5514
  */
5425
5515
  this.hasReferences = async (id, c) => {
5426
5516
  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
- }
5517
+ await this.database.query(
5518
+ {
5519
+ collection: c.name,
5520
+ filterChain: makeFilterChain({
5521
+ conditions: [
5522
+ {
5523
+ filterPath: REFS_REFERENCE_FIELD,
5524
+ filterExpression: {
5525
+ _type: "string",
5526
+ _list: false,
5527
+ eq: id
5528
+ }
5529
+ }
5530
+ ]
5531
+ }),
5532
+ sort: REFS_COLLECTIONS_SORT_KEY
5533
+ },
5534
+ (refId) => {
5535
+ count++;
5536
+ return refId;
5455
5537
  }
5538
+ );
5539
+ if (count) {
5540
+ return true;
5456
5541
  }
5457
5542
  return false;
5458
5543
  };
@@ -5460,46 +5545,41 @@ var Resolver = class {
5460
5545
  * Finds references to a document
5461
5546
  * @param id the id of the document to find references to
5462
5547
  * @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
5548
+ * @returns a map of references to the document
5464
5549
  */
5465
5550
  this.findReferences = async (id, c) => {
5466
5551
  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] = [];
5552
+ await this.database.query(
5553
+ {
5554
+ collection: c.name,
5555
+ filterChain: makeFilterChain({
5556
+ conditions: [
5557
+ {
5558
+ filterPath: REFS_REFERENCE_FIELD,
5559
+ filterExpression: {
5560
+ _type: "string",
5561
+ _list: false,
5562
+ eq: id
5563
+ }
5493
5564
  }
5494
- references[collection][refId].push({
5495
- path: ref.path,
5496
- field: ref.field
5497
- });
5498
- return refId;
5499
- }
5500
- );
5565
+ ]
5566
+ }),
5567
+ sort: REFS_COLLECTIONS_SORT_KEY
5568
+ },
5569
+ (refId, rawItem) => {
5570
+ if (!references[c.name]) {
5571
+ references[c.name] = {};
5572
+ }
5573
+ if (!references[c.name][refId]) {
5574
+ references[c.name][refId] = [];
5575
+ }
5576
+ const referencePath = rawItem == null ? void 0 : rawItem[REFS_PATH_FIELD];
5577
+ if (referencePath) {
5578
+ references[c.name][refId].push(referencePath);
5579
+ }
5580
+ return refId;
5501
5581
  }
5502
- }
5582
+ );
5503
5583
  return references;
5504
5584
  };
5505
5585
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
@@ -5571,15 +5651,13 @@ var Resolver = class {
5571
5651
  break;
5572
5652
  case "rich-text":
5573
5653
  accum[fieldName] = (0, import_mdx.stringifyMDX)(
5574
- // @ts-ignore
5575
5654
  fieldValue,
5576
5655
  field,
5577
5656
  (fieldValue2) => resolveMediaCloudToRelative(
5578
5657
  fieldValue2,
5579
5658
  this.config,
5580
5659
  this.tinaSchema.schema
5581
- ),
5582
- this.context
5660
+ )
5583
5661
  );
5584
5662
  break;
5585
5663
  case "reference":
@@ -6237,6 +6315,7 @@ var Database = class {
6237
6315
  }
6238
6316
  };
6239
6317
  this.addPendingDocument = async (filepath, data) => {
6318
+ var _a;
6240
6319
  await this.initLevel();
6241
6320
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6242
6321
  const collection = await this.collectionForPath(filepath);
@@ -6250,6 +6329,7 @@ var Database = class {
6250
6329
  );
6251
6330
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6252
6331
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6332
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collection.name];
6253
6333
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6254
6334
  if (!(collection == null ? void 0 : collection.isDetached)) {
6255
6335
  if (this.bridge) {
@@ -6278,6 +6358,14 @@ var Database = class {
6278
6358
  let delOps = [];
6279
6359
  if (!isGitKeep(normalizedPath, collection)) {
6280
6360
  putOps = [
6361
+ ...makeRefOpsForDocument(
6362
+ normalizedPath,
6363
+ collection == null ? void 0 : collection.name,
6364
+ collectionReferences,
6365
+ dataFields,
6366
+ "put",
6367
+ level
6368
+ ),
6281
6369
  ...makeIndexOpsForDocument(
6282
6370
  normalizedPath,
6283
6371
  collection == null ? void 0 : collection.name,
@@ -6301,6 +6389,14 @@ var Database = class {
6301
6389
  SUBLEVEL_OPTIONS
6302
6390
  ).get(normalizedPath);
6303
6391
  delOps = existingItem ? [
6392
+ ...makeRefOpsForDocument(
6393
+ normalizedPath,
6394
+ collection == null ? void 0 : collection.name,
6395
+ collectionReferences,
6396
+ existingItem,
6397
+ "del",
6398
+ level
6399
+ ),
6304
6400
  ...makeIndexOpsForDocument(
6305
6401
  normalizedPath,
6306
6402
  collection == null ? void 0 : collection.name,
@@ -6336,7 +6432,7 @@ var Database = class {
6336
6432
  await level.batch(ops);
6337
6433
  };
6338
6434
  this.put = async (filepath, data, collectionName) => {
6339
- var _a, _b;
6435
+ var _a, _b, _c;
6340
6436
  await this.initLevel();
6341
6437
  try {
6342
6438
  if (SYSTEM_FILES.includes(filepath)) {
@@ -6349,13 +6445,14 @@ var Database = class {
6349
6445
  );
6350
6446
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6351
6447
  }
6448
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collectionName];
6352
6449
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6353
6450
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6354
6451
  const collection = await this.collectionForPath(filepath);
6355
6452
  if (!collection) {
6356
6453
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
6357
6454
  }
6358
- if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
6455
+ if (((_b = collection.match) == null ? void 0 : _b.exclude) || ((_c = collection.match) == null ? void 0 : _c.include)) {
6359
6456
  const matches = this.tinaSchema.getMatches({ collection });
6360
6457
  const match = import_micromatch2.default.isMatch(filepath, matches);
6361
6458
  if (!match) {
@@ -6396,6 +6493,14 @@ var Database = class {
6396
6493
  let delOps = [];
6397
6494
  if (!isGitKeep(normalizedPath, collection)) {
6398
6495
  putOps = [
6496
+ ...makeRefOpsForDocument(
6497
+ normalizedPath,
6498
+ collectionName,
6499
+ collectionReferences,
6500
+ dataFields,
6501
+ "put",
6502
+ level
6503
+ ),
6399
6504
  ...makeIndexOpsForDocument(
6400
6505
  normalizedPath,
6401
6506
  collectionName,
@@ -6419,6 +6524,14 @@ var Database = class {
6419
6524
  SUBLEVEL_OPTIONS
6420
6525
  ).get(normalizedPath);
6421
6526
  delOps = existingItem ? [
6527
+ ...makeRefOpsForDocument(
6528
+ normalizedPath,
6529
+ collectionName,
6530
+ collectionReferences,
6531
+ existingItem,
6532
+ "del",
6533
+ level
6534
+ ),
6422
6535
  ...makeIndexOpsForDocument(
6423
6536
  normalizedPath,
6424
6537
  collectionName,
@@ -6581,6 +6694,22 @@ var Database = class {
6581
6694
  this.tinaSchema = await createSchema({ schema });
6582
6695
  return this.tinaSchema;
6583
6696
  };
6697
+ this.getCollectionReferences = async (level) => {
6698
+ if (this.collectionReferences) {
6699
+ return this.collectionReferences;
6700
+ }
6701
+ const result = {};
6702
+ const schema = await this.getSchema(level || this.contentLevel);
6703
+ const collections = schema.getCollections();
6704
+ for (const collection of collections) {
6705
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6706
+ collection.name
6707
+ );
6708
+ result[collection.name] = collectionReferences;
6709
+ }
6710
+ this.collectionReferences = result;
6711
+ return result;
6712
+ };
6584
6713
  this.getIndexDefinitions = async (level) => {
6585
6714
  if (!this.collectionIndexDefinitions) {
6586
6715
  await new Promise(async (resolve2, reject) => {
@@ -6590,8 +6719,23 @@ var Database = class {
6590
6719
  const collections = schema.getCollections();
6591
6720
  for (const collection of collections) {
6592
6721
  const indexDefinitions = {
6593
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6722
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6594
6723
  // provide a default sort key which is the file sort
6724
+ // pseudo-index for the collection's references
6725
+ [REFS_COLLECTIONS_SORT_KEY]: {
6726
+ fields: [
6727
+ {
6728
+ name: REFS_REFERENCE_FIELD,
6729
+ type: "string",
6730
+ list: false
6731
+ },
6732
+ {
6733
+ name: REFS_PATH_FIELD,
6734
+ type: "string",
6735
+ list: false
6736
+ }
6737
+ ]
6738
+ }
6595
6739
  };
6596
6740
  if (collection.fields) {
6597
6741
  for (const field of collection.fields) {
@@ -6743,29 +6887,36 @@ var Database = class {
6743
6887
  }
6744
6888
  startKey = startKey || key || "";
6745
6889
  endKey = key || "";
6746
- edges = [...edges, { cursor: key, path: filepath }];
6890
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6747
6891
  }
6748
6892
  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
- });
6893
+ edges: await sequential(
6894
+ edges,
6895
+ async ({
6896
+ cursor,
6897
+ path: path7,
6898
+ value
6899
+ }) => {
6900
+ try {
6901
+ const node = await hydrator(path7, value);
6902
+ return {
6903
+ node,
6904
+ cursor: btoa(cursor)
6905
+ };
6906
+ } catch (error) {
6907
+ console.log(error);
6908
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6909
+ throw new TinaQueryError({
6910
+ originalError: error,
6911
+ file: path7,
6912
+ collection: collection.name,
6913
+ stack: error.stack
6914
+ });
6915
+ }
6916
+ throw error;
6765
6917
  }
6766
- throw error;
6767
6918
  }
6768
- }),
6919
+ ),
6769
6920
  pageInfo: {
6770
6921
  hasPreviousPage,
6771
6922
  hasNextPage,
@@ -6905,12 +7056,14 @@ var Database = class {
6905
7056
  }
6906
7057
  };
6907
7058
  this.delete = async (filepath) => {
7059
+ var _a;
6908
7060
  await this.initLevel();
6909
7061
  const collection = await this.collectionForPath(filepath);
6910
7062
  if (!collection) {
6911
7063
  throw new Error(`No collection found for path: ${filepath}`);
6912
7064
  }
6913
7065
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
7066
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collection.name];
6914
7067
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6915
7068
  let level = this.contentLevel;
6916
7069
  if (collection == null ? void 0 : collection.isDetached) {
@@ -6929,6 +7082,14 @@ var Database = class {
6929
7082
  collection.path || ""
6930
7083
  );
6931
7084
  await this.contentLevel.batch([
7085
+ ...makeRefOpsForDocument(
7086
+ normalizedPath,
7087
+ collection.name,
7088
+ collectionReferences,
7089
+ item,
7090
+ "del",
7091
+ level
7092
+ ),
6932
7093
  ...makeIndexOpsForDocument(
6933
7094
  normalizedPath,
6934
7095
  collection.name,
@@ -7006,7 +7167,13 @@ var Database = class {
7006
7167
  );
7007
7168
  }
7008
7169
  } else {
7009
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7170
+ await _indexContent(
7171
+ this,
7172
+ level,
7173
+ contentPaths,
7174
+ enqueueOps,
7175
+ collection
7176
+ );
7010
7177
  }
7011
7178
  }
7012
7179
  );
@@ -7146,6 +7313,7 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
7146
7313
  );
7147
7314
  var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
7148
7315
  var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7316
+ var _a;
7149
7317
  let collectionIndexDefinitions;
7150
7318
  let collectionPath;
7151
7319
  if (collection) {
@@ -7156,14 +7324,16 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7156
7324
  }
7157
7325
  collectionPath = collection.path;
7158
7326
  }
7327
+ const collectionReferences = (_a = await database.getCollectionReferences()) == null ? void 0 : _a[collection == null ? void 0 : collection.name];
7159
7328
  const tinaSchema = await database.getSchema();
7160
7329
  let templateInfo = null;
7161
7330
  if (collection) {
7162
7331
  templateInfo = tinaSchema.getTemplatesForCollectable(collection);
7163
7332
  }
7164
7333
  const folderTreeBuilder = new FolderTreeBuilder();
7165
- await sequential(documentPaths, async (filepath) => {
7334
+ async function processFile(filepath) {
7166
7335
  try {
7336
+ console.log(`Preloading ${filepath}`);
7167
7337
  const aliasedData = await loadAndParseWithAliases(
7168
7338
  database.bridge,
7169
7339
  filepath,
@@ -7177,12 +7347,62 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7177
7347
  await hashPasswordValues(aliasedData, passwordFields);
7178
7348
  }
7179
7349
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
7350
+ const rootSublevel = level.sublevel(
7351
+ CONTENT_ROOT_PREFIX,
7352
+ SUBLEVEL_OPTIONS
7353
+ );
7180
7354
  const folderKey = folderTreeBuilder.update(
7181
7355
  normalizedPath,
7182
7356
  collectionPath || ""
7183
7357
  );
7358
+ const item = await rootSublevel.get(normalizedPath);
7359
+ await new Promise((res) => setTimeout(res, 5e3));
7360
+ console.log("Ceasing preload");
7361
+ if (item) {
7362
+ console.log("Running deletion operations");
7363
+ await database.contentLevel.batch([
7364
+ ...makeRefOpsForDocument(
7365
+ normalizedPath,
7366
+ collection == null ? void 0 : collection.name,
7367
+ collectionReferences,
7368
+ item,
7369
+ "del",
7370
+ level
7371
+ ),
7372
+ ...makeIndexOpsForDocument(
7373
+ normalizedPath,
7374
+ collection.name,
7375
+ collectionIndexDefinitions,
7376
+ item,
7377
+ "del",
7378
+ level
7379
+ ),
7380
+ // folder indices
7381
+ ...makeIndexOpsForDocument(
7382
+ normalizedPath,
7383
+ `${collection.name}_${folderKey}`,
7384
+ collectionIndexDefinitions,
7385
+ item,
7386
+ "del",
7387
+ level
7388
+ ),
7389
+ {
7390
+ type: "del",
7391
+ key: normalizedPath,
7392
+ sublevel: rootSublevel
7393
+ }
7394
+ ]);
7395
+ }
7184
7396
  if (!isGitKeep(filepath, collection)) {
7185
7397
  await enqueueOps([
7398
+ ...makeRefOpsForDocument(
7399
+ normalizedPath,
7400
+ collection == null ? void 0 : collection.name,
7401
+ collectionReferences,
7402
+ aliasedData,
7403
+ "put",
7404
+ level
7405
+ ),
7186
7406
  ...makeIndexOpsForDocument(
7187
7407
  normalizedPath,
7188
7408
  collection == null ? void 0 : collection.name,
@@ -7219,7 +7439,10 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7219
7439
  stack: error.stack
7220
7440
  });
7221
7441
  }
7222
- });
7442
+ }
7443
+ ;
7444
+ const filePromises = documentPaths.map(processFile);
7445
+ await Promise.all(filePromises);
7223
7446
  if (collection) {
7224
7447
  await enqueueOps(
7225
7448
  makeFolderOpsForCollection(
@@ -7233,6 +7456,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7233
7456
  }
7234
7457
  };
7235
7458
  var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection) => {
7459
+ var _a;
7236
7460
  if (!documentPaths.length) {
7237
7461
  return;
7238
7462
  }
@@ -7246,6 +7470,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7246
7470
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7247
7471
  }
7248
7472
  }
7473
+ const collectionReferences = (_a = await database.getCollectionReferences()) == null ? void 0 : _a[collection == null ? void 0 : collection.name];
7249
7474
  const tinaSchema = await database.getSchema();
7250
7475
  let templateInfo = null;
7251
7476
  if (collection) {
@@ -7269,6 +7494,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7269
7494
  item
7270
7495
  ) : item;
7271
7496
  await enqueueOps([
7497
+ ...makeRefOpsForDocument(
7498
+ itemKey,
7499
+ collection == null ? void 0 : collection.name,
7500
+ collectionReferences,
7501
+ aliasedData,
7502
+ "del",
7503
+ database.contentLevel
7504
+ ),
7272
7505
  ...makeIndexOpsForDocument(
7273
7506
  itemKey,
7274
7507
  collection.name,