@tinacms/graphql 0.0.0-c8b1d84-20241003015733 → 0.0.0-cef656e-20250119001929

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -68,6 +68,15 @@ var SysFieldDefinition = {
68
68
  selectionSet: {
69
69
  kind: "SelectionSet",
70
70
  selections: [
71
+ // {
72
+ // kind: 'Field' as const,
73
+ // name: {
74
+ // kind: 'Name' as const,
75
+ // value: 'title',
76
+ // },
77
+ // arguments: [],
78
+ // directives: [],
79
+ // },
71
80
  {
72
81
  kind: "Field",
73
82
  name: {
@@ -86,6 +95,15 @@ var SysFieldDefinition = {
86
95
  arguments: [],
87
96
  directives: []
88
97
  },
98
+ {
99
+ kind: "Field",
100
+ name: {
101
+ kind: "Name",
102
+ value: "hasReferences"
103
+ },
104
+ arguments: [],
105
+ directives: []
106
+ },
89
107
  {
90
108
  kind: "Field",
91
109
  name: {
@@ -126,6 +144,10 @@ var SysFieldDefinition = {
126
144
  }
127
145
  };
128
146
  var astBuilder = {
147
+ /**
148
+ * `FormFieldBuilder` acts as a shortcut to building an entire `ObjectTypeDefinition`, we use this
149
+ * because all Tina field objects share a common set of fields ('name', 'label', 'component')
150
+ */
129
151
  FormFieldBuilder: ({
130
152
  name,
131
153
  additionalFields
@@ -349,6 +371,8 @@ var astBuilder = {
349
371
  kind: "Name",
350
372
  value: name
351
373
  },
374
+ // @ts-ignore FIXME; this is being handled properly but we're lying to
375
+ // ts and then fixing it in the `extractInlineTypes` function
352
376
  fields
353
377
  }),
354
378
  UnionTypeDefinition: ({
@@ -361,6 +385,8 @@ var astBuilder = {
361
385
  value: name
362
386
  },
363
387
  directives: [],
388
+ // @ts-ignore FIXME; this is being handled properly but we're lying to
389
+ // ts and then fixing it in the `extractInlineTypes` function
364
390
  types: types.map((name2) => ({
365
391
  kind: "NamedType",
366
392
  name: {
@@ -457,8 +483,11 @@ var astBuilder = {
457
483
  string: "String",
458
484
  boolean: "Boolean",
459
485
  number: "Float",
486
+ // FIXME - needs to be float or int
460
487
  datetime: "String",
488
+ // FIXME
461
489
  image: "String",
490
+ // FIXME
462
491
  text: "String"
463
492
  };
464
493
  return scalars[type];
@@ -957,8 +986,7 @@ var astBuilder = {
957
986
  }
958
987
  };
959
988
  var capitalize = (s) => {
960
- if (typeof s !== "string")
961
- return "";
989
+ if (typeof s !== "string") return "";
962
990
  return s.charAt(0).toUpperCase() + s.slice(1);
963
991
  };
964
992
  var extractInlineTypes = (item) => {
@@ -1001,41 +1029,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1001
1029
  yield maybeNode;
1002
1030
  visited.add(maybeNode);
1003
1031
  }
1004
- function addNamespaceToSchema(maybeNode, namespace = []) {
1005
- if (typeof maybeNode === "string") {
1006
- return maybeNode;
1007
- }
1008
- if (typeof maybeNode === "boolean") {
1009
- return maybeNode;
1010
- }
1011
- const newNode = maybeNode;
1012
- const keys = Object.keys(maybeNode);
1013
- Object.values(maybeNode).map((m, index) => {
1014
- const key = keys[index];
1015
- if (Array.isArray(m)) {
1016
- newNode[key] = m.map((element) => {
1017
- if (!element) {
1018
- return;
1019
- }
1020
- if (!element.hasOwnProperty("name")) {
1021
- return element;
1022
- }
1023
- const value = element.name || element.value;
1024
- return addNamespaceToSchema(element, [...namespace, value]);
1025
- });
1026
- } else {
1027
- if (!m) {
1028
- return;
1029
- }
1030
- if (!m.hasOwnProperty("name")) {
1031
- newNode[key] = m;
1032
- } else {
1033
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1034
- }
1035
- }
1036
- });
1037
- return { ...newNode, namespace };
1038
- }
1039
1032
  var generateNamespacedFieldName = (names, suffix = "") => {
1040
1033
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1041
1034
  };
@@ -1195,6 +1188,11 @@ var scalarDefinitions = [
1195
1188
  required: true,
1196
1189
  type: astBuilder.TYPES.String
1197
1190
  }),
1191
+ astBuilder.FieldDefinition({
1192
+ name: "hasReferences",
1193
+ required: false,
1194
+ type: astBuilder.TYPES.Boolean
1195
+ }),
1198
1196
  astBuilder.FieldDefinition({
1199
1197
  name: "breadcrumbs",
1200
1198
  required: true,
@@ -1408,6 +1406,19 @@ var Builder = class {
1408
1406
  this.addToLookupMap = (lookup) => {
1409
1407
  this.lookupMap[lookup.type] = lookup;
1410
1408
  };
1409
+ /**
1410
+ * ```graphql
1411
+ * # ex.
1412
+ * {
1413
+ * getCollection(collection: $collection) {
1414
+ * name
1415
+ * documents {...}
1416
+ * }
1417
+ * }
1418
+ * ```
1419
+ *
1420
+ * @param collections
1421
+ */
1411
1422
  this.buildCollectionDefinition = async (collections) => {
1412
1423
  const name = "collection";
1413
1424
  const typeName = "Collection";
@@ -1478,6 +1489,19 @@ var Builder = class {
1478
1489
  required: true
1479
1490
  });
1480
1491
  };
1492
+ /**
1493
+ * ```graphql
1494
+ * # ex.
1495
+ * {
1496
+ * getCollections {
1497
+ * name
1498
+ * documents {...}
1499
+ * }
1500
+ * }
1501
+ * ```
1502
+ *
1503
+ * @param collections
1504
+ */
1481
1505
  this.buildMultiCollectionDefinition = async (collections) => {
1482
1506
  const name = "collections";
1483
1507
  const typeName = "Collection";
@@ -1488,6 +1512,17 @@ var Builder = class {
1488
1512
  required: true
1489
1513
  });
1490
1514
  };
1515
+ /**
1516
+ * ```graphql
1517
+ * # ex.
1518
+ * {
1519
+ * node(id: $id) {
1520
+ * id
1521
+ * data {...}
1522
+ * }
1523
+ * }
1524
+ * ```
1525
+ */
1491
1526
  this.multiNodeDocument = async () => {
1492
1527
  const name = "node";
1493
1528
  const args = [
@@ -1508,6 +1543,19 @@ var Builder = class {
1508
1543
  required: true
1509
1544
  });
1510
1545
  };
1546
+ /**
1547
+ * ```graphql
1548
+ * # ex.
1549
+ * {
1550
+ * getDocument(collection: $collection, relativePath: $relativePath) {
1551
+ * id
1552
+ * data {...}
1553
+ * }
1554
+ * }
1555
+ * ```
1556
+ *
1557
+ * @param collections
1558
+ */
1511
1559
  this.multiCollectionDocument = async (collections) => {
1512
1560
  const name = "document";
1513
1561
  const args = [
@@ -1533,6 +1581,19 @@ var Builder = class {
1533
1581
  required: true
1534
1582
  });
1535
1583
  };
1584
+ /**
1585
+ * ```graphql
1586
+ * # ex.
1587
+ * {
1588
+ * addPendingDocument(collection: $collection, relativePath: $relativePath, params: $params) {
1589
+ * id
1590
+ * data {...}
1591
+ * }
1592
+ * }
1593
+ * ```
1594
+ *
1595
+ * @param collections
1596
+ */
1536
1597
  this.addMultiCollectionDocumentMutation = async () => {
1537
1598
  return astBuilder.FieldDefinition({
1538
1599
  name: "addPendingDocument",
@@ -1557,6 +1618,19 @@ var Builder = class {
1557
1618
  type: astBuilder.TYPES.MultiCollectionDocument
1558
1619
  });
1559
1620
  };
1621
+ /**
1622
+ * ```graphql
1623
+ * # ex.
1624
+ * {
1625
+ * createDocument(relativePath: $relativePath, params: $params) {
1626
+ * id
1627
+ * data {...}
1628
+ * }
1629
+ * }
1630
+ * ```
1631
+ *
1632
+ * @param collections
1633
+ */
1560
1634
  this.buildCreateCollectionDocumentMutation = async (collections) => {
1561
1635
  return astBuilder.FieldDefinition({
1562
1636
  name: "createDocument",
@@ -1584,6 +1658,19 @@ var Builder = class {
1584
1658
  type: astBuilder.TYPES.MultiCollectionDocument
1585
1659
  });
1586
1660
  };
1661
+ /**
1662
+ * ```graphql
1663
+ * # ex.
1664
+ * {
1665
+ * updateDocument(relativePath: $relativePath, params: $params) {
1666
+ * id
1667
+ * data {...}
1668
+ * }
1669
+ * }
1670
+ * ```
1671
+ *
1672
+ * @param collections
1673
+ */
1587
1674
  this.buildUpdateCollectionDocumentMutation = async (collections) => {
1588
1675
  return astBuilder.FieldDefinition({
1589
1676
  name: "updateDocument",
@@ -1611,6 +1698,19 @@ var Builder = class {
1611
1698
  type: astBuilder.TYPES.MultiCollectionDocument
1612
1699
  });
1613
1700
  };
1701
+ /**
1702
+ * ```graphql
1703
+ * # ex.
1704
+ * {
1705
+ * deleteDocument(relativePath: $relativePath, params: $params) {
1706
+ * id
1707
+ * data {...}
1708
+ * }
1709
+ * }
1710
+ * ```
1711
+ *
1712
+ * @param collections
1713
+ */
1614
1714
  this.buildDeleteCollectionDocumentMutation = async (collections) => {
1615
1715
  return astBuilder.FieldDefinition({
1616
1716
  name: "deleteDocument",
@@ -1630,6 +1730,19 @@ var Builder = class {
1630
1730
  type: astBuilder.TYPES.MultiCollectionDocument
1631
1731
  });
1632
1732
  };
1733
+ /**
1734
+ * ```graphql
1735
+ * # ex.
1736
+ * {
1737
+ * createFolder(folderName: $folderName, params: $params) {
1738
+ * id
1739
+ * data {...}
1740
+ * }
1741
+ * }
1742
+ * ```
1743
+ *
1744
+ * @param collections
1745
+ */
1633
1746
  this.buildCreateCollectionFolderMutation = async () => {
1634
1747
  return astBuilder.FieldDefinition({
1635
1748
  name: "createFolder",
@@ -1649,6 +1762,19 @@ var Builder = class {
1649
1762
  type: astBuilder.TYPES.MultiCollectionDocument
1650
1763
  });
1651
1764
  };
1765
+ /**
1766
+ * ```graphql
1767
+ * # ex.
1768
+ * {
1769
+ * getPostDocument(relativePath: $relativePath) {
1770
+ * id
1771
+ * data {...}
1772
+ * }
1773
+ * }
1774
+ * ```
1775
+ *
1776
+ * @param collection
1777
+ */
1652
1778
  this.collectionDocument = async (collection) => {
1653
1779
  const name = NAMER.queryName([collection.name]);
1654
1780
  const type = await this._buildCollectionDocumentType(collection);
@@ -1709,6 +1835,20 @@ var Builder = class {
1709
1835
  const args = [];
1710
1836
  return astBuilder.FieldDefinition({ type, name, args, required: false });
1711
1837
  };
1838
+ /**
1839
+ * Turns a collection into a fragment that gets updated on build. This fragment does not resolve references
1840
+ * ```graphql
1841
+ * # ex.
1842
+ * fragment AuthorsParts on Authors {
1843
+ * name
1844
+ * avatar
1845
+ * ...
1846
+ * }
1847
+ * ```
1848
+ *
1849
+ * @public
1850
+ * @param collection a Tina Cloud collection
1851
+ */
1712
1852
  this.collectionFragment = async (collection) => {
1713
1853
  const name = NAMER.dataTypeName(collection.namespace);
1714
1854
  const fragmentName = NAMER.fragmentName(collection.namespace);
@@ -1722,6 +1862,20 @@ var Builder = class {
1722
1862
  selections: filterSelections(selections)
1723
1863
  });
1724
1864
  };
1865
+ /**
1866
+ * Given a collection this function returns its selections set. For example for Post this would return
1867
+ *
1868
+ * "
1869
+ * body
1870
+ * title
1871
+ * ... on Author {
1872
+ * name
1873
+ * heroImg
1874
+ * }
1875
+ *
1876
+ * But in the AST format
1877
+ *
1878
+ * */
1725
1879
  this._getCollectionFragmentSelections = async (collection, depth) => {
1726
1880
  const selections = [];
1727
1881
  selections.push({
@@ -1803,9 +1957,9 @@ var Builder = class {
1803
1957
  ]
1804
1958
  });
1805
1959
  }
1960
+ // TODO: Should we throw here?
1806
1961
  case "reference":
1807
- if (depth >= this.maxDepth)
1808
- return false;
1962
+ if (depth >= this.maxDepth) return false;
1809
1963
  if (!("collections" in field)) {
1810
1964
  return false;
1811
1965
  }
@@ -1837,6 +1991,7 @@ var Builder = class {
1837
1991
  name: field.name,
1838
1992
  selections: [
1839
1993
  ...selections,
1994
+ // This is ... on Document { id }
1840
1995
  {
1841
1996
  kind: "InlineFragment",
1842
1997
  typeCondition: {
@@ -1867,6 +2022,19 @@ var Builder = class {
1867
2022
  });
1868
2023
  }
1869
2024
  };
2025
+ /**
2026
+ * ```graphql
2027
+ * # ex.
2028
+ * mutation {
2029
+ * updatePostDocument(relativePath: $relativePath, params: $params) {
2030
+ * id
2031
+ * data {...}
2032
+ * }
2033
+ * }
2034
+ * ```
2035
+ *
2036
+ * @param collection
2037
+ */
1870
2038
  this.updateCollectionDocumentMutation = async (collection) => {
1871
2039
  return astBuilder.FieldDefinition({
1872
2040
  type: await this._buildCollectionDocumentType(collection),
@@ -1886,6 +2054,19 @@ var Builder = class {
1886
2054
  ]
1887
2055
  });
1888
2056
  };
2057
+ /**
2058
+ * ```graphql
2059
+ * # ex.
2060
+ * mutation {
2061
+ * createPostDocument(relativePath: $relativePath, params: $params) {
2062
+ * id
2063
+ * data {...}
2064
+ * }
2065
+ * }
2066
+ * ```
2067
+ *
2068
+ * @param collection
2069
+ */
1889
2070
  this.createCollectionDocumentMutation = async (collection) => {
1890
2071
  return astBuilder.FieldDefinition({
1891
2072
  type: await this._buildCollectionDocumentType(collection),
@@ -1905,6 +2086,22 @@ var Builder = class {
1905
2086
  ]
1906
2087
  });
1907
2088
  };
2089
+ /**
2090
+ * ```graphql
2091
+ * # ex.
2092
+ * {
2093
+ * getPostList(first: 10) {
2094
+ * edges {
2095
+ * node {
2096
+ * id
2097
+ * }
2098
+ * }
2099
+ * }
2100
+ * }
2101
+ * ```
2102
+ *
2103
+ * @param collection
2104
+ */
1908
2105
  this.collectionDocumentList = async (collection) => {
1909
2106
  const connectionName = NAMER.referenceConnectionType(collection.namespace);
1910
2107
  this.addToLookupMap({
@@ -1920,6 +2117,10 @@ var Builder = class {
1920
2117
  collection
1921
2118
  });
1922
2119
  };
2120
+ /**
2121
+ * GraphQL type definitions which remain unchanged regardless
2122
+ * of the supplied Tina schema. Ex. "node" interface
2123
+ */
1923
2124
  this.buildStaticDefinitions = () => staticDefinitions;
1924
2125
  this._buildCollectionDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
1925
2126
  const documentTypeName = NAMER.documentTypeName(collection.namespace);
@@ -2424,6 +2625,7 @@ var Builder = class {
2424
2625
  name: NAMER.dataFilterTypeName(namespace),
2425
2626
  fields: await sequential(collections, async (collection2) => {
2426
2627
  return astBuilder.InputValueDefinition({
2628
+ // @ts-ignore
2427
2629
  name: collection2.name,
2428
2630
  type: NAMER.dataFilterTypeName(collection2.namespace)
2429
2631
  });
@@ -2612,7 +2814,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2612
2814
  ]
2613
2815
  });
2614
2816
  };
2615
- this.maxDepth = config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2817
+ this.maxDepth = // @ts-ignore
2818
+ config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2616
2819
  this.tinaSchema = config.tinaSchema;
2617
2820
  this.lookupMap = {};
2618
2821
  }
@@ -2623,8 +2826,7 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2623
2826
  selections.push(field);
2624
2827
  });
2625
2828
  const filteredSelections = filterSelections(selections);
2626
- if (!filteredSelections.length)
2627
- return false;
2829
+ if (!filteredSelections.length) return false;
2628
2830
  return astBuilder.InlineFragmentDefinition({
2629
2831
  selections: filteredSelections,
2630
2832
  name: NAMER.dataTypeName(template.namespace)
@@ -2661,6 +2863,7 @@ var filterSelections = (arr) => {
2661
2863
  import { TinaSchema } from "@tinacms/schema-tools";
2662
2864
 
2663
2865
  // src/schema/validate.ts
2866
+ import { addNamespaceToSchema } from "@tinacms/schema-tools";
2664
2867
  import deepClone from "lodash.clonedeep";
2665
2868
  import * as yup2 from "yup";
2666
2869
  import {
@@ -2707,6 +2910,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2707
2910
  }).map((x) => `${x.path}${x.format || "md"}`);
2708
2911
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2709
2912
  throw new Error(
2913
+ // TODO: add a link to the docs
2710
2914
  "Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
2711
2915
  );
2712
2916
  }
@@ -2815,7 +3019,7 @@ var validateField = async (field) => {
2815
3019
  // package.json
2816
3020
  var package_default = {
2817
3021
  name: "@tinacms/graphql",
2818
- version: "1.5.4",
3022
+ version: "1.5.10",
2819
3023
  main: "dist/index.js",
2820
3024
  module: "dist/index.mjs",
2821
3025
  typings: "dist/index.d.ts",
@@ -2842,8 +3046,7 @@ var package_default = {
2842
3046
  build: "tinacms-scripts build",
2843
3047
  docs: "pnpm typedoc",
2844
3048
  serve: "pnpm nodemon dist/server.js",
2845
- test: "jest",
2846
- "test-watch": "jest --watch"
3049
+ test: "vitest"
2847
3050
  },
2848
3051
  dependencies: {
2849
3052
  "@iarna/toml": "^2.2.5",
@@ -2859,7 +3062,7 @@ var package_default = {
2859
3062
  "isomorphic-git": "^1.27.1",
2860
3063
  "js-sha1": "^0.6.0",
2861
3064
  "js-yaml": "^3.14.1",
2862
- "jsonpath-plus": "^6.0.1",
3065
+ "jsonpath-plus": "10.1.0",
2863
3066
  "lodash.clonedeep": "^4.5.0",
2864
3067
  "lodash.set": "^4.3.2",
2865
3068
  "lodash.uniqby": "^4.7.0",
@@ -2884,24 +3087,23 @@ var package_default = {
2884
3087
  "@types/estree": "^0.0.50",
2885
3088
  "@types/express": "^4.17.21",
2886
3089
  "@types/fs-extra": "^9.0.13",
2887
- "@types/jest": "^26.0.24",
2888
3090
  "@types/js-yaml": "^3.12.10",
2889
3091
  "@types/lodash.camelcase": "^4.3.9",
2890
3092
  "@types/lodash.upperfirst": "^4.3.9",
2891
3093
  "@types/lru-cache": "^5.1.1",
2892
3094
  "@types/mdast": "^3.0.15",
2893
3095
  "@types/micromatch": "^4.0.9",
2894
- "@types/node": "^22.7.4",
3096
+ "@types/node": "^22.9.0",
2895
3097
  "@types/normalize-path": "^3.0.2",
2896
3098
  "@types/ws": "^7.4.7",
2897
3099
  "@types/yup": "^0.29.14",
2898
- jest: "^29.7.0",
2899
- "jest-diff": "^29.7.0",
2900
3100
  "jest-file-snapshot": "^0.5.0",
2901
- "jest-matcher-utils": "^29.7.0",
2902
3101
  "memory-level": "^1.0.0",
2903
3102
  nodemon: "3.1.4",
2904
- typescript: "^5.6.2"
3103
+ typescript: "^5.6.3",
3104
+ vite: "^4.3.9",
3105
+ vitest: "^0.32.2",
3106
+ zod: "^3.23.8"
2905
3107
  }
2906
3108
  };
2907
3109
 
@@ -2972,6 +3174,7 @@ var _buildFragments = async (builder, tinaSchema) => {
2972
3174
  const fragDoc = {
2973
3175
  kind: "Document",
2974
3176
  definitions: uniqBy2(
3177
+ // @ts-ignore
2975
3178
  extractInlineTypes(fragmentDefinitionsFields),
2976
3179
  (node) => node.name.value
2977
3180
  )
@@ -2994,6 +3197,7 @@ var _buildQueries = async (builder, tinaSchema) => {
2994
3197
  fragName,
2995
3198
  queryName: queryListName,
2996
3199
  filterType: queryFilterTypeName,
3200
+ // look for flag to see if the data layer is enabled
2997
3201
  dataLayer: Boolean(
2998
3202
  tinaSchema.config?.meta?.flags?.find((x) => x === "experimentalData")
2999
3203
  )
@@ -3003,6 +3207,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3003
3207
  const queryDoc = {
3004
3208
  kind: "Document",
3005
3209
  definitions: uniqBy2(
3210
+ // @ts-ignore
3006
3211
  extractInlineTypes(operationsDefinitions),
3007
3212
  (node) => node.name.value
3008
3213
  )
@@ -3091,6 +3296,7 @@ var _buildSchema = async (builder, tinaSchema) => {
3091
3296
  return {
3092
3297
  kind: "Document",
3093
3298
  definitions: uniqBy2(
3299
+ // @ts-ignore
3094
3300
  extractInlineTypes(definitions),
3095
3301
  (node) => node.name.value
3096
3302
  )
@@ -3107,6 +3313,9 @@ import isValid from "date-fns/isValid/index.js";
3107
3313
  // src/mdx/index.ts
3108
3314
  import { parseMDX, stringifyMDX } from "@tinacms/mdx";
3109
3315
 
3316
+ // src/resolver/index.ts
3317
+ import { JSONPath as JSONPath2 } from "jsonpath-plus";
3318
+
3110
3319
  // src/resolver/error.ts
3111
3320
  var TinaGraphQLError = class extends Error {
3112
3321
  constructor(message, extensions) {
@@ -3292,8 +3501,7 @@ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, s
3292
3501
  }
3293
3502
  if (Array.isArray(value)) {
3294
3503
  return value.map((v) => {
3295
- if (!v || typeof v !== "string")
3296
- return v;
3504
+ if (!v || typeof v !== "string") return v;
3297
3505
  const cleanMediaRoot = cleanUpSlashes(
3298
3506
  schema.config.media.tina.mediaRoot
3299
3507
  );
@@ -3321,8 +3529,7 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
3321
3529
  }
3322
3530
  if (Array.isArray(value)) {
3323
3531
  return value.map((v) => {
3324
- if (!v || typeof v !== "string")
3325
- return v;
3532
+ if (!v || typeof v !== "string") return v;
3326
3533
  const strippedValue = v.replace(cleanMediaRoot, "");
3327
3534
  return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3328
3535
  });
@@ -3340,8 +3547,7 @@ var cleanUpSlashes = (path7) => {
3340
3547
  return "";
3341
3548
  };
3342
3549
  var hasTinaMediaConfig = (schema) => {
3343
- if (!schema.config?.media?.tina)
3344
- return false;
3550
+ if (!schema.config?.media?.tina) return false;
3345
3551
  if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
3346
3552
  return false;
3347
3553
  return true;
@@ -3385,6 +3591,7 @@ var LevelProxyHandler = {
3385
3591
  } else if (property === "sublevel") {
3386
3592
  return (...args) => {
3387
3593
  return new Proxy(
3594
+ // eslint-disable-next-line prefer-spread
3388
3595
  target[property].apply(target, args),
3389
3596
  LevelProxyHandler
3390
3597
  );
@@ -4261,6 +4468,7 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4261
4468
  result.push({
4262
4469
  type: opType,
4263
4470
  key: `${collection.path}/${subFolderKey}.${collection.format}`,
4471
+ // replace the root with the collection path
4264
4472
  sublevel: indexSublevel,
4265
4473
  value: {}
4266
4474
  });
@@ -4348,7 +4556,16 @@ var stringEscaper = makeStringEscaper(
4348
4556
  var createResolver = (args) => {
4349
4557
  return new Resolver(args);
4350
4558
  };
4351
- var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4559
+ var resolveFieldData = async (args) => {
4560
+ const {
4561
+ field: { namespace, ...field },
4562
+ rawData,
4563
+ accumulator,
4564
+ tinaSchema,
4565
+ config,
4566
+ isAudit,
4567
+ context
4568
+ } = args;
4352
4569
  if (!rawData) {
4353
4570
  return void 0;
4354
4571
  }
@@ -4375,6 +4592,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4375
4592
  case "password":
4376
4593
  accumulator[field.name] = {
4377
4594
  value: void 0,
4595
+ // never resolve the password hash
4378
4596
  passwordChangeRequired: value["passwordChangeRequired"] ?? false
4379
4597
  };
4380
4598
  break;
@@ -4387,9 +4605,11 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4387
4605
  break;
4388
4606
  case "rich-text":
4389
4607
  const tree = parseMDX(
4608
+ // @ts-ignore value is unknown
4390
4609
  value,
4391
4610
  field,
4392
- (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4611
+ (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema),
4612
+ context
4393
4613
  );
4394
4614
  if (tree?.children[0]?.type === "invalid_markdown") {
4395
4615
  if (isAudit) {
@@ -4420,14 +4640,15 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4420
4640
  });
4421
4641
  const payload = {};
4422
4642
  await sequential(template.fields, async (field2) => {
4423
- await resolveFieldData(
4424
- field2,
4425
- item,
4426
- payload,
4643
+ await resolveFieldData({
4644
+ field: field2,
4645
+ rawData: item,
4646
+ accumulator: payload,
4427
4647
  tinaSchema,
4428
4648
  config,
4429
- isAudit
4430
- );
4649
+ isAudit,
4650
+ context
4651
+ });
4431
4652
  });
4432
4653
  const isUnion = !!field.templates;
4433
4654
  return isUnion ? {
@@ -4448,14 +4669,15 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4448
4669
  });
4449
4670
  const payload = {};
4450
4671
  await sequential(template.fields, async (field2) => {
4451
- await resolveFieldData(
4452
- field2,
4453
- value,
4454
- payload,
4672
+ await resolveFieldData({
4673
+ field: field2,
4674
+ rawData: value,
4675
+ accumulator: payload,
4455
4676
  tinaSchema,
4456
4677
  config,
4457
- isAudit
4458
- );
4678
+ isAudit,
4679
+ context
4680
+ });
4459
4681
  });
4460
4682
  const isUnion = !!field.templates;
4461
4683
  accumulator[field.name] = isUnion ? {
@@ -4469,7 +4691,8 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4469
4691
  }
4470
4692
  return accumulator;
4471
4693
  };
4472
- var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit) => {
4694
+ var transformDocumentIntoPayload = async (args) => {
4695
+ const { fullPath, rawData, tinaSchema, config, isAudit, context } = args;
4473
4696
  const collection = tinaSchema.getCollection(rawData._collection);
4474
4697
  try {
4475
4698
  const template = tinaSchema.getTemplateForData({
@@ -4489,14 +4712,15 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4489
4712
  };
4490
4713
  try {
4491
4714
  await sequential(template.fields, async (field) => {
4492
- return resolveFieldData(
4715
+ return resolveFieldData({
4493
4716
  field,
4494
4717
  rawData,
4495
- data,
4718
+ accumulator: data,
4496
4719
  tinaSchema,
4497
4720
  config,
4498
- isAudit
4499
- );
4721
+ isAudit,
4722
+ context
4723
+ });
4500
4724
  });
4501
4725
  } catch (e) {
4502
4726
  throw new TinaParseDocumentError({
@@ -4523,6 +4747,7 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4523
4747
  basename,
4524
4748
  filename,
4525
4749
  extension,
4750
+ hasReferences: args.hasReferences,
4526
4751
  path: fullPath,
4527
4752
  relativePath,
4528
4753
  breadcrumbs,
@@ -4542,13 +4767,34 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4542
4767
  throw e;
4543
4768
  }
4544
4769
  };
4770
+ var updateObjectWithJsonPath = (obj, path7, newValue) => {
4771
+ if (!path7.includes(".") && !path7.includes("[")) {
4772
+ if (path7 in obj) {
4773
+ obj[path7] = newValue;
4774
+ }
4775
+ return obj;
4776
+ }
4777
+ const parentPath = path7.replace(/\.[^.]+$/, "");
4778
+ const keyToUpdate = path7.match(/[^.]+$/)[0];
4779
+ const parents = JSONPath2({ path: parentPath, json: obj, resultType: "value" });
4780
+ if (parents.length > 0) {
4781
+ parents.forEach((parent) => {
4782
+ if (parent && typeof parent === "object" && keyToUpdate in parent) {
4783
+ parent[keyToUpdate] = newValue;
4784
+ }
4785
+ });
4786
+ }
4787
+ return obj;
4788
+ };
4545
4789
  var Resolver = class {
4546
4790
  constructor(init) {
4547
4791
  this.init = init;
4792
+ this.context = {};
4548
4793
  this.resolveCollection = async (args, collectionName, hasDocuments) => {
4549
4794
  const collection = this.tinaSchema.getCollection(collectionName);
4550
4795
  const extraFields = {};
4551
4796
  return {
4797
+ // return the collection and hasDocuments to resolve documents at a lower level
4552
4798
  documents: { collection, hasDocuments },
4553
4799
  ...collection,
4554
4800
  ...extraFields
@@ -4574,27 +4820,33 @@ var Resolver = class {
4574
4820
  path: rawData["__folderPath"]
4575
4821
  };
4576
4822
  } else {
4577
- return transformDocumentIntoPayload(
4823
+ this.context = { ...rawData };
4824
+ return transformDocumentIntoPayload({
4578
4825
  fullPath,
4579
4826
  rawData,
4580
- this.tinaSchema,
4581
- this.config,
4582
- this.isAudit
4583
- );
4827
+ tinaSchema: this.tinaSchema,
4828
+ config: this.config,
4829
+ isAudit: this.isAudit,
4830
+ context: this.context
4831
+ });
4584
4832
  }
4585
4833
  };
4586
- this.getDocument = async (fullPath) => {
4834
+ this.getDocument = async (fullPath, opts = {}) => {
4587
4835
  if (typeof fullPath !== "string") {
4588
4836
  throw new Error(`fullPath must be of type string for getDocument request`);
4589
4837
  }
4590
4838
  const rawData = await this.getRaw(fullPath);
4591
- return transformDocumentIntoPayload(
4839
+ this.context = { ...rawData };
4840
+ const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4841
+ return transformDocumentIntoPayload({
4592
4842
  fullPath,
4593
4843
  rawData,
4594
- this.tinaSchema,
4595
- this.config,
4596
- this.isAudit
4597
- );
4844
+ tinaSchema: this.tinaSchema,
4845
+ config: this.config,
4846
+ isAudit: this.isAudit,
4847
+ context: this.context,
4848
+ hasReferences
4849
+ });
4598
4850
  };
4599
4851
  this.deleteDocument = async (fullPath) => {
4600
4852
  if (typeof fullPath !== "string") {
@@ -4633,7 +4885,9 @@ var Resolver = class {
4633
4885
  );
4634
4886
  } else {
4635
4887
  return this.buildFieldMutations(
4888
+ // @ts-ignore FIXME Argument of type 'string | object' is not assignable to parameter of type '{ [fieldName: string]: string | object | (string | object)[]; }'
4636
4889
  fieldValue,
4890
+ //@ts-ignore
4637
4891
  objectTemplate,
4638
4892
  existingData
4639
4893
  );
@@ -4645,6 +4899,7 @@ var Resolver = class {
4645
4899
  fieldValue.map(async (item) => {
4646
4900
  if (typeof item === "string") {
4647
4901
  throw new Error(
4902
+ //@ts-ignore
4648
4903
  `Expected object for template value for field ${field.name}`
4649
4904
  );
4650
4905
  }
@@ -4653,16 +4908,19 @@ var Resolver = class {
4653
4908
  });
4654
4909
  const [templateName] = Object.entries(item)[0];
4655
4910
  const template = templates.find(
4911
+ //@ts-ignore
4656
4912
  (template2) => template2.name === templateName
4657
4913
  );
4658
4914
  if (!template) {
4659
4915
  throw new Error(`Expected to find template ${templateName}`);
4660
4916
  }
4661
4917
  return {
4918
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4662
4919
  ...await this.buildFieldMutations(
4663
4920
  item[template.name],
4664
4921
  template
4665
4922
  ),
4923
+ //@ts-ignore
4666
4924
  _template: template.name
4667
4925
  };
4668
4926
  })
@@ -4670,6 +4928,7 @@ var Resolver = class {
4670
4928
  } else {
4671
4929
  if (typeof fieldValue === "string") {
4672
4930
  throw new Error(
4931
+ //@ts-ignore
4673
4932
  `Expected object for template value for field ${field.name}`
4674
4933
  );
4675
4934
  }
@@ -4678,16 +4937,19 @@ var Resolver = class {
4678
4937
  });
4679
4938
  const [templateName] = Object.entries(fieldValue)[0];
4680
4939
  const template = templates.find(
4940
+ //@ts-ignore
4681
4941
  (template2) => template2.name === templateName
4682
4942
  );
4683
4943
  if (!template) {
4684
4944
  throw new Error(`Expected to find template ${templateName}`);
4685
4945
  }
4686
4946
  return {
4947
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4687
4948
  ...await this.buildFieldMutations(
4688
4949
  fieldValue[template.name],
4689
4950
  template
4690
4951
  ),
4952
+ //@ts-ignore
4691
4953
  _template: template.name
4692
4954
  };
4693
4955
  }
@@ -4727,6 +4989,7 @@ var Resolver = class {
4727
4989
  return this.getDocument(realPath);
4728
4990
  }
4729
4991
  const params = await this.buildObjectMutations(
4992
+ // @ts-ignore
4730
4993
  args.params[collection.name],
4731
4994
  collection
4732
4995
  );
@@ -4742,56 +5005,65 @@ var Resolver = class {
4742
5005
  }) => {
4743
5006
  const doc = await this.getDocument(realPath);
4744
5007
  const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5008
+ let values;
4745
5009
  if (isAddPendingDocument === true) {
4746
5010
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
4747
- const params2 = this.buildParams(args);
5011
+ const params = this.buildParams(args);
4748
5012
  switch (templateInfo.type) {
4749
5013
  case "object":
4750
- if (params2) {
4751
- const values = await this.buildFieldMutations(
4752
- params2,
5014
+ if (params) {
5015
+ const mutationValues = await this.buildFieldMutations(
5016
+ params,
4753
5017
  templateInfo.template,
4754
5018
  doc?._rawData
4755
5019
  );
4756
- await this.database.put(
4757
- realPath,
4758
- { ...oldDoc, ...values },
4759
- collection.name
4760
- );
5020
+ values = { ...oldDoc, ...mutationValues };
4761
5021
  }
4762
5022
  break;
4763
- case "union":
5023
+ case "union": {
4764
5024
  await sequential(templateInfo.templates, async (template) => {
4765
- const templateParams = params2[lastItem(template.namespace)];
5025
+ const templateParams = params[lastItem(template.namespace)];
4766
5026
  if (templateParams) {
4767
5027
  if (typeof templateParams === "string") {
4768
5028
  throw new Error(
4769
5029
  `Expected to find an object for template params, but got string`
4770
5030
  );
4771
5031
  }
4772
- const values = {
5032
+ values = {
4773
5033
  ...oldDoc,
4774
5034
  ...await this.buildFieldMutations(
5035
+ // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
4775
5036
  templateParams,
4776
5037
  template,
4777
5038
  doc?._rawData
4778
5039
  ),
4779
5040
  _template: lastItem(template.namespace)
4780
5041
  };
4781
- await this.database.put(realPath, values, collection.name);
4782
5042
  }
4783
5043
  });
5044
+ }
4784
5045
  }
4785
- return this.getDocument(realPath);
5046
+ } else {
5047
+ const params = await this.buildObjectMutations(
5048
+ //@ts-expect-error FIXME: Argument of type 'unknown' is not assignable to parameter of type 'FieldParams'
5049
+ isCollectionSpecific ? args.params : args.params[collection.name],
5050
+ collection,
5051
+ doc?._rawData
5052
+ );
5053
+ values = { ...oldDoc, ...params };
4786
5054
  }
4787
- const params = await this.buildObjectMutations(
4788
- isCollectionSpecific ? args.params : args.params[collection.name],
4789
- collection,
4790
- doc?._rawData
5055
+ const _tinaEmbeds = this.context?._tinaEmbeds ? { _tinaEmbeds: this.context._tinaEmbeds } : {};
5056
+ await this.database.put(
5057
+ realPath,
5058
+ { ...values, ..._tinaEmbeds },
5059
+ collection.name
4791
5060
  );
4792
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
4793
5061
  return this.getDocument(realPath);
4794
5062
  };
5063
+ /**
5064
+ * Returns top-level fields which are not defined in the collection, so their
5065
+ * values are not eliminated from Tina when new values are saved
5066
+ */
4795
5067
  this.resolveLegacyValues = (oldDoc, collection) => {
4796
5068
  const legacyValues = {};
4797
5069
  Object.entries(oldDoc).forEach(([key, value]) => {
@@ -4896,6 +5168,22 @@ var Resolver = class {
4896
5168
  if (isDeletion) {
4897
5169
  const doc = await this.getDocument(realPath);
4898
5170
  await this.deleteDocument(realPath);
5171
+ if (await this.hasReferences(realPath, collection)) {
5172
+ const collRefs = await this.findReferences(realPath, collection);
5173
+ for (const [collection2, refFields] of Object.entries(collRefs)) {
5174
+ for (const [refPath, refs] of Object.entries(refFields)) {
5175
+ let refDoc = await this.getRaw(refPath);
5176
+ for (const ref of refs) {
5177
+ refDoc = updateObjectWithJsonPath(
5178
+ refDoc,
5179
+ ref.path.join("."),
5180
+ null
5181
+ );
5182
+ }
5183
+ await this.database.put(refPath, refDoc, collection2);
5184
+ }
5185
+ }
5186
+ }
4899
5187
  return doc;
4900
5188
  }
4901
5189
  if (isUpdateName) {
@@ -4914,6 +5202,20 @@ var Resolver = class {
4914
5202
  );
4915
5203
  await this.database.put(newRealPath, doc._rawData, collection.name);
4916
5204
  await this.deleteDocument(realPath);
5205
+ const collRefs = await this.findReferences(realPath, collection);
5206
+ for (const [collection2, refFields] of Object.entries(collRefs)) {
5207
+ for (const [refPath, refs] of Object.entries(refFields)) {
5208
+ let refDoc = await this.getRaw(refPath);
5209
+ for (const ref of refs) {
5210
+ refDoc = updateObjectWithJsonPath(
5211
+ refDoc,
5212
+ ref.path.join("."),
5213
+ newRealPath
5214
+ );
5215
+ }
5216
+ await this.database.put(refPath, refDoc, collection2);
5217
+ }
5218
+ }
4917
5219
  return this.getDocument(newRealPath);
4918
5220
  }
4919
5221
  if (alreadyExists === false) {
@@ -4927,7 +5229,10 @@ var Resolver = class {
4927
5229
  isCollectionSpecific
4928
5230
  });
4929
5231
  } else {
4930
- return this.getDocument(realPath);
5232
+ return this.getDocument(realPath, {
5233
+ collection,
5234
+ checkReferences: true
5235
+ });
4931
5236
  }
4932
5237
  };
4933
5238
  this.resolveCollectionConnections = async ({ ids }) => {
@@ -4964,6 +5269,7 @@ var Resolver = class {
4964
5269
  },
4965
5270
  collection: referencedCollection,
4966
5271
  hydrator: (path7) => path7
5272
+ // just return the path
4967
5273
  }
4968
5274
  );
4969
5275
  const { edges } = resolvedCollectionConnection;
@@ -5031,6 +5337,92 @@ var Resolver = class {
5031
5337
  }
5032
5338
  };
5033
5339
  };
5340
+ /**
5341
+ * Checks if a document has references to it
5342
+ * @param id The id of the document to check for references
5343
+ * @param c The collection to check for references
5344
+ * @returns true if the document has references, false otherwise
5345
+ */
5346
+ this.hasReferences = async (id, c) => {
5347
+ let count = 0;
5348
+ const deepRefs = this.tinaSchema.findReferences(c.name);
5349
+ for (const [collection, refs] of Object.entries(deepRefs)) {
5350
+ for (const ref of refs) {
5351
+ await this.database.query(
5352
+ {
5353
+ collection,
5354
+ filterChain: makeFilterChain({
5355
+ conditions: [
5356
+ {
5357
+ filterPath: ref.path.join("."),
5358
+ filterExpression: {
5359
+ _type: "reference",
5360
+ _list: false,
5361
+ eq: id
5362
+ }
5363
+ }
5364
+ ]
5365
+ }),
5366
+ sort: ref.field.name
5367
+ },
5368
+ (refId) => {
5369
+ count++;
5370
+ return refId;
5371
+ }
5372
+ );
5373
+ if (count) {
5374
+ return true;
5375
+ }
5376
+ }
5377
+ }
5378
+ return false;
5379
+ };
5380
+ /**
5381
+ * Finds references to a document
5382
+ * @param id the id of the document to find references to
5383
+ * @param c the collection to find references in
5384
+ * @returns references to the document in the form of a map of collection names to a list of fields that reference the document
5385
+ */
5386
+ this.findReferences = async (id, c) => {
5387
+ const references = {};
5388
+ const deepRefs = this.tinaSchema.findReferences(c.name);
5389
+ for (const [collection, refs] of Object.entries(deepRefs)) {
5390
+ for (const ref of refs) {
5391
+ await this.database.query(
5392
+ {
5393
+ collection,
5394
+ filterChain: makeFilterChain({
5395
+ conditions: [
5396
+ {
5397
+ filterPath: ref.path.join("."),
5398
+ filterExpression: {
5399
+ _type: "reference",
5400
+ _list: false,
5401
+ eq: id
5402
+ }
5403
+ }
5404
+ ]
5405
+ }),
5406
+ sort: ref.field.name
5407
+ },
5408
+ (refId) => {
5409
+ if (!references[collection]) {
5410
+ references[collection] = {};
5411
+ }
5412
+ if (!references[collection][refId]) {
5413
+ references[collection][refId] = [];
5414
+ }
5415
+ references[collection][refId].push({
5416
+ path: ref.path,
5417
+ field: ref.field
5418
+ });
5419
+ return refId;
5420
+ }
5421
+ );
5422
+ }
5423
+ }
5424
+ return references;
5425
+ };
5034
5426
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5035
5427
  const accum = {};
5036
5428
  for (const passwordField of template.fields.filter(
@@ -5099,13 +5491,15 @@ var Resolver = class {
5099
5491
  break;
5100
5492
  case "rich-text":
5101
5493
  accum[fieldName] = stringifyMDX(
5494
+ // @ts-ignore
5102
5495
  fieldValue,
5103
5496
  field,
5104
5497
  (fieldValue2) => resolveMediaCloudToRelative(
5105
5498
  fieldValue2,
5106
5499
  this.config,
5107
5500
  this.tinaSchema.schema
5108
- )
5501
+ ),
5502
+ this.context
5109
5503
  );
5110
5504
  break;
5111
5505
  case "reference":
@@ -5117,6 +5511,27 @@ var Resolver = class {
5117
5511
  }
5118
5512
  return accum;
5119
5513
  };
5514
+ /**
5515
+ * A mutation looks nearly identical between updateDocument:
5516
+ * ```graphql
5517
+ * updateDocument(collection: $collection,relativePath: $path, params: {
5518
+ * post: {
5519
+ * title: "Hello, World"
5520
+ * }
5521
+ * })`
5522
+ * ```
5523
+ * and `updatePostDocument`:
5524
+ * ```graphql
5525
+ * updatePostDocument(relativePath: $path, params: {
5526
+ * title: "Hello, World"
5527
+ * })
5528
+ * ```
5529
+ * The problem here is that we don't know whether the payload came from `updateDocument`
5530
+ * or `updatePostDocument` (we could, but for now it's easier not to pipe those details through),
5531
+ * But we do know that when given a `args.collection` value, we can assume that
5532
+ * this was a `updateDocument` request, and thus - should grab the data
5533
+ * from the corresponding field name in the key
5534
+ */
5120
5535
  this.buildParams = (args) => {
5121
5536
  try {
5122
5537
  assertShape(
@@ -5216,7 +5631,10 @@ var resolve = async ({
5216
5631
  const graphQLSchema = buildASTSchema(graphQLSchemaAst);
5217
5632
  const tinaConfig = await database.getTinaSchema();
5218
5633
  const tinaSchema = await createSchema({
5634
+ // TODO: please update all the types to import from @tinacms/schema-tools
5635
+ // @ts-ignore
5219
5636
  schema: tinaConfig,
5637
+ // @ts-ignore
5220
5638
  flags: tinaConfig?.meta?.flags
5221
5639
  });
5222
5640
  const resolver = createResolver({
@@ -5233,8 +5651,7 @@ var resolve = async ({
5233
5651
  database
5234
5652
  },
5235
5653
  typeResolver: async (source, _args, info) => {
5236
- if (source.__typename)
5237
- return source.__typename;
5654
+ if (source.__typename) return source.__typename;
5238
5655
  const namedType = getNamedType(info.returnType).toString();
5239
5656
  const lookup = await database.getLookup(namedType);
5240
5657
  if (lookup.resolveType === "unionData") {
@@ -5383,11 +5800,13 @@ var resolve = async ({
5383
5800
  set(
5384
5801
  params,
5385
5802
  userField.path.slice(1),
5803
+ // remove _rawData from users path
5386
5804
  users.map((u) => {
5387
5805
  if (user[idFieldName] === u[idFieldName]) {
5388
5806
  return user;
5389
5807
  }
5390
5808
  return {
5809
+ // don't overwrite other users' passwords
5391
5810
  ...u,
5392
5811
  [passwordFieldName]: {
5393
5812
  ...u[passwordFieldName],
@@ -5410,6 +5829,9 @@ var resolve = async ({
5410
5829
  }
5411
5830
  const isCreation = lookup[info.fieldName] === "create";
5412
5831
  switch (lookup.resolveType) {
5832
+ /**
5833
+ * `node(id: $id)`
5834
+ */
5413
5835
  case "nodeDocument":
5414
5836
  assertShape(
5415
5837
  args,
@@ -5441,6 +5863,7 @@ var resolve = async ({
5441
5863
  collection: args.collection,
5442
5864
  isMutation,
5443
5865
  isCreation,
5866
+ // Right now this is the only case for deletion
5444
5867
  isDeletion: info.fieldName === "deleteDocument",
5445
5868
  isFolderCreation: info.fieldName === "createFolder",
5446
5869
  isUpdateName: Boolean(args?.params?.relativePath),
@@ -5450,6 +5873,9 @@ var resolve = async ({
5450
5873
  return result;
5451
5874
  }
5452
5875
  return value;
5876
+ /**
5877
+ * eg `getMovieDocument.data.actors`
5878
+ */
5453
5879
  case "multiCollectionDocumentList":
5454
5880
  if (Array.isArray(value)) {
5455
5881
  return {
@@ -5461,7 +5887,15 @@ var resolve = async ({
5461
5887
  }
5462
5888
  if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
5463
5889
  let filter = args.filter;
5464
- if (typeof args?.filter !== "undefined" && args?.filter !== null && typeof value?.collection?.name === "string" && Object.keys(args.filter).includes(value?.collection?.name) && typeof args.filter[value?.collection?.name] !== "undefined") {
5890
+ if (
5891
+ // 1. Make sure that the filter exists
5892
+ typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
5893
+ // @ts-ignore
5894
+ typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
5895
+ // @ts-ignore
5896
+ Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
5897
+ typeof args.filter[value?.collection?.name] !== "undefined"
5898
+ ) {
5465
5899
  filter = args.filter[value.collection.name];
5466
5900
  }
5467
5901
  return resolver.resolveCollectionConnection({
@@ -5469,12 +5903,20 @@ var resolve = async ({
5469
5903
  ...args,
5470
5904
  filter
5471
5905
  },
5906
+ // @ts-ignore
5472
5907
  collection: value.collection
5473
5908
  });
5474
5909
  }
5475
5910
  throw new Error(
5476
5911
  `Expected an array for result of ${info.fieldName} at ${info.path}`
5477
5912
  );
5913
+ /**
5914
+ * Collections-specific getter
5915
+ * eg. `getPostDocument`/`createPostDocument`/`updatePostDocument`
5916
+ *
5917
+ * if coming from a query result
5918
+ * the field will be `node`
5919
+ */
5478
5920
  case "collectionDocument": {
5479
5921
  if (value) {
5480
5922
  return value;
@@ -5489,11 +5931,32 @@ var resolve = async ({
5489
5931
  });
5490
5932
  return result;
5491
5933
  }
5934
+ /**
5935
+ * Collections-specific list getter
5936
+ * eg. `getPageList`
5937
+ */
5492
5938
  case "collectionDocumentList":
5493
5939
  return resolver.resolveCollectionConnection({
5494
5940
  args,
5495
5941
  collection: tinaSchema.getCollection(lookup.collection)
5496
5942
  });
5943
+ /**
5944
+ * A polymorphic data set, it can be from a document's data
5945
+ * of any nested object which can be one of many shapes
5946
+ *
5947
+ * ```graphql
5948
+ * getPostDocument(relativePath: $relativePath) {
5949
+ * data {...} <- this part
5950
+ * }
5951
+ * ```
5952
+ * ```graphql
5953
+ * getBlockDocument(relativePath: $relativePath) {
5954
+ * data {
5955
+ * blocks {...} <- or this part
5956
+ * }
5957
+ * }
5958
+ * ```
5959
+ */
5497
5960
  case "unionData":
5498
5961
  if (!value) {
5499
5962
  if (args.relativePath) {
@@ -5558,8 +6021,7 @@ var TinaLevelClient = class extends ManyLevelGuest {
5558
6021
  this.port = port || 9e3;
5559
6022
  }
5560
6023
  openConnection() {
5561
- if (this._connected)
5562
- return;
6024
+ if (this._connected) return;
5563
6025
  const socket = connect(this.port);
5564
6026
  pipeline(socket, this.createRpcStream(), socket, () => {
5565
6027
  this._connected = false;
@@ -5569,7 +6031,7 @@ var TinaLevelClient = class extends ManyLevelGuest {
5569
6031
  };
5570
6032
 
5571
6033
  // src/database/index.ts
5572
- import path4 from "path";
6034
+ import path4 from "node:path";
5573
6035
  import { GraphQLError as GraphQLError5 } from "graphql";
5574
6036
  import micromatch2 from "micromatch";
5575
6037
  import sha2 from "js-sha1";
@@ -5740,6 +6202,7 @@ var Database = class {
5740
6202
  "put",
5741
6203
  level
5742
6204
  ),
6205
+ // folder indices
5743
6206
  ...makeIndexOpsForDocument(
5744
6207
  normalizedPath,
5745
6208
  `${collection?.name}_${folderKey}`,
@@ -5762,6 +6225,7 @@ var Database = class {
5762
6225
  "del",
5763
6226
  level
5764
6227
  ),
6228
+ // folder indices
5765
6229
  ...makeIndexOpsForDocument(
5766
6230
  normalizedPath,
5767
6231
  `${collection?.name}_${folderKey}`,
@@ -5855,6 +6319,7 @@ var Database = class {
5855
6319
  "put",
5856
6320
  level
5857
6321
  ),
6322
+ // folder indices
5858
6323
  ...makeIndexOpsForDocument(
5859
6324
  normalizedPath,
5860
6325
  `${collection?.name}_${folderKey}`,
@@ -5877,6 +6342,7 @@ var Database = class {
5877
6342
  "del",
5878
6343
  level
5879
6344
  ),
6345
+ // folder indices
5880
6346
  ...makeIndexOpsForDocument(
5881
6347
  normalizedPath,
5882
6348
  `${collection?.name}_${folderKey}`,
@@ -5954,6 +6420,7 @@ var Database = class {
5954
6420
  aliasedData,
5955
6421
  extension,
5956
6422
  writeTemplateKey,
6423
+ //templateInfo.type === 'union',
5957
6424
  {
5958
6425
  frontmatterFormat: collection?.frontmatterFormat,
5959
6426
  frontmatterDelimiters: collection?.frontmatterDelimiters
@@ -5992,6 +6459,7 @@ var Database = class {
5992
6459
  SUBLEVEL_OPTIONS
5993
6460
  ).get(graphqlPath);
5994
6461
  };
6462
+ //TODO - is there a reason why the database fetches some config with "bridge.get", and some with "store.get"?
5995
6463
  this.getGraphQLSchemaFromBridge = async () => {
5996
6464
  if (!this.bridge) {
5997
6465
  throw new Error(`No bridge configured`);
@@ -6038,6 +6506,7 @@ var Database = class {
6038
6506
  for (const collection of collections) {
6039
6507
  const indexDefinitions = {
6040
6508
  [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6509
+ // provide a default sort key which is the file sort
6041
6510
  };
6042
6511
  if (collection.fields) {
6043
6512
  for (const field of collection.fields) {
@@ -6361,12 +6830,12 @@ var Database = class {
6361
6830
  if (collection?.isDetached) {
6362
6831
  level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
6363
6832
  }
6364
- const itemKey = normalizePath(filepath);
6833
+ const normalizedPath = normalizePath(filepath);
6365
6834
  const rootSublevel = level.sublevel(
6366
6835
  CONTENT_ROOT_PREFIX,
6367
6836
  SUBLEVEL_OPTIONS
6368
6837
  );
6369
- const item = await rootSublevel.get(itemKey);
6838
+ const item = await rootSublevel.get(normalizedPath);
6370
6839
  if (item) {
6371
6840
  const folderTreeBuilder = new FolderTreeBuilder();
6372
6841
  const folderKey = folderTreeBuilder.update(
@@ -6375,15 +6844,16 @@ var Database = class {
6375
6844
  );
6376
6845
  await this.contentLevel.batch([
6377
6846
  ...makeIndexOpsForDocument(
6378
- filepath,
6847
+ normalizedPath,
6379
6848
  collection.name,
6380
6849
  collectionIndexDefinitions,
6381
6850
  item,
6382
6851
  "del",
6383
6852
  level
6384
6853
  ),
6854
+ // folder indices
6385
6855
  ...makeIndexOpsForDocument(
6386
- filepath,
6856
+ normalizedPath,
6387
6857
  `${collection.name}_${folderKey}`,
6388
6858
  collectionIndexDefinitions,
6389
6859
  item,
@@ -6392,17 +6862,17 @@ var Database = class {
6392
6862
  ),
6393
6863
  {
6394
6864
  type: "del",
6395
- key: itemKey,
6865
+ key: normalizedPath,
6396
6866
  sublevel: rootSublevel
6397
6867
  }
6398
6868
  ]);
6399
6869
  }
6400
6870
  if (!collection?.isDetached) {
6401
6871
  if (this.bridge) {
6402
- await this.bridge.delete(normalizePath(filepath));
6872
+ await this.bridge.delete(normalizedPath);
6403
6873
  }
6404
6874
  try {
6405
- await this.onDelete(normalizePath(filepath));
6875
+ await this.onDelete(normalizedPath);
6406
6876
  } catch (e) {
6407
6877
  throw new GraphQLError5(
6408
6878
  `Error running onDelete hook for ${filepath}: ${e}`,
@@ -6536,6 +7006,9 @@ var Database = class {
6536
7006
  info: templateInfo
6537
7007
  };
6538
7008
  }
7009
+ /**
7010
+ * Clears the internal cache of the tinaSchema and the lookup file. This allows the state to be reset
7011
+ */
6539
7012
  clearCache() {
6540
7013
  this.tinaSchema = null;
6541
7014
  this._lookup = null;
@@ -6632,6 +7105,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6632
7105
  "put",
6633
7106
  level
6634
7107
  ),
7108
+ // folder indexes
6635
7109
  ...makeIndexOpsForDocument(
6636
7110
  normalizedPath,
6637
7111
  `${collection?.name}_${folderKey}`,
@@ -6717,6 +7191,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6717
7191
  "del",
6718
7192
  database.contentLevel
6719
7193
  ),
7194
+ // folder indexes
6720
7195
  ...makeIndexOpsForDocument(
6721
7196
  itemKey,
6722
7197
  `${collection?.name}_${folderKey}`,
@@ -6932,17 +7407,26 @@ var IsomorphicBridge = class {
6932
7407
  getAuthor() {
6933
7408
  return {
6934
7409
  ...this.author,
6935
- timestamp: Math.round(new Date().getTime() / 1e3),
7410
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
6936
7411
  timezoneOffset: 0
6937
7412
  };
6938
7413
  }
6939
7414
  getCommitter() {
6940
7415
  return {
6941
7416
  ...this.committer,
6942
- timestamp: Math.round(new Date().getTime() / 1e3),
7417
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
6943
7418
  timezoneOffset: 0
6944
7419
  };
6945
7420
  }
7421
+ /**
7422
+ * Recursively populate paths matching `pattern` for the given `entry`
7423
+ *
7424
+ * @param pattern - pattern to filter paths by
7425
+ * @param entry - TreeEntry to start building list from
7426
+ * @param path - base path
7427
+ * @param results
7428
+ * @private
7429
+ */
6946
7430
  async listEntries({
6947
7431
  pattern,
6948
7432
  entry,
@@ -6975,6 +7459,15 @@ var IsomorphicBridge = class {
6975
7459
  });
6976
7460
  }
6977
7461
  }
7462
+ /**
7463
+ * For the specified path, returns an object with an array containing the parts of the path (pathParts)
7464
+ * and an array containing the WalkerEntry objects for the path parts (pathEntries). Any null elements in the
7465
+ * pathEntries are placeholders for non-existent entries.
7466
+ *
7467
+ * @param path - path being resolved
7468
+ * @param ref - ref to resolve path entries for
7469
+ * @private
7470
+ */
6978
7471
  async resolvePathEntries(path7, ref) {
6979
7472
  let pathParts = path7.split("/");
6980
7473
  const result = await git2.walk({
@@ -7005,6 +7498,17 @@ var IsomorphicBridge = class {
7005
7498
  }
7006
7499
  return { pathParts, pathEntries };
7007
7500
  }
7501
+ /**
7502
+ * Updates tree entry and associated parent tree entries
7503
+ *
7504
+ * @param existingOid - the existing OID
7505
+ * @param updatedOid - the updated OID
7506
+ * @param path - the path of the entry being updated
7507
+ * @param type - the type of the entry being updated (blob or tree)
7508
+ * @param pathEntries - parent path entries
7509
+ * @param pathParts - parent path parts
7510
+ * @private
7511
+ */
7008
7512
  async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
7009
7513
  const lastIdx = pathEntries.length - 1;
7010
7514
  const parentEntry = pathEntries[lastIdx];
@@ -7060,6 +7564,13 @@ var IsomorphicBridge = class {
7060
7564
  );
7061
7565
  }
7062
7566
  }
7567
+ /**
7568
+ * Creates a commit for the specified tree and updates the specified ref to point to the commit
7569
+ *
7570
+ * @param treeSha - sha of the new tree
7571
+ * @param ref - the ref that should be updated
7572
+ * @private
7573
+ */
7063
7574
  async commitTree(treeSha, ref) {
7064
7575
  const commitSha = await git2.writeCommit({
7065
7576
  ...this.isomorphicConfig,
@@ -7072,6 +7583,7 @@ var IsomorphicBridge = class {
7072
7583
  })
7073
7584
  ],
7074
7585
  message: this.commitMessage,
7586
+ // TODO these should be configurable
7075
7587
  author: this.getAuthor(),
7076
7588
  committer: this.getCommitter()
7077
7589
  }
@@ -7309,5 +7821,5 @@ export {
7309
7821
  transformDocument,
7310
7822
  transformDocumentIntoPayload
7311
7823
  };
7312
- //! Replaces _.flattenDeep()
7313
7824
  //! Replaces _.get()
7825
+ //! Replaces _.flattenDeep()