@tinacms/graphql 0.0.0-d69e892-20241003042309 → 0.0.0-d9672bc-20250218033222

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,6 +17,10 @@ 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
  ));
@@ -130,6 +134,15 @@ var SysFieldDefinition = {
130
134
  selectionSet: {
131
135
  kind: "SelectionSet",
132
136
  selections: [
137
+ // {
138
+ // kind: 'Field' as const,
139
+ // name: {
140
+ // kind: 'Name' as const,
141
+ // value: 'title',
142
+ // },
143
+ // arguments: [],
144
+ // directives: [],
145
+ // },
133
146
  {
134
147
  kind: "Field",
135
148
  name: {
@@ -148,6 +161,15 @@ var SysFieldDefinition = {
148
161
  arguments: [],
149
162
  directives: []
150
163
  },
164
+ {
165
+ kind: "Field",
166
+ name: {
167
+ kind: "Name",
168
+ value: "hasReferences"
169
+ },
170
+ arguments: [],
171
+ directives: []
172
+ },
151
173
  {
152
174
  kind: "Field",
153
175
  name: {
@@ -188,6 +210,10 @@ var SysFieldDefinition = {
188
210
  }
189
211
  };
190
212
  var astBuilder = {
213
+ /**
214
+ * `FormFieldBuilder` acts as a shortcut to building an entire `ObjectTypeDefinition`, we use this
215
+ * because all Tina field objects share a common set of fields ('name', 'label', 'component')
216
+ */
191
217
  FormFieldBuilder: ({
192
218
  name,
193
219
  additionalFields
@@ -411,6 +437,8 @@ var astBuilder = {
411
437
  kind: "Name",
412
438
  value: name
413
439
  },
440
+ // @ts-ignore FIXME; this is being handled properly but we're lying to
441
+ // ts and then fixing it in the `extractInlineTypes` function
414
442
  fields
415
443
  }),
416
444
  UnionTypeDefinition: ({
@@ -423,6 +451,8 @@ var astBuilder = {
423
451
  value: name
424
452
  },
425
453
  directives: [],
454
+ // @ts-ignore FIXME; this is being handled properly but we're lying to
455
+ // ts and then fixing it in the `extractInlineTypes` function
426
456
  types: types.map((name2) => ({
427
457
  kind: "NamedType",
428
458
  name: {
@@ -519,8 +549,11 @@ var astBuilder = {
519
549
  string: "String",
520
550
  boolean: "Boolean",
521
551
  number: "Float",
552
+ // FIXME - needs to be float or int
522
553
  datetime: "String",
554
+ // FIXME
523
555
  image: "String",
556
+ // FIXME
524
557
  text: "String"
525
558
  };
526
559
  return scalars[type];
@@ -1019,8 +1052,7 @@ var astBuilder = {
1019
1052
  }
1020
1053
  };
1021
1054
  var capitalize = (s) => {
1022
- if (typeof s !== "string")
1023
- return "";
1055
+ if (typeof s !== "string") return "";
1024
1056
  return s.charAt(0).toUpperCase() + s.slice(1);
1025
1057
  };
1026
1058
  var extractInlineTypes = (item) => {
@@ -1063,41 +1095,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1063
1095
  yield maybeNode;
1064
1096
  visited.add(maybeNode);
1065
1097
  }
1066
- function addNamespaceToSchema(maybeNode, namespace = []) {
1067
- if (typeof maybeNode === "string") {
1068
- return maybeNode;
1069
- }
1070
- if (typeof maybeNode === "boolean") {
1071
- return maybeNode;
1072
- }
1073
- const newNode = maybeNode;
1074
- const keys = Object.keys(maybeNode);
1075
- Object.values(maybeNode).map((m, index) => {
1076
- const key = keys[index];
1077
- if (Array.isArray(m)) {
1078
- newNode[key] = m.map((element) => {
1079
- if (!element) {
1080
- return;
1081
- }
1082
- if (!element.hasOwnProperty("name")) {
1083
- return element;
1084
- }
1085
- const value = element.name || element.value;
1086
- return addNamespaceToSchema(element, [...namespace, value]);
1087
- });
1088
- } else {
1089
- if (!m) {
1090
- return;
1091
- }
1092
- if (!m.hasOwnProperty("name")) {
1093
- newNode[key] = m;
1094
- } else {
1095
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1096
- }
1097
- }
1098
- });
1099
- return { ...newNode, namespace };
1100
- }
1101
1098
  var generateNamespacedFieldName = (names, suffix = "") => {
1102
1099
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1103
1100
  };
@@ -1257,6 +1254,11 @@ var scalarDefinitions = [
1257
1254
  required: true,
1258
1255
  type: astBuilder.TYPES.String
1259
1256
  }),
1257
+ astBuilder.FieldDefinition({
1258
+ name: "hasReferences",
1259
+ required: false,
1260
+ type: astBuilder.TYPES.Boolean
1261
+ }),
1260
1262
  astBuilder.FieldDefinition({
1261
1263
  name: "breadcrumbs",
1262
1264
  required: true,
@@ -1471,6 +1473,19 @@ var Builder = class {
1471
1473
  this.addToLookupMap = (lookup) => {
1472
1474
  this.lookupMap[lookup.type] = lookup;
1473
1475
  };
1476
+ /**
1477
+ * ```graphql
1478
+ * # ex.
1479
+ * {
1480
+ * getCollection(collection: $collection) {
1481
+ * name
1482
+ * documents {...}
1483
+ * }
1484
+ * }
1485
+ * ```
1486
+ *
1487
+ * @param collections
1488
+ */
1474
1489
  this.buildCollectionDefinition = async (collections) => {
1475
1490
  const name = "collection";
1476
1491
  const typeName = "Collection";
@@ -1541,6 +1556,19 @@ var Builder = class {
1541
1556
  required: true
1542
1557
  });
1543
1558
  };
1559
+ /**
1560
+ * ```graphql
1561
+ * # ex.
1562
+ * {
1563
+ * getCollections {
1564
+ * name
1565
+ * documents {...}
1566
+ * }
1567
+ * }
1568
+ * ```
1569
+ *
1570
+ * @param collections
1571
+ */
1544
1572
  this.buildMultiCollectionDefinition = async (collections) => {
1545
1573
  const name = "collections";
1546
1574
  const typeName = "Collection";
@@ -1551,6 +1579,17 @@ var Builder = class {
1551
1579
  required: true
1552
1580
  });
1553
1581
  };
1582
+ /**
1583
+ * ```graphql
1584
+ * # ex.
1585
+ * {
1586
+ * node(id: $id) {
1587
+ * id
1588
+ * data {...}
1589
+ * }
1590
+ * }
1591
+ * ```
1592
+ */
1554
1593
  this.multiNodeDocument = async () => {
1555
1594
  const name = "node";
1556
1595
  const args = [
@@ -1571,6 +1610,19 @@ var Builder = class {
1571
1610
  required: true
1572
1611
  });
1573
1612
  };
1613
+ /**
1614
+ * ```graphql
1615
+ * # ex.
1616
+ * {
1617
+ * getDocument(collection: $collection, relativePath: $relativePath) {
1618
+ * id
1619
+ * data {...}
1620
+ * }
1621
+ * }
1622
+ * ```
1623
+ *
1624
+ * @param collections
1625
+ */
1574
1626
  this.multiCollectionDocument = async (collections) => {
1575
1627
  const name = "document";
1576
1628
  const args = [
@@ -1596,6 +1648,19 @@ var Builder = class {
1596
1648
  required: true
1597
1649
  });
1598
1650
  };
1651
+ /**
1652
+ * ```graphql
1653
+ * # ex.
1654
+ * {
1655
+ * addPendingDocument(collection: $collection, relativePath: $relativePath, params: $params) {
1656
+ * id
1657
+ * data {...}
1658
+ * }
1659
+ * }
1660
+ * ```
1661
+ *
1662
+ * @param collections
1663
+ */
1599
1664
  this.addMultiCollectionDocumentMutation = async () => {
1600
1665
  return astBuilder.FieldDefinition({
1601
1666
  name: "addPendingDocument",
@@ -1620,6 +1685,19 @@ var Builder = class {
1620
1685
  type: astBuilder.TYPES.MultiCollectionDocument
1621
1686
  });
1622
1687
  };
1688
+ /**
1689
+ * ```graphql
1690
+ * # ex.
1691
+ * {
1692
+ * createDocument(relativePath: $relativePath, params: $params) {
1693
+ * id
1694
+ * data {...}
1695
+ * }
1696
+ * }
1697
+ * ```
1698
+ *
1699
+ * @param collections
1700
+ */
1623
1701
  this.buildCreateCollectionDocumentMutation = async (collections) => {
1624
1702
  return astBuilder.FieldDefinition({
1625
1703
  name: "createDocument",
@@ -1647,6 +1725,19 @@ var Builder = class {
1647
1725
  type: astBuilder.TYPES.MultiCollectionDocument
1648
1726
  });
1649
1727
  };
1728
+ /**
1729
+ * ```graphql
1730
+ * # ex.
1731
+ * {
1732
+ * updateDocument(relativePath: $relativePath, params: $params) {
1733
+ * id
1734
+ * data {...}
1735
+ * }
1736
+ * }
1737
+ * ```
1738
+ *
1739
+ * @param collections
1740
+ */
1650
1741
  this.buildUpdateCollectionDocumentMutation = async (collections) => {
1651
1742
  return astBuilder.FieldDefinition({
1652
1743
  name: "updateDocument",
@@ -1674,6 +1765,19 @@ var Builder = class {
1674
1765
  type: astBuilder.TYPES.MultiCollectionDocument
1675
1766
  });
1676
1767
  };
1768
+ /**
1769
+ * ```graphql
1770
+ * # ex.
1771
+ * {
1772
+ * deleteDocument(relativePath: $relativePath, params: $params) {
1773
+ * id
1774
+ * data {...}
1775
+ * }
1776
+ * }
1777
+ * ```
1778
+ *
1779
+ * @param collections
1780
+ */
1677
1781
  this.buildDeleteCollectionDocumentMutation = async (collections) => {
1678
1782
  return astBuilder.FieldDefinition({
1679
1783
  name: "deleteDocument",
@@ -1693,6 +1797,19 @@ var Builder = class {
1693
1797
  type: astBuilder.TYPES.MultiCollectionDocument
1694
1798
  });
1695
1799
  };
1800
+ /**
1801
+ * ```graphql
1802
+ * # ex.
1803
+ * {
1804
+ * createFolder(folderName: $folderName, params: $params) {
1805
+ * id
1806
+ * data {...}
1807
+ * }
1808
+ * }
1809
+ * ```
1810
+ *
1811
+ * @param collections
1812
+ */
1696
1813
  this.buildCreateCollectionFolderMutation = async () => {
1697
1814
  return astBuilder.FieldDefinition({
1698
1815
  name: "createFolder",
@@ -1712,6 +1829,19 @@ var Builder = class {
1712
1829
  type: astBuilder.TYPES.MultiCollectionDocument
1713
1830
  });
1714
1831
  };
1832
+ /**
1833
+ * ```graphql
1834
+ * # ex.
1835
+ * {
1836
+ * getPostDocument(relativePath: $relativePath) {
1837
+ * id
1838
+ * data {...}
1839
+ * }
1840
+ * }
1841
+ * ```
1842
+ *
1843
+ * @param collection
1844
+ */
1715
1845
  this.collectionDocument = async (collection) => {
1716
1846
  const name = NAMER.queryName([collection.name]);
1717
1847
  const type = await this._buildCollectionDocumentType(collection);
@@ -1772,6 +1902,20 @@ var Builder = class {
1772
1902
  const args = [];
1773
1903
  return astBuilder.FieldDefinition({ type, name, args, required: false });
1774
1904
  };
1905
+ /**
1906
+ * Turns a collection into a fragment that gets updated on build. This fragment does not resolve references
1907
+ * ```graphql
1908
+ * # ex.
1909
+ * fragment AuthorsParts on Authors {
1910
+ * name
1911
+ * avatar
1912
+ * ...
1913
+ * }
1914
+ * ```
1915
+ *
1916
+ * @public
1917
+ * @param collection a Tina Cloud collection
1918
+ */
1775
1919
  this.collectionFragment = async (collection) => {
1776
1920
  const name = NAMER.dataTypeName(collection.namespace);
1777
1921
  const fragmentName = NAMER.fragmentName(collection.namespace);
@@ -1785,6 +1929,20 @@ var Builder = class {
1785
1929
  selections: filterSelections(selections)
1786
1930
  });
1787
1931
  };
1932
+ /**
1933
+ * Given a collection this function returns its selections set. For example for Post this would return
1934
+ *
1935
+ * "
1936
+ * body
1937
+ * title
1938
+ * ... on Author {
1939
+ * name
1940
+ * heroImg
1941
+ * }
1942
+ *
1943
+ * But in the AST format
1944
+ *
1945
+ * */
1788
1946
  this._getCollectionFragmentSelections = async (collection, depth) => {
1789
1947
  var _a;
1790
1948
  const selections = [];
@@ -1868,9 +2026,9 @@ var Builder = class {
1868
2026
  ]
1869
2027
  });
1870
2028
  }
2029
+ // TODO: Should we throw here?
1871
2030
  case "reference":
1872
- if (depth >= this.maxDepth)
1873
- return false;
2031
+ if (depth >= this.maxDepth) return false;
1874
2032
  if (!("collections" in field)) {
1875
2033
  return false;
1876
2034
  }
@@ -1902,6 +2060,7 @@ var Builder = class {
1902
2060
  name: field.name,
1903
2061
  selections: [
1904
2062
  ...selections,
2063
+ // This is ... on Document { id }
1905
2064
  {
1906
2065
  kind: "InlineFragment",
1907
2066
  typeCondition: {
@@ -1932,6 +2091,19 @@ var Builder = class {
1932
2091
  });
1933
2092
  }
1934
2093
  };
2094
+ /**
2095
+ * ```graphql
2096
+ * # ex.
2097
+ * mutation {
2098
+ * updatePostDocument(relativePath: $relativePath, params: $params) {
2099
+ * id
2100
+ * data {...}
2101
+ * }
2102
+ * }
2103
+ * ```
2104
+ *
2105
+ * @param collection
2106
+ */
1935
2107
  this.updateCollectionDocumentMutation = async (collection) => {
1936
2108
  return astBuilder.FieldDefinition({
1937
2109
  type: await this._buildCollectionDocumentType(collection),
@@ -1951,6 +2123,19 @@ var Builder = class {
1951
2123
  ]
1952
2124
  });
1953
2125
  };
2126
+ /**
2127
+ * ```graphql
2128
+ * # ex.
2129
+ * mutation {
2130
+ * createPostDocument(relativePath: $relativePath, params: $params) {
2131
+ * id
2132
+ * data {...}
2133
+ * }
2134
+ * }
2135
+ * ```
2136
+ *
2137
+ * @param collection
2138
+ */
1954
2139
  this.createCollectionDocumentMutation = async (collection) => {
1955
2140
  return astBuilder.FieldDefinition({
1956
2141
  type: await this._buildCollectionDocumentType(collection),
@@ -1970,6 +2155,22 @@ var Builder = class {
1970
2155
  ]
1971
2156
  });
1972
2157
  };
2158
+ /**
2159
+ * ```graphql
2160
+ * # ex.
2161
+ * {
2162
+ * getPostList(first: 10) {
2163
+ * edges {
2164
+ * node {
2165
+ * id
2166
+ * }
2167
+ * }
2168
+ * }
2169
+ * }
2170
+ * ```
2171
+ *
2172
+ * @param collection
2173
+ */
1973
2174
  this.collectionDocumentList = async (collection) => {
1974
2175
  const connectionName = NAMER.referenceConnectionType(collection.namespace);
1975
2176
  this.addToLookupMap({
@@ -1985,6 +2186,10 @@ var Builder = class {
1985
2186
  collection
1986
2187
  });
1987
2188
  };
2189
+ /**
2190
+ * GraphQL type definitions which remain unchanged regardless
2191
+ * of the supplied Tina schema. Ex. "node" interface
2192
+ */
1988
2193
  this.buildStaticDefinitions = () => staticDefinitions;
1989
2194
  this._buildCollectionDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
1990
2195
  const documentTypeName = NAMER.documentTypeName(collection.namespace);
@@ -2489,6 +2694,7 @@ var Builder = class {
2489
2694
  name: NAMER.dataFilterTypeName(namespace),
2490
2695
  fields: await sequential(collections, async (collection2) => {
2491
2696
  return astBuilder.InputValueDefinition({
2697
+ // @ts-ignore
2492
2698
  name: collection2.name,
2493
2699
  type: NAMER.dataFilterTypeName(collection2.namespace)
2494
2700
  });
@@ -2678,7 +2884,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2678
2884
  });
2679
2885
  };
2680
2886
  var _a, _b, _c, _d;
2681
- this.maxDepth = (_d = (_c = (_b = (_a = config == null ? void 0 : config.tinaSchema.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.client) == null ? void 0 : _c.referenceDepth) != null ? _d : 2;
2887
+ this.maxDepth = // @ts-ignore
2888
+ (_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;
2682
2889
  this.tinaSchema = config.tinaSchema;
2683
2890
  this.lookupMap = {};
2684
2891
  }
@@ -2689,8 +2896,7 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2689
2896
  selections.push(field);
2690
2897
  });
2691
2898
  const filteredSelections = filterSelections(selections);
2692
- if (!filteredSelections.length)
2693
- return false;
2899
+ if (!filteredSelections.length) return false;
2694
2900
  return astBuilder.InlineFragmentDefinition({
2695
2901
  selections: filteredSelections,
2696
2902
  name: NAMER.dataTypeName(template.namespace)
@@ -2724,12 +2930,13 @@ var filterSelections = (arr) => {
2724
2930
  };
2725
2931
 
2726
2932
  // src/schema/createSchema.ts
2727
- var import_schema_tools2 = require("@tinacms/schema-tools");
2933
+ var import_schema_tools3 = require("@tinacms/schema-tools");
2728
2934
 
2729
2935
  // src/schema/validate.ts
2936
+ var import_schema_tools = require("@tinacms/schema-tools");
2730
2937
  var import_lodash2 = __toESM(require("lodash.clonedeep"));
2731
2938
  var yup2 = __toESM(require("yup"));
2732
- var import_schema_tools = require("@tinacms/schema-tools");
2939
+ var import_schema_tools2 = require("@tinacms/schema-tools");
2733
2940
  var FIELD_TYPES = [
2734
2941
  "string",
2735
2942
  "number",
@@ -2742,7 +2949,7 @@ var FIELD_TYPES = [
2742
2949
  "password"
2743
2950
  ];
2744
2951
  var validateSchema = async (schema) => {
2745
- const schema2 = addNamespaceToSchema(
2952
+ const schema2 = (0, import_schema_tools.addNamespaceToSchema)(
2746
2953
  (0, import_lodash2.default)(schema)
2747
2954
  );
2748
2955
  const collections = await sequential(
@@ -2751,7 +2958,7 @@ var validateSchema = async (schema) => {
2751
2958
  );
2752
2959
  validationCollectionsPathAndMatch(collections);
2753
2960
  if (schema2.config) {
2754
- const config = (0, import_schema_tools.validateTinaCloudSchemaConfig)(schema2.config);
2961
+ const config = (0, import_schema_tools2.validateTinaCloudSchemaConfig)(schema2.config);
2755
2962
  return {
2756
2963
  collections,
2757
2964
  config
@@ -2771,6 +2978,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2771
2978
  }).map((x) => `${x.path}${x.format || "md"}`);
2772
2979
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2773
2980
  throw new Error(
2981
+ // TODO: add a link to the docs
2774
2982
  "Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
2775
2983
  );
2776
2984
  }
@@ -2882,7 +3090,7 @@ var validateField = async (field) => {
2882
3090
  // package.json
2883
3091
  var package_default = {
2884
3092
  name: "@tinacms/graphql",
2885
- version: "1.5.4",
3093
+ version: "1.5.12",
2886
3094
  main: "dist/index.js",
2887
3095
  module: "dist/index.mjs",
2888
3096
  typings: "dist/index.d.ts",
@@ -2909,8 +3117,8 @@ var package_default = {
2909
3117
  build: "tinacms-scripts build",
2910
3118
  docs: "pnpm typedoc",
2911
3119
  serve: "pnpm nodemon dist/server.js",
2912
- test: "jest",
2913
- "test-watch": "jest --watch"
3120
+ test: "vitest run",
3121
+ "test-watch": "vitest"
2914
3122
  },
2915
3123
  dependencies: {
2916
3124
  "@iarna/toml": "^2.2.5",
@@ -2926,7 +3134,7 @@ var package_default = {
2926
3134
  "isomorphic-git": "^1.27.1",
2927
3135
  "js-sha1": "^0.6.0",
2928
3136
  "js-yaml": "^3.14.1",
2929
- "jsonpath-plus": "^6.0.1",
3137
+ "jsonpath-plus": "10.1.0",
2930
3138
  "lodash.clonedeep": "^4.5.0",
2931
3139
  "lodash.set": "^4.3.2",
2932
3140
  "lodash.uniqby": "^4.7.0",
@@ -2951,24 +3159,23 @@ var package_default = {
2951
3159
  "@types/estree": "^0.0.50",
2952
3160
  "@types/express": "^4.17.21",
2953
3161
  "@types/fs-extra": "^9.0.13",
2954
- "@types/jest": "^26.0.24",
2955
3162
  "@types/js-yaml": "^3.12.10",
2956
3163
  "@types/lodash.camelcase": "^4.3.9",
2957
3164
  "@types/lodash.upperfirst": "^4.3.9",
2958
3165
  "@types/lru-cache": "^5.1.1",
2959
3166
  "@types/mdast": "^3.0.15",
2960
3167
  "@types/micromatch": "^4.0.9",
2961
- "@types/node": "^22.7.4",
3168
+ "@types/node": "^22.9.0",
2962
3169
  "@types/normalize-path": "^3.0.2",
2963
3170
  "@types/ws": "^7.4.7",
2964
3171
  "@types/yup": "^0.29.14",
2965
- jest: "^29.7.0",
2966
- "jest-diff": "^29.7.0",
2967
3172
  "jest-file-snapshot": "^0.5.0",
2968
- "jest-matcher-utils": "^29.7.0",
2969
3173
  "memory-level": "^1.0.0",
2970
3174
  nodemon: "3.1.4",
2971
- typescript: "^5.6.2"
3175
+ typescript: "^5.6.3",
3176
+ vite: "^4.3.9",
3177
+ vitest: "^0.32.2",
3178
+ zod: "^3.23.8"
2972
3179
  }
2973
3180
  };
2974
3181
 
@@ -2983,7 +3190,7 @@ var createSchema = async ({
2983
3190
  if (flags && flags.length > 0) {
2984
3191
  meta["flags"] = flags;
2985
3192
  }
2986
- return new import_schema_tools2.TinaSchema({
3193
+ return new import_schema_tools3.TinaSchema({
2987
3194
  version: {
2988
3195
  fullVersion: package_default.version,
2989
3196
  major,
@@ -3039,6 +3246,7 @@ var _buildFragments = async (builder, tinaSchema) => {
3039
3246
  const fragDoc = {
3040
3247
  kind: "Document",
3041
3248
  definitions: (0, import_lodash3.default)(
3249
+ // @ts-ignore
3042
3250
  extractInlineTypes(fragmentDefinitionsFields),
3043
3251
  (node) => node.name.value
3044
3252
  )
@@ -3062,6 +3270,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3062
3270
  fragName,
3063
3271
  queryName: queryListName,
3064
3272
  filterType: queryFilterTypeName,
3273
+ // look for flag to see if the data layer is enabled
3065
3274
  dataLayer: Boolean(
3066
3275
  (_c = (_b = (_a = tinaSchema.config) == null ? void 0 : _a.meta) == null ? void 0 : _b.flags) == null ? void 0 : _c.find((x) => x === "experimentalData")
3067
3276
  )
@@ -3071,6 +3280,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3071
3280
  const queryDoc = {
3072
3281
  kind: "Document",
3073
3282
  definitions: (0, import_lodash3.default)(
3283
+ // @ts-ignore
3074
3284
  extractInlineTypes(operationsDefinitions),
3075
3285
  (node) => node.name.value
3076
3286
  )
@@ -3159,6 +3369,7 @@ var _buildSchema = async (builder, tinaSchema) => {
3159
3369
  return {
3160
3370
  kind: "Document",
3161
3371
  definitions: (0, import_lodash3.default)(
3372
+ // @ts-ignore
3162
3373
  extractInlineTypes(definitions),
3163
3374
  (node) => node.name.value
3164
3375
  )
@@ -3175,6 +3386,9 @@ var import_isValid = __toESM(require("date-fns/isValid/index.js"));
3175
3386
  // src/mdx/index.ts
3176
3387
  var import_mdx = require("@tinacms/mdx");
3177
3388
 
3389
+ // src/resolver/index.ts
3390
+ var import_jsonpath_plus2 = require("jsonpath-plus");
3391
+
3178
3392
  // src/resolver/error.ts
3179
3393
  var TinaGraphQLError = class extends Error {
3180
3394
  constructor(message, extensions) {
@@ -3360,8 +3574,7 @@ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, s
3360
3574
  }
3361
3575
  if (Array.isArray(value)) {
3362
3576
  return value.map((v) => {
3363
- if (!v || typeof v !== "string")
3364
- return v;
3577
+ if (!v || typeof v !== "string") return v;
3365
3578
  const cleanMediaRoot = cleanUpSlashes(
3366
3579
  schema.config.media.tina.mediaRoot
3367
3580
  );
@@ -3389,8 +3602,7 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
3389
3602
  }
3390
3603
  if (Array.isArray(value)) {
3391
3604
  return value.map((v) => {
3392
- if (!v || typeof v !== "string")
3393
- return v;
3605
+ if (!v || typeof v !== "string") return v;
3394
3606
  const strippedValue = v.replace(cleanMediaRoot, "");
3395
3607
  return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3396
3608
  });
@@ -3409,8 +3621,7 @@ var cleanUpSlashes = (path7) => {
3409
3621
  };
3410
3622
  var hasTinaMediaConfig = (schema) => {
3411
3623
  var _a, _b, _c, _d, _e, _f, _g, _h;
3412
- if (!((_b = (_a = schema.config) == null ? void 0 : _a.media) == null ? void 0 : _b.tina))
3413
- return false;
3624
+ if (!((_b = (_a = schema.config) == null ? void 0 : _a.media) == null ? void 0 : _b.tina)) return false;
3414
3625
  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")
3415
3626
  return false;
3416
3627
  return true;
@@ -3454,6 +3665,7 @@ var LevelProxyHandler = {
3454
3665
  } else if (property === "sublevel") {
3455
3666
  return (...args) => {
3456
3667
  return new Proxy(
3668
+ // eslint-disable-next-line prefer-spread
3457
3669
  target[property].apply(target, args),
3458
3670
  LevelProxyHandler
3459
3671
  );
@@ -3476,7 +3688,7 @@ var import_path2 = __toESM(require("path"));
3476
3688
  var import_toml = __toESM(require("@iarna/toml"));
3477
3689
  var import_js_yaml = __toESM(require("js-yaml"));
3478
3690
  var import_gray_matter = __toESM(require("gray-matter"));
3479
- var import_schema_tools3 = require("@tinacms/schema-tools");
3691
+ var import_schema_tools4 = require("@tinacms/schema-tools");
3480
3692
  var import_micromatch = __toESM(require("micromatch"));
3481
3693
  var import_path = __toESM(require("path"));
3482
3694
 
@@ -3689,7 +3901,7 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3689
3901
  const filesSeen = /* @__PURE__ */ new Map();
3690
3902
  const duplicateFiles = /* @__PURE__ */ new Set();
3691
3903
  await sequential(tinaSchema.getCollections(), async (collection) => {
3692
- const normalPath = (0, import_schema_tools3.normalizePath)(collection.path);
3904
+ const normalPath = (0, import_schema_tools4.normalizePath)(collection.path);
3693
3905
  const format = collection.format || "md";
3694
3906
  const documentPaths = await bridge.glob(normalPath, format);
3695
3907
  const matches = tinaSchema.getMatches({ collection });
@@ -3801,7 +4013,7 @@ var getTemplateForFile = (templateInfo, data) => {
3801
4013
  throw new Error(`Unable to determine template`);
3802
4014
  };
3803
4015
  var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo) => {
3804
- const dataString = await bridge.get((0, import_schema_tools3.normalizePath)(filepath));
4016
+ const dataString = await bridge.get((0, import_schema_tools4.normalizePath)(filepath));
3805
4017
  const data = parseFile(
3806
4018
  dataString,
3807
4019
  import_path.default.extname(filepath),
@@ -3823,6 +4035,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3823
4035
 
3824
4036
  // src/database/datalayer.ts
3825
4037
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
4038
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
4039
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
4040
+ var REFS_PATH_FIELD = "__tina_ref_path__";
3826
4041
  var DEFAULT_NUMERIC_LPAD = 4;
3827
4042
  var applyPadding = (input, pad) => {
3828
4043
  if (pad) {
@@ -4280,7 +4495,7 @@ var FolderTreeBuilder = class {
4280
4495
  return this._tree;
4281
4496
  }
4282
4497
  update(documentPath, collectionPath) {
4283
- let folderPath = import_path2.default.dirname((0, import_schema_tools3.normalizePath)(documentPath));
4498
+ let folderPath = import_path2.default.dirname((0, import_schema_tools4.normalizePath)(documentPath));
4284
4499
  if (folderPath === ".") {
4285
4500
  folderPath = "";
4286
4501
  }
@@ -4293,7 +4508,7 @@ var FolderTreeBuilder = class {
4293
4508
  if (!this._tree[current2]) {
4294
4509
  this._tree[current2] = /* @__PURE__ */ new Set();
4295
4510
  }
4296
- this._tree[current2].add((0, import_schema_tools3.normalizePath)(import_path2.default.join(current2, part)));
4511
+ this._tree[current2].add((0, import_schema_tools4.normalizePath)(import_path2.default.join(current2, part)));
4297
4512
  parent.push(part);
4298
4513
  });
4299
4514
  const current = parent.join("/");
@@ -4332,6 +4547,7 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4332
4547
  result.push({
4333
4548
  type: opType,
4334
4549
  key: `${collection.path}/${subFolderKey}.${collection.format}`,
4550
+ // replace the root with the collection path
4335
4551
  sublevel: indexSublevel,
4336
4552
  value: {}
4337
4553
  });
@@ -4395,6 +4611,41 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4395
4611
  }
4396
4612
  return result;
4397
4613
  };
4614
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4615
+ const result = [];
4616
+ if (collection) {
4617
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4618
+ if (!referencePaths.length) {
4619
+ continue;
4620
+ }
4621
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4622
+ const refSublevel = collectionSublevel.sublevel(
4623
+ REFS_COLLECTIONS_SORT_KEY,
4624
+ SUBLEVEL_OPTIONS
4625
+ );
4626
+ const references2 = {};
4627
+ for (const path7 of referencePaths) {
4628
+ const ref = (0, import_jsonpath_plus.JSONPath)({ path: path7, json: data });
4629
+ if (references2[ref]) {
4630
+ references2[ref].push(path7);
4631
+ } else {
4632
+ references2[ref] = [path7];
4633
+ }
4634
+ }
4635
+ for (const ref of Object.keys(references2)) {
4636
+ for (const path7 of references2[ref]) {
4637
+ result.push({
4638
+ type: opType,
4639
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4640
+ sublevel: refSublevel,
4641
+ value: opType === "put" ? {} : void 0
4642
+ });
4643
+ }
4644
+ }
4645
+ }
4646
+ }
4647
+ return result;
4648
+ };
4398
4649
  var makeStringEscaper = (regex, replacement) => {
4399
4650
  return (input) => {
4400
4651
  if (Array.isArray(input)) {
@@ -4447,6 +4698,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4447
4698
  case "password":
4448
4699
  accumulator[field.name] = {
4449
4700
  value: void 0,
4701
+ // never resolve the password hash
4450
4702
  passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4451
4703
  };
4452
4704
  break;
@@ -4541,7 +4793,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4541
4793
  }
4542
4794
  return accumulator;
4543
4795
  };
4544
- var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit) => {
4796
+ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit, hasReferences) => {
4545
4797
  const collection = tinaSchema.getCollection(rawData._collection);
4546
4798
  try {
4547
4799
  const template = tinaSchema.getTemplateForData({
@@ -4595,6 +4847,7 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4595
4847
  basename,
4596
4848
  filename,
4597
4849
  extension,
4850
+ hasReferences,
4598
4851
  path: fullPath,
4599
4852
  relativePath,
4600
4853
  breadcrumbs,
@@ -4614,6 +4867,25 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4614
4867
  throw e;
4615
4868
  }
4616
4869
  };
4870
+ var updateObjectWithJsonPath = (obj, path7, newValue) => {
4871
+ if (!path7.includes(".") && !path7.includes("[")) {
4872
+ if (path7 in obj) {
4873
+ obj[path7] = newValue;
4874
+ }
4875
+ return obj;
4876
+ }
4877
+ const parentPath = path7.replace(/\.[^.]+$/, "");
4878
+ const keyToUpdate = path7.match(/[^.]+$/)[0];
4879
+ const parents = (0, import_jsonpath_plus2.JSONPath)({ path: parentPath, json: obj, resultType: "value" });
4880
+ if (parents.length > 0) {
4881
+ parents.forEach((parent) => {
4882
+ if (parent && typeof parent === "object" && keyToUpdate in parent) {
4883
+ parent[keyToUpdate] = newValue;
4884
+ }
4885
+ });
4886
+ }
4887
+ return obj;
4888
+ };
4617
4889
  var Resolver = class {
4618
4890
  constructor(init) {
4619
4891
  this.init = init;
@@ -4621,6 +4893,7 @@ var Resolver = class {
4621
4893
  const collection = this.tinaSchema.getCollection(collectionName);
4622
4894
  const extraFields = {};
4623
4895
  return {
4896
+ // return the collection and hasDocuments to resolve documents at a lower level
4624
4897
  documents: { collection, hasDocuments },
4625
4898
  ...collection,
4626
4899
  ...extraFields
@@ -4655,17 +4928,19 @@ var Resolver = class {
4655
4928
  );
4656
4929
  }
4657
4930
  };
4658
- this.getDocument = async (fullPath) => {
4931
+ this.getDocument = async (fullPath, opts = {}) => {
4659
4932
  if (typeof fullPath !== "string") {
4660
4933
  throw new Error(`fullPath must be of type string for getDocument request`);
4661
4934
  }
4662
4935
  const rawData = await this.getRaw(fullPath);
4936
+ const hasReferences = (opts == null ? void 0 : opts.checkReferences) ? await this.hasReferences(fullPath, opts.collection) : void 0;
4663
4937
  return transformDocumentIntoPayload(
4664
4938
  fullPath,
4665
4939
  rawData,
4666
4940
  this.tinaSchema,
4667
4941
  this.config,
4668
- this.isAudit
4942
+ this.isAudit,
4943
+ hasReferences
4669
4944
  );
4670
4945
  };
4671
4946
  this.deleteDocument = async (fullPath) => {
@@ -4705,7 +4980,9 @@ var Resolver = class {
4705
4980
  );
4706
4981
  } else {
4707
4982
  return this.buildFieldMutations(
4983
+ // @ts-ignore FIXME Argument of type 'string | object' is not assignable to parameter of type '{ [fieldName: string]: string | object | (string | object)[]; }'
4708
4984
  fieldValue,
4985
+ //@ts-ignore
4709
4986
  objectTemplate,
4710
4987
  existingData
4711
4988
  );
@@ -4717,6 +4994,7 @@ var Resolver = class {
4717
4994
  fieldValue.map(async (item) => {
4718
4995
  if (typeof item === "string") {
4719
4996
  throw new Error(
4997
+ //@ts-ignore
4720
4998
  `Expected object for template value for field ${field.name}`
4721
4999
  );
4722
5000
  }
@@ -4725,16 +5003,19 @@ var Resolver = class {
4725
5003
  });
4726
5004
  const [templateName] = Object.entries(item)[0];
4727
5005
  const template = templates.find(
5006
+ //@ts-ignore
4728
5007
  (template2) => template2.name === templateName
4729
5008
  );
4730
5009
  if (!template) {
4731
5010
  throw new Error(`Expected to find template ${templateName}`);
4732
5011
  }
4733
5012
  return {
5013
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4734
5014
  ...await this.buildFieldMutations(
4735
5015
  item[template.name],
4736
5016
  template
4737
5017
  ),
5018
+ //@ts-ignore
4738
5019
  _template: template.name
4739
5020
  };
4740
5021
  })
@@ -4742,6 +5023,7 @@ var Resolver = class {
4742
5023
  } else {
4743
5024
  if (typeof fieldValue === "string") {
4744
5025
  throw new Error(
5026
+ //@ts-ignore
4745
5027
  `Expected object for template value for field ${field.name}`
4746
5028
  );
4747
5029
  }
@@ -4750,16 +5032,19 @@ var Resolver = class {
4750
5032
  });
4751
5033
  const [templateName] = Object.entries(fieldValue)[0];
4752
5034
  const template = templates.find(
5035
+ //@ts-ignore
4753
5036
  (template2) => template2.name === templateName
4754
5037
  );
4755
5038
  if (!template) {
4756
5039
  throw new Error(`Expected to find template ${templateName}`);
4757
5040
  }
4758
5041
  return {
5042
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4759
5043
  ...await this.buildFieldMutations(
4760
5044
  fieldValue[template.name],
4761
5045
  template
4762
5046
  ),
5047
+ //@ts-ignore
4763
5048
  _template: template.name
4764
5049
  };
4765
5050
  }
@@ -4799,6 +5084,7 @@ var Resolver = class {
4799
5084
  return this.getDocument(realPath);
4800
5085
  }
4801
5086
  const params = await this.buildObjectMutations(
5087
+ // @ts-ignore
4802
5088
  args.params[collection.name],
4803
5089
  collection
4804
5090
  );
@@ -4844,6 +5130,7 @@ var Resolver = class {
4844
5130
  const values = {
4845
5131
  ...oldDoc,
4846
5132
  ...await this.buildFieldMutations(
5133
+ // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
4847
5134
  templateParams,
4848
5135
  template,
4849
5136
  doc == null ? void 0 : doc._rawData
@@ -4857,6 +5144,7 @@ var Resolver = class {
4857
5144
  return this.getDocument(realPath);
4858
5145
  }
4859
5146
  const params = await this.buildObjectMutations(
5147
+ //@ts-ignore
4860
5148
  isCollectionSpecific ? args.params : args.params[collection.name],
4861
5149
  collection,
4862
5150
  doc == null ? void 0 : doc._rawData
@@ -4864,6 +5152,10 @@ var Resolver = class {
4864
5152
  await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
4865
5153
  return this.getDocument(realPath);
4866
5154
  };
5155
+ /**
5156
+ * Returns top-level fields which are not defined in the collection, so their
5157
+ * values are not eliminated from Tina when new values are saved
5158
+ */
4867
5159
  this.resolveLegacyValues = (oldDoc, collection) => {
4868
5160
  const legacyValues = {};
4869
5161
  Object.entries(oldDoc).forEach(([key, value]) => {
@@ -4969,6 +5261,20 @@ var Resolver = class {
4969
5261
  if (isDeletion) {
4970
5262
  const doc = await this.getDocument(realPath);
4971
5263
  await this.deleteDocument(realPath);
5264
+ if (await this.hasReferences(realPath, collection)) {
5265
+ const collRefs = await this.findReferences(realPath, collection);
5266
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5267
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5268
+ docsWithRefs
5269
+ )) {
5270
+ let refDoc = await this.getRaw(pathToDocWithRef);
5271
+ for (const path7 of referencePaths) {
5272
+ refDoc = updateObjectWithJsonPath(refDoc, path7, null);
5273
+ }
5274
+ await this.database.put(pathToDocWithRef, refDoc, collection2);
5275
+ }
5276
+ }
5277
+ }
4972
5278
  return doc;
4973
5279
  }
4974
5280
  if (isUpdateName) {
@@ -4987,6 +5293,22 @@ var Resolver = class {
4987
5293
  );
4988
5294
  await this.database.put(newRealPath, doc._rawData, collection.name);
4989
5295
  await this.deleteDocument(realPath);
5296
+ const collRefs = await this.findReferences(realPath, collection);
5297
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5298
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5299
+ docsWithRefs
5300
+ )) {
5301
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5302
+ for (const path7 of referencePaths) {
5303
+ docWithRef = updateObjectWithJsonPath(
5304
+ docWithRef,
5305
+ path7,
5306
+ newRealPath
5307
+ );
5308
+ }
5309
+ await this.database.put(pathToDocWithRef, docWithRef, collection2);
5310
+ }
5311
+ }
4990
5312
  return this.getDocument(newRealPath);
4991
5313
  }
4992
5314
  if (alreadyExists === false) {
@@ -5000,7 +5322,10 @@ var Resolver = class {
5000
5322
  isCollectionSpecific
5001
5323
  });
5002
5324
  } else {
5003
- return this.getDocument(realPath);
5325
+ return this.getDocument(realPath, {
5326
+ collection,
5327
+ checkReferences: true
5328
+ });
5004
5329
  }
5005
5330
  };
5006
5331
  this.resolveCollectionConnections = async ({ ids }) => {
@@ -5037,6 +5362,7 @@ var Resolver = class {
5037
5362
  },
5038
5363
  collection: referencedCollection,
5039
5364
  hydrator: (path7) => path7
5365
+ // just return the path
5040
5366
  }
5041
5367
  );
5042
5368
  const { edges } = resolvedCollectionConnection;
@@ -5104,6 +5430,82 @@ var Resolver = class {
5104
5430
  }
5105
5431
  };
5106
5432
  };
5433
+ /**
5434
+ * Checks if a document has references to it
5435
+ * @param id The id of the document to check for references
5436
+ * @param c The collection to check for references
5437
+ * @returns true if the document has references, false otherwise
5438
+ */
5439
+ this.hasReferences = async (id, c) => {
5440
+ let count = 0;
5441
+ await this.database.query(
5442
+ {
5443
+ collection: c.name,
5444
+ filterChain: makeFilterChain({
5445
+ conditions: [
5446
+ {
5447
+ filterPath: REFS_REFERENCE_FIELD,
5448
+ filterExpression: {
5449
+ _type: "string",
5450
+ _list: false,
5451
+ eq: id
5452
+ }
5453
+ }
5454
+ ]
5455
+ }),
5456
+ sort: REFS_COLLECTIONS_SORT_KEY
5457
+ },
5458
+ (refId) => {
5459
+ count++;
5460
+ return refId;
5461
+ }
5462
+ );
5463
+ if (count) {
5464
+ return true;
5465
+ }
5466
+ return false;
5467
+ };
5468
+ /**
5469
+ * Finds references to a document
5470
+ * @param id the id of the document to find references to
5471
+ * @param c the collection to find references in
5472
+ * @returns a map of references to the document
5473
+ */
5474
+ this.findReferences = async (id, c) => {
5475
+ const references = {};
5476
+ await this.database.query(
5477
+ {
5478
+ collection: c.name,
5479
+ filterChain: makeFilterChain({
5480
+ conditions: [
5481
+ {
5482
+ filterPath: REFS_REFERENCE_FIELD,
5483
+ filterExpression: {
5484
+ _type: "string",
5485
+ _list: false,
5486
+ eq: id
5487
+ }
5488
+ }
5489
+ ]
5490
+ }),
5491
+ sort: REFS_COLLECTIONS_SORT_KEY
5492
+ },
5493
+ (refId, rawItem) => {
5494
+ if (!references[c.name]) {
5495
+ references[c.name] = {};
5496
+ }
5497
+ if (!references[c.name][refId]) {
5498
+ references[c.name][refId] = [];
5499
+ }
5500
+ const referencePath = rawItem == null ? void 0 : rawItem[REFS_PATH_FIELD];
5501
+ if (referencePath) {
5502
+ references[c.name][refId].push(referencePath);
5503
+ }
5504
+ return refId;
5505
+ }
5506
+ );
5507
+ return references;
5508
+ };
5107
5509
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5108
5510
  var _a;
5109
5511
  const accum = {};
@@ -5191,6 +5593,27 @@ var Resolver = class {
5191
5593
  }
5192
5594
  return accum;
5193
5595
  };
5596
+ /**
5597
+ * A mutation looks nearly identical between updateDocument:
5598
+ * ```graphql
5599
+ * updateDocument(collection: $collection,relativePath: $path, params: {
5600
+ * post: {
5601
+ * title: "Hello, World"
5602
+ * }
5603
+ * })`
5604
+ * ```
5605
+ * and `updatePostDocument`:
5606
+ * ```graphql
5607
+ * updatePostDocument(relativePath: $path, params: {
5608
+ * title: "Hello, World"
5609
+ * })
5610
+ * ```
5611
+ * The problem here is that we don't know whether the payload came from `updateDocument`
5612
+ * or `updatePostDocument` (we could, but for now it's easier not to pipe those details through),
5613
+ * But we do know that when given a `args.collection` value, we can assume that
5614
+ * this was a `updateDocument` request, and thus - should grab the data
5615
+ * from the corresponding field name in the key
5616
+ */
5194
5617
  this.buildParams = (args) => {
5195
5618
  try {
5196
5619
  assertShape(
@@ -5291,7 +5714,10 @@ var resolve = async ({
5291
5714
  const graphQLSchema = (0, import_graphql5.buildASTSchema)(graphQLSchemaAst);
5292
5715
  const tinaConfig = await database.getTinaSchema();
5293
5716
  const tinaSchema = await createSchema({
5717
+ // TODO: please update all the types to import from @tinacms/schema-tools
5718
+ // @ts-ignore
5294
5719
  schema: tinaConfig,
5720
+ // @ts-ignore
5295
5721
  flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
5296
5722
  });
5297
5723
  const resolver = createResolver({
@@ -5308,8 +5734,7 @@ var resolve = async ({
5308
5734
  database
5309
5735
  },
5310
5736
  typeResolver: async (source, _args, info) => {
5311
- if (source.__typename)
5312
- return source.__typename;
5737
+ if (source.__typename) return source.__typename;
5313
5738
  const namedType = (0, import_graphql5.getNamedType)(info.returnType).toString();
5314
5739
  const lookup = await database.getLookup(namedType);
5315
5740
  if (lookup.resolveType === "unionData") {
@@ -5461,11 +5886,13 @@ var resolve = async ({
5461
5886
  (0, import_lodash4.default)(
5462
5887
  params,
5463
5888
  userField.path.slice(1),
5889
+ // remove _rawData from users path
5464
5890
  users.map((u) => {
5465
5891
  if (user[idFieldName] === u[idFieldName]) {
5466
5892
  return user;
5467
5893
  }
5468
5894
  return {
5895
+ // don't overwrite other users' passwords
5469
5896
  ...u,
5470
5897
  [passwordFieldName]: {
5471
5898
  ...u[passwordFieldName],
@@ -5488,6 +5915,9 @@ var resolve = async ({
5488
5915
  }
5489
5916
  const isCreation = lookup[info.fieldName] === "create";
5490
5917
  switch (lookup.resolveType) {
5918
+ /**
5919
+ * `node(id: $id)`
5920
+ */
5491
5921
  case "nodeDocument":
5492
5922
  assertShape(
5493
5923
  args,
@@ -5519,6 +5949,7 @@ var resolve = async ({
5519
5949
  collection: args.collection,
5520
5950
  isMutation,
5521
5951
  isCreation,
5952
+ // Right now this is the only case for deletion
5522
5953
  isDeletion: info.fieldName === "deleteDocument",
5523
5954
  isFolderCreation: info.fieldName === "createFolder",
5524
5955
  isUpdateName: Boolean((_a2 = args == null ? void 0 : args.params) == null ? void 0 : _a2.relativePath),
@@ -5528,6 +5959,9 @@ var resolve = async ({
5528
5959
  return result;
5529
5960
  }
5530
5961
  return value;
5962
+ /**
5963
+ * eg `getMovieDocument.data.actors`
5964
+ */
5531
5965
  case "multiCollectionDocumentList":
5532
5966
  if (Array.isArray(value)) {
5533
5967
  return {
@@ -5539,7 +5973,15 @@ var resolve = async ({
5539
5973
  }
5540
5974
  if (info.fieldName === "documents" && (value == null ? void 0 : value.collection) && (value == null ? void 0 : value.hasDocuments)) {
5541
5975
  let filter = args.filter;
5542
- if (typeof (args == null ? void 0 : args.filter) !== "undefined" && (args == null ? void 0 : args.filter) !== null && typeof ((_b = value == null ? void 0 : value.collection) == null ? void 0 : _b.name) === "string" && Object.keys(args.filter).includes((_c = value == null ? void 0 : value.collection) == null ? void 0 : _c.name) && typeof args.filter[(_d = value == null ? void 0 : value.collection) == null ? void 0 : _d.name] !== "undefined") {
5976
+ if (
5977
+ // 1. Make sure that the filter exists
5978
+ typeof (args == null ? void 0 : args.filter) !== "undefined" && (args == null ? void 0 : args.filter) !== null && // 2. Make sure that the collection name exists
5979
+ // @ts-ignore
5980
+ typeof ((_b = value == null ? void 0 : value.collection) == null ? void 0 : _b.name) === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
5981
+ // @ts-ignore
5982
+ Object.keys(args.filter).includes((_c = value == null ? void 0 : value.collection) == null ? void 0 : _c.name) && // @ts-ignore
5983
+ typeof args.filter[(_d = value == null ? void 0 : value.collection) == null ? void 0 : _d.name] !== "undefined"
5984
+ ) {
5543
5985
  filter = args.filter[value.collection.name];
5544
5986
  }
5545
5987
  return resolver.resolveCollectionConnection({
@@ -5547,12 +5989,20 @@ var resolve = async ({
5547
5989
  ...args,
5548
5990
  filter
5549
5991
  },
5992
+ // @ts-ignore
5550
5993
  collection: value.collection
5551
5994
  });
5552
5995
  }
5553
5996
  throw new Error(
5554
5997
  `Expected an array for result of ${info.fieldName} at ${info.path}`
5555
5998
  );
5999
+ /**
6000
+ * Collections-specific getter
6001
+ * eg. `getPostDocument`/`createPostDocument`/`updatePostDocument`
6002
+ *
6003
+ * if coming from a query result
6004
+ * the field will be `node`
6005
+ */
5556
6006
  case "collectionDocument": {
5557
6007
  if (value) {
5558
6008
  return value;
@@ -5567,11 +6017,32 @@ var resolve = async ({
5567
6017
  });
5568
6018
  return result;
5569
6019
  }
6020
+ /**
6021
+ * Collections-specific list getter
6022
+ * eg. `getPageList`
6023
+ */
5570
6024
  case "collectionDocumentList":
5571
6025
  return resolver.resolveCollectionConnection({
5572
6026
  args,
5573
6027
  collection: tinaSchema.getCollection(lookup.collection)
5574
6028
  });
6029
+ /**
6030
+ * A polymorphic data set, it can be from a document's data
6031
+ * of any nested object which can be one of many shapes
6032
+ *
6033
+ * ```graphql
6034
+ * getPostDocument(relativePath: $relativePath) {
6035
+ * data {...} <- this part
6036
+ * }
6037
+ * ```
6038
+ * ```graphql
6039
+ * getBlockDocument(relativePath: $relativePath) {
6040
+ * data {
6041
+ * blocks {...} <- or this part
6042
+ * }
6043
+ * }
6044
+ * ```
6045
+ */
5575
6046
  case "unionData":
5576
6047
  if (!value) {
5577
6048
  if (args.relativePath) {
@@ -5636,8 +6107,7 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5636
6107
  this.port = port || 9e3;
5637
6108
  }
5638
6109
  openConnection() {
5639
- if (this._connected)
5640
- return;
6110
+ if (this._connected) return;
5641
6111
  const socket = (0, import_net.connect)(this.port);
5642
6112
  (0, import_readable_stream.pipeline)(socket, this.createRpcStream(), socket, () => {
5643
6113
  this._connected = false;
@@ -5757,7 +6227,7 @@ var Database = class {
5757
6227
  const contentObject = await level.sublevel(
5758
6228
  CONTENT_ROOT_PREFIX,
5759
6229
  SUBLEVEL_OPTIONS
5760
- ).get((0, import_schema_tools3.normalizePath)(filepath));
6230
+ ).get((0, import_schema_tools4.normalizePath)(filepath));
5761
6231
  if (!contentObject) {
5762
6232
  throw new NotFoundError(`Unable to find record ${filepath}`);
5763
6233
  }
@@ -5769,6 +6239,7 @@ var Database = class {
5769
6239
  }
5770
6240
  };
5771
6241
  this.addPendingDocument = async (filepath, data) => {
6242
+ var _a;
5772
6243
  await this.initLevel();
5773
6244
  const dataFields = await this.formatBodyOnPayload(filepath, data);
5774
6245
  const collection = await this.collectionForPath(filepath);
@@ -5782,7 +6253,8 @@ var Database = class {
5782
6253
  );
5783
6254
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
5784
6255
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
5785
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6256
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collection.name];
6257
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
5786
6258
  if (!(collection == null ? void 0 : collection.isDetached)) {
5787
6259
  if (this.bridge) {
5788
6260
  await this.bridge.put(normalizedPath, stringifiedFile);
@@ -5810,6 +6282,14 @@ var Database = class {
5810
6282
  let delOps = [];
5811
6283
  if (!isGitKeep(normalizedPath, collection)) {
5812
6284
  putOps = [
6285
+ ...makeRefOpsForDocument(
6286
+ normalizedPath,
6287
+ collection == null ? void 0 : collection.name,
6288
+ collectionReferences,
6289
+ dataFields,
6290
+ "put",
6291
+ level
6292
+ ),
5813
6293
  ...makeIndexOpsForDocument(
5814
6294
  normalizedPath,
5815
6295
  collection == null ? void 0 : collection.name,
@@ -5818,6 +6298,7 @@ var Database = class {
5818
6298
  "put",
5819
6299
  level
5820
6300
  ),
6301
+ // folder indices
5821
6302
  ...makeIndexOpsForDocument(
5822
6303
  normalizedPath,
5823
6304
  `${collection == null ? void 0 : collection.name}_${folderKey}`,
@@ -5832,6 +6313,14 @@ var Database = class {
5832
6313
  SUBLEVEL_OPTIONS
5833
6314
  ).get(normalizedPath);
5834
6315
  delOps = existingItem ? [
6316
+ ...makeRefOpsForDocument(
6317
+ normalizedPath,
6318
+ collection == null ? void 0 : collection.name,
6319
+ collectionReferences,
6320
+ existingItem,
6321
+ "del",
6322
+ level
6323
+ ),
5835
6324
  ...makeIndexOpsForDocument(
5836
6325
  normalizedPath,
5837
6326
  collection == null ? void 0 : collection.name,
@@ -5840,6 +6329,7 @@ var Database = class {
5840
6329
  "del",
5841
6330
  level
5842
6331
  ),
6332
+ // folder indices
5843
6333
  ...makeIndexOpsForDocument(
5844
6334
  normalizedPath,
5845
6335
  `${collection == null ? void 0 : collection.name}_${folderKey}`,
@@ -5866,7 +6356,7 @@ var Database = class {
5866
6356
  await level.batch(ops);
5867
6357
  };
5868
6358
  this.put = async (filepath, data, collectionName) => {
5869
- var _a, _b;
6359
+ var _a, _b, _c;
5870
6360
  await this.initLevel();
5871
6361
  try {
5872
6362
  if (SYSTEM_FILES.includes(filepath)) {
@@ -5879,13 +6369,14 @@ var Database = class {
5879
6369
  );
5880
6370
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
5881
6371
  }
5882
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6372
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collectionName];
6373
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
5883
6374
  const dataFields = await this.formatBodyOnPayload(filepath, data);
5884
6375
  const collection = await this.collectionForPath(filepath);
5885
6376
  if (!collection) {
5886
6377
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
5887
6378
  }
5888
- if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
6379
+ if (((_b = collection.match) == null ? void 0 : _b.exclude) || ((_c = collection.match) == null ? void 0 : _c.include)) {
5889
6380
  const matches = this.tinaSchema.getMatches({ collection });
5890
6381
  const match = import_micromatch2.default.isMatch(filepath, matches);
5891
6382
  if (!match) {
@@ -5926,6 +6417,14 @@ var Database = class {
5926
6417
  let delOps = [];
5927
6418
  if (!isGitKeep(normalizedPath, collection)) {
5928
6419
  putOps = [
6420
+ ...makeRefOpsForDocument(
6421
+ normalizedPath,
6422
+ collectionName,
6423
+ collectionReferences,
6424
+ dataFields,
6425
+ "put",
6426
+ level
6427
+ ),
5929
6428
  ...makeIndexOpsForDocument(
5930
6429
  normalizedPath,
5931
6430
  collectionName,
@@ -5934,6 +6433,7 @@ var Database = class {
5934
6433
  "put",
5935
6434
  level
5936
6435
  ),
6436
+ // folder indices
5937
6437
  ...makeIndexOpsForDocument(
5938
6438
  normalizedPath,
5939
6439
  `${collection == null ? void 0 : collection.name}_${folderKey}`,
@@ -5948,6 +6448,14 @@ var Database = class {
5948
6448
  SUBLEVEL_OPTIONS
5949
6449
  ).get(normalizedPath);
5950
6450
  delOps = existingItem ? [
6451
+ ...makeRefOpsForDocument(
6452
+ normalizedPath,
6453
+ collectionName,
6454
+ collectionReferences,
6455
+ existingItem,
6456
+ "del",
6457
+ level
6458
+ ),
5951
6459
  ...makeIndexOpsForDocument(
5952
6460
  normalizedPath,
5953
6461
  collectionName,
@@ -5956,6 +6464,7 @@ var Database = class {
5956
6464
  "del",
5957
6465
  level
5958
6466
  ),
6467
+ // folder indices
5959
6468
  ...makeIndexOpsForDocument(
5960
6469
  normalizedPath,
5961
6470
  `${collection == null ? void 0 : collection.name}_${folderKey}`,
@@ -6033,6 +6542,7 @@ var Database = class {
6033
6542
  aliasedData,
6034
6543
  extension,
6035
6544
  writeTemplateKey,
6545
+ //templateInfo.type === 'union',
6036
6546
  {
6037
6547
  frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat,
6038
6548
  frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
@@ -6050,7 +6560,7 @@ var Database = class {
6050
6560
  };
6051
6561
  this.getLookup = async (returnType) => {
6052
6562
  await this.initLevel();
6053
- const lookupPath = (0, import_schema_tools3.normalizePath)(
6563
+ const lookupPath = (0, import_schema_tools4.normalizePath)(
6054
6564
  import_node_path.default.join(this.getGeneratedFolder(), `_lookup.json`)
6055
6565
  );
6056
6566
  if (!this._lookup) {
@@ -6063,7 +6573,7 @@ var Database = class {
6063
6573
  };
6064
6574
  this.getGraphQLSchema = async () => {
6065
6575
  await this.initLevel();
6066
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6576
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6067
6577
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6068
6578
  );
6069
6579
  return await this.contentLevel.sublevel(
@@ -6071,11 +6581,12 @@ var Database = class {
6071
6581
  SUBLEVEL_OPTIONS
6072
6582
  ).get(graphqlPath);
6073
6583
  };
6584
+ //TODO - is there a reason why the database fetches some config with "bridge.get", and some with "store.get"?
6074
6585
  this.getGraphQLSchemaFromBridge = async () => {
6075
6586
  if (!this.bridge) {
6076
6587
  throw new Error(`No bridge configured`);
6077
6588
  }
6078
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6589
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6079
6590
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6080
6591
  );
6081
6592
  const _graphql = await this.bridge.get(graphqlPath);
@@ -6083,7 +6594,7 @@ var Database = class {
6083
6594
  };
6084
6595
  this.getTinaSchema = async (level) => {
6085
6596
  await this.initLevel();
6086
- const schemaPath = (0, import_schema_tools3.normalizePath)(
6597
+ const schemaPath = (0, import_schema_tools4.normalizePath)(
6087
6598
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6088
6599
  );
6089
6600
  return await (level || this.contentLevel).sublevel(
@@ -6099,7 +6610,7 @@ var Database = class {
6099
6610
  const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
6100
6611
  if (!schema) {
6101
6612
  throw new Error(
6102
- `Unable to get schema from level db: ${(0, import_schema_tools3.normalizePath)(
6613
+ `Unable to get schema from level db: ${(0, import_schema_tools4.normalizePath)(
6103
6614
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6104
6615
  )}`
6105
6616
  );
@@ -6107,6 +6618,22 @@ var Database = class {
6107
6618
  this.tinaSchema = await createSchema({ schema });
6108
6619
  return this.tinaSchema;
6109
6620
  };
6621
+ this.getCollectionReferences = async (level) => {
6622
+ if (this.collectionReferences) {
6623
+ return this.collectionReferences;
6624
+ }
6625
+ const result = {};
6626
+ const schema = await this.getSchema(level || this.contentLevel);
6627
+ const collections = schema.getCollections();
6628
+ for (const collection of collections) {
6629
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6630
+ collection.name
6631
+ );
6632
+ result[collection.name] = collectionReferences;
6633
+ }
6634
+ this.collectionReferences = result;
6635
+ return result;
6636
+ };
6110
6637
  this.getIndexDefinitions = async (level) => {
6111
6638
  if (!this.collectionIndexDefinitions) {
6112
6639
  await new Promise(async (resolve2, reject) => {
@@ -6116,7 +6643,23 @@ var Database = class {
6116
6643
  const collections = schema.getCollections();
6117
6644
  for (const collection of collections) {
6118
6645
  const indexDefinitions = {
6119
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6646
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6647
+ // provide a default sort key which is the file sort
6648
+ // pseudo-index for the collection's references
6649
+ [REFS_COLLECTIONS_SORT_KEY]: {
6650
+ fields: [
6651
+ {
6652
+ name: REFS_REFERENCE_FIELD,
6653
+ type: "string",
6654
+ list: false
6655
+ },
6656
+ {
6657
+ name: REFS_PATH_FIELD,
6658
+ type: "string",
6659
+ list: false
6660
+ }
6661
+ ]
6662
+ }
6120
6663
  };
6121
6664
  if (collection.fields) {
6122
6665
  for (const field of collection.fields) {
@@ -6268,29 +6811,36 @@ var Database = class {
6268
6811
  }
6269
6812
  startKey = startKey || key || "";
6270
6813
  endKey = key || "";
6271
- edges = [...edges, { cursor: key, path: filepath }];
6814
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6272
6815
  }
6273
6816
  return {
6274
- edges: await sequential(edges, async (edge) => {
6275
- try {
6276
- const node = await hydrator(edge.path);
6277
- return {
6278
- node,
6279
- cursor: btoa(edge.cursor)
6280
- };
6281
- } catch (error) {
6282
- console.log(error);
6283
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6284
- throw new TinaQueryError({
6285
- originalError: error,
6286
- file: edge.path,
6287
- collection: collection.name,
6288
- stack: error.stack
6289
- });
6817
+ edges: await sequential(
6818
+ edges,
6819
+ async ({
6820
+ cursor,
6821
+ path: path7,
6822
+ value
6823
+ }) => {
6824
+ try {
6825
+ const node = await hydrator(path7, value);
6826
+ return {
6827
+ node,
6828
+ cursor: btoa(cursor)
6829
+ };
6830
+ } catch (error) {
6831
+ console.log(error);
6832
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6833
+ throw new TinaQueryError({
6834
+ originalError: error,
6835
+ file: path7,
6836
+ collection: collection.name,
6837
+ stack: error.stack
6838
+ });
6839
+ }
6840
+ throw error;
6290
6841
  }
6291
- throw error;
6292
6842
  }
6293
- }),
6843
+ ),
6294
6844
  pageInfo: {
6295
6845
  hasPreviousPage,
6296
6846
  hasNextPage,
@@ -6315,7 +6865,7 @@ var Database = class {
6315
6865
  try {
6316
6866
  lookup = lookupFromLockFile || JSON.parse(
6317
6867
  await this.bridge.get(
6318
- (0, import_schema_tools3.normalizePath)(
6868
+ (0, import_schema_tools4.normalizePath)(
6319
6869
  import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")
6320
6870
  )
6321
6871
  )
@@ -6340,15 +6890,15 @@ var Database = class {
6340
6890
  }
6341
6891
  const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
6342
6892
  await contentRootLevel.put(
6343
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
6893
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
6344
6894
  graphQLSchema
6345
6895
  );
6346
6896
  await contentRootLevel.put(
6347
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
6897
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
6348
6898
  tinaSchema.schema
6349
6899
  );
6350
6900
  await contentRootLevel.put(
6351
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
6901
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
6352
6902
  lookup
6353
6903
  );
6354
6904
  const result = await this._indexAllContent(
@@ -6430,23 +6980,25 @@ var Database = class {
6430
6980
  }
6431
6981
  };
6432
6982
  this.delete = async (filepath) => {
6983
+ var _a;
6433
6984
  await this.initLevel();
6434
6985
  const collection = await this.collectionForPath(filepath);
6435
6986
  if (!collection) {
6436
6987
  throw new Error(`No collection found for path: ${filepath}`);
6437
6988
  }
6438
6989
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6990
+ const collectionReferences = (_a = await this.getCollectionReferences()) == null ? void 0 : _a[collection.name];
6439
6991
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6440
6992
  let level = this.contentLevel;
6441
6993
  if (collection == null ? void 0 : collection.isDetached) {
6442
6994
  level = this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS);
6443
6995
  }
6444
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
6996
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6445
6997
  const rootSublevel = level.sublevel(
6446
6998
  CONTENT_ROOT_PREFIX,
6447
6999
  SUBLEVEL_OPTIONS
6448
7000
  );
6449
- const item = await rootSublevel.get(itemKey);
7001
+ const item = await rootSublevel.get(normalizedPath);
6450
7002
  if (item) {
6451
7003
  const folderTreeBuilder = new FolderTreeBuilder();
6452
7004
  const folderKey = folderTreeBuilder.update(
@@ -6454,16 +7006,25 @@ var Database = class {
6454
7006
  collection.path || ""
6455
7007
  );
6456
7008
  await this.contentLevel.batch([
7009
+ ...makeRefOpsForDocument(
7010
+ normalizedPath,
7011
+ collection.name,
7012
+ collectionReferences,
7013
+ item,
7014
+ "del",
7015
+ level
7016
+ ),
6457
7017
  ...makeIndexOpsForDocument(
6458
- filepath,
7018
+ normalizedPath,
6459
7019
  collection.name,
6460
7020
  collectionIndexDefinitions,
6461
7021
  item,
6462
7022
  "del",
6463
7023
  level
6464
7024
  ),
7025
+ // folder indices
6465
7026
  ...makeIndexOpsForDocument(
6466
- filepath,
7027
+ normalizedPath,
6467
7028
  `${collection.name}_${folderKey}`,
6468
7029
  collectionIndexDefinitions,
6469
7030
  item,
@@ -6472,17 +7033,17 @@ var Database = class {
6472
7033
  ),
6473
7034
  {
6474
7035
  type: "del",
6475
- key: itemKey,
7036
+ key: normalizedPath,
6476
7037
  sublevel: rootSublevel
6477
7038
  }
6478
7039
  ]);
6479
7040
  }
6480
7041
  if (!(collection == null ? void 0 : collection.isDetached)) {
6481
7042
  if (this.bridge) {
6482
- await this.bridge.delete((0, import_schema_tools3.normalizePath)(filepath));
7043
+ await this.bridge.delete(normalizedPath);
6483
7044
  }
6484
7045
  try {
6485
- await this.onDelete((0, import_schema_tools3.normalizePath)(filepath));
7046
+ await this.onDelete(normalizedPath);
6486
7047
  } catch (e) {
6487
7048
  throw new import_graphql6.GraphQLError(
6488
7049
  `Error running onDelete hook for ${filepath}: ${e}`,
@@ -6616,6 +7177,9 @@ var Database = class {
6616
7177
  info: templateInfo
6617
7178
  };
6618
7179
  }
7180
+ /**
7181
+ * Clears the internal cache of the tinaSchema and the lookup file. This allows the state to be reset
7182
+ */
6619
7183
  clearCache() {
6620
7184
  this.tinaSchema = null;
6621
7185
  this._lookup = null;
@@ -6667,6 +7231,7 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
6667
7231
  );
6668
7232
  var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
6669
7233
  var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7234
+ var _a;
6670
7235
  let collectionIndexDefinitions;
6671
7236
  let collectionPath;
6672
7237
  if (collection) {
@@ -6677,6 +7242,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6677
7242
  }
6678
7243
  collectionPath = collection.path;
6679
7244
  }
7245
+ const collectionReferences = (_a = await database.getCollectionReferences()) == null ? void 0 : _a[collection == null ? void 0 : collection.name];
6680
7246
  const tinaSchema = await database.getSchema();
6681
7247
  let templateInfo = null;
6682
7248
  if (collection) {
@@ -6697,13 +7263,60 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6697
7263
  if (passwordFields == null ? void 0 : passwordFields.length) {
6698
7264
  await hashPasswordValues(aliasedData, passwordFields);
6699
7265
  }
6700
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
7266
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
7267
+ const rootSublevel = level.sublevel(
7268
+ CONTENT_ROOT_PREFIX,
7269
+ SUBLEVEL_OPTIONS
7270
+ );
6701
7271
  const folderKey = folderTreeBuilder.update(
6702
7272
  normalizedPath,
6703
7273
  collectionPath || ""
6704
7274
  );
7275
+ const item = await rootSublevel.get(normalizedPath);
7276
+ if (item) {
7277
+ await database.contentLevel.batch([
7278
+ ...makeRefOpsForDocument(
7279
+ normalizedPath,
7280
+ collection == null ? void 0 : collection.name,
7281
+ collectionReferences,
7282
+ item,
7283
+ "del",
7284
+ level
7285
+ ),
7286
+ ...makeIndexOpsForDocument(
7287
+ normalizedPath,
7288
+ collection.name,
7289
+ collectionIndexDefinitions,
7290
+ item,
7291
+ "del",
7292
+ level
7293
+ ),
7294
+ // folder indices
7295
+ ...makeIndexOpsForDocument(
7296
+ normalizedPath,
7297
+ `${collection.name}_${folderKey}`,
7298
+ collectionIndexDefinitions,
7299
+ item,
7300
+ "del",
7301
+ level
7302
+ ),
7303
+ {
7304
+ type: "del",
7305
+ key: normalizedPath,
7306
+ sublevel: rootSublevel
7307
+ }
7308
+ ]);
7309
+ }
6705
7310
  if (!isGitKeep(filepath, collection)) {
6706
7311
  await enqueueOps([
7312
+ ...makeRefOpsForDocument(
7313
+ normalizedPath,
7314
+ collection == null ? void 0 : collection.name,
7315
+ collectionReferences,
7316
+ aliasedData,
7317
+ "put",
7318
+ level
7319
+ ),
6707
7320
  ...makeIndexOpsForDocument(
6708
7321
  normalizedPath,
6709
7322
  collection == null ? void 0 : collection.name,
@@ -6712,6 +7325,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6712
7325
  "put",
6713
7326
  level
6714
7327
  ),
7328
+ // folder indexes
6715
7329
  ...makeIndexOpsForDocument(
6716
7330
  normalizedPath,
6717
7331
  `${collection == null ? void 0 : collection.name}_${folderKey}`,
@@ -6753,6 +7367,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6753
7367
  }
6754
7368
  };
6755
7369
  var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection) => {
7370
+ var _a;
6756
7371
  if (!documentPaths.length) {
6757
7372
  return;
6758
7373
  }
@@ -6766,6 +7381,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6766
7381
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6767
7382
  }
6768
7383
  }
7384
+ const collectionReferences = (_a = await database.getCollectionReferences()) == null ? void 0 : _a[collection == null ? void 0 : collection.name];
6769
7385
  const tinaSchema = await database.getSchema();
6770
7386
  let templateInfo = null;
6771
7387
  if (collection) {
@@ -6777,7 +7393,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6777
7393
  );
6778
7394
  const folderTreeBuilder = new FolderTreeBuilder();
6779
7395
  await sequential(documentPaths, async (filepath) => {
6780
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7396
+ const itemKey = (0, import_schema_tools4.normalizePath)(filepath);
6781
7397
  const item = await rootLevel.get(itemKey);
6782
7398
  if (item) {
6783
7399
  const folderKey = folderTreeBuilder.update(
@@ -6789,6 +7405,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6789
7405
  item
6790
7406
  ) : item;
6791
7407
  await enqueueOps([
7408
+ ...makeRefOpsForDocument(
7409
+ itemKey,
7410
+ collection == null ? void 0 : collection.name,
7411
+ collectionReferences,
7412
+ aliasedData,
7413
+ "del",
7414
+ database.contentLevel
7415
+ ),
6792
7416
  ...makeIndexOpsForDocument(
6793
7417
  itemKey,
6794
7418
  collection.name,
@@ -6797,6 +7421,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6797
7421
  "del",
6798
7422
  database.contentLevel
6799
7423
  ),
7424
+ // folder indexes
6800
7425
  ...makeIndexOpsForDocument(
6801
7426
  itemKey,
6802
7427
  `${collection == null ? void 0 : collection.name}_${folderKey}`,
@@ -6863,14 +7488,14 @@ var getChangedFiles = async ({
6863
7488
  const rootDir = await findGitRoot(dir);
6864
7489
  let pathPrefix = "";
6865
7490
  if (rootDir !== dir) {
6866
- pathPrefix = (0, import_schema_tools3.normalizePath)(dir.substring(rootDir.length + 1));
7491
+ pathPrefix = (0, import_schema_tools4.normalizePath)(dir.substring(rootDir.length + 1));
6867
7492
  }
6868
7493
  await import_isomorphic_git.default.walk({
6869
7494
  fs: fs4,
6870
7495
  dir: rootDir,
6871
7496
  trees: [import_isomorphic_git.default.TREE({ ref: from }), import_isomorphic_git.default.TREE({ ref: to })],
6872
7497
  map: async function(filename, [A, B]) {
6873
- const relativePath = (0, import_schema_tools3.normalizePath)(filename).substring(pathPrefix.length);
7498
+ const relativePath = (0, import_schema_tools4.normalizePath)(filename).substring(pathPrefix.length);
6874
7499
  let matches = false;
6875
7500
  for (const [key, matcher] of Object.entries(pathFilter)) {
6876
7501
  if (relativePath.startsWith(key)) {
@@ -7012,17 +7637,26 @@ var IsomorphicBridge = class {
7012
7637
  getAuthor() {
7013
7638
  return {
7014
7639
  ...this.author,
7015
- timestamp: Math.round(new Date().getTime() / 1e3),
7640
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7016
7641
  timezoneOffset: 0
7017
7642
  };
7018
7643
  }
7019
7644
  getCommitter() {
7020
7645
  return {
7021
7646
  ...this.committer,
7022
- timestamp: Math.round(new Date().getTime() / 1e3),
7647
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7023
7648
  timezoneOffset: 0
7024
7649
  };
7025
7650
  }
7651
+ /**
7652
+ * Recursively populate paths matching `pattern` for the given `entry`
7653
+ *
7654
+ * @param pattern - pattern to filter paths by
7655
+ * @param entry - TreeEntry to start building list from
7656
+ * @param path - base path
7657
+ * @param results
7658
+ * @private
7659
+ */
7026
7660
  async listEntries({
7027
7661
  pattern,
7028
7662
  entry,
@@ -7055,6 +7689,15 @@ var IsomorphicBridge = class {
7055
7689
  });
7056
7690
  }
7057
7691
  }
7692
+ /**
7693
+ * For the specified path, returns an object with an array containing the parts of the path (pathParts)
7694
+ * and an array containing the WalkerEntry objects for the path parts (pathEntries). Any null elements in the
7695
+ * pathEntries are placeholders for non-existent entries.
7696
+ *
7697
+ * @param path - path being resolved
7698
+ * @param ref - ref to resolve path entries for
7699
+ * @private
7700
+ */
7058
7701
  async resolvePathEntries(path7, ref) {
7059
7702
  let pathParts = path7.split("/");
7060
7703
  const result = await import_isomorphic_git2.default.walk({
@@ -7085,6 +7728,17 @@ var IsomorphicBridge = class {
7085
7728
  }
7086
7729
  return { pathParts, pathEntries };
7087
7730
  }
7731
+ /**
7732
+ * Updates tree entry and associated parent tree entries
7733
+ *
7734
+ * @param existingOid - the existing OID
7735
+ * @param updatedOid - the updated OID
7736
+ * @param path - the path of the entry being updated
7737
+ * @param type - the type of the entry being updated (blob or tree)
7738
+ * @param pathEntries - parent path entries
7739
+ * @param pathParts - parent path parts
7740
+ * @private
7741
+ */
7088
7742
  async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
7089
7743
  const lastIdx = pathEntries.length - 1;
7090
7744
  const parentEntry = pathEntries[lastIdx];
@@ -7140,6 +7794,13 @@ var IsomorphicBridge = class {
7140
7794
  );
7141
7795
  }
7142
7796
  }
7797
+ /**
7798
+ * Creates a commit for the specified tree and updates the specified ref to point to the commit
7799
+ *
7800
+ * @param treeSha - sha of the new tree
7801
+ * @param ref - the ref that should be updated
7802
+ * @private
7803
+ */
7143
7804
  async commitTree(treeSha, ref) {
7144
7805
  const commitSha = await import_isomorphic_git2.default.writeCommit({
7145
7806
  ...this.isomorphicConfig,
@@ -7152,6 +7813,7 @@ var IsomorphicBridge = class {
7152
7813
  })
7153
7814
  ],
7154
7815
  message: this.commitMessage,
7816
+ // TODO these should be configurable
7155
7817
  author: this.getAuthor(),
7156
7818
  committer: this.getCommitter()
7157
7819
  }
@@ -7390,5 +8052,5 @@ var buildSchema = async (config, flags) => {
7390
8052
  transformDocument,
7391
8053
  transformDocumentIntoPayload
7392
8054
  });
7393
- //! Replaces _.flattenDeep()
7394
8055
  //! Replaces _.get()
8056
+ //! Replaces _.flattenDeep()