@tinacms/graphql 0.0.0-d69e892-20241003042309 → 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: {
@@ -148,6 +161,15 @@ var SysFieldDefinition = {
148
161
  arguments: [],
149
162
  directives: []
150
163
  },
164
+ {
165
+ kind: "Field",
166
+ name: {
167
+ kind: "Name",
168
+ value: "hasReferences"
169
+ },
170
+ arguments: [],
171
+ directives: []
172
+ },
151
173
  {
152
174
  kind: "Field",
153
175
  name: {
@@ -188,6 +210,10 @@ var SysFieldDefinition = {
188
210
  }
189
211
  };
190
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
+ */
191
217
  FormFieldBuilder: ({
192
218
  name,
193
219
  additionalFields
@@ -411,6 +437,8 @@ var astBuilder = {
411
437
  kind: "Name",
412
438
  value: name
413
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
414
442
  fields
415
443
  }),
416
444
  UnionTypeDefinition: ({
@@ -423,6 +451,8 @@ var astBuilder = {
423
451
  value: name
424
452
  },
425
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
426
456
  types: types.map((name2) => ({
427
457
  kind: "NamedType",
428
458
  name: {
@@ -519,8 +549,11 @@ var astBuilder = {
519
549
  string: "String",
520
550
  boolean: "Boolean",
521
551
  number: "Float",
552
+ // FIXME - needs to be float or int
522
553
  datetime: "String",
554
+ // FIXME
523
555
  image: "String",
556
+ // FIXME
524
557
  text: "String"
525
558
  };
526
559
  return scalars[type];
@@ -1019,8 +1052,7 @@ var astBuilder = {
1019
1052
  }
1020
1053
  };
1021
1054
  var capitalize = (s) => {
1022
- if (typeof s !== "string")
1023
- return "";
1055
+ if (typeof s !== "string") return "";
1024
1056
  return s.charAt(0).toUpperCase() + s.slice(1);
1025
1057
  };
1026
1058
  var extractInlineTypes = (item) => {
@@ -1063,41 +1095,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1063
1095
  yield maybeNode;
1064
1096
  visited.add(maybeNode);
1065
1097
  }
1066
- function addNamespaceToSchema(maybeNode, namespace = []) {
1067
- if (typeof maybeNode === "string") {
1068
- return maybeNode;
1069
- }
1070
- if (typeof maybeNode === "boolean") {
1071
- return maybeNode;
1072
- }
1073
- const newNode = maybeNode;
1074
- const keys = Object.keys(maybeNode);
1075
- Object.values(maybeNode).map((m, index) => {
1076
- const key = keys[index];
1077
- if (Array.isArray(m)) {
1078
- newNode[key] = m.map((element) => {
1079
- if (!element) {
1080
- return;
1081
- }
1082
- if (!element.hasOwnProperty("name")) {
1083
- return element;
1084
- }
1085
- const value = element.name || element.value;
1086
- return addNamespaceToSchema(element, [...namespace, value]);
1087
- });
1088
- } else {
1089
- if (!m) {
1090
- return;
1091
- }
1092
- if (!m.hasOwnProperty("name")) {
1093
- newNode[key] = m;
1094
- } else {
1095
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1096
- }
1097
- }
1098
- });
1099
- return { ...newNode, namespace };
1100
- }
1101
1098
  var generateNamespacedFieldName = (names, suffix = "") => {
1102
1099
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1103
1100
  };
@@ -1257,6 +1254,11 @@ var scalarDefinitions = [
1257
1254
  required: true,
1258
1255
  type: astBuilder.TYPES.String
1259
1256
  }),
1257
+ astBuilder.FieldDefinition({
1258
+ name: "hasReferences",
1259
+ required: false,
1260
+ type: astBuilder.TYPES.Boolean
1261
+ }),
1260
1262
  astBuilder.FieldDefinition({
1261
1263
  name: "breadcrumbs",
1262
1264
  required: true,
@@ -1433,13 +1435,12 @@ var checkPasswordHash = async ({
1433
1435
  return true;
1434
1436
  };
1435
1437
  var mapUserFields = (collectable, prefix = []) => {
1436
- var _a, _b, _c, _d, _e;
1437
1438
  const results = [];
1438
- const passwordFields = ((_a = collectable.fields) == null ? void 0 : _a.filter((field) => field.type === "password")) || [];
1439
+ const passwordFields = collectable.fields?.filter((field) => field.type === "password") || [];
1439
1440
  if (passwordFields.length > 1) {
1440
1441
  throw new Error("Only one password field is allowed");
1441
1442
  }
1442
- const idFields = ((_b = collectable.fields) == null ? void 0 : _b.filter((field) => field.uid)) || [];
1443
+ const idFields = collectable.fields?.filter((field) => field.uid) || [];
1443
1444
  if (idFields.length > 1) {
1444
1445
  throw new Error("Only one uid field is allowed");
1445
1446
  }
@@ -1447,11 +1448,11 @@ var mapUserFields = (collectable, prefix = []) => {
1447
1448
  results.push({
1448
1449
  path: prefix,
1449
1450
  collectable,
1450
- idFieldName: (_c = idFields[0]) == null ? void 0 : _c.name,
1451
- passwordFieldName: (_d = passwordFields[0]) == null ? void 0 : _d.name
1451
+ idFieldName: idFields[0]?.name,
1452
+ passwordFieldName: passwordFields[0]?.name
1452
1453
  });
1453
1454
  }
1454
- (_e = collectable.fields) == null ? void 0 : _e.forEach((field) => {
1455
+ collectable.fields?.forEach((field) => {
1455
1456
  if (field.type === "object" && field.fields) {
1456
1457
  results.push(...mapUserFields(field, [...prefix, field.name]));
1457
1458
  }
@@ -1471,6 +1472,19 @@ var Builder = class {
1471
1472
  this.addToLookupMap = (lookup) => {
1472
1473
  this.lookupMap[lookup.type] = lookup;
1473
1474
  };
1475
+ /**
1476
+ * ```graphql
1477
+ * # ex.
1478
+ * {
1479
+ * getCollection(collection: $collection) {
1480
+ * name
1481
+ * documents {...}
1482
+ * }
1483
+ * }
1484
+ * ```
1485
+ *
1486
+ * @param collections
1487
+ */
1474
1488
  this.buildCollectionDefinition = async (collections) => {
1475
1489
  const name = "collection";
1476
1490
  const typeName = "Collection";
@@ -1541,6 +1555,19 @@ var Builder = class {
1541
1555
  required: true
1542
1556
  });
1543
1557
  };
1558
+ /**
1559
+ * ```graphql
1560
+ * # ex.
1561
+ * {
1562
+ * getCollections {
1563
+ * name
1564
+ * documents {...}
1565
+ * }
1566
+ * }
1567
+ * ```
1568
+ *
1569
+ * @param collections
1570
+ */
1544
1571
  this.buildMultiCollectionDefinition = async (collections) => {
1545
1572
  const name = "collections";
1546
1573
  const typeName = "Collection";
@@ -1551,6 +1578,17 @@ var Builder = class {
1551
1578
  required: true
1552
1579
  });
1553
1580
  };
1581
+ /**
1582
+ * ```graphql
1583
+ * # ex.
1584
+ * {
1585
+ * node(id: $id) {
1586
+ * id
1587
+ * data {...}
1588
+ * }
1589
+ * }
1590
+ * ```
1591
+ */
1554
1592
  this.multiNodeDocument = async () => {
1555
1593
  const name = "node";
1556
1594
  const args = [
@@ -1571,6 +1609,19 @@ var Builder = class {
1571
1609
  required: true
1572
1610
  });
1573
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
+ */
1574
1625
  this.multiCollectionDocument = async (collections) => {
1575
1626
  const name = "document";
1576
1627
  const args = [
@@ -1596,6 +1647,19 @@ var Builder = class {
1596
1647
  required: true
1597
1648
  });
1598
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
+ */
1599
1663
  this.addMultiCollectionDocumentMutation = async () => {
1600
1664
  return astBuilder.FieldDefinition({
1601
1665
  name: "addPendingDocument",
@@ -1620,6 +1684,19 @@ var Builder = class {
1620
1684
  type: astBuilder.TYPES.MultiCollectionDocument
1621
1685
  });
1622
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
+ */
1623
1700
  this.buildCreateCollectionDocumentMutation = async (collections) => {
1624
1701
  return astBuilder.FieldDefinition({
1625
1702
  name: "createDocument",
@@ -1647,6 +1724,19 @@ var Builder = class {
1647
1724
  type: astBuilder.TYPES.MultiCollectionDocument
1648
1725
  });
1649
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
+ */
1650
1740
  this.buildUpdateCollectionDocumentMutation = async (collections) => {
1651
1741
  return astBuilder.FieldDefinition({
1652
1742
  name: "updateDocument",
@@ -1674,6 +1764,19 @@ var Builder = class {
1674
1764
  type: astBuilder.TYPES.MultiCollectionDocument
1675
1765
  });
1676
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
+ */
1677
1780
  this.buildDeleteCollectionDocumentMutation = async (collections) => {
1678
1781
  return astBuilder.FieldDefinition({
1679
1782
  name: "deleteDocument",
@@ -1693,6 +1796,19 @@ var Builder = class {
1693
1796
  type: astBuilder.TYPES.MultiCollectionDocument
1694
1797
  });
1695
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
+ */
1696
1812
  this.buildCreateCollectionFolderMutation = async () => {
1697
1813
  return astBuilder.FieldDefinition({
1698
1814
  name: "createFolder",
@@ -1712,6 +1828,19 @@ var Builder = class {
1712
1828
  type: astBuilder.TYPES.MultiCollectionDocument
1713
1829
  });
1714
1830
  };
1831
+ /**
1832
+ * ```graphql
1833
+ * # ex.
1834
+ * {
1835
+ * getPostDocument(relativePath: $relativePath) {
1836
+ * id
1837
+ * data {...}
1838
+ * }
1839
+ * }
1840
+ * ```
1841
+ *
1842
+ * @param collection
1843
+ */
1715
1844
  this.collectionDocument = async (collection) => {
1716
1845
  const name = NAMER.queryName([collection.name]);
1717
1846
  const type = await this._buildCollectionDocumentType(collection);
@@ -1772,6 +1901,20 @@ var Builder = class {
1772
1901
  const args = [];
1773
1902
  return astBuilder.FieldDefinition({ type, name, args, required: false });
1774
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
+ */
1775
1918
  this.collectionFragment = async (collection) => {
1776
1919
  const name = NAMER.dataTypeName(collection.namespace);
1777
1920
  const fragmentName = NAMER.fragmentName(collection.namespace);
@@ -1785,14 +1928,27 @@ var Builder = class {
1785
1928
  selections: filterSelections(selections)
1786
1929
  });
1787
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
+ * */
1788
1945
  this._getCollectionFragmentSelections = async (collection, depth) => {
1789
- var _a;
1790
1946
  const selections = [];
1791
1947
  selections.push({
1792
1948
  name: { kind: "Name", value: "__typename" },
1793
1949
  kind: "Field"
1794
1950
  });
1795
- if (((_a = collection.fields) == null ? void 0 : _a.length) > 0) {
1951
+ if (collection.fields?.length > 0) {
1796
1952
  await sequential(collection.fields, async (x) => {
1797
1953
  const field = await this._buildFieldNodeForFragments(x, depth);
1798
1954
  selections.push(field);
@@ -1807,7 +1963,6 @@ var Builder = class {
1807
1963
  return selections;
1808
1964
  };
1809
1965
  this._buildFieldNodeForFragments = async (field, depth) => {
1810
- var _a, _b;
1811
1966
  switch (field.type) {
1812
1967
  case "string":
1813
1968
  case "image":
@@ -1840,7 +1995,7 @@ var Builder = class {
1840
1995
  selections: filterSelections([passwordValue, passwordChangeRequired])
1841
1996
  });
1842
1997
  case "object":
1843
- if (((_a = field.fields) == null ? void 0 : _a.length) > 0) {
1998
+ if (field.fields?.length > 0) {
1844
1999
  const selections2 = [];
1845
2000
  await sequential(field.fields, async (item) => {
1846
2001
  const field2 = await this._buildFieldNodeForFragments(item, depth);
@@ -1853,7 +2008,7 @@ var Builder = class {
1853
2008
  ...filterSelections(selections2)
1854
2009
  ]
1855
2010
  });
1856
- } else if (((_b = field.templates) == null ? void 0 : _b.length) > 0) {
2011
+ } else if (field.templates?.length > 0) {
1857
2012
  const selections2 = [];
1858
2013
  await sequential(field.templates, async (tem) => {
1859
2014
  if (typeof tem === "object") {
@@ -1868,9 +2023,9 @@ var Builder = class {
1868
2023
  ]
1869
2024
  });
1870
2025
  }
2026
+ // TODO: Should we throw here?
1871
2027
  case "reference":
1872
- if (depth >= this.maxDepth)
1873
- return false;
2028
+ if (depth >= this.maxDepth) return false;
1874
2029
  if (!("collections" in field)) {
1875
2030
  return false;
1876
2031
  }
@@ -1902,6 +2057,7 @@ var Builder = class {
1902
2057
  name: field.name,
1903
2058
  selections: [
1904
2059
  ...selections,
2060
+ // This is ... on Document { id }
1905
2061
  {
1906
2062
  kind: "InlineFragment",
1907
2063
  typeCondition: {
@@ -1932,6 +2088,19 @@ var Builder = class {
1932
2088
  });
1933
2089
  }
1934
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
+ */
1935
2104
  this.updateCollectionDocumentMutation = async (collection) => {
1936
2105
  return astBuilder.FieldDefinition({
1937
2106
  type: await this._buildCollectionDocumentType(collection),
@@ -1951,6 +2120,19 @@ var Builder = class {
1951
2120
  ]
1952
2121
  });
1953
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
+ */
1954
2136
  this.createCollectionDocumentMutation = async (collection) => {
1955
2137
  return astBuilder.FieldDefinition({
1956
2138
  type: await this._buildCollectionDocumentType(collection),
@@ -1970,6 +2152,22 @@ var Builder = class {
1970
2152
  ]
1971
2153
  });
1972
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
+ */
1973
2171
  this.collectionDocumentList = async (collection) => {
1974
2172
  const connectionName = NAMER.referenceConnectionType(collection.namespace);
1975
2173
  this.addToLookupMap({
@@ -1985,6 +2183,10 @@ var Builder = class {
1985
2183
  collection
1986
2184
  });
1987
2185
  };
2186
+ /**
2187
+ * GraphQL type definitions which remain unchanged regardless
2188
+ * of the supplied Tina schema. Ex. "node" interface
2189
+ */
1988
2190
  this.buildStaticDefinitions = () => staticDefinitions;
1989
2191
  this._buildCollectionDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
1990
2192
  const documentTypeName = NAMER.documentTypeName(collection.namespace);
@@ -2468,7 +2670,7 @@ var Builder = class {
2468
2670
  this.addToLookupMap({
2469
2671
  type: name,
2470
2672
  resolveType: "unionData",
2471
- collection: collection == null ? void 0 : collection.name,
2673
+ collection: collection?.name,
2472
2674
  typeMap
2473
2675
  });
2474
2676
  return astBuilder.UnionTypeDefinition({ name, types });
@@ -2489,6 +2691,7 @@ var Builder = class {
2489
2691
  name: NAMER.dataFilterTypeName(namespace),
2490
2692
  fields: await sequential(collections, async (collection2) => {
2491
2693
  return astBuilder.InputValueDefinition({
2694
+ // @ts-ignore
2492
2695
  name: collection2.name,
2493
2696
  type: NAMER.dataFilterTypeName(collection2.namespace)
2494
2697
  });
@@ -2677,8 +2880,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2677
2880
  ]
2678
2881
  });
2679
2882
  };
2680
- var _a, _b, _c, _d;
2681
- 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;
2682
2885
  this.tinaSchema = config.tinaSchema;
2683
2886
  this.lookupMap = {};
2684
2887
  }
@@ -2689,8 +2892,7 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2689
2892
  selections.push(field);
2690
2893
  });
2691
2894
  const filteredSelections = filterSelections(selections);
2692
- if (!filteredSelections.length)
2693
- return false;
2895
+ if (!filteredSelections.length) return false;
2694
2896
  return astBuilder.InlineFragmentDefinition({
2695
2897
  selections: filteredSelections,
2696
2898
  name: NAMER.dataTypeName(template.namespace)
@@ -2724,12 +2926,13 @@ var filterSelections = (arr) => {
2724
2926
  };
2725
2927
 
2726
2928
  // src/schema/createSchema.ts
2727
- var import_schema_tools2 = require("@tinacms/schema-tools");
2929
+ var import_schema_tools3 = require("@tinacms/schema-tools");
2728
2930
 
2729
2931
  // src/schema/validate.ts
2932
+ var import_schema_tools = require("@tinacms/schema-tools");
2730
2933
  var import_lodash2 = __toESM(require("lodash.clonedeep"));
2731
2934
  var yup2 = __toESM(require("yup"));
2732
- var import_schema_tools = require("@tinacms/schema-tools");
2935
+ var import_schema_tools2 = require("@tinacms/schema-tools");
2733
2936
  var FIELD_TYPES = [
2734
2937
  "string",
2735
2938
  "number",
@@ -2742,7 +2945,7 @@ var FIELD_TYPES = [
2742
2945
  "password"
2743
2946
  ];
2744
2947
  var validateSchema = async (schema) => {
2745
- const schema2 = addNamespaceToSchema(
2948
+ const schema2 = (0, import_schema_tools.addNamespaceToSchema)(
2746
2949
  (0, import_lodash2.default)(schema)
2747
2950
  );
2748
2951
  const collections = await sequential(
@@ -2751,7 +2954,7 @@ var validateSchema = async (schema) => {
2751
2954
  );
2752
2955
  validationCollectionsPathAndMatch(collections);
2753
2956
  if (schema2.config) {
2754
- const config = (0, import_schema_tools.validateTinaCloudSchemaConfig)(schema2.config);
2957
+ const config = (0, import_schema_tools2.validateTinaCloudSchemaConfig)(schema2.config);
2755
2958
  return {
2756
2959
  collections,
2757
2960
  config
@@ -2767,20 +2970,18 @@ var validationCollectionsPathAndMatch = (collections) => {
2767
2970
  return;
2768
2971
  }
2769
2972
  const noMatchCollections = collections.filter((x) => {
2770
- return typeof (x == null ? void 0 : x.match) === "undefined";
2973
+ return typeof x?.match === "undefined";
2771
2974
  }).map((x) => `${x.path}${x.format || "md"}`);
2772
2975
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2773
2976
  throw new Error(
2977
+ // TODO: add a link to the docs
2774
2978
  "Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
2775
2979
  );
2776
2980
  }
2777
2981
  const hasMatchAndPath = collections.filter((x) => {
2778
2982
  return typeof x.path !== "undefined" && typeof x.match !== "undefined";
2779
2983
  }).map(
2780
- (x) => {
2781
- var _a, _b;
2782
- 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"}`;
2783
- }
2984
+ (x) => `${x.path}|${x?.match?.exclude || ""}|${x?.match?.include || ""}|${x.format || "md"}`
2784
2985
  );
2785
2986
  if (hasMatchAndPath.length !== new Set(hasMatchAndPath).size) {
2786
2987
  throw new Error(
@@ -2804,7 +3005,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2804
3005
  );
2805
3006
  }
2806
3007
  const matches = collectionsArr.map(
2807
- (x) => typeof (x == null ? void 0 : x.match) === "object" ? JSON.stringify(x.match) : ""
3008
+ (x) => typeof x?.match === "object" ? JSON.stringify(x.match) : ""
2808
3009
  );
2809
3010
  if (matches.length === new Set(matches).size) {
2810
3011
  return;
@@ -2882,7 +3083,7 @@ var validateField = async (field) => {
2882
3083
  // package.json
2883
3084
  var package_default = {
2884
3085
  name: "@tinacms/graphql",
2885
- version: "1.5.4",
3086
+ version: "1.5.17",
2886
3087
  main: "dist/index.js",
2887
3088
  module: "dist/index.mjs",
2888
3089
  typings: "dist/index.d.ts",
@@ -2908,9 +3109,8 @@ var package_default = {
2908
3109
  types: "pnpm tsc",
2909
3110
  build: "tinacms-scripts build",
2910
3111
  docs: "pnpm typedoc",
2911
- serve: "pnpm nodemon dist/server.js",
2912
- test: "jest",
2913
- "test-watch": "jest --watch"
3112
+ test: "vitest run",
3113
+ "test-watch": "vitest"
2914
3114
  },
2915
3115
  dependencies: {
2916
3116
  "@iarna/toml": "^2.2.5",
@@ -2918,22 +3118,22 @@ var package_default = {
2918
3118
  "@tinacms/schema-tools": "workspace:*",
2919
3119
  "abstract-level": "^1.0.4",
2920
3120
  "date-fns": "^2.30.0",
2921
- "fast-glob": "^3.3.2",
2922
- "fs-extra": "^11.2.0",
3121
+ "fast-glob": "^3.3.3",
3122
+ "fs-extra": "^11.3.0",
2923
3123
  "glob-parent": "^6.0.2",
2924
3124
  graphql: "15.8.0",
2925
3125
  "gray-matter": "^4.0.3",
2926
- "isomorphic-git": "^1.27.1",
3126
+ "isomorphic-git": "^1.29.0",
2927
3127
  "js-sha1": "^0.6.0",
2928
3128
  "js-yaml": "^3.14.1",
2929
- "jsonpath-plus": "^6.0.1",
3129
+ "jsonpath-plus": "10.1.0",
2930
3130
  "lodash.clonedeep": "^4.5.0",
2931
3131
  "lodash.set": "^4.3.2",
2932
3132
  "lodash.uniqby": "^4.7.0",
2933
3133
  "many-level": "^2.0.0",
2934
3134
  micromatch: "4.0.8",
2935
3135
  "normalize-path": "^3.0.0",
2936
- "readable-stream": "^4.5.2",
3136
+ "readable-stream": "^4.7.0",
2937
3137
  scmp: "^2.1.0",
2938
3138
  yup: "^0.32.11"
2939
3139
  },
@@ -2951,24 +3151,22 @@ var package_default = {
2951
3151
  "@types/estree": "^0.0.50",
2952
3152
  "@types/express": "^4.17.21",
2953
3153
  "@types/fs-extra": "^9.0.13",
2954
- "@types/jest": "^26.0.24",
2955
3154
  "@types/js-yaml": "^3.12.10",
2956
3155
  "@types/lodash.camelcase": "^4.3.9",
2957
3156
  "@types/lodash.upperfirst": "^4.3.9",
2958
3157
  "@types/lru-cache": "^5.1.1",
2959
3158
  "@types/mdast": "^3.0.15",
2960
3159
  "@types/micromatch": "^4.0.9",
2961
- "@types/node": "^22.7.4",
3160
+ "@types/node": "^22.13.1",
2962
3161
  "@types/normalize-path": "^3.0.2",
2963
3162
  "@types/ws": "^7.4.7",
2964
3163
  "@types/yup": "^0.29.14",
2965
- jest: "^29.7.0",
2966
- "jest-diff": "^29.7.0",
2967
3164
  "jest-file-snapshot": "^0.5.0",
2968
- "jest-matcher-utils": "^29.7.0",
2969
3165
  "memory-level": "^1.0.0",
2970
- nodemon: "3.1.4",
2971
- typescript: "^5.6.2"
3166
+ typescript: "^5.7.3",
3167
+ vite: "^4.5.9",
3168
+ vitest: "^0.32.4",
3169
+ zod: "^3.24.2"
2972
3170
  }
2973
3171
  };
2974
3172
 
@@ -2983,7 +3181,7 @@ var createSchema = async ({
2983
3181
  if (flags && flags.length > 0) {
2984
3182
  meta["flags"] = flags;
2985
3183
  }
2986
- return new import_schema_tools2.TinaSchema({
3184
+ return new import_schema_tools3.TinaSchema({
2987
3185
  version: {
2988
3186
  fullVersion: package_default.version,
2989
3187
  major,
@@ -3039,6 +3237,7 @@ var _buildFragments = async (builder, tinaSchema) => {
3039
3237
  const fragDoc = {
3040
3238
  kind: "Document",
3041
3239
  definitions: (0, import_lodash3.default)(
3240
+ // @ts-ignore
3042
3241
  extractInlineTypes(fragmentDefinitionsFields),
3043
3242
  (node) => node.name.value
3044
3243
  )
@@ -3049,7 +3248,6 @@ var _buildQueries = async (builder, tinaSchema) => {
3049
3248
  const operationsDefinitions = [];
3050
3249
  const collections = tinaSchema.getCollections();
3051
3250
  await sequential(collections, async (collection) => {
3052
- var _a, _b, _c;
3053
3251
  const queryName = NAMER.queryName(collection.namespace);
3054
3252
  const queryListName = NAMER.generateQueryListName(collection.namespace);
3055
3253
  const queryFilterTypeName = NAMER.dataFilterTypeName(collection.namespace);
@@ -3062,8 +3260,9 @@ var _buildQueries = async (builder, tinaSchema) => {
3062
3260
  fragName,
3063
3261
  queryName: queryListName,
3064
3262
  filterType: queryFilterTypeName,
3263
+ // look for flag to see if the data layer is enabled
3065
3264
  dataLayer: Boolean(
3066
- (_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")
3067
3266
  )
3068
3267
  })
3069
3268
  );
@@ -3071,6 +3270,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3071
3270
  const queryDoc = {
3072
3271
  kind: "Document",
3073
3272
  definitions: (0, import_lodash3.default)(
3273
+ // @ts-ignore
3074
3274
  extractInlineTypes(operationsDefinitions),
3075
3275
  (node) => node.name.value
3076
3276
  )
@@ -3122,7 +3322,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3122
3322
  await builder.buildCreateCollectionFolderMutation()
3123
3323
  );
3124
3324
  await sequential(collections, async (collection) => {
3125
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3325
+ queryTypeDefinitionFields.push(
3326
+ await builder.collectionDocument(collection)
3327
+ );
3126
3328
  if (collection.isAuthCollection) {
3127
3329
  queryTypeDefinitionFields.push(
3128
3330
  await builder.authenticationCollectionDocument(collection)
@@ -3159,6 +3361,7 @@ var _buildSchema = async (builder, tinaSchema) => {
3159
3361
  return {
3160
3362
  kind: "Document",
3161
3363
  definitions: (0, import_lodash3.default)(
3364
+ // @ts-ignore
3162
3365
  extractInlineTypes(definitions),
3163
3366
  (node) => node.name.value
3164
3367
  )
@@ -3175,6 +3378,9 @@ var import_isValid = __toESM(require("date-fns/isValid/index.js"));
3175
3378
  // src/mdx/index.ts
3176
3379
  var import_mdx = require("@tinacms/mdx");
3177
3380
 
3381
+ // src/resolver/index.ts
3382
+ var import_jsonpath_plus2 = require("jsonpath-plus");
3383
+
3178
3384
  // src/resolver/error.ts
3179
3385
  var TinaGraphQLError = class extends Error {
3180
3386
  constructor(message, extensions) {
@@ -3360,8 +3566,7 @@ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, s
3360
3566
  }
3361
3567
  if (Array.isArray(value)) {
3362
3568
  return value.map((v) => {
3363
- if (!v || typeof v !== "string")
3364
- return v;
3569
+ if (!v || typeof v !== "string") return v;
3365
3570
  const cleanMediaRoot = cleanUpSlashes(
3366
3571
  schema.config.media.tina.mediaRoot
3367
3572
  );
@@ -3389,8 +3594,7 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
3389
3594
  }
3390
3595
  if (Array.isArray(value)) {
3391
3596
  return value.map((v) => {
3392
- if (!v || typeof v !== "string")
3393
- return v;
3597
+ if (!v || typeof v !== "string") return v;
3394
3598
  const strippedValue = v.replace(cleanMediaRoot, "");
3395
3599
  return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3396
3600
  });
@@ -3408,10 +3612,8 @@ var cleanUpSlashes = (path7) => {
3408
3612
  return "";
3409
3613
  };
3410
3614
  var hasTinaMediaConfig = (schema) => {
3411
- var _a, _b, _c, _d, _e, _f, _g, _h;
3412
- if (!((_b = (_a = schema.config) == null ? void 0 : _a.media) == null ? void 0 : _b.tina))
3413
- return false;
3414
- 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")
3415
3617
  return false;
3416
3618
  return true;
3417
3619
  };
@@ -3437,7 +3639,9 @@ var LevelProxyHandler = {
3437
3639
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3438
3640
  }
3439
3641
  if (typeof target[property] !== "function") {
3440
- 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
+ );
3441
3645
  }
3442
3646
  if (property === "get") {
3443
3647
  return async (...args) => {
@@ -3454,6 +3658,7 @@ var LevelProxyHandler = {
3454
3658
  } else if (property === "sublevel") {
3455
3659
  return (...args) => {
3456
3660
  return new Proxy(
3661
+ // eslint-disable-next-line prefer-spread
3457
3662
  target[property].apply(target, args),
3458
3663
  LevelProxyHandler
3459
3664
  );
@@ -3476,7 +3681,7 @@ var import_path2 = __toESM(require("path"));
3476
3681
  var import_toml = __toESM(require("@iarna/toml"));
3477
3682
  var import_js_yaml = __toESM(require("js-yaml"));
3478
3683
  var import_gray_matter = __toESM(require("gray-matter"));
3479
- var import_schema_tools3 = require("@tinacms/schema-tools");
3684
+ var import_schema_tools4 = require("@tinacms/schema-tools");
3480
3685
  var import_micromatch = __toESM(require("micromatch"));
3481
3686
  var import_path = __toESM(require("path"));
3482
3687
 
@@ -3515,22 +3720,20 @@ var replaceNameOverrides = (template, obj) => {
3515
3720
  }
3516
3721
  };
3517
3722
  function isBlockField(field) {
3518
- var _a;
3519
- return field && field.type === "object" && ((_a = field.templates) == null ? void 0 : _a.length) > 0;
3723
+ return field && field.type === "object" && field.templates?.length > 0;
3520
3724
  }
3521
3725
  var _replaceNameOverrides = (fields, obj) => {
3522
3726
  const output = {};
3523
3727
  Object.keys(obj).forEach((key) => {
3524
3728
  const field = fields.find(
3525
- (fieldWithMatchingAlias) => ((fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.nameOverride) || (fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.name)) === key
3729
+ (fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
3526
3730
  );
3527
- 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];
3528
3732
  });
3529
3733
  return output;
3530
3734
  };
3531
3735
  var getTemplateForData = (field, data) => {
3532
- var _a;
3533
- if ((_a = field.templates) == null ? void 0 : _a.length) {
3736
+ if (field.templates?.length) {
3534
3737
  const templateKey = "_template";
3535
3738
  if (data[templateKey]) {
3536
3739
  const result = field.templates.find(
@@ -3588,8 +3791,8 @@ var _applyNameOverrides = (fields, obj) => {
3588
3791
  const output = {};
3589
3792
  Object.keys(obj).forEach((key) => {
3590
3793
  const field = fields.find((field2) => field2.name === key);
3591
- const outputKey = (field == null ? void 0 : field.nameOverride) || key;
3592
- 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];
3593
3796
  });
3594
3797
  return output;
3595
3798
  };
@@ -3602,7 +3805,6 @@ var matterEngines = {
3602
3805
  }
3603
3806
  };
3604
3807
  var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3605
- var _a, _b;
3606
3808
  const {
3607
3809
  _relativePath,
3608
3810
  _keepTemplateKey,
@@ -3626,9 +3828,9 @@ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3626
3828
  ${$_body}`,
3627
3829
  strippedContent,
3628
3830
  {
3629
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3831
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3630
3832
  engines: matterEngines,
3631
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
3833
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
3632
3834
  }
3633
3835
  );
3634
3836
  return ok;
@@ -3644,15 +3846,14 @@ ${$_body}`,
3644
3846
  }
3645
3847
  };
3646
3848
  var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3647
- var _a, _b;
3648
3849
  try {
3649
3850
  switch (format) {
3650
3851
  case ".markdown":
3651
3852
  case ".mdx":
3652
3853
  case ".md":
3653
3854
  const contentJSON = (0, import_gray_matter.default)(content || "", {
3654
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3655
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---",
3855
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3856
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
3656
3857
  engines: matterEngines
3657
3858
  });
3658
3859
  const markdownData = {
@@ -3689,7 +3890,7 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3689
3890
  const filesSeen = /* @__PURE__ */ new Map();
3690
3891
  const duplicateFiles = /* @__PURE__ */ new Set();
3691
3892
  await sequential(tinaSchema.getCollections(), async (collection) => {
3692
- const normalPath = (0, import_schema_tools3.normalizePath)(collection.path);
3893
+ const normalPath = (0, import_schema_tools4.normalizePath)(collection.path);
3693
3894
  const format = collection.format || "md";
3694
3895
  const documentPaths = await bridge.glob(normalPath, format);
3695
3896
  const matches = tinaSchema.getMatches({ collection });
@@ -3751,7 +3952,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3751
3952
  ),
3752
3953
  template: void 0
3753
3954
  } : tinaSchema.getCollectionAndTemplateByFullPath(filepath, templateName);
3754
- const field = template == null ? void 0 : template.fields.find((field2) => {
3955
+ const field = template?.fields.find((field2) => {
3755
3956
  if (field2.type === "string" || field2.type === "rich-text") {
3756
3957
  if (field2.isBody) {
3757
3958
  return true;
@@ -3771,7 +3972,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3771
3972
  ...data,
3772
3973
  _collection: collection.name,
3773
3974
  _keepTemplateKey: !!collection.templates,
3774
- _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,
3775
3976
  _relativePath: filepath.replace(collection.path, "").replace(/^\/|\/$/g, ""),
3776
3977
  _id: filepath
3777
3978
  };
@@ -3780,10 +3981,10 @@ function hasOwnProperty(obj, prop) {
3780
3981
  return obj.hasOwnProperty(prop);
3781
3982
  }
3782
3983
  var getTemplateForFile = (templateInfo, data) => {
3783
- if ((templateInfo == null ? void 0 : templateInfo.type) === "object") {
3984
+ if (templateInfo?.type === "object") {
3784
3985
  return templateInfo.template;
3785
3986
  }
3786
- if ((templateInfo == null ? void 0 : templateInfo.type) === "union") {
3987
+ if (templateInfo?.type === "union") {
3787
3988
  if (hasOwnProperty(data, "_template")) {
3788
3989
  const template = templateInfo.templates.find(
3789
3990
  (t) => lastItem(t.namespace) === data._template
@@ -3801,14 +4002,14 @@ var getTemplateForFile = (templateInfo, data) => {
3801
4002
  throw new Error(`Unable to determine template`);
3802
4003
  };
3803
4004
  var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo) => {
3804
- const dataString = await bridge.get((0, import_schema_tools3.normalizePath)(filepath));
4005
+ const dataString = await bridge.get((0, import_schema_tools4.normalizePath)(filepath));
3805
4006
  const data = parseFile(
3806
4007
  dataString,
3807
4008
  import_path.default.extname(filepath),
3808
4009
  (yup3) => yup3.object({}),
3809
4010
  {
3810
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
3811
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
4011
+ frontmatterDelimiters: collection?.frontmatterDelimiters,
4012
+ frontmatterFormat: collection?.frontmatterFormat
3812
4013
  }
3813
4014
  );
3814
4015
  const template = getTemplateForFile(templateInfo, data);
@@ -3823,6 +4024,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3823
4024
 
3824
4025
  // src/database/datalayer.ts
3825
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__";
3826
4030
  var DEFAULT_NUMERIC_LPAD = 4;
3827
4031
  var applyPadding = (input, pad) => {
3828
4032
  if (pad) {
@@ -4280,7 +4484,7 @@ var FolderTreeBuilder = class {
4280
4484
  return this._tree;
4281
4485
  }
4282
4486
  update(documentPath, collectionPath) {
4283
- 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));
4284
4488
  if (folderPath === ".") {
4285
4489
  folderPath = "";
4286
4490
  }
@@ -4293,7 +4497,7 @@ var FolderTreeBuilder = class {
4293
4497
  if (!this._tree[current2]) {
4294
4498
  this._tree[current2] = /* @__PURE__ */ new Set();
4295
4499
  }
4296
- 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)));
4297
4501
  parent.push(part);
4298
4502
  });
4299
4503
  const current = parent.join("/");
@@ -4332,6 +4536,7 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4332
4536
  result.push({
4333
4537
  type: opType,
4334
4538
  key: `${collection.path}/${subFolderKey}.${collection.format}`,
4539
+ // replace the root with the collection path
4335
4540
  sublevel: indexSublevel,
4336
4541
  value: {}
4337
4542
  });
@@ -4395,6 +4600,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4395
4600
  }
4396
4601
  return result;
4397
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
+ };
4398
4654
  var makeStringEscaper = (regex, replacement) => {
4399
4655
  return (input) => {
4400
4656
  if (Array.isArray(input)) {
@@ -4420,7 +4676,6 @@ var createResolver = (args) => {
4420
4676
  return new Resolver(args);
4421
4677
  };
4422
4678
  var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4423
- var _a, _b;
4424
4679
  if (!rawData) {
4425
4680
  return void 0;
4426
4681
  }
@@ -4447,7 +4702,8 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4447
4702
  case "password":
4448
4703
  accumulator[field.name] = {
4449
4704
  value: void 0,
4450
- passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4705
+ // never resolve the password hash
4706
+ passwordChangeRequired: value["passwordChangeRequired"] ?? false
4451
4707
  };
4452
4708
  break;
4453
4709
  case "image":
@@ -4463,11 +4719,11 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4463
4719
  field,
4464
4720
  (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4465
4721
  );
4466
- if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4722
+ if (tree?.children[0]?.type === "invalid_markdown") {
4467
4723
  if (isAudit) {
4468
- const invalidNode = tree == null ? void 0 : tree.children[0];
4724
+ const invalidNode = tree?.children[0];
4469
4725
  throw new import_graphql3.GraphQLError(
4470
- `${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}` : ""}`
4471
4727
  );
4472
4728
  }
4473
4729
  }
@@ -4541,7 +4797,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4541
4797
  }
4542
4798
  return accumulator;
4543
4799
  };
4544
- var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit) => {
4800
+ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit, hasReferences) => {
4545
4801
  const collection = tinaSchema.getCollection(rawData._collection);
4546
4802
  try {
4547
4803
  const template = tinaSchema.getTemplateForData({
@@ -4580,11 +4836,11 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4580
4836
  });
4581
4837
  }
4582
4838
  const titleField = template.fields.find((x) => {
4583
- if (x.type === "string" && (x == null ? void 0 : x.isTitle)) {
4839
+ if (x.type === "string" && x?.isTitle) {
4584
4840
  return true;
4585
4841
  }
4586
4842
  });
4587
- const titleFieldName = titleField == null ? void 0 : titleField.name;
4843
+ const titleFieldName = titleField?.name;
4588
4844
  const title = data[titleFieldName || " "] || null;
4589
4845
  return {
4590
4846
  __typename: collection.fields ? NAMER.documentTypeName(collection.namespace) : NAMER.documentTypeName(template.namespace),
@@ -4595,6 +4851,7 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4595
4851
  basename,
4596
4852
  filename,
4597
4853
  extension,
4854
+ hasReferences,
4598
4855
  path: fullPath,
4599
4856
  relativePath,
4600
4857
  breadcrumbs,
@@ -4614,6 +4871,34 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4614
4871
  throw e;
4615
4872
  }
4616
4873
  };
4874
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4875
+ let updated = false;
4876
+ if (!path7.includes(".") && !path7.includes("[")) {
4877
+ if (path7 in obj && obj[path7] === oldValue) {
4878
+ obj[path7] = newValue;
4879
+ updated = true;
4880
+ }
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
+ });
4890
+ if (parents.length > 0) {
4891
+ parents.forEach((parent) => {
4892
+ if (parent && typeof parent === "object" && keyToUpdate in parent) {
4893
+ if (parent[keyToUpdate] === oldValue) {
4894
+ parent[keyToUpdate] = newValue;
4895
+ updated = true;
4896
+ }
4897
+ }
4898
+ });
4899
+ }
4900
+ return { object: obj, updated };
4901
+ };
4617
4902
  var Resolver = class {
4618
4903
  constructor(init) {
4619
4904
  this.init = init;
@@ -4621,6 +4906,7 @@ var Resolver = class {
4621
4906
  const collection = this.tinaSchema.getCollection(collectionName);
4622
4907
  const extraFields = {};
4623
4908
  return {
4909
+ // return the collection and hasDocuments to resolve documents at a lower level
4624
4910
  documents: { collection, hasDocuments },
4625
4911
  ...collection,
4626
4912
  ...extraFields
@@ -4628,7 +4914,9 @@ var Resolver = class {
4628
4914
  };
4629
4915
  this.getRaw = async (fullPath) => {
4630
4916
  if (typeof fullPath !== "string") {
4631
- 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
+ );
4632
4920
  }
4633
4921
  return this.database.get(fullPath);
4634
4922
  };
@@ -4655,22 +4943,28 @@ var Resolver = class {
4655
4943
  );
4656
4944
  }
4657
4945
  };
4658
- this.getDocument = async (fullPath) => {
4946
+ this.getDocument = async (fullPath, opts = {}) => {
4659
4947
  if (typeof fullPath !== "string") {
4660
- 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
+ );
4661
4951
  }
4662
4952
  const rawData = await this.getRaw(fullPath);
4953
+ const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4663
4954
  return transformDocumentIntoPayload(
4664
4955
  fullPath,
4665
4956
  rawData,
4666
4957
  this.tinaSchema,
4667
4958
  this.config,
4668
- this.isAudit
4959
+ this.isAudit,
4960
+ hasReferences
4669
4961
  );
4670
4962
  };
4671
4963
  this.deleteDocument = async (fullPath) => {
4672
4964
  if (typeof fullPath !== "string") {
4673
- 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
+ );
4674
4968
  }
4675
4969
  await this.database.delete(fullPath);
4676
4970
  };
@@ -4696,16 +4990,18 @@ var Resolver = class {
4696
4990
  return this.buildFieldMutations(
4697
4991
  item,
4698
4992
  objectTemplate,
4699
- idField && existingData && (existingData == null ? void 0 : existingData.find(
4993
+ idField && existingData && existingData?.find(
4700
4994
  (d) => d[idField.name] === item[idField.name]
4701
- ))
4995
+ )
4702
4996
  );
4703
4997
  }
4704
4998
  )
4705
4999
  );
4706
5000
  } else {
4707
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)[]; }'
4708
5003
  fieldValue,
5004
+ //@ts-ignore
4709
5005
  objectTemplate,
4710
5006
  existingData
4711
5007
  );
@@ -4717,6 +5013,7 @@ var Resolver = class {
4717
5013
  fieldValue.map(async (item) => {
4718
5014
  if (typeof item === "string") {
4719
5015
  throw new Error(
5016
+ //@ts-ignore
4720
5017
  `Expected object for template value for field ${field.name}`
4721
5018
  );
4722
5019
  }
@@ -4725,16 +5022,19 @@ var Resolver = class {
4725
5022
  });
4726
5023
  const [templateName] = Object.entries(item)[0];
4727
5024
  const template = templates.find(
5025
+ //@ts-ignore
4728
5026
  (template2) => template2.name === templateName
4729
5027
  );
4730
5028
  if (!template) {
4731
5029
  throw new Error(`Expected to find template ${templateName}`);
4732
5030
  }
4733
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; })[]; }'
4734
5033
  ...await this.buildFieldMutations(
4735
5034
  item[template.name],
4736
5035
  template
4737
5036
  ),
5037
+ //@ts-ignore
4738
5038
  _template: template.name
4739
5039
  };
4740
5040
  })
@@ -4742,6 +5042,7 @@ var Resolver = class {
4742
5042
  } else {
4743
5043
  if (typeof fieldValue === "string") {
4744
5044
  throw new Error(
5045
+ //@ts-ignore
4745
5046
  `Expected object for template value for field ${field.name}`
4746
5047
  );
4747
5048
  }
@@ -4750,16 +5051,19 @@ var Resolver = class {
4750
5051
  });
4751
5052
  const [templateName] = Object.entries(fieldValue)[0];
4752
5053
  const template = templates.find(
5054
+ //@ts-ignore
4753
5055
  (template2) => template2.name === templateName
4754
5056
  );
4755
5057
  if (!template) {
4756
5058
  throw new Error(`Expected to find template ${templateName}`);
4757
5059
  }
4758
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; })[]; }'
4759
5062
  ...await this.buildFieldMutations(
4760
5063
  fieldValue[template.name],
4761
5064
  template
4762
5065
  ),
5066
+ //@ts-ignore
4763
5067
  _template: template.name
4764
5068
  };
4765
5069
  }
@@ -4799,6 +5103,7 @@ var Resolver = class {
4799
5103
  return this.getDocument(realPath);
4800
5104
  }
4801
5105
  const params = await this.buildObjectMutations(
5106
+ // @ts-ignore
4802
5107
  args.params[collection.name],
4803
5108
  collection
4804
5109
  );
@@ -4813,7 +5118,7 @@ var Resolver = class {
4813
5118
  isCollectionSpecific
4814
5119
  }) => {
4815
5120
  const doc = await this.getDocument(realPath);
4816
- const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5121
+ const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
4817
5122
  if (isAddPendingDocument === true) {
4818
5123
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
4819
5124
  const params2 = this.buildParams(args);
@@ -4823,7 +5128,7 @@ var Resolver = class {
4823
5128
  const values = await this.buildFieldMutations(
4824
5129
  params2,
4825
5130
  templateInfo.template,
4826
- doc == null ? void 0 : doc._rawData
5131
+ doc?._rawData
4827
5132
  );
4828
5133
  await this.database.put(
4829
5134
  realPath,
@@ -4844,9 +5149,10 @@ var Resolver = class {
4844
5149
  const values = {
4845
5150
  ...oldDoc,
4846
5151
  ...await this.buildFieldMutations(
5152
+ // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
4847
5153
  templateParams,
4848
5154
  template,
4849
- doc == null ? void 0 : doc._rawData
5155
+ doc?._rawData
4850
5156
  ),
4851
5157
  _template: lastItem(template.namespace)
4852
5158
  };
@@ -4857,17 +5163,25 @@ var Resolver = class {
4857
5163
  return this.getDocument(realPath);
4858
5164
  }
4859
5165
  const params = await this.buildObjectMutations(
5166
+ //@ts-ignore
4860
5167
  isCollectionSpecific ? args.params : args.params[collection.name],
4861
5168
  collection,
4862
- doc == null ? void 0 : doc._rawData
5169
+ doc?._rawData
5170
+ );
5171
+ await this.database.put(
5172
+ realPath,
5173
+ { ...oldDoc, ...params },
5174
+ collection.name
4863
5175
  );
4864
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
4865
5176
  return this.getDocument(realPath);
4866
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
+ */
4867
5182
  this.resolveLegacyValues = (oldDoc, collection) => {
4868
5183
  const legacyValues = {};
4869
5184
  Object.entries(oldDoc).forEach(([key, value]) => {
4870
- var _a;
4871
5185
  const reservedKeys = [
4872
5186
  "$_body",
4873
5187
  "_collection",
@@ -4880,7 +5194,7 @@ var Resolver = class {
4880
5194
  return;
4881
5195
  }
4882
5196
  if (oldDoc._template && collection.templates) {
4883
- const template = (_a = collection.templates) == null ? void 0 : _a.find(
5197
+ const template = collection.templates?.find(
4884
5198
  ({ name }) => name === oldDoc._template
4885
5199
  );
4886
5200
  if (template) {
@@ -4927,7 +5241,7 @@ var Resolver = class {
4927
5241
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
4928
5242
  );
4929
5243
  const collection = await this.tinaSchema.getCollection(collectionLookup);
4930
- 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);
4931
5245
  if (isFolderCreation) {
4932
5246
  realPath = `${realPath}/.gitkeep.${collection.format || "md"}`;
4933
5247
  }
@@ -4969,6 +5283,40 @@ var Resolver = class {
4969
5283
  if (isDeletion) {
4970
5284
  const doc = await this.getDocument(realPath);
4971
5285
  await this.deleteDocument(realPath);
5286
+ if (await this.hasReferences(realPath, collection)) {
5287
+ const collRefs = await this.findReferences(realPath, collection);
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(
5296
+ refDoc,
5297
+ path7,
5298
+ realPath,
5299
+ null
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
+ );
5316
+ }
5317
+ }
5318
+ }
5319
+ }
4972
5320
  return doc;
4973
5321
  }
4974
5322
  if (isUpdateName) {
@@ -4977,20 +5325,57 @@ var Resolver = class {
4977
5325
  (yup3) => yup3.object({ params: yup3.object().required() })
4978
5326
  );
4979
5327
  assertShape(
4980
- args == null ? void 0 : args.params,
5328
+ args?.params,
4981
5329
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
4982
5330
  );
4983
5331
  const doc = await this.getDocument(realPath);
4984
5332
  const newRealPath = import_path3.default.join(
4985
- collection == null ? void 0 : collection.path,
5333
+ collection?.path,
4986
5334
  args.params.relativePath
4987
5335
  );
5336
+ if (newRealPath === realPath) {
5337
+ return doc;
5338
+ }
4988
5339
  await this.database.put(newRealPath, doc._rawData, collection.name);
4989
5340
  await this.deleteDocument(realPath);
5341
+ const collRefs = await this.findReferences(realPath, collection);
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,
5353
+ newRealPath
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
+ );
5370
+ }
5371
+ }
5372
+ }
4990
5373
  return this.getDocument(newRealPath);
4991
5374
  }
4992
5375
  if (alreadyExists === false) {
4993
- 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
+ );
4994
5379
  }
4995
5380
  return this.updateResolveDocument({
4996
5381
  collection,
@@ -5000,7 +5385,10 @@ var Resolver = class {
5000
5385
  isCollectionSpecific
5001
5386
  });
5002
5387
  } else {
5003
- return this.getDocument(realPath);
5388
+ return this.getDocument(realPath, {
5389
+ collection,
5390
+ checkReferences: true
5391
+ });
5004
5392
  }
5005
5393
  };
5006
5394
  this.resolveCollectionConnections = async ({ ids }) => {
@@ -5037,6 +5425,7 @@ var Resolver = class {
5037
5425
  },
5038
5426
  collection: referencedCollection,
5039
5427
  hydrator: (path7) => path7
5428
+ // just return the path
5040
5429
  }
5041
5430
  );
5042
5431
  const { edges } = resolvedCollectionConnection;
@@ -5104,8 +5493,83 @@ var Resolver = class {
5104
5493
  }
5105
5494
  };
5106
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
+ */
5502
+ this.hasReferences = async (id, c) => {
5503
+ let count = 0;
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;
5524
+ }
5525
+ );
5526
+ if (count) {
5527
+ return true;
5528
+ }
5529
+ return false;
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
+ */
5537
+ this.findReferences = async (id, c) => {
5538
+ const references = {};
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
+ }
5551
+ }
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;
5568
+ }
5569
+ );
5570
+ return references;
5571
+ };
5107
5572
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5108
- var _a;
5109
5573
  const accum = {};
5110
5574
  for (const passwordField of template.fields.filter(
5111
5575
  (f) => f.type === "password"
@@ -5148,7 +5612,7 @@ var Resolver = class {
5148
5612
  accum[fieldName] = await this.buildObjectMutations(
5149
5613
  fieldValue,
5150
5614
  field,
5151
- existingData == null ? void 0 : existingData[fieldName]
5615
+ existingData?.[fieldName]
5152
5616
  );
5153
5617
  break;
5154
5618
  case "password":
@@ -5167,7 +5631,7 @@ var Resolver = class {
5167
5631
  } else {
5168
5632
  accum[fieldName] = {
5169
5633
  ...fieldValue,
5170
- value: (_a = existingData == null ? void 0 : existingData[fieldName]) == null ? void 0 : _a["value"]
5634
+ value: existingData?.[fieldName]?.["value"]
5171
5635
  };
5172
5636
  }
5173
5637
  break;
@@ -5191,6 +5655,27 @@ var Resolver = class {
5191
5655
  }
5192
5656
  return accum;
5193
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
+ */
5194
5679
  this.buildParams = (args) => {
5195
5680
  try {
5196
5681
  assertShape(
@@ -5281,9 +5766,8 @@ var resolve = async ({
5281
5766
  isAudit,
5282
5767
  ctxUser
5283
5768
  }) => {
5284
- var _a;
5285
5769
  try {
5286
- const verboseValue = verbose != null ? verbose : true;
5770
+ const verboseValue = verbose ?? true;
5287
5771
  const graphQLSchemaAst = await database.getGraphQLSchema();
5288
5772
  if (!graphQLSchemaAst) {
5289
5773
  throw new import_graphql5.GraphQLError("GraphQL schema not found");
@@ -5291,8 +5775,11 @@ var resolve = async ({
5291
5775
  const graphQLSchema = (0, import_graphql5.buildASTSchema)(graphQLSchemaAst);
5292
5776
  const tinaConfig = await database.getTinaSchema();
5293
5777
  const tinaSchema = await createSchema({
5778
+ // TODO: please update all the types to import from @tinacms/schema-tools
5779
+ // @ts-ignore
5294
5780
  schema: tinaConfig,
5295
- flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
5781
+ // @ts-ignore
5782
+ flags: tinaConfig?.meta?.flags
5296
5783
  });
5297
5784
  const resolver = createResolver({
5298
5785
  config,
@@ -5308,8 +5795,7 @@ var resolve = async ({
5308
5795
  database
5309
5796
  },
5310
5797
  typeResolver: async (source, _args, info) => {
5311
- if (source.__typename)
5312
- return source.__typename;
5798
+ if (source.__typename) return source.__typename;
5313
5799
  const namedType = (0, import_graphql5.getNamedType)(info.returnType).toString();
5314
5800
  const lookup = await database.getLookup(namedType);
5315
5801
  if (lookup.resolveType === "unionData") {
@@ -5318,7 +5804,6 @@ var resolve = async ({
5318
5804
  throw new Error(`Unable to find lookup key for ${namedType}`);
5319
5805
  },
5320
5806
  fieldResolver: async (source = {}, _args = {}, _context, info) => {
5321
- var _a2, _b, _c, _d;
5322
5807
  try {
5323
5808
  const args = JSON.parse(JSON.stringify(_args));
5324
5809
  const returnType = (0, import_graphql5.getNamedType)(info.returnType).toString();
@@ -5335,8 +5820,7 @@ var resolve = async ({
5335
5820
  );
5336
5821
  const hasDocuments2 = collectionNode2.selectionSet.selections.find(
5337
5822
  (x) => {
5338
- var _a3;
5339
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5823
+ return x?.name?.value === "documents";
5340
5824
  }
5341
5825
  );
5342
5826
  return tinaSchema.getCollections().map((collection) => {
@@ -5352,8 +5836,7 @@ var resolve = async ({
5352
5836
  );
5353
5837
  const hasDocuments = collectionNode.selectionSet.selections.find(
5354
5838
  (x) => {
5355
- var _a3;
5356
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5839
+ return x?.name?.value === "documents";
5357
5840
  }
5358
5841
  );
5359
5842
  return resolver.resolveCollection(
@@ -5372,7 +5855,7 @@ var resolve = async ({
5372
5855
  }
5373
5856
  }
5374
5857
  if (info.fieldName === "authenticate" || info.fieldName === "authorize") {
5375
- const sub = args.sub || (ctxUser == null ? void 0 : ctxUser.sub);
5858
+ const sub = args.sub || ctxUser?.sub;
5376
5859
  const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5377
5860
  if (!collection) {
5378
5861
  throw new Error("Auth collection not found");
@@ -5420,7 +5903,7 @@ var resolve = async ({
5420
5903
  return user;
5421
5904
  }
5422
5905
  if (info.fieldName === "updatePassword") {
5423
- if (!(ctxUser == null ? void 0 : ctxUser.sub)) {
5906
+ if (!ctxUser?.sub) {
5424
5907
  throw new Error("Not authorized");
5425
5908
  }
5426
5909
  if (!args.password) {
@@ -5461,11 +5944,13 @@ var resolve = async ({
5461
5944
  (0, import_lodash4.default)(
5462
5945
  params,
5463
5946
  userField.path.slice(1),
5947
+ // remove _rawData from users path
5464
5948
  users.map((u) => {
5465
5949
  if (user[idFieldName] === u[idFieldName]) {
5466
5950
  return user;
5467
5951
  }
5468
5952
  return {
5953
+ // don't overwrite other users' passwords
5469
5954
  ...u,
5470
5955
  [passwordFieldName]: {
5471
5956
  ...u[passwordFieldName],
@@ -5488,6 +5973,9 @@ var resolve = async ({
5488
5973
  }
5489
5974
  const isCreation = lookup[info.fieldName] === "create";
5490
5975
  switch (lookup.resolveType) {
5976
+ /**
5977
+ * `node(id: $id)`
5978
+ */
5491
5979
  case "nodeDocument":
5492
5980
  assertShape(
5493
5981
  args,
@@ -5498,7 +5986,7 @@ var resolve = async ({
5498
5986
  if (typeof value === "string" && value !== "") {
5499
5987
  return resolver.getDocument(value);
5500
5988
  }
5501
- if ((args == null ? void 0 : args.collection) && info.fieldName === "addPendingDocument") {
5989
+ if (args?.collection && info.fieldName === "addPendingDocument") {
5502
5990
  return resolver.resolveDocument({
5503
5991
  args: { ...args, params: {} },
5504
5992
  collection: args.collection,
@@ -5519,15 +6007,19 @@ var resolve = async ({
5519
6007
  collection: args.collection,
5520
6008
  isMutation,
5521
6009
  isCreation,
6010
+ // Right now this is the only case for deletion
5522
6011
  isDeletion: info.fieldName === "deleteDocument",
5523
6012
  isFolderCreation: info.fieldName === "createFolder",
5524
- isUpdateName: Boolean((_a2 = args == null ? void 0 : args.params) == null ? void 0 : _a2.relativePath),
6013
+ isUpdateName: Boolean(args?.params?.relativePath),
5525
6014
  isAddPendingDocument: false,
5526
6015
  isCollectionSpecific: false
5527
6016
  });
5528
6017
  return result;
5529
6018
  }
5530
6019
  return value;
6020
+ /**
6021
+ * eg `getMovieDocument.data.actors`
6022
+ */
5531
6023
  case "multiCollectionDocumentList":
5532
6024
  if (Array.isArray(value)) {
5533
6025
  return {
@@ -5537,9 +6029,17 @@ var resolve = async ({
5537
6029
  })
5538
6030
  };
5539
6031
  }
5540
- 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) {
5541
6033
  let filter = args.filter;
5542
- 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
+ ) {
5543
6043
  filter = args.filter[value.collection.name];
5544
6044
  }
5545
6045
  return resolver.resolveCollectionConnection({
@@ -5547,12 +6047,20 @@ var resolve = async ({
5547
6047
  ...args,
5548
6048
  filter
5549
6049
  },
6050
+ // @ts-ignore
5550
6051
  collection: value.collection
5551
6052
  });
5552
6053
  }
5553
6054
  throw new Error(
5554
6055
  `Expected an array for result of ${info.fieldName} at ${info.path}`
5555
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
+ */
5556
6064
  case "collectionDocument": {
5557
6065
  if (value) {
5558
6066
  return value;
@@ -5567,11 +6075,32 @@ var resolve = async ({
5567
6075
  });
5568
6076
  return result;
5569
6077
  }
6078
+ /**
6079
+ * Collections-specific list getter
6080
+ * eg. `getPageList`
6081
+ */
5570
6082
  case "collectionDocumentList":
5571
6083
  return resolver.resolveCollectionConnection({
5572
6084
  args,
5573
6085
  collection: tinaSchema.getCollection(lookup.collection)
5574
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
+ */
5575
6104
  case "unionData":
5576
6105
  if (!value) {
5577
6106
  if (args.relativePath) {
@@ -5636,8 +6165,7 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5636
6165
  this.port = port || 9e3;
5637
6166
  }
5638
6167
  openConnection() {
5639
- if (this._connected)
5640
- return;
6168
+ if (this._connected) return;
5641
6169
  const socket = (0, import_net.connect)(this.port);
5642
6170
  (0, import_readable_stream.pipeline)(socket, this.createRpcStream(), socket, () => {
5643
6171
  this._connected = false;
@@ -5647,15 +6175,15 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5647
6175
  };
5648
6176
 
5649
6177
  // src/database/index.ts
5650
- var import_node_path = __toESM(require("path"));
6178
+ var import_node_path = __toESM(require("node:path"));
5651
6179
  var import_graphql6 = require("graphql");
5652
6180
  var import_micromatch2 = __toESM(require("micromatch"));
5653
6181
  var import_js_sha12 = __toESM(require("js-sha1"));
5654
6182
  var import_lodash5 = __toESM(require("lodash.set"));
5655
6183
  var createLocalDatabase = (config) => {
5656
- const level = new TinaLevelClient(config == null ? void 0 : config.port);
6184
+ const level = new TinaLevelClient(config?.port);
5657
6185
  level.openConnection();
5658
- const fsBridge = new FilesystemBridge((config == null ? void 0 : config.rootPath) || process.cwd());
6186
+ const fsBridge = new FilesystemBridge(config?.rootPath || process.cwd());
5659
6187
  return new Database({
5660
6188
  bridge: fsBridge,
5661
6189
  ...config || {},
@@ -5728,7 +6256,7 @@ var Database = class {
5728
6256
  );
5729
6257
  }
5730
6258
  const metadata = await metadataLevel.get(`metadata_${key}`);
5731
- return metadata == null ? void 0 : metadata.value;
6259
+ return metadata?.value;
5732
6260
  };
5733
6261
  this.setMetadata = async (key, value) => {
5734
6262
  await this.initLevel();
@@ -5750,14 +6278,14 @@ var Database = class {
5750
6278
  let level = this.contentLevel;
5751
6279
  if (this.appLevel) {
5752
6280
  collection = await this.collectionForPath(filepath);
5753
- if (collection == null ? void 0 : collection.isDetached) {
6281
+ if (collection?.isDetached) {
5754
6282
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
5755
6283
  }
5756
6284
  }
5757
6285
  const contentObject = await level.sublevel(
5758
6286
  CONTENT_ROOT_PREFIX,
5759
6287
  SUBLEVEL_OPTIONS
5760
- ).get((0, import_schema_tools3.normalizePath)(filepath));
6288
+ ).get((0, import_schema_tools4.normalizePath)(filepath));
5761
6289
  if (!contentObject) {
5762
6290
  throw new NotFoundError(`Unable to find record ${filepath}`);
5763
6291
  }
@@ -5781,9 +6309,10 @@ var Database = class {
5781
6309
  collection
5782
6310
  );
5783
6311
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
5784
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
5785
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
5786
- 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) {
5787
6316
  if (this.bridge) {
5788
6317
  await this.bridge.put(normalizedPath, stringifiedFile);
5789
6318
  }
@@ -5801,7 +6330,7 @@ var Database = class {
5801
6330
  }
5802
6331
  }
5803
6332
  let level = this.contentLevel;
5804
- if (collection == null ? void 0 : collection.isDetached) {
6333
+ if (collection?.isDetached) {
5805
6334
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
5806
6335
  }
5807
6336
  const folderTreeBuilder = new FolderTreeBuilder();
@@ -5810,17 +6339,26 @@ var Database = class {
5810
6339
  let delOps = [];
5811
6340
  if (!isGitKeep(normalizedPath, collection)) {
5812
6341
  putOps = [
6342
+ ...makeRefOpsForDocument(
6343
+ normalizedPath,
6344
+ collection?.name,
6345
+ collectionReferences,
6346
+ dataFields,
6347
+ "put",
6348
+ level
6349
+ ),
5813
6350
  ...makeIndexOpsForDocument(
5814
6351
  normalizedPath,
5815
- collection == null ? void 0 : collection.name,
6352
+ collection?.name,
5816
6353
  collectionIndexDefinitions,
5817
6354
  dataFields,
5818
6355
  "put",
5819
6356
  level
5820
6357
  ),
6358
+ // folder indices
5821
6359
  ...makeIndexOpsForDocument(
5822
6360
  normalizedPath,
5823
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6361
+ `${collection?.name}_${folderKey}`,
5824
6362
  collectionIndexDefinitions,
5825
6363
  dataFields,
5826
6364
  "put",
@@ -5832,17 +6370,26 @@ var Database = class {
5832
6370
  SUBLEVEL_OPTIONS
5833
6371
  ).get(normalizedPath);
5834
6372
  delOps = existingItem ? [
6373
+ ...makeRefOpsForDocument(
6374
+ normalizedPath,
6375
+ collection?.name,
6376
+ collectionReferences,
6377
+ existingItem,
6378
+ "del",
6379
+ level
6380
+ ),
5835
6381
  ...makeIndexOpsForDocument(
5836
6382
  normalizedPath,
5837
- collection == null ? void 0 : collection.name,
6383
+ collection?.name,
5838
6384
  collectionIndexDefinitions,
5839
6385
  existingItem,
5840
6386
  "del",
5841
6387
  level
5842
6388
  ),
6389
+ // folder indices
5843
6390
  ...makeIndexOpsForDocument(
5844
6391
  normalizedPath,
5845
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6392
+ `${collection?.name}_${folderKey}`,
5846
6393
  collectionIndexDefinitions,
5847
6394
  existingItem,
5848
6395
  "del",
@@ -5866,7 +6413,6 @@ var Database = class {
5866
6413
  await level.batch(ops);
5867
6414
  };
5868
6415
  this.put = async (filepath, data, collectionName) => {
5869
- var _a, _b;
5870
6416
  await this.initLevel();
5871
6417
  try {
5872
6418
  if (SYSTEM_FILES.includes(filepath)) {
@@ -5877,15 +6423,16 @@ var Database = class {
5877
6423
  const indexDefinitions = await this.getIndexDefinitions(
5878
6424
  this.contentLevel
5879
6425
  );
5880
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6426
+ collectionIndexDefinitions = indexDefinitions?.[collectionName];
5881
6427
  }
5882
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6428
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6429
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
5883
6430
  const dataFields = await this.formatBodyOnPayload(filepath, data);
5884
6431
  const collection = await this.collectionForPath(filepath);
5885
6432
  if (!collection) {
5886
6433
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
5887
6434
  }
5888
- 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) {
5889
6436
  const matches = this.tinaSchema.getMatches({ collection });
5890
6437
  const match = import_micromatch2.default.isMatch(filepath, matches);
5891
6438
  if (!match) {
@@ -5899,7 +6446,7 @@ var Database = class {
5899
6446
  const stringifiedFile = filepath.endsWith(
5900
6447
  `.gitkeep.${collection.format || "md"}`
5901
6448
  ) ? "" : await this.stringifyFile(filepath, dataFields, collection);
5902
- if (!(collection == null ? void 0 : collection.isDetached)) {
6449
+ if (!collection?.isDetached) {
5903
6450
  if (this.bridge) {
5904
6451
  await this.bridge.put(normalizedPath, stringifiedFile);
5905
6452
  }
@@ -5921,11 +6468,19 @@ var Database = class {
5921
6468
  filepath,
5922
6469
  collection.path || ""
5923
6470
  );
5924
- 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;
5925
6472
  let putOps = [];
5926
6473
  let delOps = [];
5927
6474
  if (!isGitKeep(normalizedPath, collection)) {
5928
6475
  putOps = [
6476
+ ...makeRefOpsForDocument(
6477
+ normalizedPath,
6478
+ collectionName,
6479
+ collectionReferences,
6480
+ dataFields,
6481
+ "put",
6482
+ level
6483
+ ),
5929
6484
  ...makeIndexOpsForDocument(
5930
6485
  normalizedPath,
5931
6486
  collectionName,
@@ -5934,9 +6489,10 @@ var Database = class {
5934
6489
  "put",
5935
6490
  level
5936
6491
  ),
6492
+ // folder indices
5937
6493
  ...makeIndexOpsForDocument(
5938
6494
  normalizedPath,
5939
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6495
+ `${collection?.name}_${folderKey}`,
5940
6496
  collectionIndexDefinitions,
5941
6497
  dataFields,
5942
6498
  "put",
@@ -5948,6 +6504,14 @@ var Database = class {
5948
6504
  SUBLEVEL_OPTIONS
5949
6505
  ).get(normalizedPath);
5950
6506
  delOps = existingItem ? [
6507
+ ...makeRefOpsForDocument(
6508
+ normalizedPath,
6509
+ collectionName,
6510
+ collectionReferences,
6511
+ existingItem,
6512
+ "del",
6513
+ level
6514
+ ),
5951
6515
  ...makeIndexOpsForDocument(
5952
6516
  normalizedPath,
5953
6517
  collectionName,
@@ -5956,9 +6520,10 @@ var Database = class {
5956
6520
  "del",
5957
6521
  level
5958
6522
  ),
6523
+ // folder indices
5959
6524
  ...makeIndexOpsForDocument(
5960
6525
  normalizedPath,
5961
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6526
+ `${collection?.name}_${folderKey}`,
5962
6527
  collectionIndexDefinitions,
5963
6528
  existingItem,
5964
6529
  "del",
@@ -6033,9 +6598,10 @@ var Database = class {
6033
6598
  aliasedData,
6034
6599
  extension,
6035
6600
  writeTemplateKey,
6601
+ //templateInfo.type === 'union',
6036
6602
  {
6037
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat,
6038
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
6603
+ frontmatterFormat: collection?.frontmatterFormat,
6604
+ frontmatterDelimiters: collection?.frontmatterDelimiters
6039
6605
  }
6040
6606
  );
6041
6607
  };
@@ -6050,7 +6616,7 @@ var Database = class {
6050
6616
  };
6051
6617
  this.getLookup = async (returnType) => {
6052
6618
  await this.initLevel();
6053
- const lookupPath = (0, import_schema_tools3.normalizePath)(
6619
+ const lookupPath = (0, import_schema_tools4.normalizePath)(
6054
6620
  import_node_path.default.join(this.getGeneratedFolder(), `_lookup.json`)
6055
6621
  );
6056
6622
  if (!this._lookup) {
@@ -6063,7 +6629,7 @@ var Database = class {
6063
6629
  };
6064
6630
  this.getGraphQLSchema = async () => {
6065
6631
  await this.initLevel();
6066
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6632
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6067
6633
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6068
6634
  );
6069
6635
  return await this.contentLevel.sublevel(
@@ -6071,11 +6637,12 @@ var Database = class {
6071
6637
  SUBLEVEL_OPTIONS
6072
6638
  ).get(graphqlPath);
6073
6639
  };
6640
+ //TODO - is there a reason why the database fetches some config with "bridge.get", and some with "store.get"?
6074
6641
  this.getGraphQLSchemaFromBridge = async () => {
6075
6642
  if (!this.bridge) {
6076
6643
  throw new Error(`No bridge configured`);
6077
6644
  }
6078
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6645
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6079
6646
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6080
6647
  );
6081
6648
  const _graphql = await this.bridge.get(graphqlPath);
@@ -6083,7 +6650,7 @@ var Database = class {
6083
6650
  };
6084
6651
  this.getTinaSchema = async (level) => {
6085
6652
  await this.initLevel();
6086
- const schemaPath = (0, import_schema_tools3.normalizePath)(
6653
+ const schemaPath = (0, import_schema_tools4.normalizePath)(
6087
6654
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6088
6655
  );
6089
6656
  return await (level || this.contentLevel).sublevel(
@@ -6099,7 +6666,7 @@ var Database = class {
6099
6666
  const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
6100
6667
  if (!schema) {
6101
6668
  throw new Error(
6102
- `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)(
6103
6670
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6104
6671
  )}`
6105
6672
  );
@@ -6107,6 +6674,22 @@ var Database = class {
6107
6674
  this.tinaSchema = await createSchema({ schema });
6108
6675
  return this.tinaSchema;
6109
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
+ };
6110
6693
  this.getIndexDefinitions = async (level) => {
6111
6694
  if (!this.collectionIndexDefinitions) {
6112
6695
  await new Promise(async (resolve2, reject) => {
@@ -6116,10 +6699,53 @@ var Database = class {
6116
6699
  const collections = schema.getCollections();
6117
6700
  for (const collection of collections) {
6118
6701
  const indexDefinitions = {
6119
- [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
+ }
6120
6719
  };
6121
- if (collection.fields) {
6122
- 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) {
6123
6749
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6124
6750
  continue;
6125
6751
  }
@@ -6144,8 +6770,8 @@ var Database = class {
6144
6770
  );
6145
6771
  return {
6146
6772
  name: indexField.name,
6147
- type: field == null ? void 0 : field.type,
6148
- list: !!(field == null ? void 0 : field.list)
6773
+ type: field?.type,
6774
+ list: !!field?.list
6149
6775
  };
6150
6776
  })
6151
6777
  };
@@ -6171,7 +6797,6 @@ var Database = class {
6171
6797
  return true;
6172
6798
  };
6173
6799
  this.query = async (queryOptions, hydrator) => {
6174
- var _a;
6175
6800
  await this.initLevel();
6176
6801
  const {
6177
6802
  first,
@@ -6199,14 +6824,14 @@ var Database = class {
6199
6824
  const allIndexDefinitions = await this.getIndexDefinitions(
6200
6825
  this.contentLevel
6201
6826
  );
6202
- const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[collection.name];
6827
+ const indexDefinitions = allIndexDefinitions?.[collection.name];
6203
6828
  if (!indexDefinitions) {
6204
6829
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6205
6830
  }
6206
6831
  const filterChain = coerceFilterChainOperands(rawFilterChain);
6207
- const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
6832
+ const indexDefinition = sort && indexDefinitions?.[sort];
6208
6833
  const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
6209
- 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;
6210
6835
  const rootLevel = level.sublevel(
6211
6836
  CONTENT_ROOT_PREFIX,
6212
6837
  SUBLEVEL_OPTIONS
@@ -6216,17 +6841,17 @@ var Database = class {
6216
6841
  SUBLEVEL_OPTIONS
6217
6842
  ).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
6218
6843
  if (!query.gt && !query.gte) {
6219
- query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? filterSuffixes.left : "";
6844
+ query.gte = filterSuffixes?.left ? filterSuffixes.left : "";
6220
6845
  }
6221
6846
  if (!query.lt && !query.lte) {
6222
- query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6847
+ query.lte = filterSuffixes?.right ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6223
6848
  }
6224
6849
  let edges = [];
6225
6850
  let startKey = "";
6226
6851
  let endKey = "";
6227
6852
  let hasPreviousPage = false;
6228
6853
  let hasNextPage = false;
6229
- 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("")}` : "";
6230
6855
  const valuesRegex = indexDefinition ? new RegExp(`^${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^(?<_filepath_>.+)`);
6231
6856
  const itemFilter = makeFilter({ filterChain });
6232
6857
  const iterator = sublevel.iterator(query);
@@ -6268,29 +6893,36 @@ var Database = class {
6268
6893
  }
6269
6894
  startKey = startKey || key || "";
6270
6895
  endKey = key || "";
6271
- edges = [...edges, { cursor: key, path: filepath }];
6896
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6272
6897
  }
6273
6898
  return {
6274
- edges: await sequential(edges, async (edge) => {
6275
- try {
6276
- const node = await hydrator(edge.path);
6277
- return {
6278
- node,
6279
- cursor: btoa(edge.cursor)
6280
- };
6281
- } catch (error) {
6282
- console.log(error);
6283
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6284
- throw new TinaQueryError({
6285
- originalError: error,
6286
- file: edge.path,
6287
- collection: collection.name,
6288
- stack: error.stack
6289
- });
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;
6290
6923
  }
6291
- throw error;
6292
6924
  }
6293
- }),
6925
+ ),
6294
6926
  pageInfo: {
6295
6927
  hasPreviousPage,
6296
6928
  hasNextPage,
@@ -6315,7 +6947,7 @@ var Database = class {
6315
6947
  try {
6316
6948
  lookup = lookupFromLockFile || JSON.parse(
6317
6949
  await this.bridge.get(
6318
- (0, import_schema_tools3.normalizePath)(
6950
+ (0, import_schema_tools4.normalizePath)(
6319
6951
  import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")
6320
6952
  )
6321
6953
  )
@@ -6340,15 +6972,15 @@ var Database = class {
6340
6972
  }
6341
6973
  const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
6342
6974
  await contentRootLevel.put(
6343
- (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")),
6344
6976
  graphQLSchema
6345
6977
  );
6346
6978
  await contentRootLevel.put(
6347
- (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")),
6348
6980
  tinaSchema.schema
6349
6981
  );
6350
6982
  await contentRootLevel.put(
6351
- (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")),
6352
6984
  lookup
6353
6985
  );
6354
6986
  const result = await this._indexAllContent(
@@ -6414,13 +7046,14 @@ var Database = class {
6414
7046
  documentPaths,
6415
7047
  async (collection, documentPaths2) => {
6416
7048
  if (collection && !collection.isDetached) {
6417
- await _indexContent(
6418
- this,
6419
- this.contentLevel,
6420
- documentPaths2,
7049
+ await _indexContent({
7050
+ database: this,
7051
+ level: this.contentLevel,
7052
+ documentPaths: documentPaths2,
6421
7053
  enqueueOps,
6422
- collection
6423
- );
7054
+ collection,
7055
+ isPartialReindex: true
7056
+ });
6424
7057
  }
6425
7058
  }
6426
7059
  );
@@ -6436,17 +7069,18 @@ var Database = class {
6436
7069
  throw new Error(`No collection found for path: ${filepath}`);
6437
7070
  }
6438
7071
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6439
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7072
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
7073
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6440
7074
  let level = this.contentLevel;
6441
- if (collection == null ? void 0 : collection.isDetached) {
6442
- 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);
6443
7077
  }
6444
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7078
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6445
7079
  const rootSublevel = level.sublevel(
6446
7080
  CONTENT_ROOT_PREFIX,
6447
7081
  SUBLEVEL_OPTIONS
6448
7082
  );
6449
- const item = await rootSublevel.get(itemKey);
7083
+ const item = await rootSublevel.get(normalizedPath);
6450
7084
  if (item) {
6451
7085
  const folderTreeBuilder = new FolderTreeBuilder();
6452
7086
  const folderKey = folderTreeBuilder.update(
@@ -6454,16 +7088,25 @@ var Database = class {
6454
7088
  collection.path || ""
6455
7089
  );
6456
7090
  await this.contentLevel.batch([
7091
+ ...makeRefOpsForDocument(
7092
+ normalizedPath,
7093
+ collection.name,
7094
+ collectionReferences,
7095
+ item,
7096
+ "del",
7097
+ level
7098
+ ),
6457
7099
  ...makeIndexOpsForDocument(
6458
- filepath,
7100
+ normalizedPath,
6459
7101
  collection.name,
6460
7102
  collectionIndexDefinitions,
6461
7103
  item,
6462
7104
  "del",
6463
7105
  level
6464
7106
  ),
7107
+ // folder indices
6465
7108
  ...makeIndexOpsForDocument(
6466
- filepath,
7109
+ normalizedPath,
6467
7110
  `${collection.name}_${folderKey}`,
6468
7111
  collectionIndexDefinitions,
6469
7112
  item,
@@ -6472,17 +7115,17 @@ var Database = class {
6472
7115
  ),
6473
7116
  {
6474
7117
  type: "del",
6475
- key: itemKey,
7118
+ key: normalizedPath,
6476
7119
  sublevel: rootSublevel
6477
7120
  }
6478
7121
  ]);
6479
7122
  }
6480
- if (!(collection == null ? void 0 : collection.isDetached)) {
7123
+ if (!collection?.isDetached) {
6481
7124
  if (this.bridge) {
6482
- await this.bridge.delete((0, import_schema_tools3.normalizePath)(filepath));
7125
+ await this.bridge.delete(normalizedPath);
6483
7126
  }
6484
7127
  try {
6485
- await this.onDelete((0, import_schema_tools3.normalizePath)(filepath));
7128
+ await this.onDelete(normalizedPath);
6486
7129
  } catch (e) {
6487
7130
  throw new import_graphql6.GraphQLError(
6488
7131
  `Error running onDelete hook for ${filepath}: ${e}`,
@@ -6517,20 +7160,26 @@ var Database = class {
6517
7160
  );
6518
7161
  const doc = await level2.keys({ limit: 1 }).next();
6519
7162
  if (!doc) {
6520
- await _indexContent(
6521
- this,
6522
- level2,
6523
- contentPaths,
7163
+ await _indexContent({
7164
+ database: this,
7165
+ level: level2,
7166
+ documentPaths: contentPaths,
6524
7167
  enqueueOps,
6525
7168
  collection,
6526
- userFields.map((field) => [
7169
+ passwordFields: userFields.map((field) => [
6527
7170
  ...field.path,
6528
7171
  field.passwordFieldName
6529
7172
  ])
6530
- );
7173
+ });
6531
7174
  }
6532
7175
  } else {
6533
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7176
+ await _indexContent({
7177
+ database: this,
7178
+ level,
7179
+ documentPaths: contentPaths,
7180
+ enqueueOps,
7181
+ collection
7182
+ });
6534
7183
  }
6535
7184
  }
6536
7185
  );
@@ -6566,7 +7215,7 @@ var Database = class {
6566
7215
  );
6567
7216
  }
6568
7217
  const metadata = await metadataLevel.get("metadata");
6569
- return metadata == null ? void 0 : metadata.version;
7218
+ return metadata?.version;
6570
7219
  }
6571
7220
  async initLevel() {
6572
7221
  if (this.contentLevel) {
@@ -6616,6 +7265,9 @@ var Database = class {
6616
7265
  info: templateInfo
6617
7266
  };
6618
7267
  }
7268
+ /**
7269
+ * Clears the internal cache of the tinaSchema and the lookup file. This allows the state to be reset
7270
+ */
6619
7271
  clearCache() {
6620
7272
  this.tinaSchema = null;
6621
7273
  this._lookup = null;
@@ -6649,7 +7301,7 @@ var hashPasswordVisitor = async (node, path7) => {
6649
7301
  };
6650
7302
  var visitNodes = async (node, path7, callback) => {
6651
7303
  const [currentLevel, ...remainingLevels] = path7;
6652
- if (!(remainingLevels == null ? void 0 : remainingLevels.length)) {
7304
+ if (!remainingLevels?.length) {
6653
7305
  return callback(node, path7);
6654
7306
  }
6655
7307
  if (Array.isArray(node[currentLevel])) {
@@ -6665,18 +7317,27 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
6665
7317
  async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
6666
7318
  )
6667
7319
  );
6668
- var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
6669
- 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
+ }) => {
6670
7330
  let collectionIndexDefinitions;
6671
7331
  let collectionPath;
6672
7332
  if (collection) {
6673
7333
  const indexDefinitions = await database.getIndexDefinitions(level);
6674
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7334
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
6675
7335
  if (!collectionIndexDefinitions) {
6676
7336
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6677
7337
  }
6678
7338
  collectionPath = collection.path;
6679
7339
  }
7340
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
6680
7341
  const tinaSchema = await database.getSchema();
6681
7342
  let templateInfo = null;
6682
7343
  if (collection) {
@@ -6694,27 +7355,77 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6694
7355
  if (!aliasedData) {
6695
7356
  return;
6696
7357
  }
6697
- if (passwordFields == null ? void 0 : passwordFields.length) {
7358
+ if (passwordFields?.length) {
6698
7359
  await hashPasswordValues(aliasedData, passwordFields);
6699
7360
  }
6700
- 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
+ );
6701
7366
  const folderKey = folderTreeBuilder.update(
6702
7367
  normalizedPath,
6703
7368
  collectionPath || ""
6704
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
+ }
6705
7407
  if (!isGitKeep(filepath, collection)) {
6706
7408
  await enqueueOps([
7409
+ ...makeRefOpsForDocument(
7410
+ normalizedPath,
7411
+ collection?.name,
7412
+ collectionReferences,
7413
+ aliasedData,
7414
+ "put",
7415
+ level
7416
+ ),
6707
7417
  ...makeIndexOpsForDocument(
6708
7418
  normalizedPath,
6709
- collection == null ? void 0 : collection.name,
7419
+ collection?.name,
6710
7420
  collectionIndexDefinitions,
6711
7421
  aliasedData,
6712
7422
  "put",
6713
7423
  level
6714
7424
  ),
7425
+ // folder indexes
6715
7426
  ...makeIndexOpsForDocument(
6716
7427
  normalizedPath,
6717
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7428
+ `${collection?.name}_${folderKey}`,
6718
7429
  collectionIndexDefinitions,
6719
7430
  aliasedData,
6720
7431
  "put",
@@ -6735,7 +7446,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6735
7446
  throw new TinaFetchError(`Unable to seed ${filepath}`, {
6736
7447
  originalError: error,
6737
7448
  file: filepath,
6738
- collection: collection == null ? void 0 : collection.name,
7449
+ collection: collection?.name,
6739
7450
  stack: error.stack
6740
7451
  });
6741
7452
  }
@@ -6761,11 +7472,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6761
7472
  const indexDefinitions = await database.getIndexDefinitions(
6762
7473
  database.contentLevel
6763
7474
  );
6764
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7475
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
6765
7476
  if (!collectionIndexDefinitions) {
6766
7477
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6767
7478
  }
6768
7479
  }
7480
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
6769
7481
  const tinaSchema = await database.getSchema();
6770
7482
  let templateInfo = null;
6771
7483
  if (collection) {
@@ -6777,18 +7489,26 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6777
7489
  );
6778
7490
  const folderTreeBuilder = new FolderTreeBuilder();
6779
7491
  await sequential(documentPaths, async (filepath) => {
6780
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7492
+ const itemKey = (0, import_schema_tools4.normalizePath)(filepath);
6781
7493
  const item = await rootLevel.get(itemKey);
6782
7494
  if (item) {
6783
7495
  const folderKey = folderTreeBuilder.update(
6784
7496
  itemKey,
6785
- (collection == null ? void 0 : collection.path) || ""
7497
+ collection?.path || ""
6786
7498
  );
6787
7499
  const aliasedData = templateInfo ? replaceNameOverrides(
6788
7500
  getTemplateForFile(templateInfo, item),
6789
7501
  item
6790
7502
  ) : item;
6791
7503
  await enqueueOps([
7504
+ ...makeRefOpsForDocument(
7505
+ itemKey,
7506
+ collection?.name,
7507
+ collectionReferences,
7508
+ aliasedData,
7509
+ "del",
7510
+ database.contentLevel
7511
+ ),
6792
7512
  ...makeIndexOpsForDocument(
6793
7513
  itemKey,
6794
7514
  collection.name,
@@ -6797,9 +7517,10 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6797
7517
  "del",
6798
7518
  database.contentLevel
6799
7519
  ),
7520
+ // folder indexes
6800
7521
  ...makeIndexOpsForDocument(
6801
7522
  itemKey,
6802
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7523
+ `${collection?.name}_${folderKey}`,
6803
7524
  collectionIndexDefinitions,
6804
7525
  aliasedData,
6805
7526
  "del",
@@ -6863,14 +7584,14 @@ var getChangedFiles = async ({
6863
7584
  const rootDir = await findGitRoot(dir);
6864
7585
  let pathPrefix = "";
6865
7586
  if (rootDir !== dir) {
6866
- pathPrefix = (0, import_schema_tools3.normalizePath)(dir.substring(rootDir.length + 1));
7587
+ pathPrefix = (0, import_schema_tools4.normalizePath)(dir.substring(rootDir.length + 1));
6867
7588
  }
6868
7589
  await import_isomorphic_git.default.walk({
6869
7590
  fs: fs4,
6870
7591
  dir: rootDir,
6871
7592
  trees: [import_isomorphic_git.default.TREE({ ref: from }), import_isomorphic_git.default.TREE({ ref: to })],
6872
7593
  map: async function(filename, [A, B]) {
6873
- const relativePath = (0, import_schema_tools3.normalizePath)(filename).substring(pathPrefix.length);
7594
+ const relativePath = (0, import_schema_tools4.normalizePath)(filename).substring(pathPrefix.length);
6874
7595
  let matches = false;
6875
7596
  for (const [key, matcher] of Object.entries(pathFilter)) {
6876
7597
  if (relativePath.startsWith(key)) {
@@ -6884,12 +7605,12 @@ var getChangedFiles = async ({
6884
7605
  }
6885
7606
  }
6886
7607
  }
6887
- if (await (B == null ? void 0 : B.type()) === "tree") {
7608
+ if (await B?.type() === "tree") {
6888
7609
  return;
6889
7610
  }
6890
7611
  if (matches) {
6891
- const oidA = await (A == null ? void 0 : A.oid());
6892
- const oidB = await (B == null ? void 0 : B.oid());
7612
+ const oidA = await A?.oid();
7613
+ const oidB = await B?.oid();
6893
7614
  if (oidA !== oidB) {
6894
7615
  if (oidA === void 0) {
6895
7616
  results.added.push(relativePath);
@@ -6917,8 +7638,8 @@ var import_path5 = __toESM(require("path"));
6917
7638
  var import_normalize_path = __toESM(require("normalize-path"));
6918
7639
  var FilesystemBridge = class {
6919
7640
  constructor(rootPath, outputPath) {
6920
- this.rootPath = rootPath || "";
6921
- this.outputPath = outputPath || rootPath;
7641
+ this.rootPath = import_path5.default.resolve(rootPath);
7642
+ this.outputPath = outputPath ? import_path5.default.resolve(outputPath) : this.rootPath;
6922
7643
  }
6923
7644
  async glob(pattern, extension) {
6924
7645
  const basePath = import_path5.default.join(this.outputPath, ...pattern.split("/"));
@@ -6930,19 +7651,19 @@ var FilesystemBridge = class {
6930
7651
  }
6931
7652
  );
6932
7653
  const posixRootPath = (0, import_normalize_path.default)(this.outputPath);
6933
- return items.map((item) => {
6934
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
6935
- });
7654
+ return items.map(
7655
+ (item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
7656
+ );
6936
7657
  }
6937
7658
  async delete(filepath) {
6938
7659
  await import_fs_extra2.default.remove(import_path5.default.join(this.outputPath, filepath));
6939
7660
  }
6940
7661
  async get(filepath) {
6941
- 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();
6942
7663
  }
6943
7664
  async put(filepath, data, basePathOverride) {
6944
7665
  const basePath = basePathOverride || this.outputPath;
6945
- 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);
6946
7667
  }
6947
7668
  };
6948
7669
  var AuditFileSystemBridge = class extends FilesystemBridge {
@@ -7012,17 +7733,26 @@ var IsomorphicBridge = class {
7012
7733
  getAuthor() {
7013
7734
  return {
7014
7735
  ...this.author,
7015
- timestamp: Math.round(new Date().getTime() / 1e3),
7736
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7016
7737
  timezoneOffset: 0
7017
7738
  };
7018
7739
  }
7019
7740
  getCommitter() {
7020
7741
  return {
7021
7742
  ...this.committer,
7022
- timestamp: Math.round(new Date().getTime() / 1e3),
7743
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7023
7744
  timezoneOffset: 0
7024
7745
  };
7025
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
+ */
7026
7756
  async listEntries({
7027
7757
  pattern,
7028
7758
  entry,
@@ -7055,6 +7785,15 @@ var IsomorphicBridge = class {
7055
7785
  });
7056
7786
  }
7057
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
+ */
7058
7797
  async resolvePathEntries(path7, ref) {
7059
7798
  let pathParts = path7.split("/");
7060
7799
  const result = await import_isomorphic_git2.default.walk({
@@ -7085,6 +7824,17 @@ var IsomorphicBridge = class {
7085
7824
  }
7086
7825
  return { pathParts, pathEntries };
7087
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
+ */
7088
7838
  async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
7089
7839
  const lastIdx = pathEntries.length - 1;
7090
7840
  const parentEntry = pathEntries[lastIdx];
@@ -7140,6 +7890,13 @@ var IsomorphicBridge = class {
7140
7890
  );
7141
7891
  }
7142
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
+ */
7143
7900
  async commitTree(treeSha, ref) {
7144
7901
  const commitSha = await import_isomorphic_git2.default.writeCommit({
7145
7902
  ...this.isomorphicConfig,
@@ -7152,6 +7909,7 @@ var IsomorphicBridge = class {
7152
7909
  })
7153
7910
  ],
7154
7911
  message: this.commitMessage,
7912
+ // TODO these should be configurable
7155
7913
  author: this.getAuthor(),
7156
7914
  committer: this.getCommitter()
7157
7915
  }
@@ -7390,5 +8148,5 @@ var buildSchema = async (config, flags) => {
7390
8148
  transformDocument,
7391
8149
  transformDocumentIntoPayload
7392
8150
  });
7393
- //! Replaces _.flattenDeep()
7394
8151
  //! Replaces _.get()
8152
+ //! Replaces _.flattenDeep()