@tinacms/graphql 0.0.0-c45ac5d-20241213020122 → 0.0.0-c466c52-20250801052040

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