@tinacms/graphql 0.0.0-d524599-20241117111320 → 0.0.0-d6f7570-20250523032937

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
@@ -17,14 +17,18 @@ var __copyProps = (to, from, except, desc) => {
17
17
  return to;
18
18
  };
19
19
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
24
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
25
  mod
22
26
  ));
23
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
28
 
25
29
  // src/index.ts
26
- var src_exports = {};
27
- __export(src_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
28
32
  AuditFileSystemBridge: () => AuditFileSystemBridge,
29
33
  Database: () => Database,
30
34
  FilesystemBridge: () => FilesystemBridge,
@@ -58,7 +62,7 @@ __export(src_exports, {
58
62
  transformDocument: () => transformDocument,
59
63
  transformDocumentIntoPayload: () => transformDocumentIntoPayload
60
64
  });
61
- module.exports = __toCommonJS(src_exports);
65
+ module.exports = __toCommonJS(index_exports);
62
66
 
63
67
  // src/build.ts
64
68
  var import_graphql2 = require("graphql");
@@ -130,6 +134,15 @@ var SysFieldDefinition = {
130
134
  selectionSet: {
131
135
  kind: "SelectionSet",
132
136
  selections: [
137
+ // {
138
+ // kind: 'Field' as const,
139
+ // name: {
140
+ // kind: 'Name' as const,
141
+ // value: 'title',
142
+ // },
143
+ // arguments: [],
144
+ // directives: [],
145
+ // },
133
146
  {
134
147
  kind: "Field",
135
148
  name: {
@@ -197,6 +210,10 @@ var SysFieldDefinition = {
197
210
  }
198
211
  };
199
212
  var astBuilder = {
213
+ /**
214
+ * `FormFieldBuilder` acts as a shortcut to building an entire `ObjectTypeDefinition`, we use this
215
+ * because all Tina field objects share a common set of fields ('name', 'label', 'component')
216
+ */
200
217
  FormFieldBuilder: ({
201
218
  name,
202
219
  additionalFields
@@ -420,6 +437,8 @@ var astBuilder = {
420
437
  kind: "Name",
421
438
  value: name
422
439
  },
440
+ // @ts-ignore FIXME; this is being handled properly but we're lying to
441
+ // ts and then fixing it in the `extractInlineTypes` function
423
442
  fields
424
443
  }),
425
444
  UnionTypeDefinition: ({
@@ -432,6 +451,8 @@ var astBuilder = {
432
451
  value: name
433
452
  },
434
453
  directives: [],
454
+ // @ts-ignore FIXME; this is being handled properly but we're lying to
455
+ // ts and then fixing it in the `extractInlineTypes` function
435
456
  types: types.map((name2) => ({
436
457
  kind: "NamedType",
437
458
  name: {
@@ -528,8 +549,11 @@ var astBuilder = {
528
549
  string: "String",
529
550
  boolean: "Boolean",
530
551
  number: "Float",
552
+ // FIXME - needs to be float or int
531
553
  datetime: "String",
554
+ // FIXME
532
555
  image: "String",
556
+ // FIXME
533
557
  text: "String"
534
558
  };
535
559
  return scalars[type];
@@ -1028,8 +1052,7 @@ var astBuilder = {
1028
1052
  }
1029
1053
  };
1030
1054
  var capitalize = (s) => {
1031
- if (typeof s !== "string")
1032
- return "";
1055
+ if (typeof s !== "string") return "";
1033
1056
  return s.charAt(0).toUpperCase() + s.slice(1);
1034
1057
  };
1035
1058
  var extractInlineTypes = (item) => {
@@ -1072,41 +1095,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1072
1095
  yield maybeNode;
1073
1096
  visited.add(maybeNode);
1074
1097
  }
1075
- function addNamespaceToSchema(maybeNode, namespace = []) {
1076
- if (typeof maybeNode === "string") {
1077
- return maybeNode;
1078
- }
1079
- if (typeof maybeNode === "boolean") {
1080
- return maybeNode;
1081
- }
1082
- const newNode = maybeNode;
1083
- const keys = Object.keys(maybeNode);
1084
- Object.values(maybeNode).map((m, index) => {
1085
- const key = keys[index];
1086
- if (Array.isArray(m)) {
1087
- newNode[key] = m.map((element) => {
1088
- if (!element) {
1089
- return;
1090
- }
1091
- if (!element.hasOwnProperty("name")) {
1092
- return element;
1093
- }
1094
- const value = element.name || element.value;
1095
- return addNamespaceToSchema(element, [...namespace, value]);
1096
- });
1097
- } else {
1098
- if (!m) {
1099
- return;
1100
- }
1101
- if (!m.hasOwnProperty("name")) {
1102
- newNode[key] = m;
1103
- } else {
1104
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1105
- }
1106
- }
1107
- });
1108
- return { ...newNode, namespace };
1109
- }
1110
1098
  var generateNamespacedFieldName = (names, suffix = "") => {
1111
1099
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1112
1100
  };
@@ -1447,13 +1435,12 @@ var checkPasswordHash = async ({
1447
1435
  return true;
1448
1436
  };
1449
1437
  var mapUserFields = (collectable, prefix = []) => {
1450
- var _a, _b, _c, _d, _e;
1451
1438
  const results = [];
1452
- const passwordFields = ((_a = collectable.fields) == null ? void 0 : _a.filter((field) => field.type === "password")) || [];
1439
+ const passwordFields = collectable.fields?.filter((field) => field.type === "password") || [];
1453
1440
  if (passwordFields.length > 1) {
1454
1441
  throw new Error("Only one password field is allowed");
1455
1442
  }
1456
- const idFields = ((_b = collectable.fields) == null ? void 0 : _b.filter((field) => field.uid)) || [];
1443
+ const idFields = collectable.fields?.filter((field) => field.uid) || [];
1457
1444
  if (idFields.length > 1) {
1458
1445
  throw new Error("Only one uid field is allowed");
1459
1446
  }
@@ -1461,11 +1448,11 @@ var mapUserFields = (collectable, prefix = []) => {
1461
1448
  results.push({
1462
1449
  path: prefix,
1463
1450
  collectable,
1464
- idFieldName: (_c = idFields[0]) == null ? void 0 : _c.name,
1465
- passwordFieldName: (_d = passwordFields[0]) == null ? void 0 : _d.name
1451
+ idFieldName: idFields[0]?.name,
1452
+ passwordFieldName: passwordFields[0]?.name
1466
1453
  });
1467
1454
  }
1468
- (_e = collectable.fields) == null ? void 0 : _e.forEach((field) => {
1455
+ collectable.fields?.forEach((field) => {
1469
1456
  if (field.type === "object" && field.fields) {
1470
1457
  results.push(...mapUserFields(field, [...prefix, field.name]));
1471
1458
  }
@@ -1485,6 +1472,19 @@ var Builder = class {
1485
1472
  this.addToLookupMap = (lookup) => {
1486
1473
  this.lookupMap[lookup.type] = lookup;
1487
1474
  };
1475
+ /**
1476
+ * ```graphql
1477
+ * # ex.
1478
+ * {
1479
+ * getCollection(collection: $collection) {
1480
+ * name
1481
+ * documents {...}
1482
+ * }
1483
+ * }
1484
+ * ```
1485
+ *
1486
+ * @param collections
1487
+ */
1488
1488
  this.buildCollectionDefinition = async (collections) => {
1489
1489
  const name = "collection";
1490
1490
  const typeName = "Collection";
@@ -1555,6 +1555,19 @@ var Builder = class {
1555
1555
  required: true
1556
1556
  });
1557
1557
  };
1558
+ /**
1559
+ * ```graphql
1560
+ * # ex.
1561
+ * {
1562
+ * getCollections {
1563
+ * name
1564
+ * documents {...}
1565
+ * }
1566
+ * }
1567
+ * ```
1568
+ *
1569
+ * @param collections
1570
+ */
1558
1571
  this.buildMultiCollectionDefinition = async (collections) => {
1559
1572
  const name = "collections";
1560
1573
  const typeName = "Collection";
@@ -1565,6 +1578,17 @@ var Builder = class {
1565
1578
  required: true
1566
1579
  });
1567
1580
  };
1581
+ /**
1582
+ * ```graphql
1583
+ * # ex.
1584
+ * {
1585
+ * node(id: $id) {
1586
+ * id
1587
+ * data {...}
1588
+ * }
1589
+ * }
1590
+ * ```
1591
+ */
1568
1592
  this.multiNodeDocument = async () => {
1569
1593
  const name = "node";
1570
1594
  const args = [
@@ -1585,6 +1609,19 @@ var Builder = class {
1585
1609
  required: true
1586
1610
  });
1587
1611
  };
1612
+ /**
1613
+ * ```graphql
1614
+ * # ex.
1615
+ * {
1616
+ * getDocument(collection: $collection, relativePath: $relativePath) {
1617
+ * id
1618
+ * data {...}
1619
+ * }
1620
+ * }
1621
+ * ```
1622
+ *
1623
+ * @param collections
1624
+ */
1588
1625
  this.multiCollectionDocument = async (collections) => {
1589
1626
  const name = "document";
1590
1627
  const args = [
@@ -1610,6 +1647,19 @@ var Builder = class {
1610
1647
  required: true
1611
1648
  });
1612
1649
  };
1650
+ /**
1651
+ * ```graphql
1652
+ * # ex.
1653
+ * {
1654
+ * addPendingDocument(collection: $collection, relativePath: $relativePath, params: $params) {
1655
+ * id
1656
+ * data {...}
1657
+ * }
1658
+ * }
1659
+ * ```
1660
+ *
1661
+ * @param collections
1662
+ */
1613
1663
  this.addMultiCollectionDocumentMutation = async () => {
1614
1664
  return astBuilder.FieldDefinition({
1615
1665
  name: "addPendingDocument",
@@ -1634,6 +1684,19 @@ var Builder = class {
1634
1684
  type: astBuilder.TYPES.MultiCollectionDocument
1635
1685
  });
1636
1686
  };
1687
+ /**
1688
+ * ```graphql
1689
+ * # ex.
1690
+ * {
1691
+ * createDocument(relativePath: $relativePath, params: $params) {
1692
+ * id
1693
+ * data {...}
1694
+ * }
1695
+ * }
1696
+ * ```
1697
+ *
1698
+ * @param collections
1699
+ */
1637
1700
  this.buildCreateCollectionDocumentMutation = async (collections) => {
1638
1701
  return astBuilder.FieldDefinition({
1639
1702
  name: "createDocument",
@@ -1661,6 +1724,19 @@ var Builder = class {
1661
1724
  type: astBuilder.TYPES.MultiCollectionDocument
1662
1725
  });
1663
1726
  };
1727
+ /**
1728
+ * ```graphql
1729
+ * # ex.
1730
+ * {
1731
+ * updateDocument(relativePath: $relativePath, params: $params) {
1732
+ * id
1733
+ * data {...}
1734
+ * }
1735
+ * }
1736
+ * ```
1737
+ *
1738
+ * @param collections
1739
+ */
1664
1740
  this.buildUpdateCollectionDocumentMutation = async (collections) => {
1665
1741
  return astBuilder.FieldDefinition({
1666
1742
  name: "updateDocument",
@@ -1688,6 +1764,19 @@ var Builder = class {
1688
1764
  type: astBuilder.TYPES.MultiCollectionDocument
1689
1765
  });
1690
1766
  };
1767
+ /**
1768
+ * ```graphql
1769
+ * # ex.
1770
+ * {
1771
+ * deleteDocument(relativePath: $relativePath, params: $params) {
1772
+ * id
1773
+ * data {...}
1774
+ * }
1775
+ * }
1776
+ * ```
1777
+ *
1778
+ * @param collections
1779
+ */
1691
1780
  this.buildDeleteCollectionDocumentMutation = async (collections) => {
1692
1781
  return astBuilder.FieldDefinition({
1693
1782
  name: "deleteDocument",
@@ -1707,6 +1796,19 @@ var Builder = class {
1707
1796
  type: astBuilder.TYPES.MultiCollectionDocument
1708
1797
  });
1709
1798
  };
1799
+ /**
1800
+ * ```graphql
1801
+ * # ex.
1802
+ * {
1803
+ * createFolder(folderName: $folderName, params: $params) {
1804
+ * id
1805
+ * data {...}
1806
+ * }
1807
+ * }
1808
+ * ```
1809
+ *
1810
+ * @param collections
1811
+ */
1710
1812
  this.buildCreateCollectionFolderMutation = async () => {
1711
1813
  return astBuilder.FieldDefinition({
1712
1814
  name: "createFolder",
@@ -1726,6 +1828,19 @@ var Builder = class {
1726
1828
  type: astBuilder.TYPES.MultiCollectionDocument
1727
1829
  });
1728
1830
  };
1831
+ /**
1832
+ * ```graphql
1833
+ * # ex.
1834
+ * {
1835
+ * getPostDocument(relativePath: $relativePath) {
1836
+ * id
1837
+ * data {...}
1838
+ * }
1839
+ * }
1840
+ * ```
1841
+ *
1842
+ * @param collection
1843
+ */
1729
1844
  this.collectionDocument = async (collection) => {
1730
1845
  const name = NAMER.queryName([collection.name]);
1731
1846
  const type = await this._buildCollectionDocumentType(collection);
@@ -1786,6 +1901,20 @@ var Builder = class {
1786
1901
  const args = [];
1787
1902
  return astBuilder.FieldDefinition({ type, name, args, required: false });
1788
1903
  };
1904
+ /**
1905
+ * Turns a collection into a fragment that gets updated on build. This fragment does not resolve references
1906
+ * ```graphql
1907
+ * # ex.
1908
+ * fragment AuthorsParts on Authors {
1909
+ * name
1910
+ * avatar
1911
+ * ...
1912
+ * }
1913
+ * ```
1914
+ *
1915
+ * @public
1916
+ * @param collection a TinaCloud collection
1917
+ */
1789
1918
  this.collectionFragment = async (collection) => {
1790
1919
  const name = NAMER.dataTypeName(collection.namespace);
1791
1920
  const fragmentName = NAMER.fragmentName(collection.namespace);
@@ -1799,14 +1928,27 @@ var Builder = class {
1799
1928
  selections: filterSelections(selections)
1800
1929
  });
1801
1930
  };
1931
+ /**
1932
+ * Given a collection this function returns its selections set. For example for Post this would return
1933
+ *
1934
+ * "
1935
+ * body
1936
+ * title
1937
+ * ... on Author {
1938
+ * name
1939
+ * heroImg
1940
+ * }
1941
+ *
1942
+ * But in the AST format
1943
+ *
1944
+ * */
1802
1945
  this._getCollectionFragmentSelections = async (collection, depth) => {
1803
- var _a;
1804
1946
  const selections = [];
1805
1947
  selections.push({
1806
1948
  name: { kind: "Name", value: "__typename" },
1807
1949
  kind: "Field"
1808
1950
  });
1809
- if (((_a = collection.fields) == null ? void 0 : _a.length) > 0) {
1951
+ if (collection.fields?.length > 0) {
1810
1952
  await sequential(collection.fields, async (x) => {
1811
1953
  const field = await this._buildFieldNodeForFragments(x, depth);
1812
1954
  selections.push(field);
@@ -1821,7 +1963,6 @@ var Builder = class {
1821
1963
  return selections;
1822
1964
  };
1823
1965
  this._buildFieldNodeForFragments = async (field, depth) => {
1824
- var _a, _b;
1825
1966
  switch (field.type) {
1826
1967
  case "string":
1827
1968
  case "image":
@@ -1854,7 +1995,7 @@ var Builder = class {
1854
1995
  selections: filterSelections([passwordValue, passwordChangeRequired])
1855
1996
  });
1856
1997
  case "object":
1857
- if (((_a = field.fields) == null ? void 0 : _a.length) > 0) {
1998
+ if (field.fields?.length > 0) {
1858
1999
  const selections2 = [];
1859
2000
  await sequential(field.fields, async (item) => {
1860
2001
  const field2 = await this._buildFieldNodeForFragments(item, depth);
@@ -1867,7 +2008,7 @@ var Builder = class {
1867
2008
  ...filterSelections(selections2)
1868
2009
  ]
1869
2010
  });
1870
- } else if (((_b = field.templates) == null ? void 0 : _b.length) > 0) {
2011
+ } else if (field.templates?.length > 0) {
1871
2012
  const selections2 = [];
1872
2013
  await sequential(field.templates, async (tem) => {
1873
2014
  if (typeof tem === "object") {
@@ -1882,9 +2023,9 @@ var Builder = class {
1882
2023
  ]
1883
2024
  });
1884
2025
  }
2026
+ // TODO: Should we throw here?
1885
2027
  case "reference":
1886
- if (depth >= this.maxDepth)
1887
- return false;
2028
+ if (depth >= this.maxDepth) return false;
1888
2029
  if (!("collections" in field)) {
1889
2030
  return false;
1890
2031
  }
@@ -1916,6 +2057,7 @@ var Builder = class {
1916
2057
  name: field.name,
1917
2058
  selections: [
1918
2059
  ...selections,
2060
+ // This is ... on Document { id }
1919
2061
  {
1920
2062
  kind: "InlineFragment",
1921
2063
  typeCondition: {
@@ -1946,6 +2088,19 @@ var Builder = class {
1946
2088
  });
1947
2089
  }
1948
2090
  };
2091
+ /**
2092
+ * ```graphql
2093
+ * # ex.
2094
+ * mutation {
2095
+ * updatePostDocument(relativePath: $relativePath, params: $params) {
2096
+ * id
2097
+ * data {...}
2098
+ * }
2099
+ * }
2100
+ * ```
2101
+ *
2102
+ * @param collection
2103
+ */
1949
2104
  this.updateCollectionDocumentMutation = async (collection) => {
1950
2105
  return astBuilder.FieldDefinition({
1951
2106
  type: await this._buildCollectionDocumentType(collection),
@@ -1965,6 +2120,19 @@ var Builder = class {
1965
2120
  ]
1966
2121
  });
1967
2122
  };
2123
+ /**
2124
+ * ```graphql
2125
+ * # ex.
2126
+ * mutation {
2127
+ * createPostDocument(relativePath: $relativePath, params: $params) {
2128
+ * id
2129
+ * data {...}
2130
+ * }
2131
+ * }
2132
+ * ```
2133
+ *
2134
+ * @param collection
2135
+ */
1968
2136
  this.createCollectionDocumentMutation = async (collection) => {
1969
2137
  return astBuilder.FieldDefinition({
1970
2138
  type: await this._buildCollectionDocumentType(collection),
@@ -1984,6 +2152,22 @@ var Builder = class {
1984
2152
  ]
1985
2153
  });
1986
2154
  };
2155
+ /**
2156
+ * ```graphql
2157
+ * # ex.
2158
+ * {
2159
+ * getPostList(first: 10) {
2160
+ * edges {
2161
+ * node {
2162
+ * id
2163
+ * }
2164
+ * }
2165
+ * }
2166
+ * }
2167
+ * ```
2168
+ *
2169
+ * @param collection
2170
+ */
1987
2171
  this.collectionDocumentList = async (collection) => {
1988
2172
  const connectionName = NAMER.referenceConnectionType(collection.namespace);
1989
2173
  this.addToLookupMap({
@@ -1999,6 +2183,10 @@ var Builder = class {
1999
2183
  collection
2000
2184
  });
2001
2185
  };
2186
+ /**
2187
+ * GraphQL type definitions which remain unchanged regardless
2188
+ * of the supplied Tina schema. Ex. "node" interface
2189
+ */
2002
2190
  this.buildStaticDefinitions = () => staticDefinitions;
2003
2191
  this._buildCollectionDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
2004
2192
  const documentTypeName = NAMER.documentTypeName(collection.namespace);
@@ -2482,7 +2670,7 @@ var Builder = class {
2482
2670
  this.addToLookupMap({
2483
2671
  type: name,
2484
2672
  resolveType: "unionData",
2485
- collection: collection == null ? void 0 : collection.name,
2673
+ collection: collection?.name,
2486
2674
  typeMap
2487
2675
  });
2488
2676
  return astBuilder.UnionTypeDefinition({ name, types });
@@ -2503,6 +2691,7 @@ var Builder = class {
2503
2691
  name: NAMER.dataFilterTypeName(namespace),
2504
2692
  fields: await sequential(collections, async (collection2) => {
2505
2693
  return astBuilder.InputValueDefinition({
2694
+ // @ts-ignore
2506
2695
  name: collection2.name,
2507
2696
  type: NAMER.dataFilterTypeName(collection2.namespace)
2508
2697
  });
@@ -2691,8 +2880,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2691
2880
  ]
2692
2881
  });
2693
2882
  };
2694
- var _a, _b, _c, _d;
2695
- this.maxDepth = (_d = (_c = (_b = (_a = config == null ? void 0 : config.tinaSchema.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.client) == null ? void 0 : _c.referenceDepth) != null ? _d : 2;
2883
+ this.maxDepth = // @ts-ignore
2884
+ config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2696
2885
  this.tinaSchema = config.tinaSchema;
2697
2886
  this.lookupMap = {};
2698
2887
  }
@@ -2703,8 +2892,7 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2703
2892
  selections.push(field);
2704
2893
  });
2705
2894
  const filteredSelections = filterSelections(selections);
2706
- if (!filteredSelections.length)
2707
- return false;
2895
+ if (!filteredSelections.length) return false;
2708
2896
  return astBuilder.InlineFragmentDefinition({
2709
2897
  selections: filteredSelections,
2710
2898
  name: NAMER.dataTypeName(template.namespace)
@@ -2738,12 +2926,13 @@ var filterSelections = (arr) => {
2738
2926
  };
2739
2927
 
2740
2928
  // src/schema/createSchema.ts
2741
- var import_schema_tools2 = require("@tinacms/schema-tools");
2929
+ var import_schema_tools3 = require("@tinacms/schema-tools");
2742
2930
 
2743
2931
  // src/schema/validate.ts
2932
+ var import_schema_tools = require("@tinacms/schema-tools");
2744
2933
  var import_lodash2 = __toESM(require("lodash.clonedeep"));
2745
2934
  var yup2 = __toESM(require("yup"));
2746
- var import_schema_tools = require("@tinacms/schema-tools");
2935
+ var import_schema_tools2 = require("@tinacms/schema-tools");
2747
2936
  var FIELD_TYPES = [
2748
2937
  "string",
2749
2938
  "number",
@@ -2756,7 +2945,7 @@ var FIELD_TYPES = [
2756
2945
  "password"
2757
2946
  ];
2758
2947
  var validateSchema = async (schema) => {
2759
- const schema2 = addNamespaceToSchema(
2948
+ const schema2 = (0, import_schema_tools.addNamespaceToSchema)(
2760
2949
  (0, import_lodash2.default)(schema)
2761
2950
  );
2762
2951
  const collections = await sequential(
@@ -2765,7 +2954,7 @@ var validateSchema = async (schema) => {
2765
2954
  );
2766
2955
  validationCollectionsPathAndMatch(collections);
2767
2956
  if (schema2.config) {
2768
- const config = (0, import_schema_tools.validateTinaCloudSchemaConfig)(schema2.config);
2957
+ const config = (0, import_schema_tools2.validateTinaCloudSchemaConfig)(schema2.config);
2769
2958
  return {
2770
2959
  collections,
2771
2960
  config
@@ -2781,20 +2970,18 @@ var validationCollectionsPathAndMatch = (collections) => {
2781
2970
  return;
2782
2971
  }
2783
2972
  const noMatchCollections = collections.filter((x) => {
2784
- return typeof (x == null ? void 0 : x.match) === "undefined";
2973
+ return typeof x?.match === "undefined";
2785
2974
  }).map((x) => `${x.path}${x.format || "md"}`);
2786
2975
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2787
2976
  throw new Error(
2977
+ // TODO: add a link to the docs
2788
2978
  "Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
2789
2979
  );
2790
2980
  }
2791
2981
  const hasMatchAndPath = collections.filter((x) => {
2792
2982
  return typeof x.path !== "undefined" && typeof x.match !== "undefined";
2793
2983
  }).map(
2794
- (x) => {
2795
- var _a, _b;
2796
- return `${x.path}|${((_a = x == null ? void 0 : x.match) == null ? void 0 : _a.exclude) || ""}|${((_b = x == null ? void 0 : x.match) == null ? void 0 : _b.include) || ""}|${x.format || "md"}`;
2797
- }
2984
+ (x) => `${x.path}|${x?.match?.exclude || ""}|${x?.match?.include || ""}|${x.format || "md"}`
2798
2985
  );
2799
2986
  if (hasMatchAndPath.length !== new Set(hasMatchAndPath).size) {
2800
2987
  throw new Error(
@@ -2818,7 +3005,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2818
3005
  );
2819
3006
  }
2820
3007
  const matches = collectionsArr.map(
2821
- (x) => typeof (x == null ? void 0 : x.match) === "object" ? JSON.stringify(x.match) : ""
3008
+ (x) => typeof x?.match === "object" ? JSON.stringify(x.match) : ""
2822
3009
  );
2823
3010
  if (matches.length === new Set(matches).size) {
2824
3011
  return;
@@ -2896,7 +3083,7 @@ var validateField = async (field) => {
2896
3083
  // package.json
2897
3084
  var package_default = {
2898
3085
  name: "@tinacms/graphql",
2899
- version: "1.5.7",
3086
+ version: "1.5.17",
2900
3087
  main: "dist/index.js",
2901
3088
  module: "dist/index.mjs",
2902
3089
  typings: "dist/index.d.ts",
@@ -2922,9 +3109,8 @@ var package_default = {
2922
3109
  types: "pnpm tsc",
2923
3110
  build: "tinacms-scripts build",
2924
3111
  docs: "pnpm typedoc",
2925
- serve: "pnpm nodemon dist/server.js",
2926
- test: "jest",
2927
- "test-watch": "jest --watch"
3112
+ test: "vitest run",
3113
+ "test-watch": "vitest"
2928
3114
  },
2929
3115
  dependencies: {
2930
3116
  "@iarna/toml": "^2.2.5",
@@ -2932,12 +3118,12 @@ var package_default = {
2932
3118
  "@tinacms/schema-tools": "workspace:*",
2933
3119
  "abstract-level": "^1.0.4",
2934
3120
  "date-fns": "^2.30.0",
2935
- "fast-glob": "^3.3.2",
2936
- "fs-extra": "^11.2.0",
3121
+ "fast-glob": "^3.3.3",
3122
+ "fs-extra": "^11.3.0",
2937
3123
  "glob-parent": "^6.0.2",
2938
3124
  graphql: "15.8.0",
2939
3125
  "gray-matter": "^4.0.3",
2940
- "isomorphic-git": "^1.27.1",
3126
+ "isomorphic-git": "^1.29.0",
2941
3127
  "js-sha1": "^0.6.0",
2942
3128
  "js-yaml": "^3.14.1",
2943
3129
  "jsonpath-plus": "10.1.0",
@@ -2947,7 +3133,7 @@ var package_default = {
2947
3133
  "many-level": "^2.0.0",
2948
3134
  micromatch: "4.0.8",
2949
3135
  "normalize-path": "^3.0.0",
2950
- "readable-stream": "^4.5.2",
3136
+ "readable-stream": "^4.7.0",
2951
3137
  scmp: "^2.1.0",
2952
3138
  yup: "^0.32.11"
2953
3139
  },
@@ -2965,24 +3151,22 @@ var package_default = {
2965
3151
  "@types/estree": "^0.0.50",
2966
3152
  "@types/express": "^4.17.21",
2967
3153
  "@types/fs-extra": "^9.0.13",
2968
- "@types/jest": "^26.0.24",
2969
3154
  "@types/js-yaml": "^3.12.10",
2970
3155
  "@types/lodash.camelcase": "^4.3.9",
2971
3156
  "@types/lodash.upperfirst": "^4.3.9",
2972
3157
  "@types/lru-cache": "^5.1.1",
2973
3158
  "@types/mdast": "^3.0.15",
2974
3159
  "@types/micromatch": "^4.0.9",
2975
- "@types/node": "^22.9.0",
3160
+ "@types/node": "^22.13.1",
2976
3161
  "@types/normalize-path": "^3.0.2",
2977
3162
  "@types/ws": "^7.4.7",
2978
3163
  "@types/yup": "^0.29.14",
2979
- jest: "^29.7.0",
2980
- "jest-diff": "^29.7.0",
2981
3164
  "jest-file-snapshot": "^0.5.0",
2982
- "jest-matcher-utils": "^29.7.0",
2983
3165
  "memory-level": "^1.0.0",
2984
- nodemon: "3.1.4",
2985
- typescript: "^5.6.3"
3166
+ typescript: "^5.7.3",
3167
+ vite: "^4.5.9",
3168
+ vitest: "^0.32.4",
3169
+ zod: "^3.24.2"
2986
3170
  }
2987
3171
  };
2988
3172
 
@@ -2997,7 +3181,7 @@ var createSchema = async ({
2997
3181
  if (flags && flags.length > 0) {
2998
3182
  meta["flags"] = flags;
2999
3183
  }
3000
- return new import_schema_tools2.TinaSchema({
3184
+ return new import_schema_tools3.TinaSchema({
3001
3185
  version: {
3002
3186
  fullVersion: package_default.version,
3003
3187
  major,
@@ -3053,6 +3237,7 @@ var _buildFragments = async (builder, tinaSchema) => {
3053
3237
  const fragDoc = {
3054
3238
  kind: "Document",
3055
3239
  definitions: (0, import_lodash3.default)(
3240
+ // @ts-ignore
3056
3241
  extractInlineTypes(fragmentDefinitionsFields),
3057
3242
  (node) => node.name.value
3058
3243
  )
@@ -3063,7 +3248,6 @@ var _buildQueries = async (builder, tinaSchema) => {
3063
3248
  const operationsDefinitions = [];
3064
3249
  const collections = tinaSchema.getCollections();
3065
3250
  await sequential(collections, async (collection) => {
3066
- var _a, _b, _c;
3067
3251
  const queryName = NAMER.queryName(collection.namespace);
3068
3252
  const queryListName = NAMER.generateQueryListName(collection.namespace);
3069
3253
  const queryFilterTypeName = NAMER.dataFilterTypeName(collection.namespace);
@@ -3076,8 +3260,9 @@ var _buildQueries = async (builder, tinaSchema) => {
3076
3260
  fragName,
3077
3261
  queryName: queryListName,
3078
3262
  filterType: queryFilterTypeName,
3263
+ // look for flag to see if the data layer is enabled
3079
3264
  dataLayer: Boolean(
3080
- (_c = (_b = (_a = tinaSchema.config) == null ? void 0 : _a.meta) == null ? void 0 : _b.flags) == null ? void 0 : _c.find((x) => x === "experimentalData")
3265
+ tinaSchema.config?.meta?.flags?.find((x) => x === "experimentalData")
3081
3266
  )
3082
3267
  })
3083
3268
  );
@@ -3085,6 +3270,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3085
3270
  const queryDoc = {
3086
3271
  kind: "Document",
3087
3272
  definitions: (0, import_lodash3.default)(
3273
+ // @ts-ignore
3088
3274
  extractInlineTypes(operationsDefinitions),
3089
3275
  (node) => node.name.value
3090
3276
  )
@@ -3136,7 +3322,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3136
3322
  await builder.buildCreateCollectionFolderMutation()
3137
3323
  );
3138
3324
  await sequential(collections, async (collection) => {
3139
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3325
+ queryTypeDefinitionFields.push(
3326
+ await builder.collectionDocument(collection)
3327
+ );
3140
3328
  if (collection.isAuthCollection) {
3141
3329
  queryTypeDefinitionFields.push(
3142
3330
  await builder.authenticationCollectionDocument(collection)
@@ -3173,6 +3361,7 @@ var _buildSchema = async (builder, tinaSchema) => {
3173
3361
  return {
3174
3362
  kind: "Document",
3175
3363
  definitions: (0, import_lodash3.default)(
3364
+ // @ts-ignore
3176
3365
  extractInlineTypes(definitions),
3177
3366
  (node) => node.name.value
3178
3367
  )
@@ -3377,8 +3566,7 @@ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, s
3377
3566
  }
3378
3567
  if (Array.isArray(value)) {
3379
3568
  return value.map((v) => {
3380
- if (!v || typeof v !== "string")
3381
- return v;
3569
+ if (!v || typeof v !== "string") return v;
3382
3570
  const cleanMediaRoot = cleanUpSlashes(
3383
3571
  schema.config.media.tina.mediaRoot
3384
3572
  );
@@ -3406,8 +3594,7 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
3406
3594
  }
3407
3595
  if (Array.isArray(value)) {
3408
3596
  return value.map((v) => {
3409
- if (!v || typeof v !== "string")
3410
- return v;
3597
+ if (!v || typeof v !== "string") return v;
3411
3598
  const strippedValue = v.replace(cleanMediaRoot, "");
3412
3599
  return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3413
3600
  });
@@ -3425,10 +3612,8 @@ var cleanUpSlashes = (path7) => {
3425
3612
  return "";
3426
3613
  };
3427
3614
  var hasTinaMediaConfig = (schema) => {
3428
- var _a, _b, _c, _d, _e, _f, _g, _h;
3429
- if (!((_b = (_a = schema.config) == null ? void 0 : _a.media) == null ? void 0 : _b.tina))
3430
- return false;
3431
- if (typeof ((_e = (_d = (_c = schema.config) == null ? void 0 : _c.media) == null ? void 0 : _d.tina) == null ? void 0 : _e.publicFolder) !== "string" && typeof ((_h = (_g = (_f = schema.config) == null ? void 0 : _f.media) == null ? void 0 : _g.tina) == null ? void 0 : _h.mediaRoot) !== "string")
3615
+ if (!schema.config?.media?.tina) return false;
3616
+ if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
3432
3617
  return false;
3433
3618
  return true;
3434
3619
  };
@@ -3454,7 +3639,9 @@ var LevelProxyHandler = {
3454
3639
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3455
3640
  }
3456
3641
  if (typeof target[property] !== "function") {
3457
- throw new Error(`The property, ${property.toString()}, is not a function`);
3642
+ throw new Error(
3643
+ `The property, ${property.toString()}, is not a function`
3644
+ );
3458
3645
  }
3459
3646
  if (property === "get") {
3460
3647
  return async (...args) => {
@@ -3471,6 +3658,7 @@ var LevelProxyHandler = {
3471
3658
  } else if (property === "sublevel") {
3472
3659
  return (...args) => {
3473
3660
  return new Proxy(
3661
+ // eslint-disable-next-line prefer-spread
3474
3662
  target[property].apply(target, args),
3475
3663
  LevelProxyHandler
3476
3664
  );
@@ -3493,7 +3681,7 @@ var import_path2 = __toESM(require("path"));
3493
3681
  var import_toml = __toESM(require("@iarna/toml"));
3494
3682
  var import_js_yaml = __toESM(require("js-yaml"));
3495
3683
  var import_gray_matter = __toESM(require("gray-matter"));
3496
- var import_schema_tools3 = require("@tinacms/schema-tools");
3684
+ var import_schema_tools4 = require("@tinacms/schema-tools");
3497
3685
  var import_micromatch = __toESM(require("micromatch"));
3498
3686
  var import_path = __toESM(require("path"));
3499
3687
 
@@ -3532,22 +3720,20 @@ var replaceNameOverrides = (template, obj) => {
3532
3720
  }
3533
3721
  };
3534
3722
  function isBlockField(field) {
3535
- var _a;
3536
- return field && field.type === "object" && ((_a = field.templates) == null ? void 0 : _a.length) > 0;
3723
+ return field && field.type === "object" && field.templates?.length > 0;
3537
3724
  }
3538
3725
  var _replaceNameOverrides = (fields, obj) => {
3539
3726
  const output = {};
3540
3727
  Object.keys(obj).forEach((key) => {
3541
3728
  const field = fields.find(
3542
- (fieldWithMatchingAlias) => ((fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.nameOverride) || (fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.name)) === key
3729
+ (fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
3543
3730
  );
3544
- output[(field == null ? void 0 : field.name) || key] = (field == null ? void 0 : field.type) == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
3731
+ output[field?.name || key] = field?.type == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
3545
3732
  });
3546
3733
  return output;
3547
3734
  };
3548
3735
  var getTemplateForData = (field, data) => {
3549
- var _a;
3550
- if ((_a = field.templates) == null ? void 0 : _a.length) {
3736
+ if (field.templates?.length) {
3551
3737
  const templateKey = "_template";
3552
3738
  if (data[templateKey]) {
3553
3739
  const result = field.templates.find(
@@ -3605,8 +3791,8 @@ var _applyNameOverrides = (fields, obj) => {
3605
3791
  const output = {};
3606
3792
  Object.keys(obj).forEach((key) => {
3607
3793
  const field = fields.find((field2) => field2.name === key);
3608
- const outputKey = (field == null ? void 0 : field.nameOverride) || key;
3609
- output[outputKey] = (field == null ? void 0 : field.type) === "object" ? applyNameOverrides(field, obj[key]) : obj[key];
3794
+ const outputKey = field?.nameOverride || key;
3795
+ output[outputKey] = field?.type === "object" ? applyNameOverrides(field, obj[key]) : obj[key];
3610
3796
  });
3611
3797
  return output;
3612
3798
  };
@@ -3619,7 +3805,6 @@ var matterEngines = {
3619
3805
  }
3620
3806
  };
3621
3807
  var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3622
- var _a, _b;
3623
3808
  const {
3624
3809
  _relativePath,
3625
3810
  _keepTemplateKey,
@@ -3643,9 +3828,9 @@ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3643
3828
  ${$_body}`,
3644
3829
  strippedContent,
3645
3830
  {
3646
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3831
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3647
3832
  engines: matterEngines,
3648
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
3833
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
3649
3834
  }
3650
3835
  );
3651
3836
  return ok;
@@ -3661,15 +3846,14 @@ ${$_body}`,
3661
3846
  }
3662
3847
  };
3663
3848
  var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3664
- var _a, _b;
3665
3849
  try {
3666
3850
  switch (format) {
3667
3851
  case ".markdown":
3668
3852
  case ".mdx":
3669
3853
  case ".md":
3670
3854
  const contentJSON = (0, import_gray_matter.default)(content || "", {
3671
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3672
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---",
3855
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3856
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
3673
3857
  engines: matterEngines
3674
3858
  });
3675
3859
  const markdownData = {
@@ -3706,7 +3890,7 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3706
3890
  const filesSeen = /* @__PURE__ */ new Map();
3707
3891
  const duplicateFiles = /* @__PURE__ */ new Set();
3708
3892
  await sequential(tinaSchema.getCollections(), async (collection) => {
3709
- const normalPath = (0, import_schema_tools3.normalizePath)(collection.path);
3893
+ const normalPath = (0, import_schema_tools4.normalizePath)(collection.path);
3710
3894
  const format = collection.format || "md";
3711
3895
  const documentPaths = await bridge.glob(normalPath, format);
3712
3896
  const matches = tinaSchema.getMatches({ collection });
@@ -3768,7 +3952,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3768
3952
  ),
3769
3953
  template: void 0
3770
3954
  } : tinaSchema.getCollectionAndTemplateByFullPath(filepath, templateName);
3771
- const field = template == null ? void 0 : template.fields.find((field2) => {
3955
+ const field = template?.fields.find((field2) => {
3772
3956
  if (field2.type === "string" || field2.type === "rich-text") {
3773
3957
  if (field2.isBody) {
3774
3958
  return true;
@@ -3788,7 +3972,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3788
3972
  ...data,
3789
3973
  _collection: collection.name,
3790
3974
  _keepTemplateKey: !!collection.templates,
3791
- _template: (template == null ? void 0 : template.namespace) ? lastItem(template == null ? void 0 : template.namespace) : void 0,
3975
+ _template: template?.namespace ? lastItem(template?.namespace) : void 0,
3792
3976
  _relativePath: filepath.replace(collection.path, "").replace(/^\/|\/$/g, ""),
3793
3977
  _id: filepath
3794
3978
  };
@@ -3797,10 +3981,10 @@ function hasOwnProperty(obj, prop) {
3797
3981
  return obj.hasOwnProperty(prop);
3798
3982
  }
3799
3983
  var getTemplateForFile = (templateInfo, data) => {
3800
- if ((templateInfo == null ? void 0 : templateInfo.type) === "object") {
3984
+ if (templateInfo?.type === "object") {
3801
3985
  return templateInfo.template;
3802
3986
  }
3803
- if ((templateInfo == null ? void 0 : templateInfo.type) === "union") {
3987
+ if (templateInfo?.type === "union") {
3804
3988
  if (hasOwnProperty(data, "_template")) {
3805
3989
  const template = templateInfo.templates.find(
3806
3990
  (t) => lastItem(t.namespace) === data._template
@@ -3818,14 +4002,14 @@ var getTemplateForFile = (templateInfo, data) => {
3818
4002
  throw new Error(`Unable to determine template`);
3819
4003
  };
3820
4004
  var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo) => {
3821
- const dataString = await bridge.get((0, import_schema_tools3.normalizePath)(filepath));
4005
+ const dataString = await bridge.get((0, import_schema_tools4.normalizePath)(filepath));
3822
4006
  const data = parseFile(
3823
4007
  dataString,
3824
4008
  import_path.default.extname(filepath),
3825
4009
  (yup3) => yup3.object({}),
3826
4010
  {
3827
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
3828
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
4011
+ frontmatterDelimiters: collection?.frontmatterDelimiters,
4012
+ frontmatterFormat: collection?.frontmatterFormat
3829
4013
  }
3830
4014
  );
3831
4015
  const template = getTemplateForFile(templateInfo, data);
@@ -3840,6 +4024,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3840
4024
 
3841
4025
  // src/database/datalayer.ts
3842
4026
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
4027
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
4028
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
4029
+ var REFS_PATH_FIELD = "__tina_ref_path__";
3843
4030
  var DEFAULT_NUMERIC_LPAD = 4;
3844
4031
  var applyPadding = (input, pad) => {
3845
4032
  if (pad) {
@@ -4297,7 +4484,7 @@ var FolderTreeBuilder = class {
4297
4484
  return this._tree;
4298
4485
  }
4299
4486
  update(documentPath, collectionPath) {
4300
- let folderPath = import_path2.default.dirname((0, import_schema_tools3.normalizePath)(documentPath));
4487
+ let folderPath = import_path2.default.dirname((0, import_schema_tools4.normalizePath)(documentPath));
4301
4488
  if (folderPath === ".") {
4302
4489
  folderPath = "";
4303
4490
  }
@@ -4310,7 +4497,7 @@ var FolderTreeBuilder = class {
4310
4497
  if (!this._tree[current2]) {
4311
4498
  this._tree[current2] = /* @__PURE__ */ new Set();
4312
4499
  }
4313
- this._tree[current2].add((0, import_schema_tools3.normalizePath)(import_path2.default.join(current2, part)));
4500
+ this._tree[current2].add((0, import_schema_tools4.normalizePath)(import_path2.default.join(current2, part)));
4314
4501
  parent.push(part);
4315
4502
  });
4316
4503
  const current = parent.join("/");
@@ -4349,6 +4536,7 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4349
4536
  result.push({
4350
4537
  type: opType,
4351
4538
  key: `${collection.path}/${subFolderKey}.${collection.format}`,
4539
+ // replace the root with the collection path
4352
4540
  sublevel: indexSublevel,
4353
4541
  value: {}
4354
4542
  });
@@ -4412,6 +4600,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4412
4600
  }
4413
4601
  return result;
4414
4602
  };
4603
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4604
+ const result = [];
4605
+ if (collection) {
4606
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4607
+ if (!referencePaths.length) {
4608
+ continue;
4609
+ }
4610
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4611
+ const refSublevel = collectionSublevel.sublevel(
4612
+ REFS_COLLECTIONS_SORT_KEY,
4613
+ SUBLEVEL_OPTIONS
4614
+ );
4615
+ const references2 = {};
4616
+ for (const path7 of referencePaths) {
4617
+ const ref = (0, import_jsonpath_plus.JSONPath)({ path: path7, json: data });
4618
+ if (!ref) {
4619
+ continue;
4620
+ }
4621
+ if (Array.isArray(ref)) {
4622
+ for (const r of ref) {
4623
+ if (!r) {
4624
+ continue;
4625
+ }
4626
+ if (references2[r]) {
4627
+ references2[r].push(path7);
4628
+ } else {
4629
+ references2[r] = [path7];
4630
+ }
4631
+ }
4632
+ } else {
4633
+ if (references2[ref]) {
4634
+ references2[ref].push(path7);
4635
+ } else {
4636
+ references2[ref] = [path7];
4637
+ }
4638
+ }
4639
+ }
4640
+ for (const ref of Object.keys(references2)) {
4641
+ for (const path7 of references2[ref]) {
4642
+ result.push({
4643
+ type: opType,
4644
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4645
+ sublevel: refSublevel,
4646
+ value: opType === "put" ? {} : void 0
4647
+ });
4648
+ }
4649
+ }
4650
+ }
4651
+ }
4652
+ return result;
4653
+ };
4415
4654
  var makeStringEscaper = (regex, replacement) => {
4416
4655
  return (input) => {
4417
4656
  if (Array.isArray(input)) {
@@ -4437,7 +4676,6 @@ var createResolver = (args) => {
4437
4676
  return new Resolver(args);
4438
4677
  };
4439
4678
  var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4440
- var _a, _b;
4441
4679
  if (!rawData) {
4442
4680
  return void 0;
4443
4681
  }
@@ -4464,7 +4702,8 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4464
4702
  case "password":
4465
4703
  accumulator[field.name] = {
4466
4704
  value: void 0,
4467
- passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4705
+ // never resolve the password hash
4706
+ passwordChangeRequired: value["passwordChangeRequired"] ?? false
4468
4707
  };
4469
4708
  break;
4470
4709
  case "image":
@@ -4480,11 +4719,11 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4480
4719
  field,
4481
4720
  (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4482
4721
  );
4483
- if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4722
+ if (tree?.children[0]?.type === "invalid_markdown") {
4484
4723
  if (isAudit) {
4485
- const invalidNode = tree == null ? void 0 : tree.children[0];
4724
+ const invalidNode = tree?.children[0];
4486
4725
  throw new import_graphql3.GraphQLError(
4487
- `${invalidNode == null ? void 0 : invalidNode.message}${invalidNode.position ? ` at line ${invalidNode.position.start.line}, column ${invalidNode.position.start.column}` : ""}`
4726
+ `${invalidNode?.message}${invalidNode.position ? ` at line ${invalidNode.position.start.line}, column ${invalidNode.position.start.column}` : ""}`
4488
4727
  );
4489
4728
  }
4490
4729
  }
@@ -4597,11 +4836,11 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4597
4836
  });
4598
4837
  }
4599
4838
  const titleField = template.fields.find((x) => {
4600
- if (x.type === "string" && (x == null ? void 0 : x.isTitle)) {
4839
+ if (x.type === "string" && x?.isTitle) {
4601
4840
  return true;
4602
4841
  }
4603
4842
  });
4604
- const titleFieldName = titleField == null ? void 0 : titleField.name;
4843
+ const titleFieldName = titleField?.name;
4605
4844
  const title = data[titleFieldName || " "] || null;
4606
4845
  return {
4607
4846
  __typename: collection.fields ? NAMER.documentTypeName(collection.namespace) : NAMER.documentTypeName(template.namespace),
@@ -4632,24 +4871,33 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4632
4871
  throw e;
4633
4872
  }
4634
4873
  };
4635
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4874
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4875
+ let updated = false;
4636
4876
  if (!path7.includes(".") && !path7.includes("[")) {
4637
- if (path7 in obj) {
4877
+ if (path7 in obj && obj[path7] === oldValue) {
4638
4878
  obj[path7] = newValue;
4879
+ updated = true;
4639
4880
  }
4640
- return obj;
4641
- }
4642
- const parentPath = path7.replace(/\.[^.]+$/, "");
4643
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4644
- const parents = (0, import_jsonpath_plus2.JSONPath)({ path: parentPath, json: obj, resultType: "value" });
4881
+ return { object: obj, updated };
4882
+ }
4883
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4884
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4885
+ const parents = (0, import_jsonpath_plus2.JSONPath)({
4886
+ path: parentPath,
4887
+ json: obj,
4888
+ resultType: "value"
4889
+ });
4645
4890
  if (parents.length > 0) {
4646
4891
  parents.forEach((parent) => {
4647
4892
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4648
- parent[keyToUpdate] = newValue;
4893
+ if (parent[keyToUpdate] === oldValue) {
4894
+ parent[keyToUpdate] = newValue;
4895
+ updated = true;
4896
+ }
4649
4897
  }
4650
4898
  });
4651
4899
  }
4652
- return obj;
4900
+ return { object: obj, updated };
4653
4901
  };
4654
4902
  var Resolver = class {
4655
4903
  constructor(init) {
@@ -4658,6 +4906,7 @@ var Resolver = class {
4658
4906
  const collection = this.tinaSchema.getCollection(collectionName);
4659
4907
  const extraFields = {};
4660
4908
  return {
4909
+ // return the collection and hasDocuments to resolve documents at a lower level
4661
4910
  documents: { collection, hasDocuments },
4662
4911
  ...collection,
4663
4912
  ...extraFields
@@ -4665,7 +4914,9 @@ var Resolver = class {
4665
4914
  };
4666
4915
  this.getRaw = async (fullPath) => {
4667
4916
  if (typeof fullPath !== "string") {
4668
- throw new Error(`fullPath must be of type string for getDocument request`);
4917
+ throw new Error(
4918
+ `fullPath must be of type string for getDocument request`
4919
+ );
4669
4920
  }
4670
4921
  return this.database.get(fullPath);
4671
4922
  };
@@ -4694,10 +4945,12 @@ var Resolver = class {
4694
4945
  };
4695
4946
  this.getDocument = async (fullPath, opts = {}) => {
4696
4947
  if (typeof fullPath !== "string") {
4697
- throw new Error(`fullPath must be of type string for getDocument request`);
4948
+ throw new Error(
4949
+ `fullPath must be of type string for getDocument request`
4950
+ );
4698
4951
  }
4699
4952
  const rawData = await this.getRaw(fullPath);
4700
- const hasReferences = (opts == null ? void 0 : opts.checkReferences) ? await this.hasReferences(fullPath, opts.collection) : void 0;
4953
+ const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4701
4954
  return transformDocumentIntoPayload(
4702
4955
  fullPath,
4703
4956
  rawData,
@@ -4709,7 +4962,9 @@ var Resolver = class {
4709
4962
  };
4710
4963
  this.deleteDocument = async (fullPath) => {
4711
4964
  if (typeof fullPath !== "string") {
4712
- throw new Error(`fullPath must be of type string for getDocument request`);
4965
+ throw new Error(
4966
+ `fullPath must be of type string for getDocument request`
4967
+ );
4713
4968
  }
4714
4969
  await this.database.delete(fullPath);
4715
4970
  };
@@ -4735,16 +4990,18 @@ var Resolver = class {
4735
4990
  return this.buildFieldMutations(
4736
4991
  item,
4737
4992
  objectTemplate,
4738
- idField && existingData && (existingData == null ? void 0 : existingData.find(
4993
+ idField && existingData && existingData?.find(
4739
4994
  (d) => d[idField.name] === item[idField.name]
4740
- ))
4995
+ )
4741
4996
  );
4742
4997
  }
4743
4998
  )
4744
4999
  );
4745
5000
  } else {
4746
5001
  return this.buildFieldMutations(
5002
+ // @ts-ignore FIXME Argument of type 'string | object' is not assignable to parameter of type '{ [fieldName: string]: string | object | (string | object)[]; }'
4747
5003
  fieldValue,
5004
+ //@ts-ignore
4748
5005
  objectTemplate,
4749
5006
  existingData
4750
5007
  );
@@ -4756,6 +5013,7 @@ var Resolver = class {
4756
5013
  fieldValue.map(async (item) => {
4757
5014
  if (typeof item === "string") {
4758
5015
  throw new Error(
5016
+ //@ts-ignore
4759
5017
  `Expected object for template value for field ${field.name}`
4760
5018
  );
4761
5019
  }
@@ -4764,16 +5022,19 @@ var Resolver = class {
4764
5022
  });
4765
5023
  const [templateName] = Object.entries(item)[0];
4766
5024
  const template = templates.find(
5025
+ //@ts-ignore
4767
5026
  (template2) => template2.name === templateName
4768
5027
  );
4769
5028
  if (!template) {
4770
5029
  throw new Error(`Expected to find template ${templateName}`);
4771
5030
  }
4772
5031
  return {
5032
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4773
5033
  ...await this.buildFieldMutations(
4774
5034
  item[template.name],
4775
5035
  template
4776
5036
  ),
5037
+ //@ts-ignore
4777
5038
  _template: template.name
4778
5039
  };
4779
5040
  })
@@ -4781,6 +5042,7 @@ var Resolver = class {
4781
5042
  } else {
4782
5043
  if (typeof fieldValue === "string") {
4783
5044
  throw new Error(
5045
+ //@ts-ignore
4784
5046
  `Expected object for template value for field ${field.name}`
4785
5047
  );
4786
5048
  }
@@ -4789,16 +5051,19 @@ var Resolver = class {
4789
5051
  });
4790
5052
  const [templateName] = Object.entries(fieldValue)[0];
4791
5053
  const template = templates.find(
5054
+ //@ts-ignore
4792
5055
  (template2) => template2.name === templateName
4793
5056
  );
4794
5057
  if (!template) {
4795
5058
  throw new Error(`Expected to find template ${templateName}`);
4796
5059
  }
4797
5060
  return {
5061
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4798
5062
  ...await this.buildFieldMutations(
4799
5063
  fieldValue[template.name],
4800
5064
  template
4801
5065
  ),
5066
+ //@ts-ignore
4802
5067
  _template: template.name
4803
5068
  };
4804
5069
  }
@@ -4838,6 +5103,7 @@ var Resolver = class {
4838
5103
  return this.getDocument(realPath);
4839
5104
  }
4840
5105
  const params = await this.buildObjectMutations(
5106
+ // @ts-ignore
4841
5107
  args.params[collection.name],
4842
5108
  collection
4843
5109
  );
@@ -4852,7 +5118,7 @@ var Resolver = class {
4852
5118
  isCollectionSpecific
4853
5119
  }) => {
4854
5120
  const doc = await this.getDocument(realPath);
4855
- const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5121
+ const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
4856
5122
  if (isAddPendingDocument === true) {
4857
5123
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
4858
5124
  const params2 = this.buildParams(args);
@@ -4862,7 +5128,7 @@ var Resolver = class {
4862
5128
  const values = await this.buildFieldMutations(
4863
5129
  params2,
4864
5130
  templateInfo.template,
4865
- doc == null ? void 0 : doc._rawData
5131
+ doc?._rawData
4866
5132
  );
4867
5133
  await this.database.put(
4868
5134
  realPath,
@@ -4883,9 +5149,10 @@ var Resolver = class {
4883
5149
  const values = {
4884
5150
  ...oldDoc,
4885
5151
  ...await this.buildFieldMutations(
5152
+ // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
4886
5153
  templateParams,
4887
5154
  template,
4888
- doc == null ? void 0 : doc._rawData
5155
+ doc?._rawData
4889
5156
  ),
4890
5157
  _template: lastItem(template.namespace)
4891
5158
  };
@@ -4896,17 +5163,25 @@ var Resolver = class {
4896
5163
  return this.getDocument(realPath);
4897
5164
  }
4898
5165
  const params = await this.buildObjectMutations(
5166
+ //@ts-ignore
4899
5167
  isCollectionSpecific ? args.params : args.params[collection.name],
4900
5168
  collection,
4901
- doc == null ? void 0 : doc._rawData
5169
+ doc?._rawData
5170
+ );
5171
+ await this.database.put(
5172
+ realPath,
5173
+ { ...oldDoc, ...params },
5174
+ collection.name
4902
5175
  );
4903
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
4904
5176
  return this.getDocument(realPath);
4905
5177
  };
5178
+ /**
5179
+ * Returns top-level fields which are not defined in the collection, so their
5180
+ * values are not eliminated from Tina when new values are saved
5181
+ */
4906
5182
  this.resolveLegacyValues = (oldDoc, collection) => {
4907
5183
  const legacyValues = {};
4908
5184
  Object.entries(oldDoc).forEach(([key, value]) => {
4909
- var _a;
4910
5185
  const reservedKeys = [
4911
5186
  "$_body",
4912
5187
  "_collection",
@@ -4919,7 +5194,7 @@ var Resolver = class {
4919
5194
  return;
4920
5195
  }
4921
5196
  if (oldDoc._template && collection.templates) {
4922
- const template = (_a = collection.templates) == null ? void 0 : _a.find(
5197
+ const template = collection.templates?.find(
4923
5198
  ({ name }) => name === oldDoc._template
4924
5199
  );
4925
5200
  if (template) {
@@ -4966,7 +5241,7 @@ var Resolver = class {
4966
5241
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
4967
5242
  );
4968
5243
  const collection = await this.tinaSchema.getCollection(collectionLookup);
4969
- let realPath = import_path3.default.join(collection == null ? void 0 : collection.path, args.relativePath);
5244
+ let realPath = import_path3.default.join(collection?.path, args.relativePath);
4970
5245
  if (isFolderCreation) {
4971
5246
  realPath = `${realPath}/.gitkeep.${collection.format || "md"}`;
4972
5247
  }
@@ -5010,17 +5285,35 @@ var Resolver = class {
5010
5285
  await this.deleteDocument(realPath);
5011
5286
  if (await this.hasReferences(realPath, collection)) {
5012
5287
  const collRefs = await this.findReferences(realPath, collection);
5013
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5014
- for (const [refPath, refs] of Object.entries(refFields)) {
5015
- let refDoc = await this.getRaw(refPath);
5016
- for (const ref of refs) {
5017
- refDoc = updateObjectWithJsonPath(
5288
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5289
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5290
+ docsWithRefs
5291
+ )) {
5292
+ let refDoc = await this.getRaw(pathToDocWithRef);
5293
+ let hasUpdate = false;
5294
+ for (const path7 of referencePaths) {
5295
+ const { object: object2, updated } = updateObjectWithJsonPath(
5018
5296
  refDoc,
5019
- ref.path.join("."),
5297
+ path7,
5298
+ realPath,
5020
5299
  null
5021
5300
  );
5301
+ refDoc = object2;
5302
+ hasUpdate = updated || hasUpdate;
5303
+ }
5304
+ if (hasUpdate) {
5305
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5306
+ if (!collectionWithRef) {
5307
+ throw new Error(
5308
+ `Unable to find collection for ${pathToDocWithRef}`
5309
+ );
5310
+ }
5311
+ await this.database.put(
5312
+ pathToDocWithRef,
5313
+ refDoc,
5314
+ collectionWithRef.name
5315
+ );
5022
5316
  }
5023
- await this.database.put(refPath, refDoc, collection2);
5024
5317
  }
5025
5318
  }
5026
5319
  }
@@ -5032,34 +5325,57 @@ var Resolver = class {
5032
5325
  (yup3) => yup3.object({ params: yup3.object().required() })
5033
5326
  );
5034
5327
  assertShape(
5035
- args == null ? void 0 : args.params,
5328
+ args?.params,
5036
5329
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5037
5330
  );
5038
5331
  const doc = await this.getDocument(realPath);
5039
5332
  const newRealPath = import_path3.default.join(
5040
- collection == null ? void 0 : collection.path,
5333
+ collection?.path,
5041
5334
  args.params.relativePath
5042
5335
  );
5336
+ if (newRealPath === realPath) {
5337
+ return doc;
5338
+ }
5043
5339
  await this.database.put(newRealPath, doc._rawData, collection.name);
5044
5340
  await this.deleteDocument(realPath);
5045
5341
  const collRefs = await this.findReferences(realPath, collection);
5046
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5047
- for (const [refPath, refs] of Object.entries(refFields)) {
5048
- let refDoc = await this.getRaw(refPath);
5049
- for (const ref of refs) {
5050
- refDoc = updateObjectWithJsonPath(
5051
- refDoc,
5052
- ref.path.join("."),
5342
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5343
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5344
+ docsWithRefs
5345
+ )) {
5346
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5347
+ let hasUpdate = false;
5348
+ for (const path7 of referencePaths) {
5349
+ const { object: object2, updated } = updateObjectWithJsonPath(
5350
+ docWithRef,
5351
+ path7,
5352
+ realPath,
5053
5353
  newRealPath
5054
5354
  );
5355
+ docWithRef = object2;
5356
+ hasUpdate = updated || hasUpdate;
5357
+ }
5358
+ if (hasUpdate) {
5359
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5360
+ if (!collectionWithRef) {
5361
+ throw new Error(
5362
+ `Unable to find collection for ${pathToDocWithRef}`
5363
+ );
5364
+ }
5365
+ await this.database.put(
5366
+ pathToDocWithRef,
5367
+ docWithRef,
5368
+ collectionWithRef.name
5369
+ );
5055
5370
  }
5056
- await this.database.put(refPath, refDoc, collection2);
5057
5371
  }
5058
5372
  }
5059
5373
  return this.getDocument(newRealPath);
5060
5374
  }
5061
5375
  if (alreadyExists === false) {
5062
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5376
+ throw new Error(
5377
+ `Unable to update document, ${realPath} does not exist`
5378
+ );
5063
5379
  }
5064
5380
  return this.updateResolveDocument({
5065
5381
  collection,
@@ -5109,6 +5425,7 @@ var Resolver = class {
5109
5425
  },
5110
5426
  collection: referencedCollection,
5111
5427
  hydrator: (path7) => path7
5428
+ // just return the path
5112
5429
  }
5113
5430
  );
5114
5431
  const { edges } = resolvedCollectionConnection;
@@ -5176,82 +5493,83 @@ var Resolver = class {
5176
5493
  }
5177
5494
  };
5178
5495
  };
5496
+ /**
5497
+ * Checks if a document has references to it
5498
+ * @param id The id of the document to check for references
5499
+ * @param c The collection to check for references
5500
+ * @returns true if the document has references, false otherwise
5501
+ */
5179
5502
  this.hasReferences = async (id, c) => {
5180
5503
  let count = 0;
5181
- const deepRefs = this.tinaSchema.findReferences(c.name);
5182
- for (const [collection, refs] of Object.entries(deepRefs)) {
5183
- for (const ref of refs) {
5184
- await this.database.query(
5185
- {
5186
- collection,
5187
- filterChain: makeFilterChain({
5188
- conditions: [
5189
- {
5190
- filterPath: ref.path.join("."),
5191
- filterExpression: {
5192
- _type: "reference",
5193
- _list: false,
5194
- eq: id
5195
- }
5196
- }
5197
- ]
5198
- }),
5199
- sort: ref.field.name
5200
- },
5201
- (refId) => {
5202
- count++;
5203
- return refId;
5204
- }
5205
- );
5206
- if (count) {
5207
- return true;
5208
- }
5504
+ await this.database.query(
5505
+ {
5506
+ collection: c.name,
5507
+ filterChain: makeFilterChain({
5508
+ conditions: [
5509
+ {
5510
+ filterPath: REFS_REFERENCE_FIELD,
5511
+ filterExpression: {
5512
+ _type: "string",
5513
+ _list: false,
5514
+ eq: id
5515
+ }
5516
+ }
5517
+ ]
5518
+ }),
5519
+ sort: REFS_COLLECTIONS_SORT_KEY
5520
+ },
5521
+ (refId) => {
5522
+ count++;
5523
+ return refId;
5209
5524
  }
5525
+ );
5526
+ if (count) {
5527
+ return true;
5210
5528
  }
5211
5529
  return false;
5212
5530
  };
5531
+ /**
5532
+ * Finds references to a document
5533
+ * @param id the id of the document to find references to
5534
+ * @param c the collection to find references in
5535
+ * @returns a map of references to the document
5536
+ */
5213
5537
  this.findReferences = async (id, c) => {
5214
5538
  const references = {};
5215
- const deepRefs = this.tinaSchema.findReferences(c.name);
5216
- for (const [collection, refs] of Object.entries(deepRefs)) {
5217
- for (const ref of refs) {
5218
- await this.database.query(
5219
- {
5220
- collection,
5221
- filterChain: makeFilterChain({
5222
- conditions: [
5223
- {
5224
- filterPath: ref.path.join("."),
5225
- filterExpression: {
5226
- _type: "reference",
5227
- _list: false,
5228
- eq: id
5229
- }
5230
- }
5231
- ]
5232
- }),
5233
- sort: ref.field.name
5234
- },
5235
- (refId) => {
5236
- if (!references[collection]) {
5237
- references[collection] = {};
5238
- }
5239
- if (!references[collection][refId]) {
5240
- references[collection][refId] = [];
5539
+ await this.database.query(
5540
+ {
5541
+ collection: c.name,
5542
+ filterChain: makeFilterChain({
5543
+ conditions: [
5544
+ {
5545
+ filterPath: REFS_REFERENCE_FIELD,
5546
+ filterExpression: {
5547
+ _type: "string",
5548
+ _list: false,
5549
+ eq: id
5550
+ }
5241
5551
  }
5242
- references[collection][refId].push({
5243
- path: ref.path,
5244
- field: ref.field
5245
- });
5246
- return refId;
5247
- }
5248
- );
5552
+ ]
5553
+ }),
5554
+ sort: REFS_COLLECTIONS_SORT_KEY
5555
+ },
5556
+ (refId, rawItem) => {
5557
+ if (!references[c.name]) {
5558
+ references[c.name] = {};
5559
+ }
5560
+ if (!references[c.name][refId]) {
5561
+ references[c.name][refId] = [];
5562
+ }
5563
+ const referencePath = rawItem?.[REFS_PATH_FIELD];
5564
+ if (referencePath) {
5565
+ references[c.name][refId].push(referencePath);
5566
+ }
5567
+ return refId;
5249
5568
  }
5250
- }
5569
+ );
5251
5570
  return references;
5252
5571
  };
5253
5572
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5254
- var _a;
5255
5573
  const accum = {};
5256
5574
  for (const passwordField of template.fields.filter(
5257
5575
  (f) => f.type === "password"
@@ -5294,7 +5612,7 @@ var Resolver = class {
5294
5612
  accum[fieldName] = await this.buildObjectMutations(
5295
5613
  fieldValue,
5296
5614
  field,
5297
- existingData == null ? void 0 : existingData[fieldName]
5615
+ existingData?.[fieldName]
5298
5616
  );
5299
5617
  break;
5300
5618
  case "password":
@@ -5313,7 +5631,7 @@ var Resolver = class {
5313
5631
  } else {
5314
5632
  accum[fieldName] = {
5315
5633
  ...fieldValue,
5316
- value: (_a = existingData == null ? void 0 : existingData[fieldName]) == null ? void 0 : _a["value"]
5634
+ value: existingData?.[fieldName]?.["value"]
5317
5635
  };
5318
5636
  }
5319
5637
  break;
@@ -5337,6 +5655,27 @@ var Resolver = class {
5337
5655
  }
5338
5656
  return accum;
5339
5657
  };
5658
+ /**
5659
+ * A mutation looks nearly identical between updateDocument:
5660
+ * ```graphql
5661
+ * updateDocument(collection: $collection,relativePath: $path, params: {
5662
+ * post: {
5663
+ * title: "Hello, World"
5664
+ * }
5665
+ * })`
5666
+ * ```
5667
+ * and `updatePostDocument`:
5668
+ * ```graphql
5669
+ * updatePostDocument(relativePath: $path, params: {
5670
+ * title: "Hello, World"
5671
+ * })
5672
+ * ```
5673
+ * The problem here is that we don't know whether the payload came from `updateDocument`
5674
+ * or `updatePostDocument` (we could, but for now it's easier not to pipe those details through),
5675
+ * But we do know that when given a `args.collection` value, we can assume that
5676
+ * this was a `updateDocument` request, and thus - should grab the data
5677
+ * from the corresponding field name in the key
5678
+ */
5340
5679
  this.buildParams = (args) => {
5341
5680
  try {
5342
5681
  assertShape(
@@ -5427,9 +5766,8 @@ var resolve = async ({
5427
5766
  isAudit,
5428
5767
  ctxUser
5429
5768
  }) => {
5430
- var _a;
5431
5769
  try {
5432
- const verboseValue = verbose != null ? verbose : true;
5770
+ const verboseValue = verbose ?? true;
5433
5771
  const graphQLSchemaAst = await database.getGraphQLSchema();
5434
5772
  if (!graphQLSchemaAst) {
5435
5773
  throw new import_graphql5.GraphQLError("GraphQL schema not found");
@@ -5437,8 +5775,11 @@ var resolve = async ({
5437
5775
  const graphQLSchema = (0, import_graphql5.buildASTSchema)(graphQLSchemaAst);
5438
5776
  const tinaConfig = await database.getTinaSchema();
5439
5777
  const tinaSchema = await createSchema({
5778
+ // TODO: please update all the types to import from @tinacms/schema-tools
5779
+ // @ts-ignore
5440
5780
  schema: tinaConfig,
5441
- flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
5781
+ // @ts-ignore
5782
+ flags: tinaConfig?.meta?.flags
5442
5783
  });
5443
5784
  const resolver = createResolver({
5444
5785
  config,
@@ -5454,8 +5795,7 @@ var resolve = async ({
5454
5795
  database
5455
5796
  },
5456
5797
  typeResolver: async (source, _args, info) => {
5457
- if (source.__typename)
5458
- return source.__typename;
5798
+ if (source.__typename) return source.__typename;
5459
5799
  const namedType = (0, import_graphql5.getNamedType)(info.returnType).toString();
5460
5800
  const lookup = await database.getLookup(namedType);
5461
5801
  if (lookup.resolveType === "unionData") {
@@ -5464,7 +5804,6 @@ var resolve = async ({
5464
5804
  throw new Error(`Unable to find lookup key for ${namedType}`);
5465
5805
  },
5466
5806
  fieldResolver: async (source = {}, _args = {}, _context, info) => {
5467
- var _a2, _b, _c, _d;
5468
5807
  try {
5469
5808
  const args = JSON.parse(JSON.stringify(_args));
5470
5809
  const returnType = (0, import_graphql5.getNamedType)(info.returnType).toString();
@@ -5481,8 +5820,7 @@ var resolve = async ({
5481
5820
  );
5482
5821
  const hasDocuments2 = collectionNode2.selectionSet.selections.find(
5483
5822
  (x) => {
5484
- var _a3;
5485
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5823
+ return x?.name?.value === "documents";
5486
5824
  }
5487
5825
  );
5488
5826
  return tinaSchema.getCollections().map((collection) => {
@@ -5498,8 +5836,7 @@ var resolve = async ({
5498
5836
  );
5499
5837
  const hasDocuments = collectionNode.selectionSet.selections.find(
5500
5838
  (x) => {
5501
- var _a3;
5502
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5839
+ return x?.name?.value === "documents";
5503
5840
  }
5504
5841
  );
5505
5842
  return resolver.resolveCollection(
@@ -5518,7 +5855,7 @@ var resolve = async ({
5518
5855
  }
5519
5856
  }
5520
5857
  if (info.fieldName === "authenticate" || info.fieldName === "authorize") {
5521
- const sub = args.sub || (ctxUser == null ? void 0 : ctxUser.sub);
5858
+ const sub = args.sub || ctxUser?.sub;
5522
5859
  const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5523
5860
  if (!collection) {
5524
5861
  throw new Error("Auth collection not found");
@@ -5566,7 +5903,7 @@ var resolve = async ({
5566
5903
  return user;
5567
5904
  }
5568
5905
  if (info.fieldName === "updatePassword") {
5569
- if (!(ctxUser == null ? void 0 : ctxUser.sub)) {
5906
+ if (!ctxUser?.sub) {
5570
5907
  throw new Error("Not authorized");
5571
5908
  }
5572
5909
  if (!args.password) {
@@ -5607,11 +5944,13 @@ var resolve = async ({
5607
5944
  (0, import_lodash4.default)(
5608
5945
  params,
5609
5946
  userField.path.slice(1),
5947
+ // remove _rawData from users path
5610
5948
  users.map((u) => {
5611
5949
  if (user[idFieldName] === u[idFieldName]) {
5612
5950
  return user;
5613
5951
  }
5614
5952
  return {
5953
+ // don't overwrite other users' passwords
5615
5954
  ...u,
5616
5955
  [passwordFieldName]: {
5617
5956
  ...u[passwordFieldName],
@@ -5634,6 +5973,9 @@ var resolve = async ({
5634
5973
  }
5635
5974
  const isCreation = lookup[info.fieldName] === "create";
5636
5975
  switch (lookup.resolveType) {
5976
+ /**
5977
+ * `node(id: $id)`
5978
+ */
5637
5979
  case "nodeDocument":
5638
5980
  assertShape(
5639
5981
  args,
@@ -5644,7 +5986,7 @@ var resolve = async ({
5644
5986
  if (typeof value === "string" && value !== "") {
5645
5987
  return resolver.getDocument(value);
5646
5988
  }
5647
- if ((args == null ? void 0 : args.collection) && info.fieldName === "addPendingDocument") {
5989
+ if (args?.collection && info.fieldName === "addPendingDocument") {
5648
5990
  return resolver.resolveDocument({
5649
5991
  args: { ...args, params: {} },
5650
5992
  collection: args.collection,
@@ -5665,15 +6007,19 @@ var resolve = async ({
5665
6007
  collection: args.collection,
5666
6008
  isMutation,
5667
6009
  isCreation,
6010
+ // Right now this is the only case for deletion
5668
6011
  isDeletion: info.fieldName === "deleteDocument",
5669
6012
  isFolderCreation: info.fieldName === "createFolder",
5670
- isUpdateName: Boolean((_a2 = args == null ? void 0 : args.params) == null ? void 0 : _a2.relativePath),
6013
+ isUpdateName: Boolean(args?.params?.relativePath),
5671
6014
  isAddPendingDocument: false,
5672
6015
  isCollectionSpecific: false
5673
6016
  });
5674
6017
  return result;
5675
6018
  }
5676
6019
  return value;
6020
+ /**
6021
+ * eg `getMovieDocument.data.actors`
6022
+ */
5677
6023
  case "multiCollectionDocumentList":
5678
6024
  if (Array.isArray(value)) {
5679
6025
  return {
@@ -5683,9 +6029,17 @@ var resolve = async ({
5683
6029
  })
5684
6030
  };
5685
6031
  }
5686
- if (info.fieldName === "documents" && (value == null ? void 0 : value.collection) && (value == null ? void 0 : value.hasDocuments)) {
6032
+ if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
5687
6033
  let filter = args.filter;
5688
- if (typeof (args == null ? void 0 : args.filter) !== "undefined" && (args == null ? void 0 : args.filter) !== null && typeof ((_b = value == null ? void 0 : value.collection) == null ? void 0 : _b.name) === "string" && Object.keys(args.filter).includes((_c = value == null ? void 0 : value.collection) == null ? void 0 : _c.name) && typeof args.filter[(_d = value == null ? void 0 : value.collection) == null ? void 0 : _d.name] !== "undefined") {
6034
+ if (
6035
+ // 1. Make sure that the filter exists
6036
+ typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
6037
+ // @ts-ignore
6038
+ typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
6039
+ // @ts-ignore
6040
+ Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
6041
+ typeof args.filter[value?.collection?.name] !== "undefined"
6042
+ ) {
5689
6043
  filter = args.filter[value.collection.name];
5690
6044
  }
5691
6045
  return resolver.resolveCollectionConnection({
@@ -5693,12 +6047,20 @@ var resolve = async ({
5693
6047
  ...args,
5694
6048
  filter
5695
6049
  },
6050
+ // @ts-ignore
5696
6051
  collection: value.collection
5697
6052
  });
5698
6053
  }
5699
6054
  throw new Error(
5700
6055
  `Expected an array for result of ${info.fieldName} at ${info.path}`
5701
6056
  );
6057
+ /**
6058
+ * Collections-specific getter
6059
+ * eg. `getPostDocument`/`createPostDocument`/`updatePostDocument`
6060
+ *
6061
+ * if coming from a query result
6062
+ * the field will be `node`
6063
+ */
5702
6064
  case "collectionDocument": {
5703
6065
  if (value) {
5704
6066
  return value;
@@ -5713,11 +6075,32 @@ var resolve = async ({
5713
6075
  });
5714
6076
  return result;
5715
6077
  }
6078
+ /**
6079
+ * Collections-specific list getter
6080
+ * eg. `getPageList`
6081
+ */
5716
6082
  case "collectionDocumentList":
5717
6083
  return resolver.resolveCollectionConnection({
5718
6084
  args,
5719
6085
  collection: tinaSchema.getCollection(lookup.collection)
5720
6086
  });
6087
+ /**
6088
+ * A polymorphic data set, it can be from a document's data
6089
+ * of any nested object which can be one of many shapes
6090
+ *
6091
+ * ```graphql
6092
+ * getPostDocument(relativePath: $relativePath) {
6093
+ * data {...} <- this part
6094
+ * }
6095
+ * ```
6096
+ * ```graphql
6097
+ * getBlockDocument(relativePath: $relativePath) {
6098
+ * data {
6099
+ * blocks {...} <- or this part
6100
+ * }
6101
+ * }
6102
+ * ```
6103
+ */
5721
6104
  case "unionData":
5722
6105
  if (!value) {
5723
6106
  if (args.relativePath) {
@@ -5782,8 +6165,7 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5782
6165
  this.port = port || 9e3;
5783
6166
  }
5784
6167
  openConnection() {
5785
- if (this._connected)
5786
- return;
6168
+ if (this._connected) return;
5787
6169
  const socket = (0, import_net.connect)(this.port);
5788
6170
  (0, import_readable_stream.pipeline)(socket, this.createRpcStream(), socket, () => {
5789
6171
  this._connected = false;
@@ -5793,15 +6175,15 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5793
6175
  };
5794
6176
 
5795
6177
  // src/database/index.ts
5796
- var import_node_path = __toESM(require("path"));
6178
+ var import_node_path = __toESM(require("node:path"));
5797
6179
  var import_graphql6 = require("graphql");
5798
6180
  var import_micromatch2 = __toESM(require("micromatch"));
5799
6181
  var import_js_sha12 = __toESM(require("js-sha1"));
5800
6182
  var import_lodash5 = __toESM(require("lodash.set"));
5801
6183
  var createLocalDatabase = (config) => {
5802
- const level = new TinaLevelClient(config == null ? void 0 : config.port);
6184
+ const level = new TinaLevelClient(config?.port);
5803
6185
  level.openConnection();
5804
- const fsBridge = new FilesystemBridge((config == null ? void 0 : config.rootPath) || process.cwd());
6186
+ const fsBridge = new FilesystemBridge(config?.rootPath || process.cwd());
5805
6187
  return new Database({
5806
6188
  bridge: fsBridge,
5807
6189
  ...config || {},
@@ -5874,7 +6256,7 @@ var Database = class {
5874
6256
  );
5875
6257
  }
5876
6258
  const metadata = await metadataLevel.get(`metadata_${key}`);
5877
- return metadata == null ? void 0 : metadata.value;
6259
+ return metadata?.value;
5878
6260
  };
5879
6261
  this.setMetadata = async (key, value) => {
5880
6262
  await this.initLevel();
@@ -5896,14 +6278,14 @@ var Database = class {
5896
6278
  let level = this.contentLevel;
5897
6279
  if (this.appLevel) {
5898
6280
  collection = await this.collectionForPath(filepath);
5899
- if (collection == null ? void 0 : collection.isDetached) {
6281
+ if (collection?.isDetached) {
5900
6282
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
5901
6283
  }
5902
6284
  }
5903
6285
  const contentObject = await level.sublevel(
5904
6286
  CONTENT_ROOT_PREFIX,
5905
6287
  SUBLEVEL_OPTIONS
5906
- ).get((0, import_schema_tools3.normalizePath)(filepath));
6288
+ ).get((0, import_schema_tools4.normalizePath)(filepath));
5907
6289
  if (!contentObject) {
5908
6290
  throw new NotFoundError(`Unable to find record ${filepath}`);
5909
6291
  }
@@ -5927,9 +6309,10 @@ var Database = class {
5927
6309
  collection
5928
6310
  );
5929
6311
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
5930
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
5931
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
5932
- if (!(collection == null ? void 0 : collection.isDetached)) {
6312
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6313
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6314
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6315
+ if (!collection?.isDetached) {
5933
6316
  if (this.bridge) {
5934
6317
  await this.bridge.put(normalizedPath, stringifiedFile);
5935
6318
  }
@@ -5947,7 +6330,7 @@ var Database = class {
5947
6330
  }
5948
6331
  }
5949
6332
  let level = this.contentLevel;
5950
- if (collection == null ? void 0 : collection.isDetached) {
6333
+ if (collection?.isDetached) {
5951
6334
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
5952
6335
  }
5953
6336
  const folderTreeBuilder = new FolderTreeBuilder();
@@ -5956,17 +6339,26 @@ var Database = class {
5956
6339
  let delOps = [];
5957
6340
  if (!isGitKeep(normalizedPath, collection)) {
5958
6341
  putOps = [
6342
+ ...makeRefOpsForDocument(
6343
+ normalizedPath,
6344
+ collection?.name,
6345
+ collectionReferences,
6346
+ dataFields,
6347
+ "put",
6348
+ level
6349
+ ),
5959
6350
  ...makeIndexOpsForDocument(
5960
6351
  normalizedPath,
5961
- collection == null ? void 0 : collection.name,
6352
+ collection?.name,
5962
6353
  collectionIndexDefinitions,
5963
6354
  dataFields,
5964
6355
  "put",
5965
6356
  level
5966
6357
  ),
6358
+ // folder indices
5967
6359
  ...makeIndexOpsForDocument(
5968
6360
  normalizedPath,
5969
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6361
+ `${collection?.name}_${folderKey}`,
5970
6362
  collectionIndexDefinitions,
5971
6363
  dataFields,
5972
6364
  "put",
@@ -5978,17 +6370,26 @@ var Database = class {
5978
6370
  SUBLEVEL_OPTIONS
5979
6371
  ).get(normalizedPath);
5980
6372
  delOps = existingItem ? [
6373
+ ...makeRefOpsForDocument(
6374
+ normalizedPath,
6375
+ collection?.name,
6376
+ collectionReferences,
6377
+ existingItem,
6378
+ "del",
6379
+ level
6380
+ ),
5981
6381
  ...makeIndexOpsForDocument(
5982
6382
  normalizedPath,
5983
- collection == null ? void 0 : collection.name,
6383
+ collection?.name,
5984
6384
  collectionIndexDefinitions,
5985
6385
  existingItem,
5986
6386
  "del",
5987
6387
  level
5988
6388
  ),
6389
+ // folder indices
5989
6390
  ...makeIndexOpsForDocument(
5990
6391
  normalizedPath,
5991
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6392
+ `${collection?.name}_${folderKey}`,
5992
6393
  collectionIndexDefinitions,
5993
6394
  existingItem,
5994
6395
  "del",
@@ -6012,7 +6413,6 @@ var Database = class {
6012
6413
  await level.batch(ops);
6013
6414
  };
6014
6415
  this.put = async (filepath, data, collectionName) => {
6015
- var _a, _b;
6016
6416
  await this.initLevel();
6017
6417
  try {
6018
6418
  if (SYSTEM_FILES.includes(filepath)) {
@@ -6023,15 +6423,16 @@ var Database = class {
6023
6423
  const indexDefinitions = await this.getIndexDefinitions(
6024
6424
  this.contentLevel
6025
6425
  );
6026
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6426
+ collectionIndexDefinitions = indexDefinitions?.[collectionName];
6027
6427
  }
6028
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6428
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6429
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6029
6430
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6030
6431
  const collection = await this.collectionForPath(filepath);
6031
6432
  if (!collection) {
6032
6433
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
6033
6434
  }
6034
- if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
6435
+ if (collection.match?.exclude || collection.match?.include) {
6035
6436
  const matches = this.tinaSchema.getMatches({ collection });
6036
6437
  const match = import_micromatch2.default.isMatch(filepath, matches);
6037
6438
  if (!match) {
@@ -6045,7 +6446,7 @@ var Database = class {
6045
6446
  const stringifiedFile = filepath.endsWith(
6046
6447
  `.gitkeep.${collection.format || "md"}`
6047
6448
  ) ? "" : await this.stringifyFile(filepath, dataFields, collection);
6048
- if (!(collection == null ? void 0 : collection.isDetached)) {
6449
+ if (!collection?.isDetached) {
6049
6450
  if (this.bridge) {
6050
6451
  await this.bridge.put(normalizedPath, stringifiedFile);
6051
6452
  }
@@ -6067,11 +6468,19 @@ var Database = class {
6067
6468
  filepath,
6068
6469
  collection.path || ""
6069
6470
  );
6070
- const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6471
+ const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6071
6472
  let putOps = [];
6072
6473
  let delOps = [];
6073
6474
  if (!isGitKeep(normalizedPath, collection)) {
6074
6475
  putOps = [
6476
+ ...makeRefOpsForDocument(
6477
+ normalizedPath,
6478
+ collectionName,
6479
+ collectionReferences,
6480
+ dataFields,
6481
+ "put",
6482
+ level
6483
+ ),
6075
6484
  ...makeIndexOpsForDocument(
6076
6485
  normalizedPath,
6077
6486
  collectionName,
@@ -6080,9 +6489,10 @@ var Database = class {
6080
6489
  "put",
6081
6490
  level
6082
6491
  ),
6492
+ // folder indices
6083
6493
  ...makeIndexOpsForDocument(
6084
6494
  normalizedPath,
6085
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6495
+ `${collection?.name}_${folderKey}`,
6086
6496
  collectionIndexDefinitions,
6087
6497
  dataFields,
6088
6498
  "put",
@@ -6094,6 +6504,14 @@ var Database = class {
6094
6504
  SUBLEVEL_OPTIONS
6095
6505
  ).get(normalizedPath);
6096
6506
  delOps = existingItem ? [
6507
+ ...makeRefOpsForDocument(
6508
+ normalizedPath,
6509
+ collectionName,
6510
+ collectionReferences,
6511
+ existingItem,
6512
+ "del",
6513
+ level
6514
+ ),
6097
6515
  ...makeIndexOpsForDocument(
6098
6516
  normalizedPath,
6099
6517
  collectionName,
@@ -6102,9 +6520,10 @@ var Database = class {
6102
6520
  "del",
6103
6521
  level
6104
6522
  ),
6523
+ // folder indices
6105
6524
  ...makeIndexOpsForDocument(
6106
6525
  normalizedPath,
6107
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6526
+ `${collection?.name}_${folderKey}`,
6108
6527
  collectionIndexDefinitions,
6109
6528
  existingItem,
6110
6529
  "del",
@@ -6179,9 +6598,10 @@ var Database = class {
6179
6598
  aliasedData,
6180
6599
  extension,
6181
6600
  writeTemplateKey,
6601
+ //templateInfo.type === 'union',
6182
6602
  {
6183
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat,
6184
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
6603
+ frontmatterFormat: collection?.frontmatterFormat,
6604
+ frontmatterDelimiters: collection?.frontmatterDelimiters
6185
6605
  }
6186
6606
  );
6187
6607
  };
@@ -6196,7 +6616,7 @@ var Database = class {
6196
6616
  };
6197
6617
  this.getLookup = async (returnType) => {
6198
6618
  await this.initLevel();
6199
- const lookupPath = (0, import_schema_tools3.normalizePath)(
6619
+ const lookupPath = (0, import_schema_tools4.normalizePath)(
6200
6620
  import_node_path.default.join(this.getGeneratedFolder(), `_lookup.json`)
6201
6621
  );
6202
6622
  if (!this._lookup) {
@@ -6209,7 +6629,7 @@ var Database = class {
6209
6629
  };
6210
6630
  this.getGraphQLSchema = async () => {
6211
6631
  await this.initLevel();
6212
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6632
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6213
6633
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6214
6634
  );
6215
6635
  return await this.contentLevel.sublevel(
@@ -6217,11 +6637,12 @@ var Database = class {
6217
6637
  SUBLEVEL_OPTIONS
6218
6638
  ).get(graphqlPath);
6219
6639
  };
6640
+ //TODO - is there a reason why the database fetches some config with "bridge.get", and some with "store.get"?
6220
6641
  this.getGraphQLSchemaFromBridge = async () => {
6221
6642
  if (!this.bridge) {
6222
6643
  throw new Error(`No bridge configured`);
6223
6644
  }
6224
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6645
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6225
6646
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6226
6647
  );
6227
6648
  const _graphql = await this.bridge.get(graphqlPath);
@@ -6229,7 +6650,7 @@ var Database = class {
6229
6650
  };
6230
6651
  this.getTinaSchema = async (level) => {
6231
6652
  await this.initLevel();
6232
- const schemaPath = (0, import_schema_tools3.normalizePath)(
6653
+ const schemaPath = (0, import_schema_tools4.normalizePath)(
6233
6654
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6234
6655
  );
6235
6656
  return await (level || this.contentLevel).sublevel(
@@ -6245,7 +6666,7 @@ var Database = class {
6245
6666
  const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
6246
6667
  if (!schema) {
6247
6668
  throw new Error(
6248
- `Unable to get schema from level db: ${(0, import_schema_tools3.normalizePath)(
6669
+ `Unable to get schema from level db: ${(0, import_schema_tools4.normalizePath)(
6249
6670
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6250
6671
  )}`
6251
6672
  );
@@ -6253,6 +6674,22 @@ var Database = class {
6253
6674
  this.tinaSchema = await createSchema({ schema });
6254
6675
  return this.tinaSchema;
6255
6676
  };
6677
+ this.getCollectionReferences = async (level) => {
6678
+ if (this.collectionReferences) {
6679
+ return this.collectionReferences;
6680
+ }
6681
+ const result = {};
6682
+ const schema = await this.getSchema(level || this.contentLevel);
6683
+ const collections = schema.getCollections();
6684
+ for (const collection of collections) {
6685
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6686
+ collection.name
6687
+ );
6688
+ result[collection.name] = collectionReferences;
6689
+ }
6690
+ this.collectionReferences = result;
6691
+ return result;
6692
+ };
6256
6693
  this.getIndexDefinitions = async (level) => {
6257
6694
  if (!this.collectionIndexDefinitions) {
6258
6695
  await new Promise(async (resolve2, reject) => {
@@ -6262,10 +6699,53 @@ var Database = class {
6262
6699
  const collections = schema.getCollections();
6263
6700
  for (const collection of collections) {
6264
6701
  const indexDefinitions = {
6265
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6702
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6703
+ // provide a default sort key which is the file sort
6704
+ // pseudo-index for the collection's references
6705
+ [REFS_COLLECTIONS_SORT_KEY]: {
6706
+ fields: [
6707
+ {
6708
+ name: REFS_REFERENCE_FIELD,
6709
+ type: "string",
6710
+ list: false
6711
+ },
6712
+ {
6713
+ name: REFS_PATH_FIELD,
6714
+ type: "string",
6715
+ list: false
6716
+ }
6717
+ ]
6718
+ }
6266
6719
  };
6267
- if (collection.fields) {
6268
- for (const field of collection.fields) {
6720
+ let fields = [];
6721
+ if (collection.templates) {
6722
+ const templateFieldMap = {};
6723
+ const conflictedFields = /* @__PURE__ */ new Set();
6724
+ for (const template of collection.templates) {
6725
+ for (const field of template.fields) {
6726
+ if (!templateFieldMap[field.name]) {
6727
+ templateFieldMap[field.name] = field;
6728
+ } else {
6729
+ if (templateFieldMap[field.name].type !== field.type) {
6730
+ console.warn(
6731
+ `Field ${field.name} has conflicting types in templates - skipping index`
6732
+ );
6733
+ conflictedFields.add(field.name);
6734
+ }
6735
+ }
6736
+ }
6737
+ }
6738
+ for (const conflictedField in conflictedFields) {
6739
+ delete templateFieldMap[conflictedField];
6740
+ }
6741
+ for (const field of Object.values(templateFieldMap)) {
6742
+ fields.push(field);
6743
+ }
6744
+ } else if (collection.fields) {
6745
+ fields = collection.fields;
6746
+ }
6747
+ if (fields) {
6748
+ for (const field of fields) {
6269
6749
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6270
6750
  continue;
6271
6751
  }
@@ -6290,8 +6770,8 @@ var Database = class {
6290
6770
  );
6291
6771
  return {
6292
6772
  name: indexField.name,
6293
- type: field == null ? void 0 : field.type,
6294
- list: !!(field == null ? void 0 : field.list)
6773
+ type: field?.type,
6774
+ list: !!field?.list
6295
6775
  };
6296
6776
  })
6297
6777
  };
@@ -6317,7 +6797,6 @@ var Database = class {
6317
6797
  return true;
6318
6798
  };
6319
6799
  this.query = async (queryOptions, hydrator) => {
6320
- var _a;
6321
6800
  await this.initLevel();
6322
6801
  const {
6323
6802
  first,
@@ -6345,14 +6824,14 @@ var Database = class {
6345
6824
  const allIndexDefinitions = await this.getIndexDefinitions(
6346
6825
  this.contentLevel
6347
6826
  );
6348
- const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[collection.name];
6827
+ const indexDefinitions = allIndexDefinitions?.[collection.name];
6349
6828
  if (!indexDefinitions) {
6350
6829
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6351
6830
  }
6352
6831
  const filterChain = coerceFilterChainOperands(rawFilterChain);
6353
- const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
6832
+ const indexDefinition = sort && indexDefinitions?.[sort];
6354
6833
  const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
6355
- const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6834
+ const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6356
6835
  const rootLevel = level.sublevel(
6357
6836
  CONTENT_ROOT_PREFIX,
6358
6837
  SUBLEVEL_OPTIONS
@@ -6362,17 +6841,17 @@ var Database = class {
6362
6841
  SUBLEVEL_OPTIONS
6363
6842
  ).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
6364
6843
  if (!query.gt && !query.gte) {
6365
- query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? filterSuffixes.left : "";
6844
+ query.gte = filterSuffixes?.left ? filterSuffixes.left : "";
6366
6845
  }
6367
6846
  if (!query.lt && !query.lte) {
6368
- query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6847
+ query.lte = filterSuffixes?.right ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6369
6848
  }
6370
6849
  let edges = [];
6371
6850
  let startKey = "";
6372
6851
  let endKey = "";
6373
6852
  let hasPreviousPage = false;
6374
6853
  let hasNextPage = false;
6375
- const fieldsPattern = ((_a = indexDefinition == null ? void 0 : indexDefinition.fields) == null ? void 0 : _a.length) ? `${indexDefinition.fields.map((p) => `(?<${p.name}>.+)${INDEX_KEY_FIELD_SEPARATOR}`).join("")}` : "";
6854
+ const fieldsPattern = indexDefinition?.fields?.length ? `${indexDefinition.fields.map((p) => `(?<${p.name}>.+)${INDEX_KEY_FIELD_SEPARATOR}`).join("")}` : "";
6376
6855
  const valuesRegex = indexDefinition ? new RegExp(`^${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^(?<_filepath_>.+)`);
6377
6856
  const itemFilter = makeFilter({ filterChain });
6378
6857
  const iterator = sublevel.iterator(query);
@@ -6414,29 +6893,36 @@ var Database = class {
6414
6893
  }
6415
6894
  startKey = startKey || key || "";
6416
6895
  endKey = key || "";
6417
- edges = [...edges, { cursor: key, path: filepath }];
6896
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6418
6897
  }
6419
6898
  return {
6420
- edges: await sequential(edges, async (edge) => {
6421
- try {
6422
- const node = await hydrator(edge.path);
6423
- return {
6424
- node,
6425
- cursor: btoa(edge.cursor)
6426
- };
6427
- } catch (error) {
6428
- console.log(error);
6429
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6430
- throw new TinaQueryError({
6431
- originalError: error,
6432
- file: edge.path,
6433
- collection: collection.name,
6434
- stack: error.stack
6435
- });
6899
+ edges: await sequential(
6900
+ edges,
6901
+ async ({
6902
+ cursor,
6903
+ path: path7,
6904
+ value
6905
+ }) => {
6906
+ try {
6907
+ const node = await hydrator(path7, value);
6908
+ return {
6909
+ node,
6910
+ cursor: btoa(cursor)
6911
+ };
6912
+ } catch (error) {
6913
+ console.log(error);
6914
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6915
+ throw new TinaQueryError({
6916
+ originalError: error,
6917
+ file: path7,
6918
+ collection: collection.name,
6919
+ stack: error.stack
6920
+ });
6921
+ }
6922
+ throw error;
6436
6923
  }
6437
- throw error;
6438
6924
  }
6439
- }),
6925
+ ),
6440
6926
  pageInfo: {
6441
6927
  hasPreviousPage,
6442
6928
  hasNextPage,
@@ -6461,7 +6947,7 @@ var Database = class {
6461
6947
  try {
6462
6948
  lookup = lookupFromLockFile || JSON.parse(
6463
6949
  await this.bridge.get(
6464
- (0, import_schema_tools3.normalizePath)(
6950
+ (0, import_schema_tools4.normalizePath)(
6465
6951
  import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")
6466
6952
  )
6467
6953
  )
@@ -6486,15 +6972,15 @@ var Database = class {
6486
6972
  }
6487
6973
  const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
6488
6974
  await contentRootLevel.put(
6489
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
6975
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
6490
6976
  graphQLSchema
6491
6977
  );
6492
6978
  await contentRootLevel.put(
6493
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
6979
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
6494
6980
  tinaSchema.schema
6495
6981
  );
6496
6982
  await contentRootLevel.put(
6497
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
6983
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
6498
6984
  lookup
6499
6985
  );
6500
6986
  const result = await this._indexAllContent(
@@ -6560,13 +7046,14 @@ var Database = class {
6560
7046
  documentPaths,
6561
7047
  async (collection, documentPaths2) => {
6562
7048
  if (collection && !collection.isDetached) {
6563
- await _indexContent(
6564
- this,
6565
- this.contentLevel,
6566
- documentPaths2,
7049
+ await _indexContent({
7050
+ database: this,
7051
+ level: this.contentLevel,
7052
+ documentPaths: documentPaths2,
6567
7053
  enqueueOps,
6568
- collection
6569
- );
7054
+ collection,
7055
+ isPartialReindex: true
7056
+ });
6570
7057
  }
6571
7058
  }
6572
7059
  );
@@ -6582,17 +7069,18 @@ var Database = class {
6582
7069
  throw new Error(`No collection found for path: ${filepath}`);
6583
7070
  }
6584
7071
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6585
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7072
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
7073
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6586
7074
  let level = this.contentLevel;
6587
- if (collection == null ? void 0 : collection.isDetached) {
6588
- level = this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS);
7075
+ if (collection?.isDetached) {
7076
+ level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
6589
7077
  }
6590
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7078
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6591
7079
  const rootSublevel = level.sublevel(
6592
7080
  CONTENT_ROOT_PREFIX,
6593
7081
  SUBLEVEL_OPTIONS
6594
7082
  );
6595
- const item = await rootSublevel.get(itemKey);
7083
+ const item = await rootSublevel.get(normalizedPath);
6596
7084
  if (item) {
6597
7085
  const folderTreeBuilder = new FolderTreeBuilder();
6598
7086
  const folderKey = folderTreeBuilder.update(
@@ -6600,16 +7088,25 @@ var Database = class {
6600
7088
  collection.path || ""
6601
7089
  );
6602
7090
  await this.contentLevel.batch([
7091
+ ...makeRefOpsForDocument(
7092
+ normalizedPath,
7093
+ collection.name,
7094
+ collectionReferences,
7095
+ item,
7096
+ "del",
7097
+ level
7098
+ ),
6603
7099
  ...makeIndexOpsForDocument(
6604
- filepath,
7100
+ normalizedPath,
6605
7101
  collection.name,
6606
7102
  collectionIndexDefinitions,
6607
7103
  item,
6608
7104
  "del",
6609
7105
  level
6610
7106
  ),
7107
+ // folder indices
6611
7108
  ...makeIndexOpsForDocument(
6612
- filepath,
7109
+ normalizedPath,
6613
7110
  `${collection.name}_${folderKey}`,
6614
7111
  collectionIndexDefinitions,
6615
7112
  item,
@@ -6618,17 +7115,17 @@ var Database = class {
6618
7115
  ),
6619
7116
  {
6620
7117
  type: "del",
6621
- key: itemKey,
7118
+ key: normalizedPath,
6622
7119
  sublevel: rootSublevel
6623
7120
  }
6624
7121
  ]);
6625
7122
  }
6626
- if (!(collection == null ? void 0 : collection.isDetached)) {
7123
+ if (!collection?.isDetached) {
6627
7124
  if (this.bridge) {
6628
- await this.bridge.delete((0, import_schema_tools3.normalizePath)(filepath));
7125
+ await this.bridge.delete(normalizedPath);
6629
7126
  }
6630
7127
  try {
6631
- await this.onDelete((0, import_schema_tools3.normalizePath)(filepath));
7128
+ await this.onDelete(normalizedPath);
6632
7129
  } catch (e) {
6633
7130
  throw new import_graphql6.GraphQLError(
6634
7131
  `Error running onDelete hook for ${filepath}: ${e}`,
@@ -6663,20 +7160,26 @@ var Database = class {
6663
7160
  );
6664
7161
  const doc = await level2.keys({ limit: 1 }).next();
6665
7162
  if (!doc) {
6666
- await _indexContent(
6667
- this,
6668
- level2,
6669
- contentPaths,
7163
+ await _indexContent({
7164
+ database: this,
7165
+ level: level2,
7166
+ documentPaths: contentPaths,
6670
7167
  enqueueOps,
6671
7168
  collection,
6672
- userFields.map((field) => [
7169
+ passwordFields: userFields.map((field) => [
6673
7170
  ...field.path,
6674
7171
  field.passwordFieldName
6675
7172
  ])
6676
- );
7173
+ });
6677
7174
  }
6678
7175
  } else {
6679
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7176
+ await _indexContent({
7177
+ database: this,
7178
+ level,
7179
+ documentPaths: contentPaths,
7180
+ enqueueOps,
7181
+ collection
7182
+ });
6680
7183
  }
6681
7184
  }
6682
7185
  );
@@ -6712,7 +7215,7 @@ var Database = class {
6712
7215
  );
6713
7216
  }
6714
7217
  const metadata = await metadataLevel.get("metadata");
6715
- return metadata == null ? void 0 : metadata.version;
7218
+ return metadata?.version;
6716
7219
  }
6717
7220
  async initLevel() {
6718
7221
  if (this.contentLevel) {
@@ -6762,6 +7265,9 @@ var Database = class {
6762
7265
  info: templateInfo
6763
7266
  };
6764
7267
  }
7268
+ /**
7269
+ * Clears the internal cache of the tinaSchema and the lookup file. This allows the state to be reset
7270
+ */
6765
7271
  clearCache() {
6766
7272
  this.tinaSchema = null;
6767
7273
  this._lookup = null;
@@ -6795,7 +7301,7 @@ var hashPasswordVisitor = async (node, path7) => {
6795
7301
  };
6796
7302
  var visitNodes = async (node, path7, callback) => {
6797
7303
  const [currentLevel, ...remainingLevels] = path7;
6798
- if (!(remainingLevels == null ? void 0 : remainingLevels.length)) {
7304
+ if (!remainingLevels?.length) {
6799
7305
  return callback(node, path7);
6800
7306
  }
6801
7307
  if (Array.isArray(node[currentLevel])) {
@@ -6811,18 +7317,27 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
6811
7317
  async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
6812
7318
  )
6813
7319
  );
6814
- var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
6815
- var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7320
+ var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${collection?.format || "md"}`);
7321
+ var _indexContent = async ({
7322
+ database,
7323
+ level,
7324
+ documentPaths,
7325
+ enqueueOps,
7326
+ collection,
7327
+ passwordFields,
7328
+ isPartialReindex
7329
+ }) => {
6816
7330
  let collectionIndexDefinitions;
6817
7331
  let collectionPath;
6818
7332
  if (collection) {
6819
7333
  const indexDefinitions = await database.getIndexDefinitions(level);
6820
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7334
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
6821
7335
  if (!collectionIndexDefinitions) {
6822
7336
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6823
7337
  }
6824
7338
  collectionPath = collection.path;
6825
7339
  }
7340
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
6826
7341
  const tinaSchema = await database.getSchema();
6827
7342
  let templateInfo = null;
6828
7343
  if (collection) {
@@ -6840,27 +7355,77 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6840
7355
  if (!aliasedData) {
6841
7356
  return;
6842
7357
  }
6843
- if (passwordFields == null ? void 0 : passwordFields.length) {
7358
+ if (passwordFields?.length) {
6844
7359
  await hashPasswordValues(aliasedData, passwordFields);
6845
7360
  }
6846
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
7361
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
7362
+ const rootSublevel = level.sublevel(
7363
+ CONTENT_ROOT_PREFIX,
7364
+ SUBLEVEL_OPTIONS
7365
+ );
6847
7366
  const folderKey = folderTreeBuilder.update(
6848
7367
  normalizedPath,
6849
7368
  collectionPath || ""
6850
7369
  );
7370
+ if (isPartialReindex) {
7371
+ const item = await rootSublevel.get(normalizedPath);
7372
+ if (item) {
7373
+ await database.contentLevel.batch([
7374
+ ...makeRefOpsForDocument(
7375
+ normalizedPath,
7376
+ collection?.name,
7377
+ collectionReferences,
7378
+ item,
7379
+ "del",
7380
+ level
7381
+ ),
7382
+ ...makeIndexOpsForDocument(
7383
+ normalizedPath,
7384
+ collection.name,
7385
+ collectionIndexDefinitions,
7386
+ item,
7387
+ "del",
7388
+ level
7389
+ ),
7390
+ // folder indices
7391
+ ...makeIndexOpsForDocument(
7392
+ normalizedPath,
7393
+ `${collection.name}_${folderKey}`,
7394
+ collectionIndexDefinitions,
7395
+ item,
7396
+ "del",
7397
+ level
7398
+ ),
7399
+ {
7400
+ type: "del",
7401
+ key: normalizedPath,
7402
+ sublevel: rootSublevel
7403
+ }
7404
+ ]);
7405
+ }
7406
+ }
6851
7407
  if (!isGitKeep(filepath, collection)) {
6852
7408
  await enqueueOps([
7409
+ ...makeRefOpsForDocument(
7410
+ normalizedPath,
7411
+ collection?.name,
7412
+ collectionReferences,
7413
+ aliasedData,
7414
+ "put",
7415
+ level
7416
+ ),
6853
7417
  ...makeIndexOpsForDocument(
6854
7418
  normalizedPath,
6855
- collection == null ? void 0 : collection.name,
7419
+ collection?.name,
6856
7420
  collectionIndexDefinitions,
6857
7421
  aliasedData,
6858
7422
  "put",
6859
7423
  level
6860
7424
  ),
7425
+ // folder indexes
6861
7426
  ...makeIndexOpsForDocument(
6862
7427
  normalizedPath,
6863
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7428
+ `${collection?.name}_${folderKey}`,
6864
7429
  collectionIndexDefinitions,
6865
7430
  aliasedData,
6866
7431
  "put",
@@ -6881,7 +7446,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6881
7446
  throw new TinaFetchError(`Unable to seed ${filepath}`, {
6882
7447
  originalError: error,
6883
7448
  file: filepath,
6884
- collection: collection == null ? void 0 : collection.name,
7449
+ collection: collection?.name,
6885
7450
  stack: error.stack
6886
7451
  });
6887
7452
  }
@@ -6907,11 +7472,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6907
7472
  const indexDefinitions = await database.getIndexDefinitions(
6908
7473
  database.contentLevel
6909
7474
  );
6910
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7475
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
6911
7476
  if (!collectionIndexDefinitions) {
6912
7477
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6913
7478
  }
6914
7479
  }
7480
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
6915
7481
  const tinaSchema = await database.getSchema();
6916
7482
  let templateInfo = null;
6917
7483
  if (collection) {
@@ -6923,18 +7489,26 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6923
7489
  );
6924
7490
  const folderTreeBuilder = new FolderTreeBuilder();
6925
7491
  await sequential(documentPaths, async (filepath) => {
6926
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7492
+ const itemKey = (0, import_schema_tools4.normalizePath)(filepath);
6927
7493
  const item = await rootLevel.get(itemKey);
6928
7494
  if (item) {
6929
7495
  const folderKey = folderTreeBuilder.update(
6930
7496
  itemKey,
6931
- (collection == null ? void 0 : collection.path) || ""
7497
+ collection?.path || ""
6932
7498
  );
6933
7499
  const aliasedData = templateInfo ? replaceNameOverrides(
6934
7500
  getTemplateForFile(templateInfo, item),
6935
7501
  item
6936
7502
  ) : item;
6937
7503
  await enqueueOps([
7504
+ ...makeRefOpsForDocument(
7505
+ itemKey,
7506
+ collection?.name,
7507
+ collectionReferences,
7508
+ aliasedData,
7509
+ "del",
7510
+ database.contentLevel
7511
+ ),
6938
7512
  ...makeIndexOpsForDocument(
6939
7513
  itemKey,
6940
7514
  collection.name,
@@ -6943,9 +7517,10 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6943
7517
  "del",
6944
7518
  database.contentLevel
6945
7519
  ),
7520
+ // folder indexes
6946
7521
  ...makeIndexOpsForDocument(
6947
7522
  itemKey,
6948
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7523
+ `${collection?.name}_${folderKey}`,
6949
7524
  collectionIndexDefinitions,
6950
7525
  aliasedData,
6951
7526
  "del",
@@ -7009,14 +7584,14 @@ var getChangedFiles = async ({
7009
7584
  const rootDir = await findGitRoot(dir);
7010
7585
  let pathPrefix = "";
7011
7586
  if (rootDir !== dir) {
7012
- pathPrefix = (0, import_schema_tools3.normalizePath)(dir.substring(rootDir.length + 1));
7587
+ pathPrefix = (0, import_schema_tools4.normalizePath)(dir.substring(rootDir.length + 1));
7013
7588
  }
7014
7589
  await import_isomorphic_git.default.walk({
7015
7590
  fs: fs4,
7016
7591
  dir: rootDir,
7017
7592
  trees: [import_isomorphic_git.default.TREE({ ref: from }), import_isomorphic_git.default.TREE({ ref: to })],
7018
7593
  map: async function(filename, [A, B]) {
7019
- const relativePath = (0, import_schema_tools3.normalizePath)(filename).substring(pathPrefix.length);
7594
+ const relativePath = (0, import_schema_tools4.normalizePath)(filename).substring(pathPrefix.length);
7020
7595
  let matches = false;
7021
7596
  for (const [key, matcher] of Object.entries(pathFilter)) {
7022
7597
  if (relativePath.startsWith(key)) {
@@ -7030,12 +7605,12 @@ var getChangedFiles = async ({
7030
7605
  }
7031
7606
  }
7032
7607
  }
7033
- if (await (B == null ? void 0 : B.type()) === "tree") {
7608
+ if (await B?.type() === "tree") {
7034
7609
  return;
7035
7610
  }
7036
7611
  if (matches) {
7037
- const oidA = await (A == null ? void 0 : A.oid());
7038
- const oidB = await (B == null ? void 0 : B.oid());
7612
+ const oidA = await A?.oid();
7613
+ const oidB = await B?.oid();
7039
7614
  if (oidA !== oidB) {
7040
7615
  if (oidA === void 0) {
7041
7616
  results.added.push(relativePath);
@@ -7063,8 +7638,8 @@ var import_path5 = __toESM(require("path"));
7063
7638
  var import_normalize_path = __toESM(require("normalize-path"));
7064
7639
  var FilesystemBridge = class {
7065
7640
  constructor(rootPath, outputPath) {
7066
- this.rootPath = rootPath || "";
7067
- this.outputPath = outputPath || rootPath;
7641
+ this.rootPath = import_path5.default.resolve(rootPath);
7642
+ this.outputPath = outputPath ? import_path5.default.resolve(outputPath) : this.rootPath;
7068
7643
  }
7069
7644
  async glob(pattern, extension) {
7070
7645
  const basePath = import_path5.default.join(this.outputPath, ...pattern.split("/"));
@@ -7076,19 +7651,19 @@ var FilesystemBridge = class {
7076
7651
  }
7077
7652
  );
7078
7653
  const posixRootPath = (0, import_normalize_path.default)(this.outputPath);
7079
- return items.map((item) => {
7080
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
7081
- });
7654
+ return items.map(
7655
+ (item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
7656
+ );
7082
7657
  }
7083
7658
  async delete(filepath) {
7084
7659
  await import_fs_extra2.default.remove(import_path5.default.join(this.outputPath, filepath));
7085
7660
  }
7086
7661
  async get(filepath) {
7087
- return import_fs_extra2.default.readFileSync(import_path5.default.join(this.outputPath, filepath)).toString();
7662
+ return (await import_fs_extra2.default.readFile(import_path5.default.join(this.outputPath, filepath))).toString();
7088
7663
  }
7089
7664
  async put(filepath, data, basePathOverride) {
7090
7665
  const basePath = basePathOverride || this.outputPath;
7091
- await import_fs_extra2.default.outputFileSync(import_path5.default.join(basePath, filepath), data);
7666
+ await import_fs_extra2.default.outputFile(import_path5.default.join(basePath, filepath), data);
7092
7667
  }
7093
7668
  };
7094
7669
  var AuditFileSystemBridge = class extends FilesystemBridge {
@@ -7158,17 +7733,26 @@ var IsomorphicBridge = class {
7158
7733
  getAuthor() {
7159
7734
  return {
7160
7735
  ...this.author,
7161
- timestamp: Math.round(new Date().getTime() / 1e3),
7736
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7162
7737
  timezoneOffset: 0
7163
7738
  };
7164
7739
  }
7165
7740
  getCommitter() {
7166
7741
  return {
7167
7742
  ...this.committer,
7168
- timestamp: Math.round(new Date().getTime() / 1e3),
7743
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7169
7744
  timezoneOffset: 0
7170
7745
  };
7171
7746
  }
7747
+ /**
7748
+ * Recursively populate paths matching `pattern` for the given `entry`
7749
+ *
7750
+ * @param pattern - pattern to filter paths by
7751
+ * @param entry - TreeEntry to start building list from
7752
+ * @param path - base path
7753
+ * @param results
7754
+ * @private
7755
+ */
7172
7756
  async listEntries({
7173
7757
  pattern,
7174
7758
  entry,
@@ -7201,6 +7785,15 @@ var IsomorphicBridge = class {
7201
7785
  });
7202
7786
  }
7203
7787
  }
7788
+ /**
7789
+ * For the specified path, returns an object with an array containing the parts of the path (pathParts)
7790
+ * and an array containing the WalkerEntry objects for the path parts (pathEntries). Any null elements in the
7791
+ * pathEntries are placeholders for non-existent entries.
7792
+ *
7793
+ * @param path - path being resolved
7794
+ * @param ref - ref to resolve path entries for
7795
+ * @private
7796
+ */
7204
7797
  async resolvePathEntries(path7, ref) {
7205
7798
  let pathParts = path7.split("/");
7206
7799
  const result = await import_isomorphic_git2.default.walk({
@@ -7231,6 +7824,17 @@ var IsomorphicBridge = class {
7231
7824
  }
7232
7825
  return { pathParts, pathEntries };
7233
7826
  }
7827
+ /**
7828
+ * Updates tree entry and associated parent tree entries
7829
+ *
7830
+ * @param existingOid - the existing OID
7831
+ * @param updatedOid - the updated OID
7832
+ * @param path - the path of the entry being updated
7833
+ * @param type - the type of the entry being updated (blob or tree)
7834
+ * @param pathEntries - parent path entries
7835
+ * @param pathParts - parent path parts
7836
+ * @private
7837
+ */
7234
7838
  async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
7235
7839
  const lastIdx = pathEntries.length - 1;
7236
7840
  const parentEntry = pathEntries[lastIdx];
@@ -7286,6 +7890,13 @@ var IsomorphicBridge = class {
7286
7890
  );
7287
7891
  }
7288
7892
  }
7893
+ /**
7894
+ * Creates a commit for the specified tree and updates the specified ref to point to the commit
7895
+ *
7896
+ * @param treeSha - sha of the new tree
7897
+ * @param ref - the ref that should be updated
7898
+ * @private
7899
+ */
7289
7900
  async commitTree(treeSha, ref) {
7290
7901
  const commitSha = await import_isomorphic_git2.default.writeCommit({
7291
7902
  ...this.isomorphicConfig,
@@ -7298,6 +7909,7 @@ var IsomorphicBridge = class {
7298
7909
  })
7299
7910
  ],
7300
7911
  message: this.commitMessage,
7912
+ // TODO these should be configurable
7301
7913
  author: this.getAuthor(),
7302
7914
  committer: this.getCommitter()
7303
7915
  }
@@ -7536,5 +8148,5 @@ var buildSchema = async (config, flags) => {
7536
8148
  transformDocument,
7537
8149
  transformDocumentIntoPayload
7538
8150
  });
7539
- //! Replaces _.flattenDeep()
7540
8151
  //! Replaces _.get()
8152
+ //! Replaces _.flattenDeep()