@tinacms/graphql 0.0.0-d524599-20241117111320 → 0.0.0-d689189-20250526233934

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: {
@@ -135,6 +144,10 @@ var SysFieldDefinition = {
135
144
  }
136
145
  };
137
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
+ */
138
151
  FormFieldBuilder: ({
139
152
  name,
140
153
  additionalFields
@@ -358,6 +371,8 @@ var astBuilder = {
358
371
  kind: "Name",
359
372
  value: name
360
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
361
376
  fields
362
377
  }),
363
378
  UnionTypeDefinition: ({
@@ -370,6 +385,8 @@ var astBuilder = {
370
385
  value: name
371
386
  },
372
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
373
390
  types: types.map((name2) => ({
374
391
  kind: "NamedType",
375
392
  name: {
@@ -466,8 +483,11 @@ var astBuilder = {
466
483
  string: "String",
467
484
  boolean: "Boolean",
468
485
  number: "Float",
486
+ // FIXME - needs to be float or int
469
487
  datetime: "String",
488
+ // FIXME
470
489
  image: "String",
490
+ // FIXME
471
491
  text: "String"
472
492
  };
473
493
  return scalars[type];
@@ -966,8 +986,7 @@ var astBuilder = {
966
986
  }
967
987
  };
968
988
  var capitalize = (s) => {
969
- if (typeof s !== "string")
970
- return "";
989
+ if (typeof s !== "string") return "";
971
990
  return s.charAt(0).toUpperCase() + s.slice(1);
972
991
  };
973
992
  var extractInlineTypes = (item) => {
@@ -1010,41 +1029,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1010
1029
  yield maybeNode;
1011
1030
  visited.add(maybeNode);
1012
1031
  }
1013
- function addNamespaceToSchema(maybeNode, namespace = []) {
1014
- if (typeof maybeNode === "string") {
1015
- return maybeNode;
1016
- }
1017
- if (typeof maybeNode === "boolean") {
1018
- return maybeNode;
1019
- }
1020
- const newNode = maybeNode;
1021
- const keys = Object.keys(maybeNode);
1022
- Object.values(maybeNode).map((m, index) => {
1023
- const key = keys[index];
1024
- if (Array.isArray(m)) {
1025
- newNode[key] = m.map((element) => {
1026
- if (!element) {
1027
- return;
1028
- }
1029
- if (!element.hasOwnProperty("name")) {
1030
- return element;
1031
- }
1032
- const value = element.name || element.value;
1033
- return addNamespaceToSchema(element, [...namespace, value]);
1034
- });
1035
- } else {
1036
- if (!m) {
1037
- return;
1038
- }
1039
- if (!m.hasOwnProperty("name")) {
1040
- newNode[key] = m;
1041
- } else {
1042
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1043
- }
1044
- }
1045
- });
1046
- return { ...newNode, namespace };
1047
- }
1048
1032
  var generateNamespacedFieldName = (names, suffix = "") => {
1049
1033
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1050
1034
  };
@@ -1422,6 +1406,19 @@ var Builder = class {
1422
1406
  this.addToLookupMap = (lookup) => {
1423
1407
  this.lookupMap[lookup.type] = lookup;
1424
1408
  };
1409
+ /**
1410
+ * ```graphql
1411
+ * # ex.
1412
+ * {
1413
+ * getCollection(collection: $collection) {
1414
+ * name
1415
+ * documents {...}
1416
+ * }
1417
+ * }
1418
+ * ```
1419
+ *
1420
+ * @param collections
1421
+ */
1425
1422
  this.buildCollectionDefinition = async (collections) => {
1426
1423
  const name = "collection";
1427
1424
  const typeName = "Collection";
@@ -1492,6 +1489,19 @@ var Builder = class {
1492
1489
  required: true
1493
1490
  });
1494
1491
  };
1492
+ /**
1493
+ * ```graphql
1494
+ * # ex.
1495
+ * {
1496
+ * getCollections {
1497
+ * name
1498
+ * documents {...}
1499
+ * }
1500
+ * }
1501
+ * ```
1502
+ *
1503
+ * @param collections
1504
+ */
1495
1505
  this.buildMultiCollectionDefinition = async (collections) => {
1496
1506
  const name = "collections";
1497
1507
  const typeName = "Collection";
@@ -1502,6 +1512,17 @@ var Builder = class {
1502
1512
  required: true
1503
1513
  });
1504
1514
  };
1515
+ /**
1516
+ * ```graphql
1517
+ * # ex.
1518
+ * {
1519
+ * node(id: $id) {
1520
+ * id
1521
+ * data {...}
1522
+ * }
1523
+ * }
1524
+ * ```
1525
+ */
1505
1526
  this.multiNodeDocument = async () => {
1506
1527
  const name = "node";
1507
1528
  const args = [
@@ -1522,6 +1543,19 @@ var Builder = class {
1522
1543
  required: true
1523
1544
  });
1524
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
+ */
1525
1559
  this.multiCollectionDocument = async (collections) => {
1526
1560
  const name = "document";
1527
1561
  const args = [
@@ -1547,6 +1581,19 @@ var Builder = class {
1547
1581
  required: true
1548
1582
  });
1549
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
+ */
1550
1597
  this.addMultiCollectionDocumentMutation = async () => {
1551
1598
  return astBuilder.FieldDefinition({
1552
1599
  name: "addPendingDocument",
@@ -1571,6 +1618,19 @@ var Builder = class {
1571
1618
  type: astBuilder.TYPES.MultiCollectionDocument
1572
1619
  });
1573
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
+ */
1574
1634
  this.buildCreateCollectionDocumentMutation = async (collections) => {
1575
1635
  return astBuilder.FieldDefinition({
1576
1636
  name: "createDocument",
@@ -1598,6 +1658,19 @@ var Builder = class {
1598
1658
  type: astBuilder.TYPES.MultiCollectionDocument
1599
1659
  });
1600
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
+ */
1601
1674
  this.buildUpdateCollectionDocumentMutation = async (collections) => {
1602
1675
  return astBuilder.FieldDefinition({
1603
1676
  name: "updateDocument",
@@ -1625,6 +1698,19 @@ var Builder = class {
1625
1698
  type: astBuilder.TYPES.MultiCollectionDocument
1626
1699
  });
1627
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
+ */
1628
1714
  this.buildDeleteCollectionDocumentMutation = async (collections) => {
1629
1715
  return astBuilder.FieldDefinition({
1630
1716
  name: "deleteDocument",
@@ -1644,6 +1730,19 @@ var Builder = class {
1644
1730
  type: astBuilder.TYPES.MultiCollectionDocument
1645
1731
  });
1646
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
+ */
1647
1746
  this.buildCreateCollectionFolderMutation = async () => {
1648
1747
  return astBuilder.FieldDefinition({
1649
1748
  name: "createFolder",
@@ -1663,6 +1762,19 @@ var Builder = class {
1663
1762
  type: astBuilder.TYPES.MultiCollectionDocument
1664
1763
  });
1665
1764
  };
1765
+ /**
1766
+ * ```graphql
1767
+ * # ex.
1768
+ * {
1769
+ * getPostDocument(relativePath: $relativePath) {
1770
+ * id
1771
+ * data {...}
1772
+ * }
1773
+ * }
1774
+ * ```
1775
+ *
1776
+ * @param collection
1777
+ */
1666
1778
  this.collectionDocument = async (collection) => {
1667
1779
  const name = NAMER.queryName([collection.name]);
1668
1780
  const type = await this._buildCollectionDocumentType(collection);
@@ -1723,6 +1835,20 @@ var Builder = class {
1723
1835
  const args = [];
1724
1836
  return astBuilder.FieldDefinition({ type, name, args, required: false });
1725
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 TinaCloud collection
1851
+ */
1726
1852
  this.collectionFragment = async (collection) => {
1727
1853
  const name = NAMER.dataTypeName(collection.namespace);
1728
1854
  const fragmentName = NAMER.fragmentName(collection.namespace);
@@ -1736,6 +1862,20 @@ var Builder = class {
1736
1862
  selections: filterSelections(selections)
1737
1863
  });
1738
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
+ * */
1739
1879
  this._getCollectionFragmentSelections = async (collection, depth) => {
1740
1880
  const selections = [];
1741
1881
  selections.push({
@@ -1817,9 +1957,9 @@ var Builder = class {
1817
1957
  ]
1818
1958
  });
1819
1959
  }
1960
+ // TODO: Should we throw here?
1820
1961
  case "reference":
1821
- if (depth >= this.maxDepth)
1822
- return false;
1962
+ if (depth >= this.maxDepth) return false;
1823
1963
  if (!("collections" in field)) {
1824
1964
  return false;
1825
1965
  }
@@ -1851,6 +1991,7 @@ var Builder = class {
1851
1991
  name: field.name,
1852
1992
  selections: [
1853
1993
  ...selections,
1994
+ // This is ... on Document { id }
1854
1995
  {
1855
1996
  kind: "InlineFragment",
1856
1997
  typeCondition: {
@@ -1881,6 +2022,19 @@ var Builder = class {
1881
2022
  });
1882
2023
  }
1883
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
+ */
1884
2038
  this.updateCollectionDocumentMutation = async (collection) => {
1885
2039
  return astBuilder.FieldDefinition({
1886
2040
  type: await this._buildCollectionDocumentType(collection),
@@ -1900,6 +2054,19 @@ var Builder = class {
1900
2054
  ]
1901
2055
  });
1902
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
+ */
1903
2070
  this.createCollectionDocumentMutation = async (collection) => {
1904
2071
  return astBuilder.FieldDefinition({
1905
2072
  type: await this._buildCollectionDocumentType(collection),
@@ -1919,6 +2086,22 @@ var Builder = class {
1919
2086
  ]
1920
2087
  });
1921
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
+ */
1922
2105
  this.collectionDocumentList = async (collection) => {
1923
2106
  const connectionName = NAMER.referenceConnectionType(collection.namespace);
1924
2107
  this.addToLookupMap({
@@ -1934,6 +2117,10 @@ var Builder = class {
1934
2117
  collection
1935
2118
  });
1936
2119
  };
2120
+ /**
2121
+ * GraphQL type definitions which remain unchanged regardless
2122
+ * of the supplied Tina schema. Ex. "node" interface
2123
+ */
1937
2124
  this.buildStaticDefinitions = () => staticDefinitions;
1938
2125
  this._buildCollectionDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
1939
2126
  const documentTypeName = NAMER.documentTypeName(collection.namespace);
@@ -2438,6 +2625,7 @@ var Builder = class {
2438
2625
  name: NAMER.dataFilterTypeName(namespace),
2439
2626
  fields: await sequential(collections, async (collection2) => {
2440
2627
  return astBuilder.InputValueDefinition({
2628
+ // @ts-ignore
2441
2629
  name: collection2.name,
2442
2630
  type: NAMER.dataFilterTypeName(collection2.namespace)
2443
2631
  });
@@ -2626,7 +2814,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2626
2814
  ]
2627
2815
  });
2628
2816
  };
2629
- this.maxDepth = config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2817
+ this.maxDepth = // @ts-ignore
2818
+ config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2630
2819
  this.tinaSchema = config.tinaSchema;
2631
2820
  this.lookupMap = {};
2632
2821
  }
@@ -2637,8 +2826,7 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2637
2826
  selections.push(field);
2638
2827
  });
2639
2828
  const filteredSelections = filterSelections(selections);
2640
- if (!filteredSelections.length)
2641
- return false;
2829
+ if (!filteredSelections.length) return false;
2642
2830
  return astBuilder.InlineFragmentDefinition({
2643
2831
  selections: filteredSelections,
2644
2832
  name: NAMER.dataTypeName(template.namespace)
@@ -2675,6 +2863,7 @@ var filterSelections = (arr) => {
2675
2863
  import { TinaSchema } from "@tinacms/schema-tools";
2676
2864
 
2677
2865
  // src/schema/validate.ts
2866
+ import { addNamespaceToSchema } from "@tinacms/schema-tools";
2678
2867
  import deepClone from "lodash.clonedeep";
2679
2868
  import * as yup2 from "yup";
2680
2869
  import {
@@ -2721,6 +2910,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2721
2910
  }).map((x) => `${x.path}${x.format || "md"}`);
2722
2911
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2723
2912
  throw new Error(
2913
+ // TODO: add a link to the docs
2724
2914
  "Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
2725
2915
  );
2726
2916
  }
@@ -2829,7 +3019,7 @@ var validateField = async (field) => {
2829
3019
  // package.json
2830
3020
  var package_default = {
2831
3021
  name: "@tinacms/graphql",
2832
- version: "1.5.7",
3022
+ version: "1.5.17",
2833
3023
  main: "dist/index.js",
2834
3024
  module: "dist/index.mjs",
2835
3025
  typings: "dist/index.d.ts",
@@ -2855,9 +3045,8 @@ var package_default = {
2855
3045
  types: "pnpm tsc",
2856
3046
  build: "tinacms-scripts build",
2857
3047
  docs: "pnpm typedoc",
2858
- serve: "pnpm nodemon dist/server.js",
2859
- test: "jest",
2860
- "test-watch": "jest --watch"
3048
+ test: "vitest run",
3049
+ "test-watch": "vitest"
2861
3050
  },
2862
3051
  dependencies: {
2863
3052
  "@iarna/toml": "^2.2.5",
@@ -2865,12 +3054,12 @@ var package_default = {
2865
3054
  "@tinacms/schema-tools": "workspace:*",
2866
3055
  "abstract-level": "^1.0.4",
2867
3056
  "date-fns": "^2.30.0",
2868
- "fast-glob": "^3.3.2",
2869
- "fs-extra": "^11.2.0",
3057
+ "fast-glob": "^3.3.3",
3058
+ "fs-extra": "^11.3.0",
2870
3059
  "glob-parent": "^6.0.2",
2871
3060
  graphql: "15.8.0",
2872
3061
  "gray-matter": "^4.0.3",
2873
- "isomorphic-git": "^1.27.1",
3062
+ "isomorphic-git": "^1.29.0",
2874
3063
  "js-sha1": "^0.6.0",
2875
3064
  "js-yaml": "^3.14.1",
2876
3065
  "jsonpath-plus": "10.1.0",
@@ -2880,7 +3069,7 @@ var package_default = {
2880
3069
  "many-level": "^2.0.0",
2881
3070
  micromatch: "4.0.8",
2882
3071
  "normalize-path": "^3.0.0",
2883
- "readable-stream": "^4.5.2",
3072
+ "readable-stream": "^4.7.0",
2884
3073
  scmp: "^2.1.0",
2885
3074
  yup: "^0.32.11"
2886
3075
  },
@@ -2898,24 +3087,22 @@ var package_default = {
2898
3087
  "@types/estree": "^0.0.50",
2899
3088
  "@types/express": "^4.17.21",
2900
3089
  "@types/fs-extra": "^9.0.13",
2901
- "@types/jest": "^26.0.24",
2902
3090
  "@types/js-yaml": "^3.12.10",
2903
3091
  "@types/lodash.camelcase": "^4.3.9",
2904
3092
  "@types/lodash.upperfirst": "^4.3.9",
2905
3093
  "@types/lru-cache": "^5.1.1",
2906
3094
  "@types/mdast": "^3.0.15",
2907
3095
  "@types/micromatch": "^4.0.9",
2908
- "@types/node": "^22.9.0",
3096
+ "@types/node": "^22.13.1",
2909
3097
  "@types/normalize-path": "^3.0.2",
2910
3098
  "@types/ws": "^7.4.7",
2911
3099
  "@types/yup": "^0.29.14",
2912
- jest: "^29.7.0",
2913
- "jest-diff": "^29.7.0",
2914
3100
  "jest-file-snapshot": "^0.5.0",
2915
- "jest-matcher-utils": "^29.7.0",
2916
3101
  "memory-level": "^1.0.0",
2917
- nodemon: "3.1.4",
2918
- typescript: "^5.6.3"
3102
+ typescript: "^5.7.3",
3103
+ vite: "^4.5.9",
3104
+ vitest: "^0.32.4",
3105
+ zod: "^3.24.2"
2919
3106
  }
2920
3107
  };
2921
3108
 
@@ -2986,6 +3173,7 @@ var _buildFragments = async (builder, tinaSchema) => {
2986
3173
  const fragDoc = {
2987
3174
  kind: "Document",
2988
3175
  definitions: uniqBy2(
3176
+ // @ts-ignore
2989
3177
  extractInlineTypes(fragmentDefinitionsFields),
2990
3178
  (node) => node.name.value
2991
3179
  )
@@ -3008,6 +3196,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3008
3196
  fragName,
3009
3197
  queryName: queryListName,
3010
3198
  filterType: queryFilterTypeName,
3199
+ // look for flag to see if the data layer is enabled
3011
3200
  dataLayer: Boolean(
3012
3201
  tinaSchema.config?.meta?.flags?.find((x) => x === "experimentalData")
3013
3202
  )
@@ -3017,6 +3206,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3017
3206
  const queryDoc = {
3018
3207
  kind: "Document",
3019
3208
  definitions: uniqBy2(
3209
+ // @ts-ignore
3020
3210
  extractInlineTypes(operationsDefinitions),
3021
3211
  (node) => node.name.value
3022
3212
  )
@@ -3068,7 +3258,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3068
3258
  await builder.buildCreateCollectionFolderMutation()
3069
3259
  );
3070
3260
  await sequential(collections, async (collection) => {
3071
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3261
+ queryTypeDefinitionFields.push(
3262
+ await builder.collectionDocument(collection)
3263
+ );
3072
3264
  if (collection.isAuthCollection) {
3073
3265
  queryTypeDefinitionFields.push(
3074
3266
  await builder.authenticationCollectionDocument(collection)
@@ -3105,6 +3297,7 @@ var _buildSchema = async (builder, tinaSchema) => {
3105
3297
  return {
3106
3298
  kind: "Document",
3107
3299
  definitions: uniqBy2(
3300
+ // @ts-ignore
3108
3301
  extractInlineTypes(definitions),
3109
3302
  (node) => node.name.value
3110
3303
  )
@@ -3309,8 +3502,7 @@ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, s
3309
3502
  }
3310
3503
  if (Array.isArray(value)) {
3311
3504
  return value.map((v) => {
3312
- if (!v || typeof v !== "string")
3313
- return v;
3505
+ if (!v || typeof v !== "string") return v;
3314
3506
  const cleanMediaRoot = cleanUpSlashes(
3315
3507
  schema.config.media.tina.mediaRoot
3316
3508
  );
@@ -3338,8 +3530,7 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
3338
3530
  }
3339
3531
  if (Array.isArray(value)) {
3340
3532
  return value.map((v) => {
3341
- if (!v || typeof v !== "string")
3342
- return v;
3533
+ if (!v || typeof v !== "string") return v;
3343
3534
  const strippedValue = v.replace(cleanMediaRoot, "");
3344
3535
  return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3345
3536
  });
@@ -3357,8 +3548,7 @@ var cleanUpSlashes = (path7) => {
3357
3548
  return "";
3358
3549
  };
3359
3550
  var hasTinaMediaConfig = (schema) => {
3360
- if (!schema.config?.media?.tina)
3361
- return false;
3551
+ if (!schema.config?.media?.tina) return false;
3362
3552
  if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
3363
3553
  return false;
3364
3554
  return true;
@@ -3385,7 +3575,9 @@ var LevelProxyHandler = {
3385
3575
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3386
3576
  }
3387
3577
  if (typeof target[property] !== "function") {
3388
- throw new Error(`The property, ${property.toString()}, is not a function`);
3578
+ throw new Error(
3579
+ `The property, ${property.toString()}, is not a function`
3580
+ );
3389
3581
  }
3390
3582
  if (property === "get") {
3391
3583
  return async (...args) => {
@@ -3402,6 +3594,7 @@ var LevelProxyHandler = {
3402
3594
  } else if (property === "sublevel") {
3403
3595
  return (...args) => {
3404
3596
  return new Proxy(
3597
+ // eslint-disable-next-line prefer-spread
3405
3598
  target[property].apply(target, args),
3406
3599
  LevelProxyHandler
3407
3600
  );
@@ -3769,6 +3962,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3769
3962
 
3770
3963
  // src/database/datalayer.ts
3771
3964
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
3965
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
3966
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
3967
+ var REFS_PATH_FIELD = "__tina_ref_path__";
3772
3968
  var DEFAULT_NUMERIC_LPAD = 4;
3773
3969
  var applyPadding = (input, pad) => {
3774
3970
  if (pad) {
@@ -4278,6 +4474,7 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4278
4474
  result.push({
4279
4475
  type: opType,
4280
4476
  key: `${collection.path}/${subFolderKey}.${collection.format}`,
4477
+ // replace the root with the collection path
4281
4478
  sublevel: indexSublevel,
4282
4479
  value: {}
4283
4480
  });
@@ -4341,6 +4538,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4341
4538
  }
4342
4539
  return result;
4343
4540
  };
4541
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4542
+ const result = [];
4543
+ if (collection) {
4544
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4545
+ if (!referencePaths.length) {
4546
+ continue;
4547
+ }
4548
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4549
+ const refSublevel = collectionSublevel.sublevel(
4550
+ REFS_COLLECTIONS_SORT_KEY,
4551
+ SUBLEVEL_OPTIONS
4552
+ );
4553
+ const references2 = {};
4554
+ for (const path7 of referencePaths) {
4555
+ const ref = JSONPath({ path: path7, json: data });
4556
+ if (!ref) {
4557
+ continue;
4558
+ }
4559
+ if (Array.isArray(ref)) {
4560
+ for (const r of ref) {
4561
+ if (!r) {
4562
+ continue;
4563
+ }
4564
+ if (references2[r]) {
4565
+ references2[r].push(path7);
4566
+ } else {
4567
+ references2[r] = [path7];
4568
+ }
4569
+ }
4570
+ } else {
4571
+ if (references2[ref]) {
4572
+ references2[ref].push(path7);
4573
+ } else {
4574
+ references2[ref] = [path7];
4575
+ }
4576
+ }
4577
+ }
4578
+ for (const ref of Object.keys(references2)) {
4579
+ for (const path7 of references2[ref]) {
4580
+ result.push({
4581
+ type: opType,
4582
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4583
+ sublevel: refSublevel,
4584
+ value: opType === "put" ? {} : void 0
4585
+ });
4586
+ }
4587
+ }
4588
+ }
4589
+ }
4590
+ return result;
4591
+ };
4344
4592
  var makeStringEscaper = (regex, replacement) => {
4345
4593
  return (input) => {
4346
4594
  if (Array.isArray(input)) {
@@ -4392,6 +4640,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4392
4640
  case "password":
4393
4641
  accumulator[field.name] = {
4394
4642
  value: void 0,
4643
+ // never resolve the password hash
4395
4644
  passwordChangeRequired: value["passwordChangeRequired"] ?? false
4396
4645
  };
4397
4646
  break;
@@ -4560,24 +4809,33 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4560
4809
  throw e;
4561
4810
  }
4562
4811
  };
4563
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4812
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4813
+ let updated = false;
4564
4814
  if (!path7.includes(".") && !path7.includes("[")) {
4565
- if (path7 in obj) {
4815
+ if (path7 in obj && obj[path7] === oldValue) {
4566
4816
  obj[path7] = newValue;
4817
+ updated = true;
4567
4818
  }
4568
- return obj;
4569
- }
4570
- const parentPath = path7.replace(/\.[^.]+$/, "");
4571
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4572
- const parents = JSONPath2({ path: parentPath, json: obj, resultType: "value" });
4819
+ return { object: obj, updated };
4820
+ }
4821
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4822
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4823
+ const parents = JSONPath2({
4824
+ path: parentPath,
4825
+ json: obj,
4826
+ resultType: "value"
4827
+ });
4573
4828
  if (parents.length > 0) {
4574
4829
  parents.forEach((parent) => {
4575
4830
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4576
- parent[keyToUpdate] = newValue;
4831
+ if (parent[keyToUpdate] === oldValue) {
4832
+ parent[keyToUpdate] = newValue;
4833
+ updated = true;
4834
+ }
4577
4835
  }
4578
4836
  });
4579
4837
  }
4580
- return obj;
4838
+ return { object: obj, updated };
4581
4839
  };
4582
4840
  var Resolver = class {
4583
4841
  constructor(init) {
@@ -4586,6 +4844,7 @@ var Resolver = class {
4586
4844
  const collection = this.tinaSchema.getCollection(collectionName);
4587
4845
  const extraFields = {};
4588
4846
  return {
4847
+ // return the collection and hasDocuments to resolve documents at a lower level
4589
4848
  documents: { collection, hasDocuments },
4590
4849
  ...collection,
4591
4850
  ...extraFields
@@ -4593,7 +4852,9 @@ var Resolver = class {
4593
4852
  };
4594
4853
  this.getRaw = async (fullPath) => {
4595
4854
  if (typeof fullPath !== "string") {
4596
- throw new Error(`fullPath must be of type string for getDocument request`);
4855
+ throw new Error(
4856
+ `fullPath must be of type string for getDocument request`
4857
+ );
4597
4858
  }
4598
4859
  return this.database.get(fullPath);
4599
4860
  };
@@ -4622,7 +4883,9 @@ var Resolver = class {
4622
4883
  };
4623
4884
  this.getDocument = async (fullPath, opts = {}) => {
4624
4885
  if (typeof fullPath !== "string") {
4625
- throw new Error(`fullPath must be of type string for getDocument request`);
4886
+ throw new Error(
4887
+ `fullPath must be of type string for getDocument request`
4888
+ );
4626
4889
  }
4627
4890
  const rawData = await this.getRaw(fullPath);
4628
4891
  const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
@@ -4637,7 +4900,9 @@ var Resolver = class {
4637
4900
  };
4638
4901
  this.deleteDocument = async (fullPath) => {
4639
4902
  if (typeof fullPath !== "string") {
4640
- throw new Error(`fullPath must be of type string for getDocument request`);
4903
+ throw new Error(
4904
+ `fullPath must be of type string for getDocument request`
4905
+ );
4641
4906
  }
4642
4907
  await this.database.delete(fullPath);
4643
4908
  };
@@ -4672,7 +4937,9 @@ var Resolver = class {
4672
4937
  );
4673
4938
  } else {
4674
4939
  return this.buildFieldMutations(
4940
+ // @ts-ignore FIXME Argument of type 'string | object' is not assignable to parameter of type '{ [fieldName: string]: string | object | (string | object)[]; }'
4675
4941
  fieldValue,
4942
+ //@ts-ignore
4676
4943
  objectTemplate,
4677
4944
  existingData
4678
4945
  );
@@ -4684,6 +4951,7 @@ var Resolver = class {
4684
4951
  fieldValue.map(async (item) => {
4685
4952
  if (typeof item === "string") {
4686
4953
  throw new Error(
4954
+ //@ts-ignore
4687
4955
  `Expected object for template value for field ${field.name}`
4688
4956
  );
4689
4957
  }
@@ -4692,16 +4960,19 @@ var Resolver = class {
4692
4960
  });
4693
4961
  const [templateName] = Object.entries(item)[0];
4694
4962
  const template = templates.find(
4963
+ //@ts-ignore
4695
4964
  (template2) => template2.name === templateName
4696
4965
  );
4697
4966
  if (!template) {
4698
4967
  throw new Error(`Expected to find template ${templateName}`);
4699
4968
  }
4700
4969
  return {
4970
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4701
4971
  ...await this.buildFieldMutations(
4702
4972
  item[template.name],
4703
4973
  template
4704
4974
  ),
4975
+ //@ts-ignore
4705
4976
  _template: template.name
4706
4977
  };
4707
4978
  })
@@ -4709,6 +4980,7 @@ var Resolver = class {
4709
4980
  } else {
4710
4981
  if (typeof fieldValue === "string") {
4711
4982
  throw new Error(
4983
+ //@ts-ignore
4712
4984
  `Expected object for template value for field ${field.name}`
4713
4985
  );
4714
4986
  }
@@ -4717,16 +4989,19 @@ var Resolver = class {
4717
4989
  });
4718
4990
  const [templateName] = Object.entries(fieldValue)[0];
4719
4991
  const template = templates.find(
4992
+ //@ts-ignore
4720
4993
  (template2) => template2.name === templateName
4721
4994
  );
4722
4995
  if (!template) {
4723
4996
  throw new Error(`Expected to find template ${templateName}`);
4724
4997
  }
4725
4998
  return {
4999
+ // @ts-ignore FIXME Argument of type 'unknown' is not assignable to parameter of type '{ [fieldName: string]: string | { [key: string]: unknown; } | (string | { [key: string]: unknown; })[]; }'
4726
5000
  ...await this.buildFieldMutations(
4727
5001
  fieldValue[template.name],
4728
5002
  template
4729
5003
  ),
5004
+ //@ts-ignore
4730
5005
  _template: template.name
4731
5006
  };
4732
5007
  }
@@ -4766,6 +5041,7 @@ var Resolver = class {
4766
5041
  return this.getDocument(realPath);
4767
5042
  }
4768
5043
  const params = await this.buildObjectMutations(
5044
+ // @ts-ignore
4769
5045
  args.params[collection.name],
4770
5046
  collection
4771
5047
  );
@@ -4811,6 +5087,7 @@ var Resolver = class {
4811
5087
  const values = {
4812
5088
  ...oldDoc,
4813
5089
  ...await this.buildFieldMutations(
5090
+ // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
4814
5091
  templateParams,
4815
5092
  template,
4816
5093
  doc?._rawData
@@ -4824,13 +5101,22 @@ var Resolver = class {
4824
5101
  return this.getDocument(realPath);
4825
5102
  }
4826
5103
  const params = await this.buildObjectMutations(
5104
+ //@ts-ignore
4827
5105
  isCollectionSpecific ? args.params : args.params[collection.name],
4828
5106
  collection,
4829
5107
  doc?._rawData
4830
5108
  );
4831
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
5109
+ await this.database.put(
5110
+ realPath,
5111
+ { ...oldDoc, ...params },
5112
+ collection.name
5113
+ );
4832
5114
  return this.getDocument(realPath);
4833
5115
  };
5116
+ /**
5117
+ * Returns top-level fields which are not defined in the collection, so their
5118
+ * values are not eliminated from Tina when new values are saved
5119
+ */
4834
5120
  this.resolveLegacyValues = (oldDoc, collection) => {
4835
5121
  const legacyValues = {};
4836
5122
  Object.entries(oldDoc).forEach(([key, value]) => {
@@ -4937,17 +5223,35 @@ var Resolver = class {
4937
5223
  await this.deleteDocument(realPath);
4938
5224
  if (await this.hasReferences(realPath, collection)) {
4939
5225
  const collRefs = await this.findReferences(realPath, collection);
4940
- for (const [collection2, refFields] of Object.entries(collRefs)) {
4941
- for (const [refPath, refs] of Object.entries(refFields)) {
4942
- let refDoc = await this.getRaw(refPath);
4943
- for (const ref of refs) {
4944
- refDoc = updateObjectWithJsonPath(
5226
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5227
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5228
+ docsWithRefs
5229
+ )) {
5230
+ let refDoc = await this.getRaw(pathToDocWithRef);
5231
+ let hasUpdate = false;
5232
+ for (const path7 of referencePaths) {
5233
+ const { object: object2, updated } = updateObjectWithJsonPath(
4945
5234
  refDoc,
4946
- ref.path.join("."),
5235
+ path7,
5236
+ realPath,
4947
5237
  null
4948
5238
  );
5239
+ refDoc = object2;
5240
+ hasUpdate = updated || hasUpdate;
5241
+ }
5242
+ if (hasUpdate) {
5243
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5244
+ if (!collectionWithRef) {
5245
+ throw new Error(
5246
+ `Unable to find collection for ${pathToDocWithRef}`
5247
+ );
5248
+ }
5249
+ await this.database.put(
5250
+ pathToDocWithRef,
5251
+ refDoc,
5252
+ collectionWithRef.name
5253
+ );
4949
5254
  }
4950
- await this.database.put(refPath, refDoc, collection2);
4951
5255
  }
4952
5256
  }
4953
5257
  }
@@ -4967,26 +5271,49 @@ var Resolver = class {
4967
5271
  collection?.path,
4968
5272
  args.params.relativePath
4969
5273
  );
5274
+ if (newRealPath === realPath) {
5275
+ return doc;
5276
+ }
4970
5277
  await this.database.put(newRealPath, doc._rawData, collection.name);
4971
5278
  await this.deleteDocument(realPath);
4972
5279
  const collRefs = await this.findReferences(realPath, collection);
4973
- for (const [collection2, refFields] of Object.entries(collRefs)) {
4974
- for (const [refPath, refs] of Object.entries(refFields)) {
4975
- let refDoc = await this.getRaw(refPath);
4976
- for (const ref of refs) {
4977
- refDoc = updateObjectWithJsonPath(
4978
- refDoc,
4979
- ref.path.join("."),
5280
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5281
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5282
+ docsWithRefs
5283
+ )) {
5284
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5285
+ let hasUpdate = false;
5286
+ for (const path7 of referencePaths) {
5287
+ const { object: object2, updated } = updateObjectWithJsonPath(
5288
+ docWithRef,
5289
+ path7,
5290
+ realPath,
4980
5291
  newRealPath
4981
5292
  );
5293
+ docWithRef = object2;
5294
+ hasUpdate = updated || hasUpdate;
5295
+ }
5296
+ if (hasUpdate) {
5297
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5298
+ if (!collectionWithRef) {
5299
+ throw new Error(
5300
+ `Unable to find collection for ${pathToDocWithRef}`
5301
+ );
5302
+ }
5303
+ await this.database.put(
5304
+ pathToDocWithRef,
5305
+ docWithRef,
5306
+ collectionWithRef.name
5307
+ );
4982
5308
  }
4983
- await this.database.put(refPath, refDoc, collection2);
4984
5309
  }
4985
5310
  }
4986
5311
  return this.getDocument(newRealPath);
4987
5312
  }
4988
5313
  if (alreadyExists === false) {
4989
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5314
+ throw new Error(
5315
+ `Unable to update document, ${realPath} does not exist`
5316
+ );
4990
5317
  }
4991
5318
  return this.updateResolveDocument({
4992
5319
  collection,
@@ -5036,6 +5363,7 @@ var Resolver = class {
5036
5363
  },
5037
5364
  collection: referencedCollection,
5038
5365
  hydrator: (path7) => path7
5366
+ // just return the path
5039
5367
  }
5040
5368
  );
5041
5369
  const { edges } = resolvedCollectionConnection;
@@ -5103,78 +5431,80 @@ var Resolver = class {
5103
5431
  }
5104
5432
  };
5105
5433
  };
5434
+ /**
5435
+ * Checks if a document has references to it
5436
+ * @param id The id of the document to check for references
5437
+ * @param c The collection to check for references
5438
+ * @returns true if the document has references, false otherwise
5439
+ */
5106
5440
  this.hasReferences = async (id, c) => {
5107
5441
  let count = 0;
5108
- const deepRefs = this.tinaSchema.findReferences(c.name);
5109
- for (const [collection, refs] of Object.entries(deepRefs)) {
5110
- for (const ref of refs) {
5111
- await this.database.query(
5112
- {
5113
- collection,
5114
- filterChain: makeFilterChain({
5115
- conditions: [
5116
- {
5117
- filterPath: ref.path.join("."),
5118
- filterExpression: {
5119
- _type: "reference",
5120
- _list: false,
5121
- eq: id
5122
- }
5123
- }
5124
- ]
5125
- }),
5126
- sort: ref.field.name
5127
- },
5128
- (refId) => {
5129
- count++;
5130
- return refId;
5131
- }
5132
- );
5133
- if (count) {
5134
- return true;
5135
- }
5442
+ await this.database.query(
5443
+ {
5444
+ collection: c.name,
5445
+ filterChain: makeFilterChain({
5446
+ conditions: [
5447
+ {
5448
+ filterPath: REFS_REFERENCE_FIELD,
5449
+ filterExpression: {
5450
+ _type: "string",
5451
+ _list: false,
5452
+ eq: id
5453
+ }
5454
+ }
5455
+ ]
5456
+ }),
5457
+ sort: REFS_COLLECTIONS_SORT_KEY
5458
+ },
5459
+ (refId) => {
5460
+ count++;
5461
+ return refId;
5136
5462
  }
5463
+ );
5464
+ if (count) {
5465
+ return true;
5137
5466
  }
5138
5467
  return false;
5139
5468
  };
5469
+ /**
5470
+ * Finds references to a document
5471
+ * @param id the id of the document to find references to
5472
+ * @param c the collection to find references in
5473
+ * @returns a map of references to the document
5474
+ */
5140
5475
  this.findReferences = async (id, c) => {
5141
5476
  const references = {};
5142
- const deepRefs = this.tinaSchema.findReferences(c.name);
5143
- for (const [collection, refs] of Object.entries(deepRefs)) {
5144
- for (const ref of refs) {
5145
- await this.database.query(
5146
- {
5147
- collection,
5148
- filterChain: makeFilterChain({
5149
- conditions: [
5150
- {
5151
- filterPath: ref.path.join("."),
5152
- filterExpression: {
5153
- _type: "reference",
5154
- _list: false,
5155
- eq: id
5156
- }
5157
- }
5158
- ]
5159
- }),
5160
- sort: ref.field.name
5161
- },
5162
- (refId) => {
5163
- if (!references[collection]) {
5164
- references[collection] = {};
5165
- }
5166
- if (!references[collection][refId]) {
5167
- references[collection][refId] = [];
5477
+ await this.database.query(
5478
+ {
5479
+ collection: c.name,
5480
+ filterChain: makeFilterChain({
5481
+ conditions: [
5482
+ {
5483
+ filterPath: REFS_REFERENCE_FIELD,
5484
+ filterExpression: {
5485
+ _type: "string",
5486
+ _list: false,
5487
+ eq: id
5488
+ }
5168
5489
  }
5169
- references[collection][refId].push({
5170
- path: ref.path,
5171
- field: ref.field
5172
- });
5173
- return refId;
5174
- }
5175
- );
5490
+ ]
5491
+ }),
5492
+ sort: REFS_COLLECTIONS_SORT_KEY
5493
+ },
5494
+ (refId, rawItem) => {
5495
+ if (!references[c.name]) {
5496
+ references[c.name] = {};
5497
+ }
5498
+ if (!references[c.name][refId]) {
5499
+ references[c.name][refId] = [];
5500
+ }
5501
+ const referencePath = rawItem?.[REFS_PATH_FIELD];
5502
+ if (referencePath) {
5503
+ references[c.name][refId].push(referencePath);
5504
+ }
5505
+ return refId;
5176
5506
  }
5177
- }
5507
+ );
5178
5508
  return references;
5179
5509
  };
5180
5510
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
@@ -5263,6 +5593,27 @@ var Resolver = class {
5263
5593
  }
5264
5594
  return accum;
5265
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
+ */
5266
5617
  this.buildParams = (args) => {
5267
5618
  try {
5268
5619
  assertShape(
@@ -5362,7 +5713,10 @@ var resolve = async ({
5362
5713
  const graphQLSchema = buildASTSchema(graphQLSchemaAst);
5363
5714
  const tinaConfig = await database.getTinaSchema();
5364
5715
  const tinaSchema = await createSchema({
5716
+ // TODO: please update all the types to import from @tinacms/schema-tools
5717
+ // @ts-ignore
5365
5718
  schema: tinaConfig,
5719
+ // @ts-ignore
5366
5720
  flags: tinaConfig?.meta?.flags
5367
5721
  });
5368
5722
  const resolver = createResolver({
@@ -5379,8 +5733,7 @@ var resolve = async ({
5379
5733
  database
5380
5734
  },
5381
5735
  typeResolver: async (source, _args, info) => {
5382
- if (source.__typename)
5383
- return source.__typename;
5736
+ if (source.__typename) return source.__typename;
5384
5737
  const namedType = getNamedType(info.returnType).toString();
5385
5738
  const lookup = await database.getLookup(namedType);
5386
5739
  if (lookup.resolveType === "unionData") {
@@ -5529,11 +5882,13 @@ var resolve = async ({
5529
5882
  set(
5530
5883
  params,
5531
5884
  userField.path.slice(1),
5885
+ // remove _rawData from users path
5532
5886
  users.map((u) => {
5533
5887
  if (user[idFieldName] === u[idFieldName]) {
5534
5888
  return user;
5535
5889
  }
5536
5890
  return {
5891
+ // don't overwrite other users' passwords
5537
5892
  ...u,
5538
5893
  [passwordFieldName]: {
5539
5894
  ...u[passwordFieldName],
@@ -5556,6 +5911,9 @@ var resolve = async ({
5556
5911
  }
5557
5912
  const isCreation = lookup[info.fieldName] === "create";
5558
5913
  switch (lookup.resolveType) {
5914
+ /**
5915
+ * `node(id: $id)`
5916
+ */
5559
5917
  case "nodeDocument":
5560
5918
  assertShape(
5561
5919
  args,
@@ -5587,6 +5945,7 @@ var resolve = async ({
5587
5945
  collection: args.collection,
5588
5946
  isMutation,
5589
5947
  isCreation,
5948
+ // Right now this is the only case for deletion
5590
5949
  isDeletion: info.fieldName === "deleteDocument",
5591
5950
  isFolderCreation: info.fieldName === "createFolder",
5592
5951
  isUpdateName: Boolean(args?.params?.relativePath),
@@ -5596,6 +5955,9 @@ var resolve = async ({
5596
5955
  return result;
5597
5956
  }
5598
5957
  return value;
5958
+ /**
5959
+ * eg `getMovieDocument.data.actors`
5960
+ */
5599
5961
  case "multiCollectionDocumentList":
5600
5962
  if (Array.isArray(value)) {
5601
5963
  return {
@@ -5607,7 +5969,15 @@ var resolve = async ({
5607
5969
  }
5608
5970
  if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
5609
5971
  let filter = args.filter;
5610
- 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") {
5972
+ if (
5973
+ // 1. Make sure that the filter exists
5974
+ typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
5975
+ // @ts-ignore
5976
+ typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
5977
+ // @ts-ignore
5978
+ Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
5979
+ typeof args.filter[value?.collection?.name] !== "undefined"
5980
+ ) {
5611
5981
  filter = args.filter[value.collection.name];
5612
5982
  }
5613
5983
  return resolver.resolveCollectionConnection({
@@ -5615,12 +5985,20 @@ var resolve = async ({
5615
5985
  ...args,
5616
5986
  filter
5617
5987
  },
5988
+ // @ts-ignore
5618
5989
  collection: value.collection
5619
5990
  });
5620
5991
  }
5621
5992
  throw new Error(
5622
5993
  `Expected an array for result of ${info.fieldName} at ${info.path}`
5623
5994
  );
5995
+ /**
5996
+ * Collections-specific getter
5997
+ * eg. `getPostDocument`/`createPostDocument`/`updatePostDocument`
5998
+ *
5999
+ * if coming from a query result
6000
+ * the field will be `node`
6001
+ */
5624
6002
  case "collectionDocument": {
5625
6003
  if (value) {
5626
6004
  return value;
@@ -5635,11 +6013,32 @@ var resolve = async ({
5635
6013
  });
5636
6014
  return result;
5637
6015
  }
6016
+ /**
6017
+ * Collections-specific list getter
6018
+ * eg. `getPageList`
6019
+ */
5638
6020
  case "collectionDocumentList":
5639
6021
  return resolver.resolveCollectionConnection({
5640
6022
  args,
5641
6023
  collection: tinaSchema.getCollection(lookup.collection)
5642
6024
  });
6025
+ /**
6026
+ * A polymorphic data set, it can be from a document's data
6027
+ * of any nested object which can be one of many shapes
6028
+ *
6029
+ * ```graphql
6030
+ * getPostDocument(relativePath: $relativePath) {
6031
+ * data {...} <- this part
6032
+ * }
6033
+ * ```
6034
+ * ```graphql
6035
+ * getBlockDocument(relativePath: $relativePath) {
6036
+ * data {
6037
+ * blocks {...} <- or this part
6038
+ * }
6039
+ * }
6040
+ * ```
6041
+ */
5643
6042
  case "unionData":
5644
6043
  if (!value) {
5645
6044
  if (args.relativePath) {
@@ -5704,8 +6103,7 @@ var TinaLevelClient = class extends ManyLevelGuest {
5704
6103
  this.port = port || 9e3;
5705
6104
  }
5706
6105
  openConnection() {
5707
- if (this._connected)
5708
- return;
6106
+ if (this._connected) return;
5709
6107
  const socket = connect(this.port);
5710
6108
  pipeline(socket, this.createRpcStream(), socket, () => {
5711
6109
  this._connected = false;
@@ -5715,7 +6113,7 @@ var TinaLevelClient = class extends ManyLevelGuest {
5715
6113
  };
5716
6114
 
5717
6115
  // src/database/index.ts
5718
- import path4 from "path";
6116
+ import path4 from "node:path";
5719
6117
  import { GraphQLError as GraphQLError5 } from "graphql";
5720
6118
  import micromatch2 from "micromatch";
5721
6119
  import sha2 from "js-sha1";
@@ -5850,6 +6248,7 @@ var Database = class {
5850
6248
  );
5851
6249
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
5852
6250
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6251
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
5853
6252
  const normalizedPath = normalizePath(filepath);
5854
6253
  if (!collection?.isDetached) {
5855
6254
  if (this.bridge) {
@@ -5878,6 +6277,14 @@ var Database = class {
5878
6277
  let delOps = [];
5879
6278
  if (!isGitKeep(normalizedPath, collection)) {
5880
6279
  putOps = [
6280
+ ...makeRefOpsForDocument(
6281
+ normalizedPath,
6282
+ collection?.name,
6283
+ collectionReferences,
6284
+ dataFields,
6285
+ "put",
6286
+ level
6287
+ ),
5881
6288
  ...makeIndexOpsForDocument(
5882
6289
  normalizedPath,
5883
6290
  collection?.name,
@@ -5886,6 +6293,7 @@ var Database = class {
5886
6293
  "put",
5887
6294
  level
5888
6295
  ),
6296
+ // folder indices
5889
6297
  ...makeIndexOpsForDocument(
5890
6298
  normalizedPath,
5891
6299
  `${collection?.name}_${folderKey}`,
@@ -5900,6 +6308,14 @@ var Database = class {
5900
6308
  SUBLEVEL_OPTIONS
5901
6309
  ).get(normalizedPath);
5902
6310
  delOps = existingItem ? [
6311
+ ...makeRefOpsForDocument(
6312
+ normalizedPath,
6313
+ collection?.name,
6314
+ collectionReferences,
6315
+ existingItem,
6316
+ "del",
6317
+ level
6318
+ ),
5903
6319
  ...makeIndexOpsForDocument(
5904
6320
  normalizedPath,
5905
6321
  collection?.name,
@@ -5908,6 +6324,7 @@ var Database = class {
5908
6324
  "del",
5909
6325
  level
5910
6326
  ),
6327
+ // folder indices
5911
6328
  ...makeIndexOpsForDocument(
5912
6329
  normalizedPath,
5913
6330
  `${collection?.name}_${folderKey}`,
@@ -5946,6 +6363,7 @@ var Database = class {
5946
6363
  );
5947
6364
  collectionIndexDefinitions = indexDefinitions?.[collectionName];
5948
6365
  }
6366
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
5949
6367
  const normalizedPath = normalizePath(filepath);
5950
6368
  const dataFields = await this.formatBodyOnPayload(filepath, data);
5951
6369
  const collection = await this.collectionForPath(filepath);
@@ -5993,6 +6411,14 @@ var Database = class {
5993
6411
  let delOps = [];
5994
6412
  if (!isGitKeep(normalizedPath, collection)) {
5995
6413
  putOps = [
6414
+ ...makeRefOpsForDocument(
6415
+ normalizedPath,
6416
+ collectionName,
6417
+ collectionReferences,
6418
+ dataFields,
6419
+ "put",
6420
+ level
6421
+ ),
5996
6422
  ...makeIndexOpsForDocument(
5997
6423
  normalizedPath,
5998
6424
  collectionName,
@@ -6001,6 +6427,7 @@ var Database = class {
6001
6427
  "put",
6002
6428
  level
6003
6429
  ),
6430
+ // folder indices
6004
6431
  ...makeIndexOpsForDocument(
6005
6432
  normalizedPath,
6006
6433
  `${collection?.name}_${folderKey}`,
@@ -6015,6 +6442,14 @@ var Database = class {
6015
6442
  SUBLEVEL_OPTIONS
6016
6443
  ).get(normalizedPath);
6017
6444
  delOps = existingItem ? [
6445
+ ...makeRefOpsForDocument(
6446
+ normalizedPath,
6447
+ collectionName,
6448
+ collectionReferences,
6449
+ existingItem,
6450
+ "del",
6451
+ level
6452
+ ),
6018
6453
  ...makeIndexOpsForDocument(
6019
6454
  normalizedPath,
6020
6455
  collectionName,
@@ -6023,6 +6458,7 @@ var Database = class {
6023
6458
  "del",
6024
6459
  level
6025
6460
  ),
6461
+ // folder indices
6026
6462
  ...makeIndexOpsForDocument(
6027
6463
  normalizedPath,
6028
6464
  `${collection?.name}_${folderKey}`,
@@ -6100,6 +6536,7 @@ var Database = class {
6100
6536
  aliasedData,
6101
6537
  extension,
6102
6538
  writeTemplateKey,
6539
+ //templateInfo.type === 'union',
6103
6540
  {
6104
6541
  frontmatterFormat: collection?.frontmatterFormat,
6105
6542
  frontmatterDelimiters: collection?.frontmatterDelimiters
@@ -6138,6 +6575,7 @@ var Database = class {
6138
6575
  SUBLEVEL_OPTIONS
6139
6576
  ).get(graphqlPath);
6140
6577
  };
6578
+ //TODO - is there a reason why the database fetches some config with "bridge.get", and some with "store.get"?
6141
6579
  this.getGraphQLSchemaFromBridge = async () => {
6142
6580
  if (!this.bridge) {
6143
6581
  throw new Error(`No bridge configured`);
@@ -6174,6 +6612,22 @@ var Database = class {
6174
6612
  this.tinaSchema = await createSchema({ schema });
6175
6613
  return this.tinaSchema;
6176
6614
  };
6615
+ this.getCollectionReferences = async (level) => {
6616
+ if (this.collectionReferences) {
6617
+ return this.collectionReferences;
6618
+ }
6619
+ const result = {};
6620
+ const schema = await this.getSchema(level || this.contentLevel);
6621
+ const collections = schema.getCollections();
6622
+ for (const collection of collections) {
6623
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6624
+ collection.name
6625
+ );
6626
+ result[collection.name] = collectionReferences;
6627
+ }
6628
+ this.collectionReferences = result;
6629
+ return result;
6630
+ };
6177
6631
  this.getIndexDefinitions = async (level) => {
6178
6632
  if (!this.collectionIndexDefinitions) {
6179
6633
  await new Promise(async (resolve2, reject) => {
@@ -6183,10 +6637,53 @@ var Database = class {
6183
6637
  const collections = schema.getCollections();
6184
6638
  for (const collection of collections) {
6185
6639
  const indexDefinitions = {
6186
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6640
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6641
+ // provide a default sort key which is the file sort
6642
+ // pseudo-index for the collection's references
6643
+ [REFS_COLLECTIONS_SORT_KEY]: {
6644
+ fields: [
6645
+ {
6646
+ name: REFS_REFERENCE_FIELD,
6647
+ type: "string",
6648
+ list: false
6649
+ },
6650
+ {
6651
+ name: REFS_PATH_FIELD,
6652
+ type: "string",
6653
+ list: false
6654
+ }
6655
+ ]
6656
+ }
6187
6657
  };
6188
- if (collection.fields) {
6189
- for (const field of collection.fields) {
6658
+ let fields = [];
6659
+ if (collection.templates) {
6660
+ const templateFieldMap = {};
6661
+ const conflictedFields = /* @__PURE__ */ new Set();
6662
+ for (const template of collection.templates) {
6663
+ for (const field of template.fields) {
6664
+ if (!templateFieldMap[field.name]) {
6665
+ templateFieldMap[field.name] = field;
6666
+ } else {
6667
+ if (templateFieldMap[field.name].type !== field.type) {
6668
+ console.warn(
6669
+ `Field ${field.name} has conflicting types in templates - skipping index`
6670
+ );
6671
+ conflictedFields.add(field.name);
6672
+ }
6673
+ }
6674
+ }
6675
+ }
6676
+ for (const conflictedField in conflictedFields) {
6677
+ delete templateFieldMap[conflictedField];
6678
+ }
6679
+ for (const field of Object.values(templateFieldMap)) {
6680
+ fields.push(field);
6681
+ }
6682
+ } else if (collection.fields) {
6683
+ fields = collection.fields;
6684
+ }
6685
+ if (fields) {
6686
+ for (const field of fields) {
6190
6687
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6191
6688
  continue;
6192
6689
  }
@@ -6334,29 +6831,36 @@ var Database = class {
6334
6831
  }
6335
6832
  startKey = startKey || key || "";
6336
6833
  endKey = key || "";
6337
- edges = [...edges, { cursor: key, path: filepath }];
6834
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6338
6835
  }
6339
6836
  return {
6340
- edges: await sequential(edges, async (edge) => {
6341
- try {
6342
- const node = await hydrator(edge.path);
6343
- return {
6344
- node,
6345
- cursor: btoa(edge.cursor)
6346
- };
6347
- } catch (error) {
6348
- console.log(error);
6349
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6350
- throw new TinaQueryError({
6351
- originalError: error,
6352
- file: edge.path,
6353
- collection: collection.name,
6354
- stack: error.stack
6355
- });
6837
+ edges: await sequential(
6838
+ edges,
6839
+ async ({
6840
+ cursor,
6841
+ path: path7,
6842
+ value
6843
+ }) => {
6844
+ try {
6845
+ const node = await hydrator(path7, value);
6846
+ return {
6847
+ node,
6848
+ cursor: btoa(cursor)
6849
+ };
6850
+ } catch (error) {
6851
+ console.log(error);
6852
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6853
+ throw new TinaQueryError({
6854
+ originalError: error,
6855
+ file: path7,
6856
+ collection: collection.name,
6857
+ stack: error.stack
6858
+ });
6859
+ }
6860
+ throw error;
6356
6861
  }
6357
- throw error;
6358
6862
  }
6359
- }),
6863
+ ),
6360
6864
  pageInfo: {
6361
6865
  hasPreviousPage,
6362
6866
  hasNextPage,
@@ -6480,13 +6984,14 @@ var Database = class {
6480
6984
  documentPaths,
6481
6985
  async (collection, documentPaths2) => {
6482
6986
  if (collection && !collection.isDetached) {
6483
- await _indexContent(
6484
- this,
6485
- this.contentLevel,
6486
- documentPaths2,
6987
+ await _indexContent({
6988
+ database: this,
6989
+ level: this.contentLevel,
6990
+ documentPaths: documentPaths2,
6487
6991
  enqueueOps,
6488
- collection
6489
- );
6992
+ collection,
6993
+ isPartialReindex: true
6994
+ });
6490
6995
  }
6491
6996
  }
6492
6997
  );
@@ -6502,17 +7007,18 @@ var Database = class {
6502
7007
  throw new Error(`No collection found for path: ${filepath}`);
6503
7008
  }
6504
7009
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
7010
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6505
7011
  const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6506
7012
  let level = this.contentLevel;
6507
7013
  if (collection?.isDetached) {
6508
7014
  level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
6509
7015
  }
6510
- const itemKey = normalizePath(filepath);
7016
+ const normalizedPath = normalizePath(filepath);
6511
7017
  const rootSublevel = level.sublevel(
6512
7018
  CONTENT_ROOT_PREFIX,
6513
7019
  SUBLEVEL_OPTIONS
6514
7020
  );
6515
- const item = await rootSublevel.get(itemKey);
7021
+ const item = await rootSublevel.get(normalizedPath);
6516
7022
  if (item) {
6517
7023
  const folderTreeBuilder = new FolderTreeBuilder();
6518
7024
  const folderKey = folderTreeBuilder.update(
@@ -6520,16 +7026,25 @@ var Database = class {
6520
7026
  collection.path || ""
6521
7027
  );
6522
7028
  await this.contentLevel.batch([
7029
+ ...makeRefOpsForDocument(
7030
+ normalizedPath,
7031
+ collection.name,
7032
+ collectionReferences,
7033
+ item,
7034
+ "del",
7035
+ level
7036
+ ),
6523
7037
  ...makeIndexOpsForDocument(
6524
- filepath,
7038
+ normalizedPath,
6525
7039
  collection.name,
6526
7040
  collectionIndexDefinitions,
6527
7041
  item,
6528
7042
  "del",
6529
7043
  level
6530
7044
  ),
7045
+ // folder indices
6531
7046
  ...makeIndexOpsForDocument(
6532
- filepath,
7047
+ normalizedPath,
6533
7048
  `${collection.name}_${folderKey}`,
6534
7049
  collectionIndexDefinitions,
6535
7050
  item,
@@ -6538,17 +7053,17 @@ var Database = class {
6538
7053
  ),
6539
7054
  {
6540
7055
  type: "del",
6541
- key: itemKey,
7056
+ key: normalizedPath,
6542
7057
  sublevel: rootSublevel
6543
7058
  }
6544
7059
  ]);
6545
7060
  }
6546
7061
  if (!collection?.isDetached) {
6547
7062
  if (this.bridge) {
6548
- await this.bridge.delete(normalizePath(filepath));
7063
+ await this.bridge.delete(normalizedPath);
6549
7064
  }
6550
7065
  try {
6551
- await this.onDelete(normalizePath(filepath));
7066
+ await this.onDelete(normalizedPath);
6552
7067
  } catch (e) {
6553
7068
  throw new GraphQLError5(
6554
7069
  `Error running onDelete hook for ${filepath}: ${e}`,
@@ -6583,20 +7098,26 @@ var Database = class {
6583
7098
  );
6584
7099
  const doc = await level2.keys({ limit: 1 }).next();
6585
7100
  if (!doc) {
6586
- await _indexContent(
6587
- this,
6588
- level2,
6589
- contentPaths,
7101
+ await _indexContent({
7102
+ database: this,
7103
+ level: level2,
7104
+ documentPaths: contentPaths,
6590
7105
  enqueueOps,
6591
7106
  collection,
6592
- userFields.map((field) => [
7107
+ passwordFields: userFields.map((field) => [
6593
7108
  ...field.path,
6594
7109
  field.passwordFieldName
6595
7110
  ])
6596
- );
7111
+ });
6597
7112
  }
6598
7113
  } else {
6599
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7114
+ await _indexContent({
7115
+ database: this,
7116
+ level,
7117
+ documentPaths: contentPaths,
7118
+ enqueueOps,
7119
+ collection
7120
+ });
6600
7121
  }
6601
7122
  }
6602
7123
  );
@@ -6682,6 +7203,9 @@ var Database = class {
6682
7203
  info: templateInfo
6683
7204
  };
6684
7205
  }
7206
+ /**
7207
+ * Clears the internal cache of the tinaSchema and the lookup file. This allows the state to be reset
7208
+ */
6685
7209
  clearCache() {
6686
7210
  this.tinaSchema = null;
6687
7211
  this._lookup = null;
@@ -6732,7 +7256,15 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
6732
7256
  )
6733
7257
  );
6734
7258
  var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${collection?.format || "md"}`);
6735
- var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7259
+ var _indexContent = async ({
7260
+ database,
7261
+ level,
7262
+ documentPaths,
7263
+ enqueueOps,
7264
+ collection,
7265
+ passwordFields,
7266
+ isPartialReindex
7267
+ }) => {
6736
7268
  let collectionIndexDefinitions;
6737
7269
  let collectionPath;
6738
7270
  if (collection) {
@@ -6743,6 +7275,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6743
7275
  }
6744
7276
  collectionPath = collection.path;
6745
7277
  }
7278
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
6746
7279
  const tinaSchema = await database.getSchema();
6747
7280
  let templateInfo = null;
6748
7281
  if (collection) {
@@ -6764,12 +7297,61 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6764
7297
  await hashPasswordValues(aliasedData, passwordFields);
6765
7298
  }
6766
7299
  const normalizedPath = normalizePath(filepath);
7300
+ const rootSublevel = level.sublevel(
7301
+ CONTENT_ROOT_PREFIX,
7302
+ SUBLEVEL_OPTIONS
7303
+ );
6767
7304
  const folderKey = folderTreeBuilder.update(
6768
7305
  normalizedPath,
6769
7306
  collectionPath || ""
6770
7307
  );
7308
+ if (isPartialReindex) {
7309
+ const item = await rootSublevel.get(normalizedPath);
7310
+ if (item) {
7311
+ await database.contentLevel.batch([
7312
+ ...makeRefOpsForDocument(
7313
+ normalizedPath,
7314
+ collection?.name,
7315
+ collectionReferences,
7316
+ item,
7317
+ "del",
7318
+ level
7319
+ ),
7320
+ ...makeIndexOpsForDocument(
7321
+ normalizedPath,
7322
+ collection.name,
7323
+ collectionIndexDefinitions,
7324
+ item,
7325
+ "del",
7326
+ level
7327
+ ),
7328
+ // folder indices
7329
+ ...makeIndexOpsForDocument(
7330
+ normalizedPath,
7331
+ `${collection.name}_${folderKey}`,
7332
+ collectionIndexDefinitions,
7333
+ item,
7334
+ "del",
7335
+ level
7336
+ ),
7337
+ {
7338
+ type: "del",
7339
+ key: normalizedPath,
7340
+ sublevel: rootSublevel
7341
+ }
7342
+ ]);
7343
+ }
7344
+ }
6771
7345
  if (!isGitKeep(filepath, collection)) {
6772
7346
  await enqueueOps([
7347
+ ...makeRefOpsForDocument(
7348
+ normalizedPath,
7349
+ collection?.name,
7350
+ collectionReferences,
7351
+ aliasedData,
7352
+ "put",
7353
+ level
7354
+ ),
6773
7355
  ...makeIndexOpsForDocument(
6774
7356
  normalizedPath,
6775
7357
  collection?.name,
@@ -6778,6 +7360,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6778
7360
  "put",
6779
7361
  level
6780
7362
  ),
7363
+ // folder indexes
6781
7364
  ...makeIndexOpsForDocument(
6782
7365
  normalizedPath,
6783
7366
  `${collection?.name}_${folderKey}`,
@@ -6832,6 +7415,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6832
7415
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6833
7416
  }
6834
7417
  }
7418
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
6835
7419
  const tinaSchema = await database.getSchema();
6836
7420
  let templateInfo = null;
6837
7421
  if (collection) {
@@ -6855,6 +7439,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6855
7439
  item
6856
7440
  ) : item;
6857
7441
  await enqueueOps([
7442
+ ...makeRefOpsForDocument(
7443
+ itemKey,
7444
+ collection?.name,
7445
+ collectionReferences,
7446
+ aliasedData,
7447
+ "del",
7448
+ database.contentLevel
7449
+ ),
6858
7450
  ...makeIndexOpsForDocument(
6859
7451
  itemKey,
6860
7452
  collection.name,
@@ -6863,6 +7455,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6863
7455
  "del",
6864
7456
  database.contentLevel
6865
7457
  ),
7458
+ // folder indexes
6866
7459
  ...makeIndexOpsForDocument(
6867
7460
  itemKey,
6868
7461
  `${collection?.name}_${folderKey}`,
@@ -6983,8 +7576,8 @@ import path6 from "path";
6983
7576
  import normalize from "normalize-path";
6984
7577
  var FilesystemBridge = class {
6985
7578
  constructor(rootPath, outputPath) {
6986
- this.rootPath = rootPath || "";
6987
- this.outputPath = outputPath || rootPath;
7579
+ this.rootPath = path6.resolve(rootPath);
7580
+ this.outputPath = outputPath ? path6.resolve(outputPath) : this.rootPath;
6988
7581
  }
6989
7582
  async glob(pattern, extension) {
6990
7583
  const basePath = path6.join(this.outputPath, ...pattern.split("/"));
@@ -6996,19 +7589,19 @@ var FilesystemBridge = class {
6996
7589
  }
6997
7590
  );
6998
7591
  const posixRootPath = normalize(this.outputPath);
6999
- return items.map((item) => {
7000
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
7001
- });
7592
+ return items.map(
7593
+ (item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
7594
+ );
7002
7595
  }
7003
7596
  async delete(filepath) {
7004
7597
  await fs2.remove(path6.join(this.outputPath, filepath));
7005
7598
  }
7006
7599
  async get(filepath) {
7007
- return fs2.readFileSync(path6.join(this.outputPath, filepath)).toString();
7600
+ return (await fs2.readFile(path6.join(this.outputPath, filepath))).toString();
7008
7601
  }
7009
7602
  async put(filepath, data, basePathOverride) {
7010
7603
  const basePath = basePathOverride || this.outputPath;
7011
- await fs2.outputFileSync(path6.join(basePath, filepath), data);
7604
+ await fs2.outputFile(path6.join(basePath, filepath), data);
7012
7605
  }
7013
7606
  };
7014
7607
  var AuditFileSystemBridge = class extends FilesystemBridge {
@@ -7078,17 +7671,26 @@ var IsomorphicBridge = class {
7078
7671
  getAuthor() {
7079
7672
  return {
7080
7673
  ...this.author,
7081
- timestamp: Math.round(new Date().getTime() / 1e3),
7674
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7082
7675
  timezoneOffset: 0
7083
7676
  };
7084
7677
  }
7085
7678
  getCommitter() {
7086
7679
  return {
7087
7680
  ...this.committer,
7088
- timestamp: Math.round(new Date().getTime() / 1e3),
7681
+ timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
7089
7682
  timezoneOffset: 0
7090
7683
  };
7091
7684
  }
7685
+ /**
7686
+ * Recursively populate paths matching `pattern` for the given `entry`
7687
+ *
7688
+ * @param pattern - pattern to filter paths by
7689
+ * @param entry - TreeEntry to start building list from
7690
+ * @param path - base path
7691
+ * @param results
7692
+ * @private
7693
+ */
7092
7694
  async listEntries({
7093
7695
  pattern,
7094
7696
  entry,
@@ -7121,6 +7723,15 @@ var IsomorphicBridge = class {
7121
7723
  });
7122
7724
  }
7123
7725
  }
7726
+ /**
7727
+ * For the specified path, returns an object with an array containing the parts of the path (pathParts)
7728
+ * and an array containing the WalkerEntry objects for the path parts (pathEntries). Any null elements in the
7729
+ * pathEntries are placeholders for non-existent entries.
7730
+ *
7731
+ * @param path - path being resolved
7732
+ * @param ref - ref to resolve path entries for
7733
+ * @private
7734
+ */
7124
7735
  async resolvePathEntries(path7, ref) {
7125
7736
  let pathParts = path7.split("/");
7126
7737
  const result = await git2.walk({
@@ -7151,6 +7762,17 @@ var IsomorphicBridge = class {
7151
7762
  }
7152
7763
  return { pathParts, pathEntries };
7153
7764
  }
7765
+ /**
7766
+ * Updates tree entry and associated parent tree entries
7767
+ *
7768
+ * @param existingOid - the existing OID
7769
+ * @param updatedOid - the updated OID
7770
+ * @param path - the path of the entry being updated
7771
+ * @param type - the type of the entry being updated (blob or tree)
7772
+ * @param pathEntries - parent path entries
7773
+ * @param pathParts - parent path parts
7774
+ * @private
7775
+ */
7154
7776
  async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
7155
7777
  const lastIdx = pathEntries.length - 1;
7156
7778
  const parentEntry = pathEntries[lastIdx];
@@ -7206,6 +7828,13 @@ var IsomorphicBridge = class {
7206
7828
  );
7207
7829
  }
7208
7830
  }
7831
+ /**
7832
+ * Creates a commit for the specified tree and updates the specified ref to point to the commit
7833
+ *
7834
+ * @param treeSha - sha of the new tree
7835
+ * @param ref - the ref that should be updated
7836
+ * @private
7837
+ */
7209
7838
  async commitTree(treeSha, ref) {
7210
7839
  const commitSha = await git2.writeCommit({
7211
7840
  ...this.isomorphicConfig,
@@ -7218,6 +7847,7 @@ var IsomorphicBridge = class {
7218
7847
  })
7219
7848
  ],
7220
7849
  message: this.commitMessage,
7850
+ // TODO these should be configurable
7221
7851
  author: this.getAuthor(),
7222
7852
  committer: this.getCommitter()
7223
7853
  }
@@ -7455,5 +8085,5 @@ export {
7455
8085
  transformDocument,
7456
8086
  transformDocumentIntoPayload
7457
8087
  };
7458
- //! Replaces _.flattenDeep()
7459
8088
  //! Replaces _.get()
8089
+ //! Replaces _.flattenDeep()