@tinacms/graphql 0.0.0-ed38135-20250102012919 → 0.0.0-ee8d9a3-20250429131017

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
@@ -1029,41 +1029,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1029
1029
  yield maybeNode;
1030
1030
  visited.add(maybeNode);
1031
1031
  }
1032
- function addNamespaceToSchema(maybeNode, namespace = []) {
1033
- if (typeof maybeNode === "string") {
1034
- return maybeNode;
1035
- }
1036
- if (typeof maybeNode === "boolean") {
1037
- return maybeNode;
1038
- }
1039
- const newNode = maybeNode;
1040
- const keys = Object.keys(maybeNode);
1041
- Object.values(maybeNode).map((m, index) => {
1042
- const key = keys[index];
1043
- if (Array.isArray(m)) {
1044
- newNode[key] = m.map((element) => {
1045
- if (!element) {
1046
- return;
1047
- }
1048
- if (!element.hasOwnProperty("name")) {
1049
- return element;
1050
- }
1051
- const value = element.name || element.value;
1052
- return addNamespaceToSchema(element, [...namespace, value]);
1053
- });
1054
- } else {
1055
- if (!m) {
1056
- return;
1057
- }
1058
- if (!m.hasOwnProperty("name")) {
1059
- newNode[key] = m;
1060
- } else {
1061
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1062
- }
1063
- }
1064
- });
1065
- return { ...newNode, namespace };
1066
- }
1067
1032
  var generateNamespacedFieldName = (names, suffix = "") => {
1068
1033
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1069
1034
  };
@@ -1882,7 +1847,7 @@ var Builder = class {
1882
1847
  * ```
1883
1848
  *
1884
1849
  * @public
1885
- * @param collection a Tina Cloud collection
1850
+ * @param collection a TinaCloud collection
1886
1851
  */
1887
1852
  this.collectionFragment = async (collection) => {
1888
1853
  const name = NAMER.dataTypeName(collection.namespace);
@@ -2898,6 +2863,7 @@ var filterSelections = (arr) => {
2898
2863
  import { TinaSchema } from "@tinacms/schema-tools";
2899
2864
 
2900
2865
  // src/schema/validate.ts
2866
+ import { addNamespaceToSchema } from "@tinacms/schema-tools";
2901
2867
  import deepClone from "lodash.clonedeep";
2902
2868
  import * as yup2 from "yup";
2903
2869
  import {
@@ -3053,7 +3019,7 @@ var validateField = async (field) => {
3053
3019
  // package.json
3054
3020
  var package_default = {
3055
3021
  name: "@tinacms/graphql",
3056
- version: "1.5.9",
3022
+ version: "1.5.16",
3057
3023
  main: "dist/index.js",
3058
3024
  module: "dist/index.mjs",
3059
3025
  typings: "dist/index.d.ts",
@@ -3080,8 +3046,8 @@ var package_default = {
3080
3046
  build: "tinacms-scripts build",
3081
3047
  docs: "pnpm typedoc",
3082
3048
  serve: "pnpm nodemon dist/server.js",
3083
- test: "jest",
3084
- "test-watch": "jest --watch"
3049
+ test: "vitest run",
3050
+ "test-watch": "vitest"
3085
3051
  },
3086
3052
  dependencies: {
3087
3053
  "@iarna/toml": "^2.2.5",
@@ -3089,12 +3055,12 @@ var package_default = {
3089
3055
  "@tinacms/schema-tools": "workspace:*",
3090
3056
  "abstract-level": "^1.0.4",
3091
3057
  "date-fns": "^2.30.0",
3092
- "fast-glob": "^3.3.2",
3093
- "fs-extra": "^11.2.0",
3058
+ "fast-glob": "^3.3.3",
3059
+ "fs-extra": "^11.3.0",
3094
3060
  "glob-parent": "^6.0.2",
3095
3061
  graphql: "15.8.0",
3096
3062
  "gray-matter": "^4.0.3",
3097
- "isomorphic-git": "^1.27.1",
3063
+ "isomorphic-git": "^1.29.0",
3098
3064
  "js-sha1": "^0.6.0",
3099
3065
  "js-yaml": "^3.14.1",
3100
3066
  "jsonpath-plus": "10.1.0",
@@ -3104,7 +3070,7 @@ var package_default = {
3104
3070
  "many-level": "^2.0.0",
3105
3071
  micromatch: "4.0.8",
3106
3072
  "normalize-path": "^3.0.0",
3107
- "readable-stream": "^4.5.2",
3073
+ "readable-stream": "^4.7.0",
3108
3074
  scmp: "^2.1.0",
3109
3075
  yup: "^0.32.11"
3110
3076
  },
@@ -3122,24 +3088,23 @@ var package_default = {
3122
3088
  "@types/estree": "^0.0.50",
3123
3089
  "@types/express": "^4.17.21",
3124
3090
  "@types/fs-extra": "^9.0.13",
3125
- "@types/jest": "^26.0.24",
3126
3091
  "@types/js-yaml": "^3.12.10",
3127
3092
  "@types/lodash.camelcase": "^4.3.9",
3128
3093
  "@types/lodash.upperfirst": "^4.3.9",
3129
3094
  "@types/lru-cache": "^5.1.1",
3130
3095
  "@types/mdast": "^3.0.15",
3131
3096
  "@types/micromatch": "^4.0.9",
3132
- "@types/node": "^22.9.0",
3097
+ "@types/node": "^22.13.1",
3133
3098
  "@types/normalize-path": "^3.0.2",
3134
3099
  "@types/ws": "^7.4.7",
3135
3100
  "@types/yup": "^0.29.14",
3136
- jest: "^29.7.0",
3137
- "jest-diff": "^29.7.0",
3138
3101
  "jest-file-snapshot": "^0.5.0",
3139
- "jest-matcher-utils": "^29.7.0",
3140
3102
  "memory-level": "^1.0.0",
3141
3103
  nodemon: "3.1.4",
3142
- typescript: "^5.6.3"
3104
+ typescript: "^5.7.3",
3105
+ vite: "^4.5.9",
3106
+ vitest: "^0.32.4",
3107
+ zod: "^3.24.2"
3143
3108
  }
3144
3109
  };
3145
3110
 
@@ -3295,7 +3260,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3295
3260
  await builder.buildCreateCollectionFolderMutation()
3296
3261
  );
3297
3262
  await sequential(collections, async (collection) => {
3298
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3263
+ queryTypeDefinitionFields.push(
3264
+ await builder.collectionDocument(collection)
3265
+ );
3299
3266
  if (collection.isAuthCollection) {
3300
3267
  queryTypeDefinitionFields.push(
3301
3268
  await builder.authenticationCollectionDocument(collection)
@@ -3610,7 +3577,9 @@ var LevelProxyHandler = {
3610
3577
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3611
3578
  }
3612
3579
  if (typeof target[property] !== "function") {
3613
- 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
+ );
3614
3583
  }
3615
3584
  if (property === "get") {
3616
3585
  return async (...args) => {
@@ -3995,6 +3964,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3995
3964
 
3996
3965
  // src/database/datalayer.ts
3997
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__";
3998
3970
  var DEFAULT_NUMERIC_LPAD = 4;
3999
3971
  var applyPadding = (input, pad) => {
4000
3972
  if (pad) {
@@ -4568,6 +4540,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4568
4540
  }
4569
4541
  return result;
4570
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
+ };
4571
4594
  var makeStringEscaper = (regex, replacement) => {
4572
4595
  return (input) => {
4573
4596
  if (Array.isArray(input)) {
@@ -4788,24 +4811,33 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4788
4811
  throw e;
4789
4812
  }
4790
4813
  };
4791
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4814
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4815
+ let updated = false;
4792
4816
  if (!path7.includes(".") && !path7.includes("[")) {
4793
- if (path7 in obj) {
4817
+ if (path7 in obj && obj[path7] === oldValue) {
4794
4818
  obj[path7] = newValue;
4819
+ updated = true;
4795
4820
  }
4796
- return obj;
4797
- }
4798
- const parentPath = path7.replace(/\.[^.]+$/, "");
4799
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4800
- 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
+ });
4801
4830
  if (parents.length > 0) {
4802
4831
  parents.forEach((parent) => {
4803
4832
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4804
- parent[keyToUpdate] = newValue;
4833
+ if (parent[keyToUpdate] === oldValue) {
4834
+ parent[keyToUpdate] = newValue;
4835
+ updated = true;
4836
+ }
4805
4837
  }
4806
4838
  });
4807
4839
  }
4808
- return obj;
4840
+ return { object: obj, updated };
4809
4841
  };
4810
4842
  var Resolver = class {
4811
4843
  constructor(init) {
@@ -4822,7 +4854,9 @@ var Resolver = class {
4822
4854
  };
4823
4855
  this.getRaw = async (fullPath) => {
4824
4856
  if (typeof fullPath !== "string") {
4825
- 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
+ );
4826
4860
  }
4827
4861
  return this.database.get(fullPath);
4828
4862
  };
@@ -4851,7 +4885,9 @@ var Resolver = class {
4851
4885
  };
4852
4886
  this.getDocument = async (fullPath, opts = {}) => {
4853
4887
  if (typeof fullPath !== "string") {
4854
- 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
+ );
4855
4891
  }
4856
4892
  const rawData = await this.getRaw(fullPath);
4857
4893
  const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
@@ -4866,7 +4902,9 @@ var Resolver = class {
4866
4902
  };
4867
4903
  this.deleteDocument = async (fullPath) => {
4868
4904
  if (typeof fullPath !== "string") {
4869
- 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
+ );
4870
4908
  }
4871
4909
  await this.database.delete(fullPath);
4872
4910
  };
@@ -5070,7 +5108,11 @@ var Resolver = class {
5070
5108
  collection,
5071
5109
  doc?._rawData
5072
5110
  );
5073
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
5111
+ await this.database.put(
5112
+ realPath,
5113
+ { ...oldDoc, ...params },
5114
+ collection.name
5115
+ );
5074
5116
  return this.getDocument(realPath);
5075
5117
  };
5076
5118
  /**
@@ -5183,17 +5225,35 @@ var Resolver = class {
5183
5225
  await this.deleteDocument(realPath);
5184
5226
  if (await this.hasReferences(realPath, collection)) {
5185
5227
  const collRefs = await this.findReferences(realPath, collection);
5186
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5187
- for (const [refPath, refs] of Object.entries(refFields)) {
5188
- let refDoc = await this.getRaw(refPath);
5189
- for (const ref of refs) {
5190
- 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(
5191
5236
  refDoc,
5192
- ref.path.join("."),
5237
+ path7,
5238
+ realPath,
5193
5239
  null
5194
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
+ );
5195
5256
  }
5196
- await this.database.put(refPath, refDoc, collection2);
5197
5257
  }
5198
5258
  }
5199
5259
  }
@@ -5213,26 +5273,49 @@ var Resolver = class {
5213
5273
  collection?.path,
5214
5274
  args.params.relativePath
5215
5275
  );
5276
+ if (newRealPath === realPath) {
5277
+ return doc;
5278
+ }
5216
5279
  await this.database.put(newRealPath, doc._rawData, collection.name);
5217
5280
  await this.deleteDocument(realPath);
5218
5281
  const collRefs = await this.findReferences(realPath, collection);
5219
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5220
- for (const [refPath, refs] of Object.entries(refFields)) {
5221
- let refDoc = await this.getRaw(refPath);
5222
- for (const ref of refs) {
5223
- refDoc = updateObjectWithJsonPath(
5224
- refDoc,
5225
- 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,
5226
5293
  newRealPath
5227
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
+ );
5228
5310
  }
5229
- await this.database.put(refPath, refDoc, collection2);
5230
5311
  }
5231
5312
  }
5232
5313
  return this.getDocument(newRealPath);
5233
5314
  }
5234
5315
  if (alreadyExists === false) {
5235
- 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
+ );
5236
5319
  }
5237
5320
  return this.updateResolveDocument({
5238
5321
  collection,
@@ -5358,35 +5441,30 @@ var Resolver = class {
5358
5441
  */
5359
5442
  this.hasReferences = async (id, c) => {
5360
5443
  let count = 0;
5361
- const deepRefs = this.tinaSchema.findReferences(c.name);
5362
- for (const [collection, refs] of Object.entries(deepRefs)) {
5363
- for (const ref of refs) {
5364
- await this.database.query(
5365
- {
5366
- collection,
5367
- filterChain: makeFilterChain({
5368
- conditions: [
5369
- {
5370
- filterPath: ref.path.join("."),
5371
- filterExpression: {
5372
- _type: "reference",
5373
- _list: false,
5374
- eq: id
5375
- }
5376
- }
5377
- ]
5378
- }),
5379
- sort: ref.field.name
5380
- },
5381
- (refId) => {
5382
- count++;
5383
- return refId;
5384
- }
5385
- );
5386
- if (count) {
5387
- return true;
5388
- }
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;
5389
5464
  }
5465
+ );
5466
+ if (count) {
5467
+ return true;
5390
5468
  }
5391
5469
  return false;
5392
5470
  };
@@ -5394,46 +5472,41 @@ var Resolver = class {
5394
5472
  * Finds references to a document
5395
5473
  * @param id the id of the document to find references to
5396
5474
  * @param c the collection to find references in
5397
- * @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
5398
5476
  */
5399
5477
  this.findReferences = async (id, c) => {
5400
5478
  const references = {};
5401
- const deepRefs = this.tinaSchema.findReferences(c.name);
5402
- for (const [collection, refs] of Object.entries(deepRefs)) {
5403
- for (const ref of refs) {
5404
- await this.database.query(
5405
- {
5406
- collection,
5407
- filterChain: makeFilterChain({
5408
- conditions: [
5409
- {
5410
- filterPath: ref.path.join("."),
5411
- filterExpression: {
5412
- _type: "reference",
5413
- _list: false,
5414
- eq: id
5415
- }
5416
- }
5417
- ]
5418
- }),
5419
- sort: ref.field.name
5420
- },
5421
- (refId) => {
5422
- if (!references[collection]) {
5423
- references[collection] = {};
5424
- }
5425
- if (!references[collection][refId]) {
5426
- 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
+ }
5427
5491
  }
5428
- references[collection][refId].push({
5429
- path: ref.path,
5430
- field: ref.field
5431
- });
5432
- return refId;
5433
- }
5434
- );
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;
5435
5508
  }
5436
- }
5509
+ );
5437
5510
  return references;
5438
5511
  };
5439
5512
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
@@ -6177,6 +6250,7 @@ var Database = class {
6177
6250
  );
6178
6251
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6179
6252
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6253
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6180
6254
  const normalizedPath = normalizePath(filepath);
6181
6255
  if (!collection?.isDetached) {
6182
6256
  if (this.bridge) {
@@ -6205,6 +6279,14 @@ var Database = class {
6205
6279
  let delOps = [];
6206
6280
  if (!isGitKeep(normalizedPath, collection)) {
6207
6281
  putOps = [
6282
+ ...makeRefOpsForDocument(
6283
+ normalizedPath,
6284
+ collection?.name,
6285
+ collectionReferences,
6286
+ dataFields,
6287
+ "put",
6288
+ level
6289
+ ),
6208
6290
  ...makeIndexOpsForDocument(
6209
6291
  normalizedPath,
6210
6292
  collection?.name,
@@ -6228,6 +6310,14 @@ var Database = class {
6228
6310
  SUBLEVEL_OPTIONS
6229
6311
  ).get(normalizedPath);
6230
6312
  delOps = existingItem ? [
6313
+ ...makeRefOpsForDocument(
6314
+ normalizedPath,
6315
+ collection?.name,
6316
+ collectionReferences,
6317
+ existingItem,
6318
+ "del",
6319
+ level
6320
+ ),
6231
6321
  ...makeIndexOpsForDocument(
6232
6322
  normalizedPath,
6233
6323
  collection?.name,
@@ -6275,6 +6365,7 @@ var Database = class {
6275
6365
  );
6276
6366
  collectionIndexDefinitions = indexDefinitions?.[collectionName];
6277
6367
  }
6368
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6278
6369
  const normalizedPath = normalizePath(filepath);
6279
6370
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6280
6371
  const collection = await this.collectionForPath(filepath);
@@ -6322,6 +6413,14 @@ var Database = class {
6322
6413
  let delOps = [];
6323
6414
  if (!isGitKeep(normalizedPath, collection)) {
6324
6415
  putOps = [
6416
+ ...makeRefOpsForDocument(
6417
+ normalizedPath,
6418
+ collectionName,
6419
+ collectionReferences,
6420
+ dataFields,
6421
+ "put",
6422
+ level
6423
+ ),
6325
6424
  ...makeIndexOpsForDocument(
6326
6425
  normalizedPath,
6327
6426
  collectionName,
@@ -6345,6 +6444,14 @@ var Database = class {
6345
6444
  SUBLEVEL_OPTIONS
6346
6445
  ).get(normalizedPath);
6347
6446
  delOps = existingItem ? [
6447
+ ...makeRefOpsForDocument(
6448
+ normalizedPath,
6449
+ collectionName,
6450
+ collectionReferences,
6451
+ existingItem,
6452
+ "del",
6453
+ level
6454
+ ),
6348
6455
  ...makeIndexOpsForDocument(
6349
6456
  normalizedPath,
6350
6457
  collectionName,
@@ -6507,6 +6614,22 @@ var Database = class {
6507
6614
  this.tinaSchema = await createSchema({ schema });
6508
6615
  return this.tinaSchema;
6509
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
+ };
6510
6633
  this.getIndexDefinitions = async (level) => {
6511
6634
  if (!this.collectionIndexDefinitions) {
6512
6635
  await new Promise(async (resolve2, reject) => {
@@ -6516,11 +6639,53 @@ var Database = class {
6516
6639
  const collections = schema.getCollections();
6517
6640
  for (const collection of collections) {
6518
6641
  const indexDefinitions = {
6519
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6642
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6520
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
+ }
6521
6659
  };
6522
- if (collection.fields) {
6523
- 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) {
6524
6689
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6525
6690
  continue;
6526
6691
  }
@@ -6668,29 +6833,36 @@ var Database = class {
6668
6833
  }
6669
6834
  startKey = startKey || key || "";
6670
6835
  endKey = key || "";
6671
- edges = [...edges, { cursor: key, path: filepath }];
6836
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6672
6837
  }
6673
6838
  return {
6674
- edges: await sequential(edges, async (edge) => {
6675
- try {
6676
- const node = await hydrator(edge.path);
6677
- return {
6678
- node,
6679
- cursor: btoa(edge.cursor)
6680
- };
6681
- } catch (error) {
6682
- console.log(error);
6683
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6684
- throw new TinaQueryError({
6685
- originalError: error,
6686
- file: edge.path,
6687
- collection: collection.name,
6688
- stack: error.stack
6689
- });
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;
6690
6863
  }
6691
- throw error;
6692
6864
  }
6693
- }),
6865
+ ),
6694
6866
  pageInfo: {
6695
6867
  hasPreviousPage,
6696
6868
  hasNextPage,
@@ -6814,13 +6986,14 @@ var Database = class {
6814
6986
  documentPaths,
6815
6987
  async (collection, documentPaths2) => {
6816
6988
  if (collection && !collection.isDetached) {
6817
- await _indexContent(
6818
- this,
6819
- this.contentLevel,
6820
- documentPaths2,
6989
+ await _indexContent({
6990
+ database: this,
6991
+ level: this.contentLevel,
6992
+ documentPaths: documentPaths2,
6821
6993
  enqueueOps,
6822
- collection
6823
- );
6994
+ collection,
6995
+ isPartialReindex: true
6996
+ });
6824
6997
  }
6825
6998
  }
6826
6999
  );
@@ -6836,6 +7009,7 @@ var Database = class {
6836
7009
  throw new Error(`No collection found for path: ${filepath}`);
6837
7010
  }
6838
7011
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
7012
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6839
7013
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6840
7014
  let level = this.contentLevel;
6841
7015
  if (collection?.isDetached) {
@@ -6854,6 +7028,14 @@ var Database = class {
6854
7028
  collection.path || ""
6855
7029
  );
6856
7030
  await this.contentLevel.batch([
7031
+ ...makeRefOpsForDocument(
7032
+ normalizedPath,
7033
+ collection.name,
7034
+ collectionReferences,
7035
+ item,
7036
+ "del",
7037
+ level
7038
+ ),
6857
7039
  ...makeIndexOpsForDocument(
6858
7040
  normalizedPath,
6859
7041
  collection.name,
@@ -6918,20 +7100,26 @@ var Database = class {
6918
7100
  );
6919
7101
  const doc = await level2.keys({ limit: 1 }).next();
6920
7102
  if (!doc) {
6921
- await _indexContent(
6922
- this,
6923
- level2,
6924
- contentPaths,
7103
+ await _indexContent({
7104
+ database: this,
7105
+ level: level2,
7106
+ documentPaths: contentPaths,
6925
7107
  enqueueOps,
6926
7108
  collection,
6927
- userFields.map((field) => [
7109
+ passwordFields: userFields.map((field) => [
6928
7110
  ...field.path,
6929
7111
  field.passwordFieldName
6930
7112
  ])
6931
- );
7113
+ });
6932
7114
  }
6933
7115
  } else {
6934
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7116
+ await _indexContent({
7117
+ database: this,
7118
+ level,
7119
+ documentPaths: contentPaths,
7120
+ enqueueOps,
7121
+ collection
7122
+ });
6935
7123
  }
6936
7124
  }
6937
7125
  );
@@ -7070,7 +7258,15 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
7070
7258
  )
7071
7259
  );
7072
7260
  var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${collection?.format || "md"}`);
7073
- var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7261
+ var _indexContent = async ({
7262
+ database,
7263
+ level,
7264
+ documentPaths,
7265
+ enqueueOps,
7266
+ collection,
7267
+ passwordFields,
7268
+ isPartialReindex
7269
+ }) => {
7074
7270
  let collectionIndexDefinitions;
7075
7271
  let collectionPath;
7076
7272
  if (collection) {
@@ -7081,6 +7277,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7081
7277
  }
7082
7278
  collectionPath = collection.path;
7083
7279
  }
7280
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7084
7281
  const tinaSchema = await database.getSchema();
7085
7282
  let templateInfo = null;
7086
7283
  if (collection) {
@@ -7102,12 +7299,61 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7102
7299
  await hashPasswordValues(aliasedData, passwordFields);
7103
7300
  }
7104
7301
  const normalizedPath = normalizePath(filepath);
7302
+ const rootSublevel = level.sublevel(
7303
+ CONTENT_ROOT_PREFIX,
7304
+ SUBLEVEL_OPTIONS
7305
+ );
7105
7306
  const folderKey = folderTreeBuilder.update(
7106
7307
  normalizedPath,
7107
7308
  collectionPath || ""
7108
7309
  );
7310
+ if (isPartialReindex) {
7311
+ const item = await rootSublevel.get(normalizedPath);
7312
+ if (item) {
7313
+ await database.contentLevel.batch([
7314
+ ...makeRefOpsForDocument(
7315
+ normalizedPath,
7316
+ collection?.name,
7317
+ collectionReferences,
7318
+ item,
7319
+ "del",
7320
+ level
7321
+ ),
7322
+ ...makeIndexOpsForDocument(
7323
+ normalizedPath,
7324
+ collection.name,
7325
+ collectionIndexDefinitions,
7326
+ item,
7327
+ "del",
7328
+ level
7329
+ ),
7330
+ // folder indices
7331
+ ...makeIndexOpsForDocument(
7332
+ normalizedPath,
7333
+ `${collection.name}_${folderKey}`,
7334
+ collectionIndexDefinitions,
7335
+ item,
7336
+ "del",
7337
+ level
7338
+ ),
7339
+ {
7340
+ type: "del",
7341
+ key: normalizedPath,
7342
+ sublevel: rootSublevel
7343
+ }
7344
+ ]);
7345
+ }
7346
+ }
7109
7347
  if (!isGitKeep(filepath, collection)) {
7110
7348
  await enqueueOps([
7349
+ ...makeRefOpsForDocument(
7350
+ normalizedPath,
7351
+ collection?.name,
7352
+ collectionReferences,
7353
+ aliasedData,
7354
+ "put",
7355
+ level
7356
+ ),
7111
7357
  ...makeIndexOpsForDocument(
7112
7358
  normalizedPath,
7113
7359
  collection?.name,
@@ -7171,6 +7417,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7171
7417
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7172
7418
  }
7173
7419
  }
7420
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7174
7421
  const tinaSchema = await database.getSchema();
7175
7422
  let templateInfo = null;
7176
7423
  if (collection) {
@@ -7194,6 +7441,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7194
7441
  item
7195
7442
  ) : item;
7196
7443
  await enqueueOps([
7444
+ ...makeRefOpsForDocument(
7445
+ itemKey,
7446
+ collection?.name,
7447
+ collectionReferences,
7448
+ aliasedData,
7449
+ "del",
7450
+ database.contentLevel
7451
+ ),
7197
7452
  ...makeIndexOpsForDocument(
7198
7453
  itemKey,
7199
7454
  collection.name,