@tinacms/graphql 0.0.0-ecea7ac-20241011043815 → 0.0.0-ed6025e-20251201040055
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/README.md +144 -0
- package/dist/ast-builder/index.d.ts +2 -3
- package/dist/build.d.ts +2 -4
- package/dist/builder/index.d.ts +2 -2
- package/dist/database/bridge/filesystem.d.ts +1 -1
- package/dist/database/datalayer.d.ts +5 -1
- package/dist/database/index.d.ts +2 -0
- package/dist/database/util.d.ts +6 -9
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1576 -793
- package/dist/index.mjs +1438 -635
- package/dist/mdx/index.d.ts +2 -7
- package/dist/resolver/auth-fields.d.ts +31 -0
- package/dist/resolver/error.d.ts +1 -2
- package/dist/resolver/index.d.ts +42 -7
- package/dist/resolver/media-utils.d.ts +3 -3
- package/dist/schema/createSchema.d.ts +0 -3
- package/dist/schema/validate.d.ts +0 -3
- package/package.json +19 -27
- package/readme.md +0 -194
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/build.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
print
|
|
4
|
+
} from "graphql";
|
|
5
|
+
import { uniqBy as uniqBy2 } from "es-toolkit";
|
|
4
6
|
|
|
5
7
|
// src/util.ts
|
|
6
8
|
import * as yup from "yup";
|
|
@@ -56,7 +58,7 @@ var flattenDeep = (arr) => arr.flatMap(
|
|
|
56
58
|
);
|
|
57
59
|
|
|
58
60
|
// src/ast-builder/index.ts
|
|
59
|
-
import uniqBy from "
|
|
61
|
+
import { uniqBy } from "es-toolkit";
|
|
60
62
|
var SysFieldDefinition = {
|
|
61
63
|
kind: "Field",
|
|
62
64
|
name: {
|
|
@@ -68,6 +70,15 @@ var SysFieldDefinition = {
|
|
|
68
70
|
selectionSet: {
|
|
69
71
|
kind: "SelectionSet",
|
|
70
72
|
selections: [
|
|
73
|
+
// {
|
|
74
|
+
// kind: 'Field' as const,
|
|
75
|
+
// name: {
|
|
76
|
+
// kind: 'Name' as const,
|
|
77
|
+
// value: 'title',
|
|
78
|
+
// },
|
|
79
|
+
// arguments: [],
|
|
80
|
+
// directives: [],
|
|
81
|
+
// },
|
|
71
82
|
{
|
|
72
83
|
kind: "Field",
|
|
73
84
|
name: {
|
|
@@ -86,6 +97,15 @@ var SysFieldDefinition = {
|
|
|
86
97
|
arguments: [],
|
|
87
98
|
directives: []
|
|
88
99
|
},
|
|
100
|
+
{
|
|
101
|
+
kind: "Field",
|
|
102
|
+
name: {
|
|
103
|
+
kind: "Name",
|
|
104
|
+
value: "hasReferences"
|
|
105
|
+
},
|
|
106
|
+
arguments: [],
|
|
107
|
+
directives: []
|
|
108
|
+
},
|
|
89
109
|
{
|
|
90
110
|
kind: "Field",
|
|
91
111
|
name: {
|
|
@@ -126,6 +146,10 @@ var SysFieldDefinition = {
|
|
|
126
146
|
}
|
|
127
147
|
};
|
|
128
148
|
var astBuilder = {
|
|
149
|
+
/**
|
|
150
|
+
* `FormFieldBuilder` acts as a shortcut to building an entire `ObjectTypeDefinition`, we use this
|
|
151
|
+
* because all Tina field objects share a common set of fields ('name', 'label', 'component')
|
|
152
|
+
*/
|
|
129
153
|
FormFieldBuilder: ({
|
|
130
154
|
name,
|
|
131
155
|
additionalFields
|
|
@@ -349,6 +373,8 @@ var astBuilder = {
|
|
|
349
373
|
kind: "Name",
|
|
350
374
|
value: name
|
|
351
375
|
},
|
|
376
|
+
// @ts-ignore FIXME; this is being handled properly but we're lying to
|
|
377
|
+
// ts and then fixing it in the `extractInlineTypes` function
|
|
352
378
|
fields
|
|
353
379
|
}),
|
|
354
380
|
UnionTypeDefinition: ({
|
|
@@ -361,6 +387,8 @@ var astBuilder = {
|
|
|
361
387
|
value: name
|
|
362
388
|
},
|
|
363
389
|
directives: [],
|
|
390
|
+
// @ts-ignore FIXME; this is being handled properly but we're lying to
|
|
391
|
+
// ts and then fixing it in the `extractInlineTypes` function
|
|
364
392
|
types: types.map((name2) => ({
|
|
365
393
|
kind: "NamedType",
|
|
366
394
|
name: {
|
|
@@ -457,8 +485,11 @@ var astBuilder = {
|
|
|
457
485
|
string: "String",
|
|
458
486
|
boolean: "Boolean",
|
|
459
487
|
number: "Float",
|
|
488
|
+
// FIXME - needs to be float or int
|
|
460
489
|
datetime: "String",
|
|
490
|
+
// FIXME
|
|
461
491
|
image: "String",
|
|
492
|
+
// FIXME
|
|
462
493
|
text: "String"
|
|
463
494
|
};
|
|
464
495
|
return scalars[type];
|
|
@@ -948,6 +979,7 @@ var astBuilder = {
|
|
|
948
979
|
...extractInlineTypes(ast.globalTemplates),
|
|
949
980
|
...ast.definitions
|
|
950
981
|
],
|
|
982
|
+
// @ts-ignore - all nodes have a name property in practice
|
|
951
983
|
(field) => field.name.value
|
|
952
984
|
);
|
|
953
985
|
return {
|
|
@@ -957,8 +989,7 @@ var astBuilder = {
|
|
|
957
989
|
}
|
|
958
990
|
};
|
|
959
991
|
var capitalize = (s) => {
|
|
960
|
-
if (typeof s !== "string")
|
|
961
|
-
return "";
|
|
992
|
+
if (typeof s !== "string") return "";
|
|
962
993
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
963
994
|
};
|
|
964
995
|
var extractInlineTypes = (item) => {
|
|
@@ -1001,41 +1032,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
|
|
|
1001
1032
|
yield maybeNode;
|
|
1002
1033
|
visited.add(maybeNode);
|
|
1003
1034
|
}
|
|
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
1035
|
var generateNamespacedFieldName = (names, suffix = "") => {
|
|
1040
1036
|
return (suffix ? [...names, suffix] : names).map(capitalize).join("");
|
|
1041
1037
|
};
|
|
@@ -1195,6 +1191,11 @@ var scalarDefinitions = [
|
|
|
1195
1191
|
required: true,
|
|
1196
1192
|
type: astBuilder.TYPES.String
|
|
1197
1193
|
}),
|
|
1194
|
+
astBuilder.FieldDefinition({
|
|
1195
|
+
name: "hasReferences",
|
|
1196
|
+
required: false,
|
|
1197
|
+
type: astBuilder.TYPES.Boolean
|
|
1198
|
+
}),
|
|
1198
1199
|
astBuilder.FieldDefinition({
|
|
1199
1200
|
name: "breadcrumbs",
|
|
1200
1201
|
required: true,
|
|
@@ -1408,6 +1409,19 @@ var Builder = class {
|
|
|
1408
1409
|
this.addToLookupMap = (lookup) => {
|
|
1409
1410
|
this.lookupMap[lookup.type] = lookup;
|
|
1410
1411
|
};
|
|
1412
|
+
/**
|
|
1413
|
+
* ```graphql
|
|
1414
|
+
* # ex.
|
|
1415
|
+
* {
|
|
1416
|
+
* getCollection(collection: $collection) {
|
|
1417
|
+
* name
|
|
1418
|
+
* documents {...}
|
|
1419
|
+
* }
|
|
1420
|
+
* }
|
|
1421
|
+
* ```
|
|
1422
|
+
*
|
|
1423
|
+
* @param collections
|
|
1424
|
+
*/
|
|
1411
1425
|
this.buildCollectionDefinition = async (collections) => {
|
|
1412
1426
|
const name = "collection";
|
|
1413
1427
|
const typeName = "Collection";
|
|
@@ -1478,6 +1492,19 @@ var Builder = class {
|
|
|
1478
1492
|
required: true
|
|
1479
1493
|
});
|
|
1480
1494
|
};
|
|
1495
|
+
/**
|
|
1496
|
+
* ```graphql
|
|
1497
|
+
* # ex.
|
|
1498
|
+
* {
|
|
1499
|
+
* getCollections {
|
|
1500
|
+
* name
|
|
1501
|
+
* documents {...}
|
|
1502
|
+
* }
|
|
1503
|
+
* }
|
|
1504
|
+
* ```
|
|
1505
|
+
*
|
|
1506
|
+
* @param collections
|
|
1507
|
+
*/
|
|
1481
1508
|
this.buildMultiCollectionDefinition = async (collections) => {
|
|
1482
1509
|
const name = "collections";
|
|
1483
1510
|
const typeName = "Collection";
|
|
@@ -1488,6 +1515,17 @@ var Builder = class {
|
|
|
1488
1515
|
required: true
|
|
1489
1516
|
});
|
|
1490
1517
|
};
|
|
1518
|
+
/**
|
|
1519
|
+
* ```graphql
|
|
1520
|
+
* # ex.
|
|
1521
|
+
* {
|
|
1522
|
+
* node(id: $id) {
|
|
1523
|
+
* id
|
|
1524
|
+
* data {...}
|
|
1525
|
+
* }
|
|
1526
|
+
* }
|
|
1527
|
+
* ```
|
|
1528
|
+
*/
|
|
1491
1529
|
this.multiNodeDocument = async () => {
|
|
1492
1530
|
const name = "node";
|
|
1493
1531
|
const args = [
|
|
@@ -1508,6 +1546,19 @@ var Builder = class {
|
|
|
1508
1546
|
required: true
|
|
1509
1547
|
});
|
|
1510
1548
|
};
|
|
1549
|
+
/**
|
|
1550
|
+
* ```graphql
|
|
1551
|
+
* # ex.
|
|
1552
|
+
* {
|
|
1553
|
+
* getDocument(collection: $collection, relativePath: $relativePath) {
|
|
1554
|
+
* id
|
|
1555
|
+
* data {...}
|
|
1556
|
+
* }
|
|
1557
|
+
* }
|
|
1558
|
+
* ```
|
|
1559
|
+
*
|
|
1560
|
+
* @param collections
|
|
1561
|
+
*/
|
|
1511
1562
|
this.multiCollectionDocument = async (collections) => {
|
|
1512
1563
|
const name = "document";
|
|
1513
1564
|
const args = [
|
|
@@ -1533,6 +1584,19 @@ var Builder = class {
|
|
|
1533
1584
|
required: true
|
|
1534
1585
|
});
|
|
1535
1586
|
};
|
|
1587
|
+
/**
|
|
1588
|
+
* ```graphql
|
|
1589
|
+
* # ex.
|
|
1590
|
+
* {
|
|
1591
|
+
* addPendingDocument(collection: $collection, relativePath: $relativePath, params: $params) {
|
|
1592
|
+
* id
|
|
1593
|
+
* data {...}
|
|
1594
|
+
* }
|
|
1595
|
+
* }
|
|
1596
|
+
* ```
|
|
1597
|
+
*
|
|
1598
|
+
* @param collections
|
|
1599
|
+
*/
|
|
1536
1600
|
this.addMultiCollectionDocumentMutation = async () => {
|
|
1537
1601
|
return astBuilder.FieldDefinition({
|
|
1538
1602
|
name: "addPendingDocument",
|
|
@@ -1557,6 +1621,19 @@ var Builder = class {
|
|
|
1557
1621
|
type: astBuilder.TYPES.MultiCollectionDocument
|
|
1558
1622
|
});
|
|
1559
1623
|
};
|
|
1624
|
+
/**
|
|
1625
|
+
* ```graphql
|
|
1626
|
+
* # ex.
|
|
1627
|
+
* {
|
|
1628
|
+
* createDocument(relativePath: $relativePath, params: $params) {
|
|
1629
|
+
* id
|
|
1630
|
+
* data {...}
|
|
1631
|
+
* }
|
|
1632
|
+
* }
|
|
1633
|
+
* ```
|
|
1634
|
+
*
|
|
1635
|
+
* @param collections
|
|
1636
|
+
*/
|
|
1560
1637
|
this.buildCreateCollectionDocumentMutation = async (collections) => {
|
|
1561
1638
|
return astBuilder.FieldDefinition({
|
|
1562
1639
|
name: "createDocument",
|
|
@@ -1584,6 +1661,19 @@ var Builder = class {
|
|
|
1584
1661
|
type: astBuilder.TYPES.MultiCollectionDocument
|
|
1585
1662
|
});
|
|
1586
1663
|
};
|
|
1664
|
+
/**
|
|
1665
|
+
* ```graphql
|
|
1666
|
+
* # ex.
|
|
1667
|
+
* {
|
|
1668
|
+
* updateDocument(relativePath: $relativePath, params: $params) {
|
|
1669
|
+
* id
|
|
1670
|
+
* data {...}
|
|
1671
|
+
* }
|
|
1672
|
+
* }
|
|
1673
|
+
* ```
|
|
1674
|
+
*
|
|
1675
|
+
* @param collections
|
|
1676
|
+
*/
|
|
1587
1677
|
this.buildUpdateCollectionDocumentMutation = async (collections) => {
|
|
1588
1678
|
return astBuilder.FieldDefinition({
|
|
1589
1679
|
name: "updateDocument",
|
|
@@ -1611,6 +1701,19 @@ var Builder = class {
|
|
|
1611
1701
|
type: astBuilder.TYPES.MultiCollectionDocument
|
|
1612
1702
|
});
|
|
1613
1703
|
};
|
|
1704
|
+
/**
|
|
1705
|
+
* ```graphql
|
|
1706
|
+
* # ex.
|
|
1707
|
+
* {
|
|
1708
|
+
* deleteDocument(relativePath: $relativePath, params: $params) {
|
|
1709
|
+
* id
|
|
1710
|
+
* data {...}
|
|
1711
|
+
* }
|
|
1712
|
+
* }
|
|
1713
|
+
* ```
|
|
1714
|
+
*
|
|
1715
|
+
* @param collections
|
|
1716
|
+
*/
|
|
1614
1717
|
this.buildDeleteCollectionDocumentMutation = async (collections) => {
|
|
1615
1718
|
return astBuilder.FieldDefinition({
|
|
1616
1719
|
name: "deleteDocument",
|
|
@@ -1630,6 +1733,19 @@ var Builder = class {
|
|
|
1630
1733
|
type: astBuilder.TYPES.MultiCollectionDocument
|
|
1631
1734
|
});
|
|
1632
1735
|
};
|
|
1736
|
+
/**
|
|
1737
|
+
* ```graphql
|
|
1738
|
+
* # ex.
|
|
1739
|
+
* {
|
|
1740
|
+
* createFolder(folderName: $folderName, params: $params) {
|
|
1741
|
+
* id
|
|
1742
|
+
* data {...}
|
|
1743
|
+
* }
|
|
1744
|
+
* }
|
|
1745
|
+
* ```
|
|
1746
|
+
*
|
|
1747
|
+
* @param collections
|
|
1748
|
+
*/
|
|
1633
1749
|
this.buildCreateCollectionFolderMutation = async () => {
|
|
1634
1750
|
return astBuilder.FieldDefinition({
|
|
1635
1751
|
name: "createFolder",
|
|
@@ -1649,6 +1765,19 @@ var Builder = class {
|
|
|
1649
1765
|
type: astBuilder.TYPES.MultiCollectionDocument
|
|
1650
1766
|
});
|
|
1651
1767
|
};
|
|
1768
|
+
/**
|
|
1769
|
+
* ```graphql
|
|
1770
|
+
* # ex.
|
|
1771
|
+
* {
|
|
1772
|
+
* getPostDocument(relativePath: $relativePath) {
|
|
1773
|
+
* id
|
|
1774
|
+
* data {...}
|
|
1775
|
+
* }
|
|
1776
|
+
* }
|
|
1777
|
+
* ```
|
|
1778
|
+
*
|
|
1779
|
+
* @param collection
|
|
1780
|
+
*/
|
|
1652
1781
|
this.collectionDocument = async (collection) => {
|
|
1653
1782
|
const name = NAMER.queryName([collection.name]);
|
|
1654
1783
|
const type = await this._buildCollectionDocumentType(collection);
|
|
@@ -1709,6 +1838,20 @@ var Builder = class {
|
|
|
1709
1838
|
const args = [];
|
|
1710
1839
|
return astBuilder.FieldDefinition({ type, name, args, required: false });
|
|
1711
1840
|
};
|
|
1841
|
+
/**
|
|
1842
|
+
* Turns a collection into a fragment that gets updated on build. This fragment does not resolve references
|
|
1843
|
+
* ```graphql
|
|
1844
|
+
* # ex.
|
|
1845
|
+
* fragment AuthorsParts on Authors {
|
|
1846
|
+
* name
|
|
1847
|
+
* avatar
|
|
1848
|
+
* ...
|
|
1849
|
+
* }
|
|
1850
|
+
* ```
|
|
1851
|
+
*
|
|
1852
|
+
* @public
|
|
1853
|
+
* @param collection a TinaCloud collection
|
|
1854
|
+
*/
|
|
1712
1855
|
this.collectionFragment = async (collection) => {
|
|
1713
1856
|
const name = NAMER.dataTypeName(collection.namespace);
|
|
1714
1857
|
const fragmentName = NAMER.fragmentName(collection.namespace);
|
|
@@ -1722,6 +1865,20 @@ var Builder = class {
|
|
|
1722
1865
|
selections: filterSelections(selections)
|
|
1723
1866
|
});
|
|
1724
1867
|
};
|
|
1868
|
+
/**
|
|
1869
|
+
* Given a collection this function returns its selections set. For example for Post this would return
|
|
1870
|
+
*
|
|
1871
|
+
* "
|
|
1872
|
+
* body
|
|
1873
|
+
* title
|
|
1874
|
+
* ... on Author {
|
|
1875
|
+
* name
|
|
1876
|
+
* heroImg
|
|
1877
|
+
* }
|
|
1878
|
+
*
|
|
1879
|
+
* But in the AST format
|
|
1880
|
+
*
|
|
1881
|
+
* */
|
|
1725
1882
|
this._getCollectionFragmentSelections = async (collection, depth) => {
|
|
1726
1883
|
const selections = [];
|
|
1727
1884
|
selections.push({
|
|
@@ -1803,9 +1960,9 @@ var Builder = class {
|
|
|
1803
1960
|
]
|
|
1804
1961
|
});
|
|
1805
1962
|
}
|
|
1963
|
+
// TODO: Should we throw here?
|
|
1806
1964
|
case "reference":
|
|
1807
|
-
if (depth >= this.maxDepth)
|
|
1808
|
-
return false;
|
|
1965
|
+
if (depth >= this.maxDepth) return false;
|
|
1809
1966
|
if (!("collections" in field)) {
|
|
1810
1967
|
return false;
|
|
1811
1968
|
}
|
|
@@ -1837,6 +1994,7 @@ var Builder = class {
|
|
|
1837
1994
|
name: field.name,
|
|
1838
1995
|
selections: [
|
|
1839
1996
|
...selections,
|
|
1997
|
+
// This is ... on Document { id }
|
|
1840
1998
|
{
|
|
1841
1999
|
kind: "InlineFragment",
|
|
1842
2000
|
typeCondition: {
|
|
@@ -1867,6 +2025,19 @@ var Builder = class {
|
|
|
1867
2025
|
});
|
|
1868
2026
|
}
|
|
1869
2027
|
};
|
|
2028
|
+
/**
|
|
2029
|
+
* ```graphql
|
|
2030
|
+
* # ex.
|
|
2031
|
+
* mutation {
|
|
2032
|
+
* updatePostDocument(relativePath: $relativePath, params: $params) {
|
|
2033
|
+
* id
|
|
2034
|
+
* data {...}
|
|
2035
|
+
* }
|
|
2036
|
+
* }
|
|
2037
|
+
* ```
|
|
2038
|
+
*
|
|
2039
|
+
* @param collection
|
|
2040
|
+
*/
|
|
1870
2041
|
this.updateCollectionDocumentMutation = async (collection) => {
|
|
1871
2042
|
return astBuilder.FieldDefinition({
|
|
1872
2043
|
type: await this._buildCollectionDocumentType(collection),
|
|
@@ -1886,6 +2057,19 @@ var Builder = class {
|
|
|
1886
2057
|
]
|
|
1887
2058
|
});
|
|
1888
2059
|
};
|
|
2060
|
+
/**
|
|
2061
|
+
* ```graphql
|
|
2062
|
+
* # ex.
|
|
2063
|
+
* mutation {
|
|
2064
|
+
* createPostDocument(relativePath: $relativePath, params: $params) {
|
|
2065
|
+
* id
|
|
2066
|
+
* data {...}
|
|
2067
|
+
* }
|
|
2068
|
+
* }
|
|
2069
|
+
* ```
|
|
2070
|
+
*
|
|
2071
|
+
* @param collection
|
|
2072
|
+
*/
|
|
1889
2073
|
this.createCollectionDocumentMutation = async (collection) => {
|
|
1890
2074
|
return astBuilder.FieldDefinition({
|
|
1891
2075
|
type: await this._buildCollectionDocumentType(collection),
|
|
@@ -1905,6 +2089,22 @@ var Builder = class {
|
|
|
1905
2089
|
]
|
|
1906
2090
|
});
|
|
1907
2091
|
};
|
|
2092
|
+
/**
|
|
2093
|
+
* ```graphql
|
|
2094
|
+
* # ex.
|
|
2095
|
+
* {
|
|
2096
|
+
* getPostList(first: 10) {
|
|
2097
|
+
* edges {
|
|
2098
|
+
* node {
|
|
2099
|
+
* id
|
|
2100
|
+
* }
|
|
2101
|
+
* }
|
|
2102
|
+
* }
|
|
2103
|
+
* }
|
|
2104
|
+
* ```
|
|
2105
|
+
*
|
|
2106
|
+
* @param collection
|
|
2107
|
+
*/
|
|
1908
2108
|
this.collectionDocumentList = async (collection) => {
|
|
1909
2109
|
const connectionName = NAMER.referenceConnectionType(collection.namespace);
|
|
1910
2110
|
this.addToLookupMap({
|
|
@@ -1920,6 +2120,10 @@ var Builder = class {
|
|
|
1920
2120
|
collection
|
|
1921
2121
|
});
|
|
1922
2122
|
};
|
|
2123
|
+
/**
|
|
2124
|
+
* GraphQL type definitions which remain unchanged regardless
|
|
2125
|
+
* of the supplied Tina schema. Ex. "node" interface
|
|
2126
|
+
*/
|
|
1923
2127
|
this.buildStaticDefinitions = () => staticDefinitions;
|
|
1924
2128
|
this._buildCollectionDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
|
|
1925
2129
|
const documentTypeName = NAMER.documentTypeName(collection.namespace);
|
|
@@ -2424,6 +2628,7 @@ var Builder = class {
|
|
|
2424
2628
|
name: NAMER.dataFilterTypeName(namespace),
|
|
2425
2629
|
fields: await sequential(collections, async (collection2) => {
|
|
2426
2630
|
return astBuilder.InputValueDefinition({
|
|
2631
|
+
// @ts-ignore
|
|
2427
2632
|
name: collection2.name,
|
|
2428
2633
|
type: NAMER.dataFilterTypeName(collection2.namespace)
|
|
2429
2634
|
});
|
|
@@ -2509,7 +2714,7 @@ var Builder = class {
|
|
|
2509
2714
|
this._buildDataField = async (field) => {
|
|
2510
2715
|
const listWarningMsg = `
|
|
2511
2716
|
WARNING: The user interface for ${field.type} does not support \`list: true\`
|
|
2512
|
-
Visit https://tina.io/docs/
|
|
2717
|
+
Visit https://tina.io/docs/r/content-fields/#list-fields/ for more information
|
|
2513
2718
|
|
|
2514
2719
|
`;
|
|
2515
2720
|
switch (field.type) {
|
|
@@ -2612,7 +2817,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
|
|
|
2612
2817
|
]
|
|
2613
2818
|
});
|
|
2614
2819
|
};
|
|
2615
|
-
this.maxDepth =
|
|
2820
|
+
this.maxDepth = // @ts-ignore
|
|
2821
|
+
config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
|
|
2616
2822
|
this.tinaSchema = config.tinaSchema;
|
|
2617
2823
|
this.lookupMap = {};
|
|
2618
2824
|
}
|
|
@@ -2623,8 +2829,7 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
|
|
|
2623
2829
|
selections.push(field);
|
|
2624
2830
|
});
|
|
2625
2831
|
const filteredSelections = filterSelections(selections);
|
|
2626
|
-
if (!filteredSelections.length)
|
|
2627
|
-
return false;
|
|
2832
|
+
if (!filteredSelections.length) return false;
|
|
2628
2833
|
return astBuilder.InlineFragmentDefinition({
|
|
2629
2834
|
selections: filteredSelections,
|
|
2630
2835
|
name: NAMER.dataTypeName(template.namespace)
|
|
@@ -2661,8 +2866,9 @@ var filterSelections = (arr) => {
|
|
|
2661
2866
|
import { TinaSchema } from "@tinacms/schema-tools";
|
|
2662
2867
|
|
|
2663
2868
|
// src/schema/validate.ts
|
|
2664
|
-
import
|
|
2869
|
+
import { addNamespaceToSchema } from "@tinacms/schema-tools";
|
|
2665
2870
|
import * as yup2 from "yup";
|
|
2871
|
+
import { cloneDeep } from "es-toolkit";
|
|
2666
2872
|
import {
|
|
2667
2873
|
validateTinaCloudSchemaConfig
|
|
2668
2874
|
} from "@tinacms/schema-tools";
|
|
@@ -2679,7 +2885,7 @@ var FIELD_TYPES = [
|
|
|
2679
2885
|
];
|
|
2680
2886
|
var validateSchema = async (schema) => {
|
|
2681
2887
|
const schema2 = addNamespaceToSchema(
|
|
2682
|
-
|
|
2888
|
+
cloneDeep(schema)
|
|
2683
2889
|
);
|
|
2684
2890
|
const collections = await sequential(
|
|
2685
2891
|
schema2.collections,
|
|
@@ -2707,6 +2913,7 @@ var validationCollectionsPathAndMatch = (collections) => {
|
|
|
2707
2913
|
}).map((x) => `${x.path}${x.format || "md"}`);
|
|
2708
2914
|
if (noMatchCollections.length !== new Set(noMatchCollections).size) {
|
|
2709
2915
|
throw new Error(
|
|
2916
|
+
// TODO: add a link to the docs
|
|
2710
2917
|
"Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
|
|
2711
2918
|
);
|
|
2712
2919
|
}
|
|
@@ -2815,7 +3022,7 @@ var validateField = async (field) => {
|
|
|
2815
3022
|
// package.json
|
|
2816
3023
|
var package_default = {
|
|
2817
3024
|
name: "@tinacms/graphql",
|
|
2818
|
-
version: "1.
|
|
3025
|
+
version: "1.6.3",
|
|
2819
3026
|
main: "dist/index.js",
|
|
2820
3027
|
module: "dist/index.mjs",
|
|
2821
3028
|
typings: "dist/index.d.ts",
|
|
@@ -2841,34 +3048,31 @@ var package_default = {
|
|
|
2841
3048
|
types: "pnpm tsc",
|
|
2842
3049
|
build: "tinacms-scripts build",
|
|
2843
3050
|
docs: "pnpm typedoc",
|
|
2844
|
-
|
|
2845
|
-
test: "
|
|
2846
|
-
"test-watch": "jest --watch"
|
|
3051
|
+
test: "vitest run",
|
|
3052
|
+
"test-watch": "vitest"
|
|
2847
3053
|
},
|
|
2848
3054
|
dependencies: {
|
|
2849
|
-
"@iarna/toml": "
|
|
3055
|
+
"@iarna/toml": "catalog:",
|
|
2850
3056
|
"@tinacms/mdx": "workspace:*",
|
|
2851
3057
|
"@tinacms/schema-tools": "workspace:*",
|
|
2852
|
-
"abstract-level": "
|
|
3058
|
+
"abstract-level": "catalog:",
|
|
2853
3059
|
"date-fns": "^2.30.0",
|
|
2854
|
-
"
|
|
2855
|
-
"
|
|
2856
|
-
"
|
|
3060
|
+
"es-toolkit": "^1.42.0",
|
|
3061
|
+
"fast-glob": "catalog:",
|
|
3062
|
+
"fs-extra": "catalog:",
|
|
3063
|
+
"glob-parent": "catalog:",
|
|
2857
3064
|
graphql: "15.8.0",
|
|
2858
|
-
"gray-matter": "
|
|
2859
|
-
"isomorphic-git": "
|
|
2860
|
-
"js-sha1": "
|
|
3065
|
+
"gray-matter": "catalog:",
|
|
3066
|
+
"isomorphic-git": "catalog:",
|
|
3067
|
+
"js-sha1": "catalog:",
|
|
2861
3068
|
"js-yaml": "^3.14.1",
|
|
2862
|
-
"jsonpath-plus": "
|
|
2863
|
-
"
|
|
2864
|
-
|
|
2865
|
-
"
|
|
2866
|
-
"
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
"readable-stream": "^4.5.2",
|
|
2870
|
-
scmp: "^2.1.0",
|
|
2871
|
-
yup: "^0.32.11"
|
|
3069
|
+
"jsonpath-plus": "catalog:",
|
|
3070
|
+
"many-level": "catalog:",
|
|
3071
|
+
micromatch: "catalog:",
|
|
3072
|
+
"normalize-path": "catalog:",
|
|
3073
|
+
"readable-stream": "catalog:",
|
|
3074
|
+
scmp: "catalog:",
|
|
3075
|
+
yup: "^1.6.1"
|
|
2872
3076
|
},
|
|
2873
3077
|
publishConfig: {
|
|
2874
3078
|
registry: "https://registry.npmjs.org"
|
|
@@ -2882,26 +3086,21 @@ var package_default = {
|
|
|
2882
3086
|
"@tinacms/scripts": "workspace:*",
|
|
2883
3087
|
"@types/cors": "^2.8.17",
|
|
2884
3088
|
"@types/estree": "^0.0.50",
|
|
2885
|
-
"@types/express": "
|
|
3089
|
+
"@types/express": "catalog:",
|
|
2886
3090
|
"@types/fs-extra": "^9.0.13",
|
|
2887
|
-
"@types/jest": "^26.0.24",
|
|
2888
3091
|
"@types/js-yaml": "^3.12.10",
|
|
2889
|
-
"@types/
|
|
2890
|
-
"@types/
|
|
2891
|
-
"@types/
|
|
2892
|
-
"@types/
|
|
2893
|
-
"@types/
|
|
2894
|
-
"@types/
|
|
2895
|
-
"@types/normalize-path": "^3.0.2",
|
|
2896
|
-
"@types/ws": "^7.4.7",
|
|
2897
|
-
"@types/yup": "^0.29.14",
|
|
2898
|
-
jest: "^29.7.0",
|
|
2899
|
-
"jest-diff": "^29.7.0",
|
|
3092
|
+
"@types/lru-cache": "catalog:",
|
|
3093
|
+
"@types/mdast": "catalog:",
|
|
3094
|
+
"@types/micromatch": "catalog:",
|
|
3095
|
+
"@types/node": "^22.13.1",
|
|
3096
|
+
"@types/normalize-path": "catalog:",
|
|
3097
|
+
"@types/ws": "catalog:",
|
|
2900
3098
|
"jest-file-snapshot": "^0.5.0",
|
|
2901
|
-
"
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
3099
|
+
"memory-level": "catalog:",
|
|
3100
|
+
typescript: "^5.7.3",
|
|
3101
|
+
vite: "^4.5.9",
|
|
3102
|
+
vitest: "^0.32.4",
|
|
3103
|
+
zod: "catalog:"
|
|
2905
3104
|
}
|
|
2906
3105
|
};
|
|
2907
3106
|
|
|
@@ -2973,6 +3172,7 @@ var _buildFragments = async (builder, tinaSchema) => {
|
|
|
2973
3172
|
kind: "Document",
|
|
2974
3173
|
definitions: uniqBy2(
|
|
2975
3174
|
extractInlineTypes(fragmentDefinitionsFields),
|
|
3175
|
+
// @ts-ignore - all nodes returned by extractInlineTypes have a name property
|
|
2976
3176
|
(node) => node.name.value
|
|
2977
3177
|
)
|
|
2978
3178
|
};
|
|
@@ -2994,6 +3194,7 @@ var _buildQueries = async (builder, tinaSchema) => {
|
|
|
2994
3194
|
fragName,
|
|
2995
3195
|
queryName: queryListName,
|
|
2996
3196
|
filterType: queryFilterTypeName,
|
|
3197
|
+
// look for flag to see if the data layer is enabled
|
|
2997
3198
|
dataLayer: Boolean(
|
|
2998
3199
|
tinaSchema.config?.meta?.flags?.find((x) => x === "experimentalData")
|
|
2999
3200
|
)
|
|
@@ -3004,6 +3205,7 @@ var _buildQueries = async (builder, tinaSchema) => {
|
|
|
3004
3205
|
kind: "Document",
|
|
3005
3206
|
definitions: uniqBy2(
|
|
3006
3207
|
extractInlineTypes(operationsDefinitions),
|
|
3208
|
+
// @ts-ignore - all nodes returned by extractInlineTypes have a name property
|
|
3007
3209
|
(node) => node.name.value
|
|
3008
3210
|
)
|
|
3009
3211
|
};
|
|
@@ -3054,7 +3256,9 @@ var _buildSchema = async (builder, tinaSchema) => {
|
|
|
3054
3256
|
await builder.buildCreateCollectionFolderMutation()
|
|
3055
3257
|
);
|
|
3056
3258
|
await sequential(collections, async (collection) => {
|
|
3057
|
-
queryTypeDefinitionFields.push(
|
|
3259
|
+
queryTypeDefinitionFields.push(
|
|
3260
|
+
await builder.collectionDocument(collection)
|
|
3261
|
+
);
|
|
3058
3262
|
if (collection.isAuthCollection) {
|
|
3059
3263
|
queryTypeDefinitionFields.push(
|
|
3060
3264
|
await builder.authenticationCollectionDocument(collection)
|
|
@@ -3088,13 +3292,15 @@ var _buildSchema = async (builder, tinaSchema) => {
|
|
|
3088
3292
|
fields: mutationTypeDefinitionFields
|
|
3089
3293
|
})
|
|
3090
3294
|
);
|
|
3091
|
-
|
|
3295
|
+
const schema = {
|
|
3092
3296
|
kind: "Document",
|
|
3093
3297
|
definitions: uniqBy2(
|
|
3094
3298
|
extractInlineTypes(definitions),
|
|
3299
|
+
// @ts-ignore - all nodes returned by extractInlineTypes have a name property
|
|
3095
3300
|
(node) => node.name.value
|
|
3096
3301
|
)
|
|
3097
3302
|
};
|
|
3303
|
+
return schema;
|
|
3098
3304
|
};
|
|
3099
3305
|
|
|
3100
3306
|
// src/resolve.ts
|
|
@@ -3103,382 +3309,146 @@ import { graphql, buildASTSchema, getNamedType, GraphQLError as GraphQLError4 }
|
|
|
3103
3309
|
// src/resolver/index.ts
|
|
3104
3310
|
import path3 from "path";
|
|
3105
3311
|
import isValid from "date-fns/isValid/index.js";
|
|
3312
|
+
import { JSONPath as JSONPath2 } from "jsonpath-plus";
|
|
3106
3313
|
|
|
3107
3314
|
// src/mdx/index.ts
|
|
3108
|
-
import { parseMDX,
|
|
3315
|
+
import { parseMDX, serializeMDX } from "@tinacms/mdx";
|
|
3109
3316
|
|
|
3110
|
-
// src/resolver/
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3317
|
+
// src/resolver/index.ts
|
|
3318
|
+
import { GraphQLError as GraphQLError2 } from "graphql";
|
|
3319
|
+
|
|
3320
|
+
// src/database/datalayer.ts
|
|
3321
|
+
import { JSONPath } from "jsonpath-plus";
|
|
3322
|
+
import sha from "js-sha1";
|
|
3323
|
+
|
|
3324
|
+
// src/database/level.ts
|
|
3325
|
+
var ARRAY_ITEM_VALUE_SEPARATOR = ",";
|
|
3326
|
+
var INDEX_KEY_FIELD_SEPARATOR = "";
|
|
3327
|
+
var CONTENT_ROOT_PREFIX = "~";
|
|
3328
|
+
var SUBLEVEL_OPTIONS = {
|
|
3329
|
+
separator: INDEX_KEY_FIELD_SEPARATOR,
|
|
3330
|
+
valueEncoding: "json"
|
|
3119
3331
|
};
|
|
3120
|
-
var
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3332
|
+
var LevelProxyHandler = {
|
|
3333
|
+
get: function(target, property) {
|
|
3334
|
+
if (!target[property]) {
|
|
3335
|
+
throw new Error(`The property, ${property.toString()}, doesn't exist`);
|
|
3336
|
+
}
|
|
3337
|
+
if (typeof target[property] !== "function") {
|
|
3338
|
+
throw new Error(
|
|
3339
|
+
`The property, ${property.toString()}, is not a function`
|
|
3340
|
+
);
|
|
3341
|
+
}
|
|
3342
|
+
if (property === "get") {
|
|
3343
|
+
return async (...args) => {
|
|
3344
|
+
let result;
|
|
3345
|
+
try {
|
|
3346
|
+
result = await target[property].apply(target, args);
|
|
3347
|
+
} catch (e) {
|
|
3348
|
+
if (e.code !== "LEVEL_NOT_FOUND") {
|
|
3349
|
+
throw e;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
return result;
|
|
3353
|
+
};
|
|
3354
|
+
} else if (property === "sublevel") {
|
|
3355
|
+
return (...args) => {
|
|
3356
|
+
return new Proxy(
|
|
3357
|
+
// eslint-disable-next-line prefer-spread
|
|
3358
|
+
target[property].apply(target, args),
|
|
3359
|
+
LevelProxyHandler
|
|
3360
|
+
);
|
|
3361
|
+
};
|
|
3362
|
+
} else {
|
|
3363
|
+
return (...args) => target[property].apply(target, args);
|
|
3364
|
+
}
|
|
3128
3365
|
}
|
|
3129
3366
|
};
|
|
3130
|
-
var
|
|
3131
|
-
constructor(
|
|
3132
|
-
|
|
3133
|
-
`Error querying file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
|
|
3134
|
-
args
|
|
3135
|
-
);
|
|
3367
|
+
var LevelProxy = class {
|
|
3368
|
+
constructor(level) {
|
|
3369
|
+
return new Proxy(level, LevelProxyHandler);
|
|
3136
3370
|
}
|
|
3137
3371
|
};
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3372
|
+
|
|
3373
|
+
// src/database/datalayer.ts
|
|
3374
|
+
import path2 from "path";
|
|
3375
|
+
|
|
3376
|
+
// src/database/util.ts
|
|
3377
|
+
import toml from "@iarna/toml";
|
|
3378
|
+
import {
|
|
3379
|
+
normalizePath
|
|
3380
|
+
} from "@tinacms/schema-tools";
|
|
3381
|
+
import matter from "gray-matter";
|
|
3382
|
+
import yaml from "js-yaml";
|
|
3383
|
+
import path from "path";
|
|
3384
|
+
import micromatch from "micromatch";
|
|
3385
|
+
|
|
3386
|
+
// src/database/alias-utils.ts
|
|
3387
|
+
var replaceBlockAliases = (template, item) => {
|
|
3388
|
+
const output = { ...item };
|
|
3389
|
+
const templateKey = template.templateKey || "_template";
|
|
3390
|
+
const templateName = output[templateKey];
|
|
3391
|
+
const matchingTemplate = template.templates.find(
|
|
3392
|
+
(t) => t.nameOverride == templateName || t.name == templateName
|
|
3393
|
+
);
|
|
3394
|
+
if (!matchingTemplate) {
|
|
3395
|
+
throw new Error(
|
|
3396
|
+
`Block template "${templateName}" is not defined for field "${template.name}"`
|
|
3143
3397
|
);
|
|
3144
3398
|
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3399
|
+
output._template = matchingTemplate.name;
|
|
3400
|
+
if (templateKey != "_template") {
|
|
3401
|
+
delete output[templateKey];
|
|
3147
3402
|
}
|
|
3403
|
+
return output;
|
|
3148
3404
|
};
|
|
3149
|
-
var
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
console.log(e.toString());
|
|
3155
|
-
console.log(e);
|
|
3156
|
-
console.log(e.stack);
|
|
3405
|
+
var replaceNameOverrides = (template, obj) => {
|
|
3406
|
+
if (template.list) {
|
|
3407
|
+
return obj.map((item) => {
|
|
3408
|
+
if (isBlockField(template)) {
|
|
3409
|
+
item = replaceBlockAliases(template, item);
|
|
3157
3410
|
}
|
|
3158
|
-
|
|
3411
|
+
return _replaceNameOverrides(
|
|
3412
|
+
getTemplateForData(template, item).fields,
|
|
3413
|
+
item
|
|
3414
|
+
);
|
|
3415
|
+
});
|
|
3159
3416
|
} else {
|
|
3160
|
-
|
|
3417
|
+
return _replaceNameOverrides(getTemplateForData(template, obj).fields, obj);
|
|
3161
3418
|
}
|
|
3162
|
-
throw e;
|
|
3163
3419
|
};
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3420
|
+
function isBlockField(field) {
|
|
3421
|
+
return field && field.type === "object" && field.templates?.length > 0;
|
|
3422
|
+
}
|
|
3423
|
+
var _replaceNameOverrides = (fields, obj) => {
|
|
3424
|
+
const output = {};
|
|
3425
|
+
Object.keys(obj).forEach((key) => {
|
|
3426
|
+
const field = fields.find(
|
|
3427
|
+
(fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
|
|
3170
3428
|
);
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
if (edges.length === 1) {
|
|
3175
|
-
filter[fieldKey] = {
|
|
3176
|
-
eq: values[0]
|
|
3177
|
-
};
|
|
3178
|
-
} else if (edges.length > 1) {
|
|
3179
|
-
filter[fieldKey] = {
|
|
3180
|
-
in: values
|
|
3181
|
-
};
|
|
3182
|
-
} else {
|
|
3183
|
-
filter[fieldKey] = {
|
|
3184
|
-
eq: "___null___"
|
|
3185
|
-
};
|
|
3186
|
-
}
|
|
3187
|
-
} else if (fieldDefinition.type === "object") {
|
|
3188
|
-
if (fieldDefinition.templates) {
|
|
3189
|
-
for (const templateName of Object.keys(filter[fieldKey])) {
|
|
3190
|
-
const template = fieldDefinition.templates.find(
|
|
3191
|
-
(template2) => !(typeof template2 === "string") && template2.name === templateName
|
|
3192
|
-
);
|
|
3193
|
-
if (template) {
|
|
3194
|
-
await resolveReferences(
|
|
3195
|
-
filter[fieldKey][templateName],
|
|
3196
|
-
template.fields,
|
|
3197
|
-
resolver
|
|
3198
|
-
);
|
|
3199
|
-
} else {
|
|
3200
|
-
throw new Error(`Template ${templateName} not found`);
|
|
3201
|
-
}
|
|
3202
|
-
}
|
|
3203
|
-
} else {
|
|
3204
|
-
await resolveReferences(
|
|
3205
|
-
filter[fieldKey],
|
|
3206
|
-
fieldDefinition.fields,
|
|
3207
|
-
resolver
|
|
3208
|
-
);
|
|
3209
|
-
}
|
|
3210
|
-
}
|
|
3211
|
-
} else {
|
|
3212
|
-
throw new Error(`Unable to find field ${fieldKey}`);
|
|
3213
|
-
}
|
|
3214
|
-
}
|
|
3429
|
+
output[field?.name || key] = field?.type == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
|
|
3430
|
+
});
|
|
3431
|
+
return output;
|
|
3215
3432
|
};
|
|
3216
|
-
var
|
|
3217
|
-
|
|
3218
|
-
const
|
|
3219
|
-
if (
|
|
3220
|
-
|
|
3433
|
+
var getTemplateForData = (field, data) => {
|
|
3434
|
+
if (field.templates?.length) {
|
|
3435
|
+
const templateKey = "_template";
|
|
3436
|
+
if (data[templateKey]) {
|
|
3437
|
+
const result = field.templates.find(
|
|
3438
|
+
(template) => template.nameOverride === data[templateKey] || template.name === data[templateKey]
|
|
3439
|
+
);
|
|
3440
|
+
if (result) {
|
|
3441
|
+
return result;
|
|
3442
|
+
}
|
|
3443
|
+
throw new Error(
|
|
3444
|
+
`Template "${data[templateKey]}" is not defined for field "${field.name}"`
|
|
3445
|
+
);
|
|
3221
3446
|
}
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
childField,
|
|
3225
|
-
filterNode[childFieldName],
|
|
3226
|
-
pathExpression,
|
|
3227
|
-
collectCondition
|
|
3447
|
+
throw new Error(
|
|
3448
|
+
`Missing required key "${templateKey}" on field "${field.name}"`
|
|
3228
3449
|
);
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
|
-
var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
|
|
3232
|
-
if (field.list && field.templates) {
|
|
3233
|
-
for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
|
|
3234
|
-
const template = field.templates.find(
|
|
3235
|
-
(template2) => !(typeof template2 === "string") && template2.name === filterKey
|
|
3236
|
-
);
|
|
3237
|
-
const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
|
|
3238
|
-
const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
|
|
3239
|
-
collectConditionsForChildFields(
|
|
3240
|
-
childFilterNode,
|
|
3241
|
-
template.fields,
|
|
3242
|
-
filterPath,
|
|
3243
|
-
collectCondition
|
|
3244
|
-
);
|
|
3245
|
-
}
|
|
3246
|
-
} else {
|
|
3247
|
-
const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
|
|
3248
|
-
const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
|
|
3249
|
-
collectConditionsForChildFields(
|
|
3250
|
-
filterNode,
|
|
3251
|
-
field.fields,
|
|
3252
|
-
filterPath,
|
|
3253
|
-
collectCondition
|
|
3254
|
-
);
|
|
3255
|
-
}
|
|
3256
|
-
};
|
|
3257
|
-
var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
|
|
3258
|
-
if (field.type === "object") {
|
|
3259
|
-
collectConditionsForObjectField(
|
|
3260
|
-
fieldName,
|
|
3261
|
-
field,
|
|
3262
|
-
filterNode,
|
|
3263
|
-
pathExpression,
|
|
3264
|
-
collectCondition
|
|
3265
|
-
);
|
|
3266
|
-
} else {
|
|
3267
|
-
collectCondition({
|
|
3268
|
-
filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
|
|
3269
|
-
filterExpression: {
|
|
3270
|
-
_type: field.type,
|
|
3271
|
-
_list: !!field.list,
|
|
3272
|
-
...filterNode
|
|
3273
|
-
}
|
|
3274
|
-
});
|
|
3275
|
-
}
|
|
3276
|
-
};
|
|
3277
|
-
|
|
3278
|
-
// src/resolver/media-utils.ts
|
|
3279
|
-
var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, schema) => {
|
|
3280
|
-
if (config && value) {
|
|
3281
|
-
if (config.useRelativeMedia === true) {
|
|
3282
|
-
return value;
|
|
3283
|
-
}
|
|
3284
|
-
if (hasTinaMediaConfig(schema) === true) {
|
|
3285
|
-
const assetsURL = `https://${config.assetsHost}/${config.clientId}`;
|
|
3286
|
-
if (typeof value === "string" && value.includes(assetsURL)) {
|
|
3287
|
-
const cleanMediaRoot = cleanUpSlashes(
|
|
3288
|
-
schema.config.media.tina.mediaRoot
|
|
3289
|
-
);
|
|
3290
|
-
const strippedURL = value.replace(assetsURL, "");
|
|
3291
|
-
return `${cleanMediaRoot}${strippedURL}`;
|
|
3292
|
-
}
|
|
3293
|
-
if (Array.isArray(value)) {
|
|
3294
|
-
return value.map((v) => {
|
|
3295
|
-
if (!v || typeof v !== "string")
|
|
3296
|
-
return v;
|
|
3297
|
-
const cleanMediaRoot = cleanUpSlashes(
|
|
3298
|
-
schema.config.media.tina.mediaRoot
|
|
3299
|
-
);
|
|
3300
|
-
const strippedURL = v.replace(assetsURL, "");
|
|
3301
|
-
return `${cleanMediaRoot}${strippedURL}`;
|
|
3302
|
-
});
|
|
3303
|
-
}
|
|
3304
|
-
return value;
|
|
3305
|
-
}
|
|
3306
|
-
return value;
|
|
3307
|
-
} else {
|
|
3308
|
-
return value;
|
|
3309
|
-
}
|
|
3310
|
-
};
|
|
3311
|
-
var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, schema) => {
|
|
3312
|
-
if (config && value) {
|
|
3313
|
-
if (config.useRelativeMedia === true) {
|
|
3314
|
-
return value;
|
|
3315
|
-
}
|
|
3316
|
-
if (hasTinaMediaConfig(schema) === true) {
|
|
3317
|
-
const cleanMediaRoot = cleanUpSlashes(schema.config.media.tina.mediaRoot);
|
|
3318
|
-
if (typeof value === "string") {
|
|
3319
|
-
const strippedValue = value.replace(cleanMediaRoot, "");
|
|
3320
|
-
return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
|
|
3321
|
-
}
|
|
3322
|
-
if (Array.isArray(value)) {
|
|
3323
|
-
return value.map((v) => {
|
|
3324
|
-
if (!v || typeof v !== "string")
|
|
3325
|
-
return v;
|
|
3326
|
-
const strippedValue = v.replace(cleanMediaRoot, "");
|
|
3327
|
-
return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
|
|
3328
|
-
});
|
|
3329
|
-
}
|
|
3330
|
-
}
|
|
3331
|
-
return value;
|
|
3332
|
-
} else {
|
|
3333
|
-
return value;
|
|
3334
|
-
}
|
|
3335
|
-
};
|
|
3336
|
-
var cleanUpSlashes = (path7) => {
|
|
3337
|
-
if (path7) {
|
|
3338
|
-
return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
|
|
3339
|
-
}
|
|
3340
|
-
return "";
|
|
3341
|
-
};
|
|
3342
|
-
var hasTinaMediaConfig = (schema) => {
|
|
3343
|
-
if (!schema.config?.media?.tina)
|
|
3344
|
-
return false;
|
|
3345
|
-
if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
|
|
3346
|
-
return false;
|
|
3347
|
-
return true;
|
|
3348
|
-
};
|
|
3349
|
-
|
|
3350
|
-
// src/resolver/index.ts
|
|
3351
|
-
import { GraphQLError as GraphQLError2 } from "graphql";
|
|
3352
|
-
|
|
3353
|
-
// src/database/datalayer.ts
|
|
3354
|
-
import { JSONPath } from "jsonpath-plus";
|
|
3355
|
-
import sha from "js-sha1";
|
|
3356
|
-
|
|
3357
|
-
// src/database/level.ts
|
|
3358
|
-
var ARRAY_ITEM_VALUE_SEPARATOR = ",";
|
|
3359
|
-
var INDEX_KEY_FIELD_SEPARATOR = "";
|
|
3360
|
-
var CONTENT_ROOT_PREFIX = "~";
|
|
3361
|
-
var SUBLEVEL_OPTIONS = {
|
|
3362
|
-
separator: INDEX_KEY_FIELD_SEPARATOR,
|
|
3363
|
-
valueEncoding: "json"
|
|
3364
|
-
};
|
|
3365
|
-
var LevelProxyHandler = {
|
|
3366
|
-
get: function(target, property) {
|
|
3367
|
-
if (!target[property]) {
|
|
3368
|
-
throw new Error(`The property, ${property.toString()}, doesn't exist`);
|
|
3369
|
-
}
|
|
3370
|
-
if (typeof target[property] !== "function") {
|
|
3371
|
-
throw new Error(`The property, ${property.toString()}, is not a function`);
|
|
3372
|
-
}
|
|
3373
|
-
if (property === "get") {
|
|
3374
|
-
return async (...args) => {
|
|
3375
|
-
let result;
|
|
3376
|
-
try {
|
|
3377
|
-
result = await target[property].apply(target, args);
|
|
3378
|
-
} catch (e) {
|
|
3379
|
-
if (e.code !== "LEVEL_NOT_FOUND") {
|
|
3380
|
-
throw e;
|
|
3381
|
-
}
|
|
3382
|
-
}
|
|
3383
|
-
return result;
|
|
3384
|
-
};
|
|
3385
|
-
} else if (property === "sublevel") {
|
|
3386
|
-
return (...args) => {
|
|
3387
|
-
return new Proxy(
|
|
3388
|
-
target[property].apply(target, args),
|
|
3389
|
-
LevelProxyHandler
|
|
3390
|
-
);
|
|
3391
|
-
};
|
|
3392
|
-
} else {
|
|
3393
|
-
return (...args) => target[property].apply(target, args);
|
|
3394
|
-
}
|
|
3395
|
-
}
|
|
3396
|
-
};
|
|
3397
|
-
var LevelProxy = class {
|
|
3398
|
-
constructor(level) {
|
|
3399
|
-
return new Proxy(level, LevelProxyHandler);
|
|
3400
|
-
}
|
|
3401
|
-
};
|
|
3402
|
-
|
|
3403
|
-
// src/database/datalayer.ts
|
|
3404
|
-
import path2 from "path";
|
|
3405
|
-
|
|
3406
|
-
// src/database/util.ts
|
|
3407
|
-
import toml from "@iarna/toml";
|
|
3408
|
-
import yaml from "js-yaml";
|
|
3409
|
-
import matter from "gray-matter";
|
|
3410
|
-
import {
|
|
3411
|
-
normalizePath
|
|
3412
|
-
} from "@tinacms/schema-tools";
|
|
3413
|
-
import micromatch from "micromatch";
|
|
3414
|
-
import path from "path";
|
|
3415
|
-
|
|
3416
|
-
// src/database/alias-utils.ts
|
|
3417
|
-
var replaceBlockAliases = (template, item) => {
|
|
3418
|
-
const output = { ...item };
|
|
3419
|
-
const templateKey = template.templateKey || "_template";
|
|
3420
|
-
const templateName = output[templateKey];
|
|
3421
|
-
const matchingTemplate = template.templates.find(
|
|
3422
|
-
(t) => t.nameOverride == templateName || t.name == templateName
|
|
3423
|
-
);
|
|
3424
|
-
if (!matchingTemplate) {
|
|
3425
|
-
throw new Error(
|
|
3426
|
-
`Block template "${templateName}" is not defined for field "${template.name}"`
|
|
3427
|
-
);
|
|
3428
|
-
}
|
|
3429
|
-
output._template = matchingTemplate.name;
|
|
3430
|
-
if (templateKey != "_template") {
|
|
3431
|
-
delete output[templateKey];
|
|
3432
|
-
}
|
|
3433
|
-
return output;
|
|
3434
|
-
};
|
|
3435
|
-
var replaceNameOverrides = (template, obj) => {
|
|
3436
|
-
if (template.list) {
|
|
3437
|
-
return obj.map((item) => {
|
|
3438
|
-
if (isBlockField(template)) {
|
|
3439
|
-
item = replaceBlockAliases(template, item);
|
|
3440
|
-
}
|
|
3441
|
-
return _replaceNameOverrides(
|
|
3442
|
-
getTemplateForData(template, item).fields,
|
|
3443
|
-
item
|
|
3444
|
-
);
|
|
3445
|
-
});
|
|
3446
|
-
} else {
|
|
3447
|
-
return _replaceNameOverrides(getTemplateForData(template, obj).fields, obj);
|
|
3448
|
-
}
|
|
3449
|
-
};
|
|
3450
|
-
function isBlockField(field) {
|
|
3451
|
-
return field && field.type === "object" && field.templates?.length > 0;
|
|
3452
|
-
}
|
|
3453
|
-
var _replaceNameOverrides = (fields, obj) => {
|
|
3454
|
-
const output = {};
|
|
3455
|
-
Object.keys(obj).forEach((key) => {
|
|
3456
|
-
const field = fields.find(
|
|
3457
|
-
(fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
|
|
3458
|
-
);
|
|
3459
|
-
output[field?.name || key] = field?.type == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
|
|
3460
|
-
});
|
|
3461
|
-
return output;
|
|
3462
|
-
};
|
|
3463
|
-
var getTemplateForData = (field, data) => {
|
|
3464
|
-
if (field.templates?.length) {
|
|
3465
|
-
const templateKey = "_template";
|
|
3466
|
-
if (data[templateKey]) {
|
|
3467
|
-
const result = field.templates.find(
|
|
3468
|
-
(template) => template.nameOverride === data[templateKey] || template.name === data[templateKey]
|
|
3469
|
-
);
|
|
3470
|
-
if (result) {
|
|
3471
|
-
return result;
|
|
3472
|
-
}
|
|
3473
|
-
throw new Error(
|
|
3474
|
-
`Template "${data[templateKey]}" is not defined for field "${field.name}"`
|
|
3475
|
-
);
|
|
3476
|
-
}
|
|
3477
|
-
throw new Error(
|
|
3478
|
-
`Missing required key "${templateKey}" on field "${field.name}"`
|
|
3479
|
-
);
|
|
3480
|
-
} else {
|
|
3481
|
-
return field;
|
|
3450
|
+
} else {
|
|
3451
|
+
return field;
|
|
3482
3452
|
}
|
|
3483
3453
|
};
|
|
3484
3454
|
var applyBlockAliases = (template, item) => {
|
|
@@ -3752,6 +3722,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
|
|
|
3752
3722
|
|
|
3753
3723
|
// src/database/datalayer.ts
|
|
3754
3724
|
var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
|
|
3725
|
+
var REFS_COLLECTIONS_SORT_KEY = "__refs__";
|
|
3726
|
+
var REFS_REFERENCE_FIELD = "__tina_ref__";
|
|
3727
|
+
var REFS_PATH_FIELD = "__tina_ref_path__";
|
|
3755
3728
|
var DEFAULT_NUMERIC_LPAD = 4;
|
|
3756
3729
|
var applyPadding = (input, pad) => {
|
|
3757
3730
|
if (pad) {
|
|
@@ -4261,6 +4234,7 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
|
|
|
4261
4234
|
result.push({
|
|
4262
4235
|
type: opType,
|
|
4263
4236
|
key: `${collection.path}/${subFolderKey}.${collection.format}`,
|
|
4237
|
+
// replace the root with the collection path
|
|
4264
4238
|
sublevel: indexSublevel,
|
|
4265
4239
|
value: {}
|
|
4266
4240
|
});
|
|
@@ -4324,6 +4298,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
|
|
|
4324
4298
|
}
|
|
4325
4299
|
return result;
|
|
4326
4300
|
};
|
|
4301
|
+
var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
|
|
4302
|
+
const result = [];
|
|
4303
|
+
if (collection) {
|
|
4304
|
+
for (const [c, referencePaths] of Object.entries(references || {})) {
|
|
4305
|
+
if (!referencePaths.length) {
|
|
4306
|
+
continue;
|
|
4307
|
+
}
|
|
4308
|
+
const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
|
|
4309
|
+
const refSublevel = collectionSublevel.sublevel(
|
|
4310
|
+
REFS_COLLECTIONS_SORT_KEY,
|
|
4311
|
+
SUBLEVEL_OPTIONS
|
|
4312
|
+
);
|
|
4313
|
+
const references2 = {};
|
|
4314
|
+
for (const path7 of referencePaths) {
|
|
4315
|
+
const ref = JSONPath({ path: path7, json: data });
|
|
4316
|
+
if (!ref) {
|
|
4317
|
+
continue;
|
|
4318
|
+
}
|
|
4319
|
+
if (Array.isArray(ref)) {
|
|
4320
|
+
for (const r of ref) {
|
|
4321
|
+
if (!r) {
|
|
4322
|
+
continue;
|
|
4323
|
+
}
|
|
4324
|
+
if (references2[r]) {
|
|
4325
|
+
references2[r].push(path7);
|
|
4326
|
+
} else {
|
|
4327
|
+
references2[r] = [path7];
|
|
4328
|
+
}
|
|
4329
|
+
}
|
|
4330
|
+
} else {
|
|
4331
|
+
if (references2[ref]) {
|
|
4332
|
+
references2[ref].push(path7);
|
|
4333
|
+
} else {
|
|
4334
|
+
references2[ref] = [path7];
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
for (const ref of Object.keys(references2)) {
|
|
4339
|
+
for (const path7 of references2[ref]) {
|
|
4340
|
+
result.push({
|
|
4341
|
+
type: opType,
|
|
4342
|
+
key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
|
|
4343
|
+
sublevel: refSublevel,
|
|
4344
|
+
value: opType === "put" ? {} : void 0
|
|
4345
|
+
});
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
}
|
|
4350
|
+
return result;
|
|
4351
|
+
};
|
|
4327
4352
|
var makeStringEscaper = (regex, replacement) => {
|
|
4328
4353
|
return (input) => {
|
|
4329
4354
|
if (Array.isArray(input)) {
|
|
@@ -4339,10 +4364,246 @@ var makeStringEscaper = (regex, replacement) => {
|
|
|
4339
4364
|
}
|
|
4340
4365
|
};
|
|
4341
4366
|
};
|
|
4342
|
-
var stringEscaper = makeStringEscaper(
|
|
4343
|
-
new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
|
|
4344
|
-
encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
|
|
4345
|
-
);
|
|
4367
|
+
var stringEscaper = makeStringEscaper(
|
|
4368
|
+
new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
|
|
4369
|
+
encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
|
|
4370
|
+
);
|
|
4371
|
+
|
|
4372
|
+
// src/resolver/error.ts
|
|
4373
|
+
var TinaGraphQLError = class extends Error {
|
|
4374
|
+
constructor(message, extensions) {
|
|
4375
|
+
super(message);
|
|
4376
|
+
if (!this.name) {
|
|
4377
|
+
Object.defineProperty(this, "name", { value: "TinaGraphQLError" });
|
|
4378
|
+
}
|
|
4379
|
+
this.extensions = { ...extensions };
|
|
4380
|
+
}
|
|
4381
|
+
};
|
|
4382
|
+
var TinaFetchError = class extends Error {
|
|
4383
|
+
constructor(message, args) {
|
|
4384
|
+
super(message);
|
|
4385
|
+
this.name = "TinaFetchError";
|
|
4386
|
+
this.collection = args.collection;
|
|
4387
|
+
this.file = args.file;
|
|
4388
|
+
this.originalError = args.originalError;
|
|
4389
|
+
}
|
|
4390
|
+
};
|
|
4391
|
+
var TinaQueryError = class extends TinaFetchError {
|
|
4392
|
+
constructor(args) {
|
|
4393
|
+
super(
|
|
4394
|
+
`Error querying file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
|
|
4395
|
+
args
|
|
4396
|
+
);
|
|
4397
|
+
}
|
|
4398
|
+
};
|
|
4399
|
+
var TinaParseDocumentError = class extends TinaFetchError {
|
|
4400
|
+
constructor(args) {
|
|
4401
|
+
super(
|
|
4402
|
+
`Error parsing file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
|
|
4403
|
+
args
|
|
4404
|
+
);
|
|
4405
|
+
}
|
|
4406
|
+
toString() {
|
|
4407
|
+
return super.toString() + "\n OriginalError: \n" + this.originalError.toString();
|
|
4408
|
+
}
|
|
4409
|
+
};
|
|
4410
|
+
var auditMessage = (includeAuditMessage = true) => includeAuditMessage ? `Please run "tinacms audit" or add the --verbose option for more info` : "";
|
|
4411
|
+
var handleFetchErrorError = (e, verbose) => {
|
|
4412
|
+
if (e instanceof Error) {
|
|
4413
|
+
if (e instanceof TinaFetchError) {
|
|
4414
|
+
if (verbose) {
|
|
4415
|
+
console.log(e.toString());
|
|
4416
|
+
console.log(e);
|
|
4417
|
+
console.log(e.stack);
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
} else {
|
|
4421
|
+
console.error(e);
|
|
4422
|
+
}
|
|
4423
|
+
throw e;
|
|
4424
|
+
};
|
|
4425
|
+
|
|
4426
|
+
// src/resolver/filter-utils.ts
|
|
4427
|
+
var resolveReferences = async (filter, fields, resolver) => {
|
|
4428
|
+
for (const fieldKey of Object.keys(filter)) {
|
|
4429
|
+
const fieldDefinition = fields.find(
|
|
4430
|
+
(f) => f.name === fieldKey
|
|
4431
|
+
);
|
|
4432
|
+
if (fieldDefinition) {
|
|
4433
|
+
if (fieldDefinition.type === "reference") {
|
|
4434
|
+
const { edges, values } = await resolver(filter, fieldDefinition);
|
|
4435
|
+
if (edges.length === 1) {
|
|
4436
|
+
filter[fieldKey] = {
|
|
4437
|
+
eq: values[0]
|
|
4438
|
+
};
|
|
4439
|
+
} else if (edges.length > 1) {
|
|
4440
|
+
filter[fieldKey] = {
|
|
4441
|
+
in: values
|
|
4442
|
+
};
|
|
4443
|
+
} else {
|
|
4444
|
+
filter[fieldKey] = {
|
|
4445
|
+
eq: "___null___"
|
|
4446
|
+
};
|
|
4447
|
+
}
|
|
4448
|
+
} else if (fieldDefinition.type === "object") {
|
|
4449
|
+
if (fieldDefinition.templates) {
|
|
4450
|
+
for (const templateName of Object.keys(filter[fieldKey])) {
|
|
4451
|
+
const template = fieldDefinition.templates.find(
|
|
4452
|
+
(template2) => !(typeof template2 === "string") && template2.name === templateName
|
|
4453
|
+
);
|
|
4454
|
+
if (template) {
|
|
4455
|
+
await resolveReferences(
|
|
4456
|
+
filter[fieldKey][templateName],
|
|
4457
|
+
template.fields,
|
|
4458
|
+
resolver
|
|
4459
|
+
);
|
|
4460
|
+
} else {
|
|
4461
|
+
throw new Error(`Template ${templateName} not found`);
|
|
4462
|
+
}
|
|
4463
|
+
}
|
|
4464
|
+
} else {
|
|
4465
|
+
await resolveReferences(
|
|
4466
|
+
filter[fieldKey],
|
|
4467
|
+
fieldDefinition.fields,
|
|
4468
|
+
resolver
|
|
4469
|
+
);
|
|
4470
|
+
}
|
|
4471
|
+
}
|
|
4472
|
+
} else {
|
|
4473
|
+
throw new Error(`Unable to find field ${fieldKey}`);
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
};
|
|
4477
|
+
var collectConditionsForChildFields = (filterNode, fields, pathExpression, collectCondition) => {
|
|
4478
|
+
for (const childFieldName of Object.keys(filterNode)) {
|
|
4479
|
+
const childField = fields.find((field) => field.name === childFieldName);
|
|
4480
|
+
if (!childField) {
|
|
4481
|
+
throw new Error(`Unable to find type for field ${childFieldName}`);
|
|
4482
|
+
}
|
|
4483
|
+
collectConditionsForField(
|
|
4484
|
+
childFieldName,
|
|
4485
|
+
childField,
|
|
4486
|
+
filterNode[childFieldName],
|
|
4487
|
+
pathExpression,
|
|
4488
|
+
collectCondition
|
|
4489
|
+
);
|
|
4490
|
+
}
|
|
4491
|
+
};
|
|
4492
|
+
var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
|
|
4493
|
+
if (field.list && field.templates) {
|
|
4494
|
+
for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
|
|
4495
|
+
const template = field.templates.find(
|
|
4496
|
+
(template2) => !(typeof template2 === "string") && template2.name === filterKey
|
|
4497
|
+
);
|
|
4498
|
+
const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
|
|
4499
|
+
const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
|
|
4500
|
+
collectConditionsForChildFields(
|
|
4501
|
+
childFilterNode,
|
|
4502
|
+
template.fields,
|
|
4503
|
+
filterPath,
|
|
4504
|
+
collectCondition
|
|
4505
|
+
);
|
|
4506
|
+
}
|
|
4507
|
+
} else {
|
|
4508
|
+
const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
|
|
4509
|
+
const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
|
|
4510
|
+
collectConditionsForChildFields(
|
|
4511
|
+
filterNode,
|
|
4512
|
+
field.fields,
|
|
4513
|
+
filterPath,
|
|
4514
|
+
collectCondition
|
|
4515
|
+
);
|
|
4516
|
+
}
|
|
4517
|
+
};
|
|
4518
|
+
var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
|
|
4519
|
+
if (field.type === "object") {
|
|
4520
|
+
collectConditionsForObjectField(
|
|
4521
|
+
fieldName,
|
|
4522
|
+
field,
|
|
4523
|
+
filterNode,
|
|
4524
|
+
pathExpression,
|
|
4525
|
+
collectCondition
|
|
4526
|
+
);
|
|
4527
|
+
} else {
|
|
4528
|
+
collectCondition({
|
|
4529
|
+
filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
|
|
4530
|
+
filterExpression: {
|
|
4531
|
+
_type: field.type,
|
|
4532
|
+
_list: !!field.list,
|
|
4533
|
+
...filterNode
|
|
4534
|
+
}
|
|
4535
|
+
});
|
|
4536
|
+
}
|
|
4537
|
+
};
|
|
4538
|
+
|
|
4539
|
+
// src/resolver/media-utils.ts
|
|
4540
|
+
var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, schema) => {
|
|
4541
|
+
if (config && value) {
|
|
4542
|
+
if (config.useRelativeMedia === true) {
|
|
4543
|
+
return value;
|
|
4544
|
+
}
|
|
4545
|
+
if (hasTinaMediaConfig(schema) === true) {
|
|
4546
|
+
const assetsURL = `https://${config.assetsHost}/${config.clientId}`;
|
|
4547
|
+
if (typeof value === "string" && value.includes(assetsURL)) {
|
|
4548
|
+
const cleanMediaRoot = cleanUpSlashes(
|
|
4549
|
+
schema.config.media.tina.mediaRoot
|
|
4550
|
+
);
|
|
4551
|
+
const strippedURL = value.replace(assetsURL, "");
|
|
4552
|
+
return `${cleanMediaRoot}${strippedURL}`;
|
|
4553
|
+
}
|
|
4554
|
+
if (Array.isArray(value)) {
|
|
4555
|
+
return value.map((v) => {
|
|
4556
|
+
if (!v || typeof v !== "string") return v;
|
|
4557
|
+
const cleanMediaRoot = cleanUpSlashes(
|
|
4558
|
+
schema.config.media.tina.mediaRoot
|
|
4559
|
+
);
|
|
4560
|
+
const strippedURL = v.replace(assetsURL, "");
|
|
4561
|
+
return `${cleanMediaRoot}${strippedURL}`;
|
|
4562
|
+
});
|
|
4563
|
+
}
|
|
4564
|
+
return value;
|
|
4565
|
+
}
|
|
4566
|
+
return value;
|
|
4567
|
+
} else {
|
|
4568
|
+
return value;
|
|
4569
|
+
}
|
|
4570
|
+
};
|
|
4571
|
+
var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, schema) => {
|
|
4572
|
+
if (config && value) {
|
|
4573
|
+
if (config.useRelativeMedia === true) {
|
|
4574
|
+
return value;
|
|
4575
|
+
}
|
|
4576
|
+
if (hasTinaMediaConfig(schema) === true) {
|
|
4577
|
+
const cleanMediaRoot = cleanUpSlashes(schema.config.media.tina.mediaRoot);
|
|
4578
|
+
if (typeof value === "string") {
|
|
4579
|
+
const strippedValue = value.replace(cleanMediaRoot, "");
|
|
4580
|
+
return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
|
|
4581
|
+
}
|
|
4582
|
+
if (Array.isArray(value)) {
|
|
4583
|
+
return value.map((v) => {
|
|
4584
|
+
if (!v || typeof v !== "string") return v;
|
|
4585
|
+
const strippedValue = v.replace(cleanMediaRoot, "");
|
|
4586
|
+
return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
|
|
4587
|
+
});
|
|
4588
|
+
}
|
|
4589
|
+
}
|
|
4590
|
+
return value;
|
|
4591
|
+
} else {
|
|
4592
|
+
return value;
|
|
4593
|
+
}
|
|
4594
|
+
};
|
|
4595
|
+
var cleanUpSlashes = (path7) => {
|
|
4596
|
+
if (path7) {
|
|
4597
|
+
return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
|
|
4598
|
+
}
|
|
4599
|
+
return "";
|
|
4600
|
+
};
|
|
4601
|
+
var hasTinaMediaConfig = (schema) => {
|
|
4602
|
+
if (!schema.config?.media?.tina) return false;
|
|
4603
|
+
if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
|
|
4604
|
+
return false;
|
|
4605
|
+
return true;
|
|
4606
|
+
};
|
|
4346
4607
|
|
|
4347
4608
|
// src/resolver/index.ts
|
|
4348
4609
|
var createResolver = (args) => {
|
|
@@ -4375,6 +4636,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
|
|
|
4375
4636
|
case "password":
|
|
4376
4637
|
accumulator[field.name] = {
|
|
4377
4638
|
value: void 0,
|
|
4639
|
+
// never resolve the password hash
|
|
4378
4640
|
passwordChangeRequired: value["passwordChangeRequired"] ?? false
|
|
4379
4641
|
};
|
|
4380
4642
|
break;
|
|
@@ -4469,7 +4731,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
|
|
|
4469
4731
|
}
|
|
4470
4732
|
return accumulator;
|
|
4471
4733
|
};
|
|
4472
|
-
var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit) => {
|
|
4734
|
+
var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config, isAudit, hasReferences) => {
|
|
4473
4735
|
const collection = tinaSchema.getCollection(rawData._collection);
|
|
4474
4736
|
try {
|
|
4475
4737
|
const template = tinaSchema.getTemplateForData({
|
|
@@ -4503,8 +4765,7 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
|
|
|
4503
4765
|
originalError: e,
|
|
4504
4766
|
collection: collection.name,
|
|
4505
4767
|
includeAuditMessage: !isAudit,
|
|
4506
|
-
file: relativePath
|
|
4507
|
-
stack: e.stack
|
|
4768
|
+
file: relativePath
|
|
4508
4769
|
});
|
|
4509
4770
|
}
|
|
4510
4771
|
const titleField = template.fields.find((x) => {
|
|
@@ -4523,6 +4784,7 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
|
|
|
4523
4784
|
basename,
|
|
4524
4785
|
filename,
|
|
4525
4786
|
extension,
|
|
4787
|
+
hasReferences,
|
|
4526
4788
|
path: fullPath,
|
|
4527
4789
|
relativePath,
|
|
4528
4790
|
breadcrumbs,
|
|
@@ -4542,6 +4804,34 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
|
|
|
4542
4804
|
throw e;
|
|
4543
4805
|
}
|
|
4544
4806
|
};
|
|
4807
|
+
var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
|
|
4808
|
+
let updated = false;
|
|
4809
|
+
if (!path7.includes(".") && !path7.includes("[")) {
|
|
4810
|
+
if (path7 in obj && obj[path7] === oldValue) {
|
|
4811
|
+
obj[path7] = newValue;
|
|
4812
|
+
updated = true;
|
|
4813
|
+
}
|
|
4814
|
+
return { object: obj, updated };
|
|
4815
|
+
}
|
|
4816
|
+
const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
|
|
4817
|
+
const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
|
|
4818
|
+
const parents = JSONPath2({
|
|
4819
|
+
path: parentPath,
|
|
4820
|
+
json: obj,
|
|
4821
|
+
resultType: "value"
|
|
4822
|
+
});
|
|
4823
|
+
if (parents.length > 0) {
|
|
4824
|
+
parents.forEach((parent) => {
|
|
4825
|
+
if (parent && typeof parent === "object" && keyToUpdate in parent) {
|
|
4826
|
+
if (parent[keyToUpdate] === oldValue) {
|
|
4827
|
+
parent[keyToUpdate] = newValue;
|
|
4828
|
+
updated = true;
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
});
|
|
4832
|
+
}
|
|
4833
|
+
return { object: obj, updated };
|
|
4834
|
+
};
|
|
4545
4835
|
var Resolver = class {
|
|
4546
4836
|
constructor(init) {
|
|
4547
4837
|
this.init = init;
|
|
@@ -4549,6 +4839,7 @@ var Resolver = class {
|
|
|
4549
4839
|
const collection = this.tinaSchema.getCollection(collectionName);
|
|
4550
4840
|
const extraFields = {};
|
|
4551
4841
|
return {
|
|
4842
|
+
// return the collection and hasDocuments to resolve documents at a lower level
|
|
4552
4843
|
documents: { collection, hasDocuments },
|
|
4553
4844
|
...collection,
|
|
4554
4845
|
...extraFields
|
|
@@ -4556,7 +4847,9 @@ var Resolver = class {
|
|
|
4556
4847
|
};
|
|
4557
4848
|
this.getRaw = async (fullPath) => {
|
|
4558
4849
|
if (typeof fullPath !== "string") {
|
|
4559
|
-
throw new Error(
|
|
4850
|
+
throw new Error(
|
|
4851
|
+
`fullPath must be of type string for getDocument request`
|
|
4852
|
+
);
|
|
4560
4853
|
}
|
|
4561
4854
|
return this.database.get(fullPath);
|
|
4562
4855
|
};
|
|
@@ -4583,22 +4876,28 @@ var Resolver = class {
|
|
|
4583
4876
|
);
|
|
4584
4877
|
}
|
|
4585
4878
|
};
|
|
4586
|
-
this.getDocument = async (fullPath) => {
|
|
4879
|
+
this.getDocument = async (fullPath, opts = {}) => {
|
|
4587
4880
|
if (typeof fullPath !== "string") {
|
|
4588
|
-
throw new Error(
|
|
4881
|
+
throw new Error(
|
|
4882
|
+
`fullPath must be of type string for getDocument request`
|
|
4883
|
+
);
|
|
4589
4884
|
}
|
|
4590
4885
|
const rawData = await this.getRaw(fullPath);
|
|
4886
|
+
const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
|
|
4591
4887
|
return transformDocumentIntoPayload(
|
|
4592
4888
|
fullPath,
|
|
4593
4889
|
rawData,
|
|
4594
4890
|
this.tinaSchema,
|
|
4595
4891
|
this.config,
|
|
4596
|
-
this.isAudit
|
|
4892
|
+
this.isAudit,
|
|
4893
|
+
hasReferences
|
|
4597
4894
|
);
|
|
4598
4895
|
};
|
|
4599
4896
|
this.deleteDocument = async (fullPath) => {
|
|
4600
4897
|
if (typeof fullPath !== "string") {
|
|
4601
|
-
throw new Error(
|
|
4898
|
+
throw new Error(
|
|
4899
|
+
`fullPath must be of type string for getDocument request`
|
|
4900
|
+
);
|
|
4602
4901
|
}
|
|
4603
4902
|
await this.database.delete(fullPath);
|
|
4604
4903
|
};
|
|
@@ -4633,7 +4932,9 @@ var Resolver = class {
|
|
|
4633
4932
|
);
|
|
4634
4933
|
} else {
|
|
4635
4934
|
return this.buildFieldMutations(
|
|
4935
|
+
// @ts-ignore FIXME Argument of type 'string | object' is not assignable to parameter of type '{ [fieldName: string]: string | object | (string | object)[]; }'
|
|
4636
4936
|
fieldValue,
|
|
4937
|
+
//@ts-ignore
|
|
4637
4938
|
objectTemplate,
|
|
4638
4939
|
existingData
|
|
4639
4940
|
);
|
|
@@ -4645,6 +4946,7 @@ var Resolver = class {
|
|
|
4645
4946
|
fieldValue.map(async (item) => {
|
|
4646
4947
|
if (typeof item === "string") {
|
|
4647
4948
|
throw new Error(
|
|
4949
|
+
//@ts-ignore
|
|
4648
4950
|
`Expected object for template value for field ${field.name}`
|
|
4649
4951
|
);
|
|
4650
4952
|
}
|
|
@@ -4653,16 +4955,19 @@ var Resolver = class {
|
|
|
4653
4955
|
});
|
|
4654
4956
|
const [templateName] = Object.entries(item)[0];
|
|
4655
4957
|
const template = templates.find(
|
|
4958
|
+
//@ts-ignore
|
|
4656
4959
|
(template2) => template2.name === templateName
|
|
4657
4960
|
);
|
|
4658
4961
|
if (!template) {
|
|
4659
4962
|
throw new Error(`Expected to find template ${templateName}`);
|
|
4660
4963
|
}
|
|
4661
4964
|
return {
|
|
4965
|
+
// @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
4966
|
...await this.buildFieldMutations(
|
|
4663
4967
|
item[template.name],
|
|
4664
4968
|
template
|
|
4665
4969
|
),
|
|
4970
|
+
//@ts-ignore
|
|
4666
4971
|
_template: template.name
|
|
4667
4972
|
};
|
|
4668
4973
|
})
|
|
@@ -4670,6 +4975,7 @@ var Resolver = class {
|
|
|
4670
4975
|
} else {
|
|
4671
4976
|
if (typeof fieldValue === "string") {
|
|
4672
4977
|
throw new Error(
|
|
4978
|
+
//@ts-ignore
|
|
4673
4979
|
`Expected object for template value for field ${field.name}`
|
|
4674
4980
|
);
|
|
4675
4981
|
}
|
|
@@ -4678,16 +4984,19 @@ var Resolver = class {
|
|
|
4678
4984
|
});
|
|
4679
4985
|
const [templateName] = Object.entries(fieldValue)[0];
|
|
4680
4986
|
const template = templates.find(
|
|
4987
|
+
//@ts-ignore
|
|
4681
4988
|
(template2) => template2.name === templateName
|
|
4682
4989
|
);
|
|
4683
4990
|
if (!template) {
|
|
4684
4991
|
throw new Error(`Expected to find template ${templateName}`);
|
|
4685
4992
|
}
|
|
4686
4993
|
return {
|
|
4994
|
+
// @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
4995
|
...await this.buildFieldMutations(
|
|
4688
4996
|
fieldValue[template.name],
|
|
4689
4997
|
template
|
|
4690
4998
|
),
|
|
4999
|
+
//@ts-ignore
|
|
4691
5000
|
_template: template.name
|
|
4692
5001
|
};
|
|
4693
5002
|
}
|
|
@@ -4727,6 +5036,7 @@ var Resolver = class {
|
|
|
4727
5036
|
return this.getDocument(realPath);
|
|
4728
5037
|
}
|
|
4729
5038
|
const params = await this.buildObjectMutations(
|
|
5039
|
+
// @ts-ignore
|
|
4730
5040
|
args.params[collection.name],
|
|
4731
5041
|
collection
|
|
4732
5042
|
);
|
|
@@ -4772,6 +5082,7 @@ var Resolver = class {
|
|
|
4772
5082
|
const values = {
|
|
4773
5083
|
...oldDoc,
|
|
4774
5084
|
...await this.buildFieldMutations(
|
|
5085
|
+
// @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
|
|
4775
5086
|
templateParams,
|
|
4776
5087
|
template,
|
|
4777
5088
|
doc?._rawData
|
|
@@ -4785,13 +5096,22 @@ var Resolver = class {
|
|
|
4785
5096
|
return this.getDocument(realPath);
|
|
4786
5097
|
}
|
|
4787
5098
|
const params = await this.buildObjectMutations(
|
|
5099
|
+
//@ts-ignore
|
|
4788
5100
|
isCollectionSpecific ? args.params : args.params[collection.name],
|
|
4789
5101
|
collection,
|
|
4790
5102
|
doc?._rawData
|
|
4791
5103
|
);
|
|
4792
|
-
await this.database.put(
|
|
5104
|
+
await this.database.put(
|
|
5105
|
+
realPath,
|
|
5106
|
+
{ ...oldDoc, ...params },
|
|
5107
|
+
collection.name
|
|
5108
|
+
);
|
|
4793
5109
|
return this.getDocument(realPath);
|
|
4794
5110
|
};
|
|
5111
|
+
/**
|
|
5112
|
+
* Returns top-level fields which are not defined in the collection, so their
|
|
5113
|
+
* values are not eliminated from Tina when new values are saved
|
|
5114
|
+
*/
|
|
4795
5115
|
this.resolveLegacyValues = (oldDoc, collection) => {
|
|
4796
5116
|
const legacyValues = {};
|
|
4797
5117
|
Object.entries(oldDoc).forEach(([key, value]) => {
|
|
@@ -4896,6 +5216,40 @@ var Resolver = class {
|
|
|
4896
5216
|
if (isDeletion) {
|
|
4897
5217
|
const doc = await this.getDocument(realPath);
|
|
4898
5218
|
await this.deleteDocument(realPath);
|
|
5219
|
+
if (await this.hasReferences(realPath, collection)) {
|
|
5220
|
+
const collRefs = await this.findReferences(realPath, collection);
|
|
5221
|
+
for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
|
|
5222
|
+
for (const [pathToDocWithRef, referencePaths] of Object.entries(
|
|
5223
|
+
docsWithRefs
|
|
5224
|
+
)) {
|
|
5225
|
+
let refDoc = await this.getRaw(pathToDocWithRef);
|
|
5226
|
+
let hasUpdate = false;
|
|
5227
|
+
for (const path7 of referencePaths) {
|
|
5228
|
+
const { object: object2, updated } = updateObjectWithJsonPath(
|
|
5229
|
+
refDoc,
|
|
5230
|
+
path7,
|
|
5231
|
+
realPath,
|
|
5232
|
+
null
|
|
5233
|
+
);
|
|
5234
|
+
refDoc = object2;
|
|
5235
|
+
hasUpdate = updated || hasUpdate;
|
|
5236
|
+
}
|
|
5237
|
+
if (hasUpdate) {
|
|
5238
|
+
const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
|
|
5239
|
+
if (!collectionWithRef) {
|
|
5240
|
+
throw new Error(
|
|
5241
|
+
`Unable to find collection for ${pathToDocWithRef}`
|
|
5242
|
+
);
|
|
5243
|
+
}
|
|
5244
|
+
await this.database.put(
|
|
5245
|
+
pathToDocWithRef,
|
|
5246
|
+
refDoc,
|
|
5247
|
+
collectionWithRef.name
|
|
5248
|
+
);
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
4899
5253
|
return doc;
|
|
4900
5254
|
}
|
|
4901
5255
|
if (isUpdateName) {
|
|
@@ -4912,12 +5266,49 @@ var Resolver = class {
|
|
|
4912
5266
|
collection?.path,
|
|
4913
5267
|
args.params.relativePath
|
|
4914
5268
|
);
|
|
5269
|
+
if (newRealPath === realPath) {
|
|
5270
|
+
return doc;
|
|
5271
|
+
}
|
|
4915
5272
|
await this.database.put(newRealPath, doc._rawData, collection.name);
|
|
4916
5273
|
await this.deleteDocument(realPath);
|
|
5274
|
+
const collRefs = await this.findReferences(realPath, collection);
|
|
5275
|
+
for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
|
|
5276
|
+
for (const [pathToDocWithRef, referencePaths] of Object.entries(
|
|
5277
|
+
docsWithRefs
|
|
5278
|
+
)) {
|
|
5279
|
+
let docWithRef = await this.getRaw(pathToDocWithRef);
|
|
5280
|
+
let hasUpdate = false;
|
|
5281
|
+
for (const path7 of referencePaths) {
|
|
5282
|
+
const { object: object2, updated } = updateObjectWithJsonPath(
|
|
5283
|
+
docWithRef,
|
|
5284
|
+
path7,
|
|
5285
|
+
realPath,
|
|
5286
|
+
newRealPath
|
|
5287
|
+
);
|
|
5288
|
+
docWithRef = object2;
|
|
5289
|
+
hasUpdate = updated || hasUpdate;
|
|
5290
|
+
}
|
|
5291
|
+
if (hasUpdate) {
|
|
5292
|
+
const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
|
|
5293
|
+
if (!collectionWithRef) {
|
|
5294
|
+
throw new Error(
|
|
5295
|
+
`Unable to find collection for ${pathToDocWithRef}`
|
|
5296
|
+
);
|
|
5297
|
+
}
|
|
5298
|
+
await this.database.put(
|
|
5299
|
+
pathToDocWithRef,
|
|
5300
|
+
docWithRef,
|
|
5301
|
+
collectionWithRef.name
|
|
5302
|
+
);
|
|
5303
|
+
}
|
|
5304
|
+
}
|
|
5305
|
+
}
|
|
4917
5306
|
return this.getDocument(newRealPath);
|
|
4918
5307
|
}
|
|
4919
5308
|
if (alreadyExists === false) {
|
|
4920
|
-
throw new Error(
|
|
5309
|
+
throw new Error(
|
|
5310
|
+
`Unable to update document, ${realPath} does not exist`
|
|
5311
|
+
);
|
|
4921
5312
|
}
|
|
4922
5313
|
return this.updateResolveDocument({
|
|
4923
5314
|
collection,
|
|
@@ -4927,7 +5318,10 @@ var Resolver = class {
|
|
|
4927
5318
|
isCollectionSpecific
|
|
4928
5319
|
});
|
|
4929
5320
|
} else {
|
|
4930
|
-
return this.getDocument(realPath
|
|
5321
|
+
return this.getDocument(realPath, {
|
|
5322
|
+
collection,
|
|
5323
|
+
checkReferences: true
|
|
5324
|
+
});
|
|
4931
5325
|
}
|
|
4932
5326
|
};
|
|
4933
5327
|
this.resolveCollectionConnections = async ({ ids }) => {
|
|
@@ -4964,6 +5358,7 @@ var Resolver = class {
|
|
|
4964
5358
|
},
|
|
4965
5359
|
collection: referencedCollection,
|
|
4966
5360
|
hydrator: (path7) => path7
|
|
5361
|
+
// just return the path
|
|
4967
5362
|
}
|
|
4968
5363
|
);
|
|
4969
5364
|
const { edges } = resolvedCollectionConnection;
|
|
@@ -5031,6 +5426,82 @@ var Resolver = class {
|
|
|
5031
5426
|
}
|
|
5032
5427
|
};
|
|
5033
5428
|
};
|
|
5429
|
+
/**
|
|
5430
|
+
* Checks if a document has references to it
|
|
5431
|
+
* @param id The id of the document to check for references
|
|
5432
|
+
* @param c The collection to check for references
|
|
5433
|
+
* @returns true if the document has references, false otherwise
|
|
5434
|
+
*/
|
|
5435
|
+
this.hasReferences = async (id, c) => {
|
|
5436
|
+
let count = 0;
|
|
5437
|
+
await this.database.query(
|
|
5438
|
+
{
|
|
5439
|
+
collection: c.name,
|
|
5440
|
+
filterChain: makeFilterChain({
|
|
5441
|
+
conditions: [
|
|
5442
|
+
{
|
|
5443
|
+
filterPath: REFS_REFERENCE_FIELD,
|
|
5444
|
+
filterExpression: {
|
|
5445
|
+
_type: "string",
|
|
5446
|
+
_list: false,
|
|
5447
|
+
eq: id
|
|
5448
|
+
}
|
|
5449
|
+
}
|
|
5450
|
+
]
|
|
5451
|
+
}),
|
|
5452
|
+
sort: REFS_COLLECTIONS_SORT_KEY
|
|
5453
|
+
},
|
|
5454
|
+
(refId) => {
|
|
5455
|
+
count++;
|
|
5456
|
+
return refId;
|
|
5457
|
+
}
|
|
5458
|
+
);
|
|
5459
|
+
if (count) {
|
|
5460
|
+
return true;
|
|
5461
|
+
}
|
|
5462
|
+
return false;
|
|
5463
|
+
};
|
|
5464
|
+
/**
|
|
5465
|
+
* Finds references to a document
|
|
5466
|
+
* @param id the id of the document to find references to
|
|
5467
|
+
* @param c the collection to find references in
|
|
5468
|
+
* @returns a map of references to the document
|
|
5469
|
+
*/
|
|
5470
|
+
this.findReferences = async (id, c) => {
|
|
5471
|
+
const references = {};
|
|
5472
|
+
await this.database.query(
|
|
5473
|
+
{
|
|
5474
|
+
collection: c.name,
|
|
5475
|
+
filterChain: makeFilterChain({
|
|
5476
|
+
conditions: [
|
|
5477
|
+
{
|
|
5478
|
+
filterPath: REFS_REFERENCE_FIELD,
|
|
5479
|
+
filterExpression: {
|
|
5480
|
+
_type: "string",
|
|
5481
|
+
_list: false,
|
|
5482
|
+
eq: id
|
|
5483
|
+
}
|
|
5484
|
+
}
|
|
5485
|
+
]
|
|
5486
|
+
}),
|
|
5487
|
+
sort: REFS_COLLECTIONS_SORT_KEY
|
|
5488
|
+
},
|
|
5489
|
+
(refId, rawItem) => {
|
|
5490
|
+
if (!references[c.name]) {
|
|
5491
|
+
references[c.name] = {};
|
|
5492
|
+
}
|
|
5493
|
+
if (!references[c.name][refId]) {
|
|
5494
|
+
references[c.name][refId] = [];
|
|
5495
|
+
}
|
|
5496
|
+
const referencePath = rawItem?.[REFS_PATH_FIELD];
|
|
5497
|
+
if (referencePath) {
|
|
5498
|
+
references[c.name][refId].push(referencePath);
|
|
5499
|
+
}
|
|
5500
|
+
return refId;
|
|
5501
|
+
}
|
|
5502
|
+
);
|
|
5503
|
+
return references;
|
|
5504
|
+
};
|
|
5034
5505
|
this.buildFieldMutations = async (fieldParams, template, existingData) => {
|
|
5035
5506
|
const accum = {};
|
|
5036
5507
|
for (const passwordField of template.fields.filter(
|
|
@@ -5098,7 +5569,7 @@ var Resolver = class {
|
|
|
5098
5569
|
}
|
|
5099
5570
|
break;
|
|
5100
5571
|
case "rich-text":
|
|
5101
|
-
accum[fieldName] =
|
|
5572
|
+
accum[fieldName] = serializeMDX(
|
|
5102
5573
|
fieldValue,
|
|
5103
5574
|
field,
|
|
5104
5575
|
(fieldValue2) => resolveMediaCloudToRelative(
|
|
@@ -5117,6 +5588,27 @@ var Resolver = class {
|
|
|
5117
5588
|
}
|
|
5118
5589
|
return accum;
|
|
5119
5590
|
};
|
|
5591
|
+
/**
|
|
5592
|
+
* A mutation looks nearly identical between updateDocument:
|
|
5593
|
+
* ```graphql
|
|
5594
|
+
* updateDocument(collection: $collection,relativePath: $path, params: {
|
|
5595
|
+
* post: {
|
|
5596
|
+
* title: "Hello, World"
|
|
5597
|
+
* }
|
|
5598
|
+
* })`
|
|
5599
|
+
* ```
|
|
5600
|
+
* and `updatePostDocument`:
|
|
5601
|
+
* ```graphql
|
|
5602
|
+
* updatePostDocument(relativePath: $path, params: {
|
|
5603
|
+
* title: "Hello, World"
|
|
5604
|
+
* })
|
|
5605
|
+
* ```
|
|
5606
|
+
* The problem here is that we don't know whether the payload came from `updateDocument`
|
|
5607
|
+
* or `updatePostDocument` (we could, but for now it's easier not to pipe those details through),
|
|
5608
|
+
* But we do know that when given a `args.collection` value, we can assume that
|
|
5609
|
+
* this was a `updateDocument` request, and thus - should grab the data
|
|
5610
|
+
* from the corresponding field name in the key
|
|
5611
|
+
*/
|
|
5120
5612
|
this.buildParams = (args) => {
|
|
5121
5613
|
try {
|
|
5122
5614
|
assertShape(
|
|
@@ -5184,8 +5676,129 @@ var resolveDateInput = (value) => {
|
|
|
5184
5676
|
return date;
|
|
5185
5677
|
};
|
|
5186
5678
|
|
|
5187
|
-
// src/
|
|
5188
|
-
import set from "
|
|
5679
|
+
// src/resolver/auth-fields.ts
|
|
5680
|
+
import { set } from "es-toolkit/compat";
|
|
5681
|
+
async function getUserDocumentContext(tinaSchema, resolver) {
|
|
5682
|
+
const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
|
|
5683
|
+
if (!collection) {
|
|
5684
|
+
throw new Error("Auth collection not found");
|
|
5685
|
+
}
|
|
5686
|
+
const userFields = mapUserFields(collection, ["_rawData"]);
|
|
5687
|
+
if (!userFields.length) {
|
|
5688
|
+
throw new Error(`No user field found in collection ${collection.name}`);
|
|
5689
|
+
}
|
|
5690
|
+
if (userFields.length > 1) {
|
|
5691
|
+
throw new Error(
|
|
5692
|
+
`Multiple user fields found in collection ${collection.name}`
|
|
5693
|
+
);
|
|
5694
|
+
}
|
|
5695
|
+
const userField = userFields[0];
|
|
5696
|
+
const realPath = `${collection.path}/index.json`;
|
|
5697
|
+
const userDoc = await resolver.getDocument(realPath);
|
|
5698
|
+
const users = get(userDoc, userField.path);
|
|
5699
|
+
if (!users) {
|
|
5700
|
+
throw new Error("No users found");
|
|
5701
|
+
}
|
|
5702
|
+
return { collection, userField, users, userDoc, realPath };
|
|
5703
|
+
}
|
|
5704
|
+
function findUserInCollection(users, userField, userSub) {
|
|
5705
|
+
const { idFieldName } = userField;
|
|
5706
|
+
if (!idFieldName) {
|
|
5707
|
+
throw new Error("No uid field found on user field");
|
|
5708
|
+
}
|
|
5709
|
+
return users.find((u) => u[idFieldName] === userSub) || null;
|
|
5710
|
+
}
|
|
5711
|
+
async function handleAuthenticate({
|
|
5712
|
+
tinaSchema,
|
|
5713
|
+
resolver,
|
|
5714
|
+
sub,
|
|
5715
|
+
password,
|
|
5716
|
+
ctxUser
|
|
5717
|
+
}) {
|
|
5718
|
+
const userSub = sub || ctxUser?.sub;
|
|
5719
|
+
const { userField, users } = await getUserDocumentContext(
|
|
5720
|
+
tinaSchema,
|
|
5721
|
+
resolver
|
|
5722
|
+
);
|
|
5723
|
+
const user = findUserInCollection(users, userField, userSub);
|
|
5724
|
+
if (!user) {
|
|
5725
|
+
return null;
|
|
5726
|
+
}
|
|
5727
|
+
const { passwordFieldName } = userField;
|
|
5728
|
+
const saltedHash = get(user, [passwordFieldName || "", "value"]);
|
|
5729
|
+
if (!saltedHash) {
|
|
5730
|
+
throw new Error("No password field found on user field");
|
|
5731
|
+
}
|
|
5732
|
+
const matches = await checkPasswordHash({
|
|
5733
|
+
saltedHash,
|
|
5734
|
+
password
|
|
5735
|
+
});
|
|
5736
|
+
return matches ? user : null;
|
|
5737
|
+
}
|
|
5738
|
+
async function handleAuthorize({
|
|
5739
|
+
tinaSchema,
|
|
5740
|
+
resolver,
|
|
5741
|
+
sub,
|
|
5742
|
+
ctxUser
|
|
5743
|
+
}) {
|
|
5744
|
+
const userSub = sub || ctxUser?.sub;
|
|
5745
|
+
const { userField, users } = await getUserDocumentContext(
|
|
5746
|
+
tinaSchema,
|
|
5747
|
+
resolver
|
|
5748
|
+
);
|
|
5749
|
+
const user = findUserInCollection(users, userField, userSub);
|
|
5750
|
+
return user ? user : null;
|
|
5751
|
+
}
|
|
5752
|
+
async function handleUpdatePassword({
|
|
5753
|
+
tinaSchema,
|
|
5754
|
+
resolver,
|
|
5755
|
+
password,
|
|
5756
|
+
ctxUser
|
|
5757
|
+
}) {
|
|
5758
|
+
if (!ctxUser?.sub) {
|
|
5759
|
+
throw new Error("Not authorized");
|
|
5760
|
+
}
|
|
5761
|
+
if (!password) {
|
|
5762
|
+
throw new Error("No password provided");
|
|
5763
|
+
}
|
|
5764
|
+
const { collection, userField, users, realPath } = await getUserDocumentContext(tinaSchema, resolver);
|
|
5765
|
+
const { idFieldName, passwordFieldName } = userField;
|
|
5766
|
+
const user = users.find((u) => u[idFieldName] === ctxUser.sub);
|
|
5767
|
+
if (!user) {
|
|
5768
|
+
throw new Error("Not authorized");
|
|
5769
|
+
}
|
|
5770
|
+
user[passwordFieldName] = {
|
|
5771
|
+
value: password,
|
|
5772
|
+
passwordChangeRequired: false
|
|
5773
|
+
};
|
|
5774
|
+
const params = {};
|
|
5775
|
+
set(
|
|
5776
|
+
params,
|
|
5777
|
+
userField.path.slice(1),
|
|
5778
|
+
// remove _rawData from users path
|
|
5779
|
+
users.map((u) => {
|
|
5780
|
+
if (user[idFieldName] === u[idFieldName]) {
|
|
5781
|
+
return user;
|
|
5782
|
+
}
|
|
5783
|
+
return {
|
|
5784
|
+
// don't overwrite other users' passwords
|
|
5785
|
+
...u,
|
|
5786
|
+
[passwordFieldName]: {
|
|
5787
|
+
...u[passwordFieldName],
|
|
5788
|
+
value: ""
|
|
5789
|
+
}
|
|
5790
|
+
};
|
|
5791
|
+
})
|
|
5792
|
+
);
|
|
5793
|
+
await resolver.updateResolveDocument({
|
|
5794
|
+
collection,
|
|
5795
|
+
args: { params },
|
|
5796
|
+
realPath,
|
|
5797
|
+
isCollectionSpecific: true,
|
|
5798
|
+
isAddPendingDocument: false
|
|
5799
|
+
});
|
|
5800
|
+
return true;
|
|
5801
|
+
}
|
|
5189
5802
|
|
|
5190
5803
|
// src/error.ts
|
|
5191
5804
|
import { GraphQLError as GraphQLError3 } from "graphql";
|
|
@@ -5216,7 +5829,10 @@ var resolve = async ({
|
|
|
5216
5829
|
const graphQLSchema = buildASTSchema(graphQLSchemaAst);
|
|
5217
5830
|
const tinaConfig = await database.getTinaSchema();
|
|
5218
5831
|
const tinaSchema = await createSchema({
|
|
5832
|
+
// TODO: please update all the types to import from @tinacms/schema-tools
|
|
5833
|
+
// @ts-ignore
|
|
5219
5834
|
schema: tinaConfig,
|
|
5835
|
+
// @ts-ignore
|
|
5220
5836
|
flags: tinaConfig?.meta?.flags
|
|
5221
5837
|
});
|
|
5222
5838
|
const resolver = createResolver({
|
|
@@ -5233,8 +5849,7 @@ var resolve = async ({
|
|
|
5233
5849
|
database
|
|
5234
5850
|
},
|
|
5235
5851
|
typeResolver: async (source, _args, info) => {
|
|
5236
|
-
if (source.__typename)
|
|
5237
|
-
return source.__typename;
|
|
5852
|
+
if (source.__typename) return source.__typename;
|
|
5238
5853
|
const namedType = getNamedType(info.returnType).toString();
|
|
5239
5854
|
const lookup = await database.getLookup(namedType);
|
|
5240
5855
|
if (lookup.resolveType === "unionData") {
|
|
@@ -5293,123 +5908,42 @@ var resolve = async ({
|
|
|
5293
5908
|
);
|
|
5294
5909
|
}
|
|
5295
5910
|
}
|
|
5296
|
-
if (info.fieldName === "authenticate"
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
const realPath = `${collection.path}/index.json`;
|
|
5315
|
-
const userDoc = await resolver.getDocument(realPath);
|
|
5316
|
-
const users = get(userDoc, userField.path);
|
|
5317
|
-
if (!users) {
|
|
5318
|
-
throw new Error("No users found");
|
|
5319
|
-
}
|
|
5320
|
-
const { idFieldName, passwordFieldName } = userField;
|
|
5321
|
-
if (!idFieldName) {
|
|
5322
|
-
throw new Error("No uid field found on user field");
|
|
5323
|
-
}
|
|
5324
|
-
const user = users.find((u) => u[idFieldName] === sub);
|
|
5325
|
-
if (!user) {
|
|
5326
|
-
return null;
|
|
5327
|
-
}
|
|
5328
|
-
if (info.fieldName === "authenticate") {
|
|
5329
|
-
const saltedHash = get(user, [passwordFieldName || "", "value"]);
|
|
5330
|
-
if (!saltedHash) {
|
|
5331
|
-
throw new Error("No password field found on user field");
|
|
5332
|
-
}
|
|
5333
|
-
const matches = await checkPasswordHash({
|
|
5334
|
-
saltedHash,
|
|
5335
|
-
password: args.password
|
|
5336
|
-
});
|
|
5337
|
-
if (matches) {
|
|
5338
|
-
return user;
|
|
5339
|
-
}
|
|
5340
|
-
return null;
|
|
5341
|
-
}
|
|
5342
|
-
return user;
|
|
5911
|
+
if (info.fieldName === "authenticate") {
|
|
5912
|
+
return handleAuthenticate({
|
|
5913
|
+
tinaSchema,
|
|
5914
|
+
resolver,
|
|
5915
|
+
sub: args.sub,
|
|
5916
|
+
password: args.password,
|
|
5917
|
+
info,
|
|
5918
|
+
ctxUser
|
|
5919
|
+
});
|
|
5920
|
+
}
|
|
5921
|
+
if (info.fieldName === "authorize") {
|
|
5922
|
+
return handleAuthorize({
|
|
5923
|
+
tinaSchema,
|
|
5924
|
+
resolver,
|
|
5925
|
+
sub: args.sub,
|
|
5926
|
+
info,
|
|
5927
|
+
ctxUser
|
|
5928
|
+
});
|
|
5343
5929
|
}
|
|
5344
5930
|
if (info.fieldName === "updatePassword") {
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
|
|
5352
|
-
if (!collection) {
|
|
5353
|
-
throw new Error("Auth collection not found");
|
|
5354
|
-
}
|
|
5355
|
-
const userFields = mapUserFields(collection, ["_rawData"]);
|
|
5356
|
-
if (!userFields.length) {
|
|
5357
|
-
throw new Error(
|
|
5358
|
-
`No user field found in collection ${collection.name}`
|
|
5359
|
-
);
|
|
5360
|
-
}
|
|
5361
|
-
if (userFields.length > 1) {
|
|
5362
|
-
throw new Error(
|
|
5363
|
-
`Multiple user fields found in collection ${collection.name}`
|
|
5364
|
-
);
|
|
5365
|
-
}
|
|
5366
|
-
const userField = userFields[0];
|
|
5367
|
-
const realPath = `${collection.path}/index.json`;
|
|
5368
|
-
const userDoc = await resolver.getDocument(realPath);
|
|
5369
|
-
const users = get(userDoc, userField.path);
|
|
5370
|
-
if (!users) {
|
|
5371
|
-
throw new Error("No users found");
|
|
5372
|
-
}
|
|
5373
|
-
const { idFieldName, passwordFieldName } = userField;
|
|
5374
|
-
const user = users.find((u) => u[idFieldName] === ctxUser.sub);
|
|
5375
|
-
if (!user) {
|
|
5376
|
-
throw new Error("Not authorized");
|
|
5377
|
-
}
|
|
5378
|
-
user[passwordFieldName] = {
|
|
5379
|
-
value: args.password,
|
|
5380
|
-
passwordChangeRequired: false
|
|
5381
|
-
};
|
|
5382
|
-
const params = {};
|
|
5383
|
-
set(
|
|
5384
|
-
params,
|
|
5385
|
-
userField.path.slice(1),
|
|
5386
|
-
users.map((u) => {
|
|
5387
|
-
if (user[idFieldName] === u[idFieldName]) {
|
|
5388
|
-
return user;
|
|
5389
|
-
}
|
|
5390
|
-
return {
|
|
5391
|
-
...u,
|
|
5392
|
-
[passwordFieldName]: {
|
|
5393
|
-
...u[passwordFieldName],
|
|
5394
|
-
value: ""
|
|
5395
|
-
}
|
|
5396
|
-
};
|
|
5397
|
-
})
|
|
5398
|
-
);
|
|
5399
|
-
await resolver.updateResolveDocument({
|
|
5400
|
-
collection,
|
|
5401
|
-
args: { params },
|
|
5402
|
-
realPath,
|
|
5403
|
-
isCollectionSpecific: true,
|
|
5404
|
-
isAddPendingDocument: false
|
|
5931
|
+
return handleUpdatePassword({
|
|
5932
|
+
tinaSchema,
|
|
5933
|
+
resolver,
|
|
5934
|
+
password: args.password,
|
|
5935
|
+
info,
|
|
5936
|
+
ctxUser
|
|
5405
5937
|
});
|
|
5406
|
-
return true;
|
|
5407
5938
|
}
|
|
5408
5939
|
if (!lookup) {
|
|
5409
5940
|
return value;
|
|
5410
5941
|
}
|
|
5411
5942
|
const isCreation = lookup[info.fieldName] === "create";
|
|
5412
5943
|
switch (lookup.resolveType) {
|
|
5944
|
+
/**
|
|
5945
|
+
* `node(id: $id)`
|
|
5946
|
+
*/
|
|
5413
5947
|
case "nodeDocument":
|
|
5414
5948
|
assertShape(
|
|
5415
5949
|
args,
|
|
@@ -5441,6 +5975,7 @@ var resolve = async ({
|
|
|
5441
5975
|
collection: args.collection,
|
|
5442
5976
|
isMutation,
|
|
5443
5977
|
isCreation,
|
|
5978
|
+
// Right now this is the only case for deletion
|
|
5444
5979
|
isDeletion: info.fieldName === "deleteDocument",
|
|
5445
5980
|
isFolderCreation: info.fieldName === "createFolder",
|
|
5446
5981
|
isUpdateName: Boolean(args?.params?.relativePath),
|
|
@@ -5450,6 +5985,9 @@ var resolve = async ({
|
|
|
5450
5985
|
return result;
|
|
5451
5986
|
}
|
|
5452
5987
|
return value;
|
|
5988
|
+
/**
|
|
5989
|
+
* eg `getMovieDocument.data.actors`
|
|
5990
|
+
*/
|
|
5453
5991
|
case "multiCollectionDocumentList":
|
|
5454
5992
|
if (Array.isArray(value)) {
|
|
5455
5993
|
return {
|
|
@@ -5461,7 +5999,15 @@ var resolve = async ({
|
|
|
5461
5999
|
}
|
|
5462
6000
|
if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
|
|
5463
6001
|
let filter = args.filter;
|
|
5464
|
-
if (
|
|
6002
|
+
if (
|
|
6003
|
+
// 1. Make sure that the filter exists
|
|
6004
|
+
typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
|
|
6005
|
+
// @ts-ignore
|
|
6006
|
+
typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
|
|
6007
|
+
// @ts-ignore
|
|
6008
|
+
Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
|
|
6009
|
+
typeof args.filter[value?.collection?.name] !== "undefined"
|
|
6010
|
+
) {
|
|
5465
6011
|
filter = args.filter[value.collection.name];
|
|
5466
6012
|
}
|
|
5467
6013
|
return resolver.resolveCollectionConnection({
|
|
@@ -5469,12 +6015,20 @@ var resolve = async ({
|
|
|
5469
6015
|
...args,
|
|
5470
6016
|
filter
|
|
5471
6017
|
},
|
|
6018
|
+
// @ts-ignore
|
|
5472
6019
|
collection: value.collection
|
|
5473
6020
|
});
|
|
5474
6021
|
}
|
|
5475
6022
|
throw new Error(
|
|
5476
6023
|
`Expected an array for result of ${info.fieldName} at ${info.path}`
|
|
5477
6024
|
);
|
|
6025
|
+
/**
|
|
6026
|
+
* Collections-specific getter
|
|
6027
|
+
* eg. `getPostDocument`/`createPostDocument`/`updatePostDocument`
|
|
6028
|
+
*
|
|
6029
|
+
* if coming from a query result
|
|
6030
|
+
* the field will be `node`
|
|
6031
|
+
*/
|
|
5478
6032
|
case "collectionDocument": {
|
|
5479
6033
|
if (value) {
|
|
5480
6034
|
return value;
|
|
@@ -5489,11 +6043,32 @@ var resolve = async ({
|
|
|
5489
6043
|
});
|
|
5490
6044
|
return result;
|
|
5491
6045
|
}
|
|
6046
|
+
/**
|
|
6047
|
+
* Collections-specific list getter
|
|
6048
|
+
* eg. `getPageList`
|
|
6049
|
+
*/
|
|
5492
6050
|
case "collectionDocumentList":
|
|
5493
6051
|
return resolver.resolveCollectionConnection({
|
|
5494
6052
|
args,
|
|
5495
6053
|
collection: tinaSchema.getCollection(lookup.collection)
|
|
5496
6054
|
});
|
|
6055
|
+
/**
|
|
6056
|
+
* A polymorphic data set, it can be from a document's data
|
|
6057
|
+
* of any nested object which can be one of many shapes
|
|
6058
|
+
*
|
|
6059
|
+
* ```graphql
|
|
6060
|
+
* getPostDocument(relativePath: $relativePath) {
|
|
6061
|
+
* data {...} <- this part
|
|
6062
|
+
* }
|
|
6063
|
+
* ```
|
|
6064
|
+
* ```graphql
|
|
6065
|
+
* getBlockDocument(relativePath: $relativePath) {
|
|
6066
|
+
* data {
|
|
6067
|
+
* blocks {...} <- or this part
|
|
6068
|
+
* }
|
|
6069
|
+
* }
|
|
6070
|
+
* ```
|
|
6071
|
+
*/
|
|
5497
6072
|
case "unionData":
|
|
5498
6073
|
if (!value) {
|
|
5499
6074
|
if (args.relativePath) {
|
|
@@ -5558,8 +6133,7 @@ var TinaLevelClient = class extends ManyLevelGuest {
|
|
|
5558
6133
|
this.port = port || 9e3;
|
|
5559
6134
|
}
|
|
5560
6135
|
openConnection() {
|
|
5561
|
-
if (this._connected)
|
|
5562
|
-
return;
|
|
6136
|
+
if (this._connected) return;
|
|
5563
6137
|
const socket = connect(this.port);
|
|
5564
6138
|
pipeline(socket, this.createRpcStream(), socket, () => {
|
|
5565
6139
|
this._connected = false;
|
|
@@ -5569,11 +6143,11 @@ var TinaLevelClient = class extends ManyLevelGuest {
|
|
|
5569
6143
|
};
|
|
5570
6144
|
|
|
5571
6145
|
// src/database/index.ts
|
|
5572
|
-
import path4 from "path";
|
|
6146
|
+
import path4 from "node:path";
|
|
5573
6147
|
import { GraphQLError as GraphQLError5 } from "graphql";
|
|
5574
6148
|
import micromatch2 from "micromatch";
|
|
5575
6149
|
import sha2 from "js-sha1";
|
|
5576
|
-
import set2 from "
|
|
6150
|
+
import { set as set2 } from "es-toolkit/compat";
|
|
5577
6151
|
var createLocalDatabase = (config) => {
|
|
5578
6152
|
const level = new TinaLevelClient(config?.port);
|
|
5579
6153
|
level.openConnection();
|
|
@@ -5704,6 +6278,7 @@ var Database = class {
|
|
|
5704
6278
|
);
|
|
5705
6279
|
const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
|
|
5706
6280
|
const collectionIndexDefinitions = indexDefinitions?.[collection.name];
|
|
6281
|
+
const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
|
|
5707
6282
|
const normalizedPath = normalizePath(filepath);
|
|
5708
6283
|
if (!collection?.isDetached) {
|
|
5709
6284
|
if (this.bridge) {
|
|
@@ -5732,6 +6307,14 @@ var Database = class {
|
|
|
5732
6307
|
let delOps = [];
|
|
5733
6308
|
if (!isGitKeep(normalizedPath, collection)) {
|
|
5734
6309
|
putOps = [
|
|
6310
|
+
...makeRefOpsForDocument(
|
|
6311
|
+
normalizedPath,
|
|
6312
|
+
collection?.name,
|
|
6313
|
+
collectionReferences,
|
|
6314
|
+
dataFields,
|
|
6315
|
+
"put",
|
|
6316
|
+
level
|
|
6317
|
+
),
|
|
5735
6318
|
...makeIndexOpsForDocument(
|
|
5736
6319
|
normalizedPath,
|
|
5737
6320
|
collection?.name,
|
|
@@ -5740,6 +6323,7 @@ var Database = class {
|
|
|
5740
6323
|
"put",
|
|
5741
6324
|
level
|
|
5742
6325
|
),
|
|
6326
|
+
// folder indices
|
|
5743
6327
|
...makeIndexOpsForDocument(
|
|
5744
6328
|
normalizedPath,
|
|
5745
6329
|
`${collection?.name}_${folderKey}`,
|
|
@@ -5754,6 +6338,14 @@ var Database = class {
|
|
|
5754
6338
|
SUBLEVEL_OPTIONS
|
|
5755
6339
|
).get(normalizedPath);
|
|
5756
6340
|
delOps = existingItem ? [
|
|
6341
|
+
...makeRefOpsForDocument(
|
|
6342
|
+
normalizedPath,
|
|
6343
|
+
collection?.name,
|
|
6344
|
+
collectionReferences,
|
|
6345
|
+
existingItem,
|
|
6346
|
+
"del",
|
|
6347
|
+
level
|
|
6348
|
+
),
|
|
5757
6349
|
...makeIndexOpsForDocument(
|
|
5758
6350
|
normalizedPath,
|
|
5759
6351
|
collection?.name,
|
|
@@ -5762,6 +6354,7 @@ var Database = class {
|
|
|
5762
6354
|
"del",
|
|
5763
6355
|
level
|
|
5764
6356
|
),
|
|
6357
|
+
// folder indices
|
|
5765
6358
|
...makeIndexOpsForDocument(
|
|
5766
6359
|
normalizedPath,
|
|
5767
6360
|
`${collection?.name}_${folderKey}`,
|
|
@@ -5800,6 +6393,7 @@ var Database = class {
|
|
|
5800
6393
|
);
|
|
5801
6394
|
collectionIndexDefinitions = indexDefinitions?.[collectionName];
|
|
5802
6395
|
}
|
|
6396
|
+
const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
|
|
5803
6397
|
const normalizedPath = normalizePath(filepath);
|
|
5804
6398
|
const dataFields = await this.formatBodyOnPayload(filepath, data);
|
|
5805
6399
|
const collection = await this.collectionForPath(filepath);
|
|
@@ -5847,6 +6441,14 @@ var Database = class {
|
|
|
5847
6441
|
let delOps = [];
|
|
5848
6442
|
if (!isGitKeep(normalizedPath, collection)) {
|
|
5849
6443
|
putOps = [
|
|
6444
|
+
...makeRefOpsForDocument(
|
|
6445
|
+
normalizedPath,
|
|
6446
|
+
collectionName,
|
|
6447
|
+
collectionReferences,
|
|
6448
|
+
dataFields,
|
|
6449
|
+
"put",
|
|
6450
|
+
level
|
|
6451
|
+
),
|
|
5850
6452
|
...makeIndexOpsForDocument(
|
|
5851
6453
|
normalizedPath,
|
|
5852
6454
|
collectionName,
|
|
@@ -5855,6 +6457,7 @@ var Database = class {
|
|
|
5855
6457
|
"put",
|
|
5856
6458
|
level
|
|
5857
6459
|
),
|
|
6460
|
+
// folder indices
|
|
5858
6461
|
...makeIndexOpsForDocument(
|
|
5859
6462
|
normalizedPath,
|
|
5860
6463
|
`${collection?.name}_${folderKey}`,
|
|
@@ -5869,6 +6472,14 @@ var Database = class {
|
|
|
5869
6472
|
SUBLEVEL_OPTIONS
|
|
5870
6473
|
).get(normalizedPath);
|
|
5871
6474
|
delOps = existingItem ? [
|
|
6475
|
+
...makeRefOpsForDocument(
|
|
6476
|
+
normalizedPath,
|
|
6477
|
+
collectionName,
|
|
6478
|
+
collectionReferences,
|
|
6479
|
+
existingItem,
|
|
6480
|
+
"del",
|
|
6481
|
+
level
|
|
6482
|
+
),
|
|
5872
6483
|
...makeIndexOpsForDocument(
|
|
5873
6484
|
normalizedPath,
|
|
5874
6485
|
collectionName,
|
|
@@ -5877,6 +6488,7 @@ var Database = class {
|
|
|
5877
6488
|
"del",
|
|
5878
6489
|
level
|
|
5879
6490
|
),
|
|
6491
|
+
// folder indices
|
|
5880
6492
|
...makeIndexOpsForDocument(
|
|
5881
6493
|
normalizedPath,
|
|
5882
6494
|
`${collection?.name}_${folderKey}`,
|
|
@@ -5910,8 +6522,7 @@ var Database = class {
|
|
|
5910
6522
|
throw new TinaFetchError(`Error in PUT for ${filepath}`, {
|
|
5911
6523
|
originalError: error,
|
|
5912
6524
|
file: filepath,
|
|
5913
|
-
collection: collectionName
|
|
5914
|
-
stack: error.stack
|
|
6525
|
+
collection: collectionName
|
|
5915
6526
|
});
|
|
5916
6527
|
}
|
|
5917
6528
|
};
|
|
@@ -5954,6 +6565,7 @@ var Database = class {
|
|
|
5954
6565
|
aliasedData,
|
|
5955
6566
|
extension,
|
|
5956
6567
|
writeTemplateKey,
|
|
6568
|
+
//templateInfo.type === 'union',
|
|
5957
6569
|
{
|
|
5958
6570
|
frontmatterFormat: collection?.frontmatterFormat,
|
|
5959
6571
|
frontmatterDelimiters: collection?.frontmatterDelimiters
|
|
@@ -5992,6 +6604,7 @@ var Database = class {
|
|
|
5992
6604
|
SUBLEVEL_OPTIONS
|
|
5993
6605
|
).get(graphqlPath);
|
|
5994
6606
|
};
|
|
6607
|
+
//TODO - is there a reason why the database fetches some config with "bridge.get", and some with "store.get"?
|
|
5995
6608
|
this.getGraphQLSchemaFromBridge = async () => {
|
|
5996
6609
|
if (!this.bridge) {
|
|
5997
6610
|
throw new Error(`No bridge configured`);
|
|
@@ -6028,6 +6641,22 @@ var Database = class {
|
|
|
6028
6641
|
this.tinaSchema = await createSchema({ schema });
|
|
6029
6642
|
return this.tinaSchema;
|
|
6030
6643
|
};
|
|
6644
|
+
this.getCollectionReferences = async (level) => {
|
|
6645
|
+
if (this.collectionReferences) {
|
|
6646
|
+
return this.collectionReferences;
|
|
6647
|
+
}
|
|
6648
|
+
const result = {};
|
|
6649
|
+
const schema = await this.getSchema(level || this.contentLevel);
|
|
6650
|
+
const collections = schema.getCollections();
|
|
6651
|
+
for (const collection of collections) {
|
|
6652
|
+
const collectionReferences = this.tinaSchema.findReferencesFromCollection(
|
|
6653
|
+
collection.name
|
|
6654
|
+
);
|
|
6655
|
+
result[collection.name] = collectionReferences;
|
|
6656
|
+
}
|
|
6657
|
+
this.collectionReferences = result;
|
|
6658
|
+
return result;
|
|
6659
|
+
};
|
|
6031
6660
|
this.getIndexDefinitions = async (level) => {
|
|
6032
6661
|
if (!this.collectionIndexDefinitions) {
|
|
6033
6662
|
await new Promise(async (resolve2, reject) => {
|
|
@@ -6037,10 +6666,53 @@ var Database = class {
|
|
|
6037
6666
|
const collections = schema.getCollections();
|
|
6038
6667
|
for (const collection of collections) {
|
|
6039
6668
|
const indexDefinitions = {
|
|
6040
|
-
[DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
|
|
6669
|
+
[DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
|
|
6670
|
+
// provide a default sort key which is the file sort
|
|
6671
|
+
// pseudo-index for the collection's references
|
|
6672
|
+
[REFS_COLLECTIONS_SORT_KEY]: {
|
|
6673
|
+
fields: [
|
|
6674
|
+
{
|
|
6675
|
+
name: REFS_REFERENCE_FIELD,
|
|
6676
|
+
type: "string",
|
|
6677
|
+
list: false
|
|
6678
|
+
},
|
|
6679
|
+
{
|
|
6680
|
+
name: REFS_PATH_FIELD,
|
|
6681
|
+
type: "string",
|
|
6682
|
+
list: false
|
|
6683
|
+
}
|
|
6684
|
+
]
|
|
6685
|
+
}
|
|
6041
6686
|
};
|
|
6042
|
-
|
|
6043
|
-
|
|
6687
|
+
let fields = [];
|
|
6688
|
+
if (collection.templates) {
|
|
6689
|
+
const templateFieldMap = {};
|
|
6690
|
+
const conflictedFields = /* @__PURE__ */ new Set();
|
|
6691
|
+
for (const template of collection.templates) {
|
|
6692
|
+
for (const field of template.fields) {
|
|
6693
|
+
if (!templateFieldMap[field.name]) {
|
|
6694
|
+
templateFieldMap[field.name] = field;
|
|
6695
|
+
} else {
|
|
6696
|
+
if (templateFieldMap[field.name].type !== field.type) {
|
|
6697
|
+
console.warn(
|
|
6698
|
+
`Field ${field.name} has conflicting types in templates - skipping index`
|
|
6699
|
+
);
|
|
6700
|
+
conflictedFields.add(field.name);
|
|
6701
|
+
}
|
|
6702
|
+
}
|
|
6703
|
+
}
|
|
6704
|
+
}
|
|
6705
|
+
for (const conflictedField in conflictedFields) {
|
|
6706
|
+
delete templateFieldMap[conflictedField];
|
|
6707
|
+
}
|
|
6708
|
+
for (const field of Object.values(templateFieldMap)) {
|
|
6709
|
+
fields.push(field);
|
|
6710
|
+
}
|
|
6711
|
+
} else if (collection.fields) {
|
|
6712
|
+
fields = collection.fields;
|
|
6713
|
+
}
|
|
6714
|
+
if (fields) {
|
|
6715
|
+
for (const field of fields) {
|
|
6044
6716
|
if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
|
|
6045
6717
|
continue;
|
|
6046
6718
|
}
|
|
@@ -6188,29 +6860,35 @@ var Database = class {
|
|
|
6188
6860
|
}
|
|
6189
6861
|
startKey = startKey || key || "";
|
|
6190
6862
|
endKey = key || "";
|
|
6191
|
-
edges = [...edges, { cursor: key, path: filepath }];
|
|
6863
|
+
edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
|
|
6192
6864
|
}
|
|
6193
6865
|
return {
|
|
6194
|
-
edges: await sequential(
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6866
|
+
edges: await sequential(
|
|
6867
|
+
edges,
|
|
6868
|
+
async ({
|
|
6869
|
+
cursor,
|
|
6870
|
+
path: path7,
|
|
6871
|
+
value
|
|
6872
|
+
}) => {
|
|
6873
|
+
try {
|
|
6874
|
+
const node = await hydrator(path7, value);
|
|
6875
|
+
return {
|
|
6876
|
+
node,
|
|
6877
|
+
cursor: btoa(cursor)
|
|
6878
|
+
};
|
|
6879
|
+
} catch (error) {
|
|
6880
|
+
console.log(error);
|
|
6881
|
+
if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
|
|
6882
|
+
throw new TinaQueryError({
|
|
6883
|
+
originalError: error,
|
|
6884
|
+
file: path7,
|
|
6885
|
+
collection: collection.name
|
|
6886
|
+
});
|
|
6887
|
+
}
|
|
6888
|
+
throw error;
|
|
6210
6889
|
}
|
|
6211
|
-
throw error;
|
|
6212
6890
|
}
|
|
6213
|
-
|
|
6891
|
+
),
|
|
6214
6892
|
pageInfo: {
|
|
6215
6893
|
hasPreviousPage,
|
|
6216
6894
|
hasNextPage,
|
|
@@ -6334,13 +7012,14 @@ var Database = class {
|
|
|
6334
7012
|
documentPaths,
|
|
6335
7013
|
async (collection, documentPaths2) => {
|
|
6336
7014
|
if (collection && !collection.isDetached) {
|
|
6337
|
-
await _indexContent(
|
|
6338
|
-
this,
|
|
6339
|
-
this.contentLevel,
|
|
6340
|
-
documentPaths2,
|
|
7015
|
+
await _indexContent({
|
|
7016
|
+
database: this,
|
|
7017
|
+
level: this.contentLevel,
|
|
7018
|
+
documentPaths: documentPaths2,
|
|
6341
7019
|
enqueueOps,
|
|
6342
|
-
collection
|
|
6343
|
-
|
|
7020
|
+
collection,
|
|
7021
|
+
isPartialReindex: true
|
|
7022
|
+
});
|
|
6344
7023
|
}
|
|
6345
7024
|
}
|
|
6346
7025
|
);
|
|
@@ -6356,17 +7035,18 @@ var Database = class {
|
|
|
6356
7035
|
throw new Error(`No collection found for path: ${filepath}`);
|
|
6357
7036
|
}
|
|
6358
7037
|
const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
|
|
7038
|
+
const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
|
|
6359
7039
|
const collectionIndexDefinitions = indexDefinitions?.[collection.name];
|
|
6360
7040
|
let level = this.contentLevel;
|
|
6361
7041
|
if (collection?.isDetached) {
|
|
6362
7042
|
level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
|
|
6363
7043
|
}
|
|
6364
|
-
const
|
|
7044
|
+
const normalizedPath = normalizePath(filepath);
|
|
6365
7045
|
const rootSublevel = level.sublevel(
|
|
6366
7046
|
CONTENT_ROOT_PREFIX,
|
|
6367
7047
|
SUBLEVEL_OPTIONS
|
|
6368
7048
|
);
|
|
6369
|
-
const item = await rootSublevel.get(
|
|
7049
|
+
const item = await rootSublevel.get(normalizedPath);
|
|
6370
7050
|
if (item) {
|
|
6371
7051
|
const folderTreeBuilder = new FolderTreeBuilder();
|
|
6372
7052
|
const folderKey = folderTreeBuilder.update(
|
|
@@ -6374,16 +7054,25 @@ var Database = class {
|
|
|
6374
7054
|
collection.path || ""
|
|
6375
7055
|
);
|
|
6376
7056
|
await this.contentLevel.batch([
|
|
7057
|
+
...makeRefOpsForDocument(
|
|
7058
|
+
normalizedPath,
|
|
7059
|
+
collection.name,
|
|
7060
|
+
collectionReferences,
|
|
7061
|
+
item,
|
|
7062
|
+
"del",
|
|
7063
|
+
level
|
|
7064
|
+
),
|
|
6377
7065
|
...makeIndexOpsForDocument(
|
|
6378
|
-
|
|
7066
|
+
normalizedPath,
|
|
6379
7067
|
collection.name,
|
|
6380
7068
|
collectionIndexDefinitions,
|
|
6381
7069
|
item,
|
|
6382
7070
|
"del",
|
|
6383
7071
|
level
|
|
6384
7072
|
),
|
|
7073
|
+
// folder indices
|
|
6385
7074
|
...makeIndexOpsForDocument(
|
|
6386
|
-
|
|
7075
|
+
normalizedPath,
|
|
6387
7076
|
`${collection.name}_${folderKey}`,
|
|
6388
7077
|
collectionIndexDefinitions,
|
|
6389
7078
|
item,
|
|
@@ -6392,17 +7081,17 @@ var Database = class {
|
|
|
6392
7081
|
),
|
|
6393
7082
|
{
|
|
6394
7083
|
type: "del",
|
|
6395
|
-
key:
|
|
7084
|
+
key: normalizedPath,
|
|
6396
7085
|
sublevel: rootSublevel
|
|
6397
7086
|
}
|
|
6398
7087
|
]);
|
|
6399
7088
|
}
|
|
6400
7089
|
if (!collection?.isDetached) {
|
|
6401
7090
|
if (this.bridge) {
|
|
6402
|
-
await this.bridge.delete(
|
|
7091
|
+
await this.bridge.delete(normalizedPath);
|
|
6403
7092
|
}
|
|
6404
7093
|
try {
|
|
6405
|
-
await this.onDelete(
|
|
7094
|
+
await this.onDelete(normalizedPath);
|
|
6406
7095
|
} catch (e) {
|
|
6407
7096
|
throw new GraphQLError5(
|
|
6408
7097
|
`Error running onDelete hook for ${filepath}: ${e}`,
|
|
@@ -6437,20 +7126,26 @@ var Database = class {
|
|
|
6437
7126
|
);
|
|
6438
7127
|
const doc = await level2.keys({ limit: 1 }).next();
|
|
6439
7128
|
if (!doc) {
|
|
6440
|
-
await _indexContent(
|
|
6441
|
-
this,
|
|
6442
|
-
level2,
|
|
6443
|
-
contentPaths,
|
|
7129
|
+
await _indexContent({
|
|
7130
|
+
database: this,
|
|
7131
|
+
level: level2,
|
|
7132
|
+
documentPaths: contentPaths,
|
|
6444
7133
|
enqueueOps,
|
|
6445
7134
|
collection,
|
|
6446
|
-
userFields.map((field) => [
|
|
7135
|
+
passwordFields: userFields.map((field) => [
|
|
6447
7136
|
...field.path,
|
|
6448
7137
|
field.passwordFieldName
|
|
6449
7138
|
])
|
|
6450
|
-
);
|
|
7139
|
+
});
|
|
6451
7140
|
}
|
|
6452
7141
|
} else {
|
|
6453
|
-
await _indexContent(
|
|
7142
|
+
await _indexContent({
|
|
7143
|
+
database: this,
|
|
7144
|
+
level,
|
|
7145
|
+
documentPaths: contentPaths,
|
|
7146
|
+
enqueueOps,
|
|
7147
|
+
collection
|
|
7148
|
+
});
|
|
6454
7149
|
}
|
|
6455
7150
|
}
|
|
6456
7151
|
);
|
|
@@ -6536,6 +7231,9 @@ var Database = class {
|
|
|
6536
7231
|
info: templateInfo
|
|
6537
7232
|
};
|
|
6538
7233
|
}
|
|
7234
|
+
/**
|
|
7235
|
+
* Clears the internal cache of the tinaSchema and the lookup file. This allows the state to be reset
|
|
7236
|
+
*/
|
|
6539
7237
|
clearCache() {
|
|
6540
7238
|
this.tinaSchema = null;
|
|
6541
7239
|
this._lookup = null;
|
|
@@ -6586,7 +7284,15 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
|
|
|
6586
7284
|
)
|
|
6587
7285
|
);
|
|
6588
7286
|
var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${collection?.format || "md"}`);
|
|
6589
|
-
var _indexContent = async (
|
|
7287
|
+
var _indexContent = async ({
|
|
7288
|
+
database,
|
|
7289
|
+
level,
|
|
7290
|
+
documentPaths,
|
|
7291
|
+
enqueueOps,
|
|
7292
|
+
collection,
|
|
7293
|
+
passwordFields,
|
|
7294
|
+
isPartialReindex
|
|
7295
|
+
}) => {
|
|
6590
7296
|
let collectionIndexDefinitions;
|
|
6591
7297
|
let collectionPath;
|
|
6592
7298
|
if (collection) {
|
|
@@ -6597,6 +7303,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
|
|
|
6597
7303
|
}
|
|
6598
7304
|
collectionPath = collection.path;
|
|
6599
7305
|
}
|
|
7306
|
+
const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
|
|
6600
7307
|
const tinaSchema = await database.getSchema();
|
|
6601
7308
|
let templateInfo = null;
|
|
6602
7309
|
if (collection) {
|
|
@@ -6618,12 +7325,61 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
|
|
|
6618
7325
|
await hashPasswordValues(aliasedData, passwordFields);
|
|
6619
7326
|
}
|
|
6620
7327
|
const normalizedPath = normalizePath(filepath);
|
|
7328
|
+
const rootSublevel = level.sublevel(
|
|
7329
|
+
CONTENT_ROOT_PREFIX,
|
|
7330
|
+
SUBLEVEL_OPTIONS
|
|
7331
|
+
);
|
|
6621
7332
|
const folderKey = folderTreeBuilder.update(
|
|
6622
7333
|
normalizedPath,
|
|
6623
7334
|
collectionPath || ""
|
|
6624
7335
|
);
|
|
7336
|
+
if (isPartialReindex) {
|
|
7337
|
+
const item = await rootSublevel.get(normalizedPath);
|
|
7338
|
+
if (item) {
|
|
7339
|
+
await database.contentLevel.batch([
|
|
7340
|
+
...makeRefOpsForDocument(
|
|
7341
|
+
normalizedPath,
|
|
7342
|
+
collection?.name,
|
|
7343
|
+
collectionReferences,
|
|
7344
|
+
item,
|
|
7345
|
+
"del",
|
|
7346
|
+
level
|
|
7347
|
+
),
|
|
7348
|
+
...makeIndexOpsForDocument(
|
|
7349
|
+
normalizedPath,
|
|
7350
|
+
collection.name,
|
|
7351
|
+
collectionIndexDefinitions,
|
|
7352
|
+
item,
|
|
7353
|
+
"del",
|
|
7354
|
+
level
|
|
7355
|
+
),
|
|
7356
|
+
// folder indices
|
|
7357
|
+
...makeIndexOpsForDocument(
|
|
7358
|
+
normalizedPath,
|
|
7359
|
+
`${collection.name}_${folderKey}`,
|
|
7360
|
+
collectionIndexDefinitions,
|
|
7361
|
+
item,
|
|
7362
|
+
"del",
|
|
7363
|
+
level
|
|
7364
|
+
),
|
|
7365
|
+
{
|
|
7366
|
+
type: "del",
|
|
7367
|
+
key: normalizedPath,
|
|
7368
|
+
sublevel: rootSublevel
|
|
7369
|
+
}
|
|
7370
|
+
]);
|
|
7371
|
+
}
|
|
7372
|
+
}
|
|
6625
7373
|
if (!isGitKeep(filepath, collection)) {
|
|
6626
7374
|
await enqueueOps([
|
|
7375
|
+
...makeRefOpsForDocument(
|
|
7376
|
+
normalizedPath,
|
|
7377
|
+
collection?.name,
|
|
7378
|
+
collectionReferences,
|
|
7379
|
+
aliasedData,
|
|
7380
|
+
"put",
|
|
7381
|
+
level
|
|
7382
|
+
),
|
|
6627
7383
|
...makeIndexOpsForDocument(
|
|
6628
7384
|
normalizedPath,
|
|
6629
7385
|
collection?.name,
|
|
@@ -6632,6 +7388,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
|
|
|
6632
7388
|
"put",
|
|
6633
7389
|
level
|
|
6634
7390
|
),
|
|
7391
|
+
// folder indexes
|
|
6635
7392
|
...makeIndexOpsForDocument(
|
|
6636
7393
|
normalizedPath,
|
|
6637
7394
|
`${collection?.name}_${folderKey}`,
|
|
@@ -6655,8 +7412,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
|
|
|
6655
7412
|
throw new TinaFetchError(`Unable to seed ${filepath}`, {
|
|
6656
7413
|
originalError: error,
|
|
6657
7414
|
file: filepath,
|
|
6658
|
-
collection: collection?.name
|
|
6659
|
-
stack: error.stack
|
|
7415
|
+
collection: collection?.name
|
|
6660
7416
|
});
|
|
6661
7417
|
}
|
|
6662
7418
|
});
|
|
@@ -6686,6 +7442,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6686
7442
|
throw new Error(`No indexDefinitions for collection ${collection.name}`);
|
|
6687
7443
|
}
|
|
6688
7444
|
}
|
|
7445
|
+
const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
|
|
6689
7446
|
const tinaSchema = await database.getSchema();
|
|
6690
7447
|
let templateInfo = null;
|
|
6691
7448
|
if (collection) {
|
|
@@ -6709,6 +7466,14 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6709
7466
|
item
|
|
6710
7467
|
) : item;
|
|
6711
7468
|
await enqueueOps([
|
|
7469
|
+
...makeRefOpsForDocument(
|
|
7470
|
+
itemKey,
|
|
7471
|
+
collection?.name,
|
|
7472
|
+
collectionReferences,
|
|
7473
|
+
aliasedData,
|
|
7474
|
+
"del",
|
|
7475
|
+
database.contentLevel
|
|
7476
|
+
),
|
|
6712
7477
|
...makeIndexOpsForDocument(
|
|
6713
7478
|
itemKey,
|
|
6714
7479
|
collection.name,
|
|
@@ -6717,6 +7482,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6717
7482
|
"del",
|
|
6718
7483
|
database.contentLevel
|
|
6719
7484
|
),
|
|
7485
|
+
// folder indexes
|
|
6720
7486
|
...makeIndexOpsForDocument(
|
|
6721
7487
|
itemKey,
|
|
6722
7488
|
`${collection?.name}_${folderKey}`,
|
|
@@ -6837,8 +7603,8 @@ import path6 from "path";
|
|
|
6837
7603
|
import normalize from "normalize-path";
|
|
6838
7604
|
var FilesystemBridge = class {
|
|
6839
7605
|
constructor(rootPath, outputPath) {
|
|
6840
|
-
this.rootPath = rootPath
|
|
6841
|
-
this.outputPath = outputPath
|
|
7606
|
+
this.rootPath = path6.resolve(rootPath);
|
|
7607
|
+
this.outputPath = outputPath ? path6.resolve(outputPath) : this.rootPath;
|
|
6842
7608
|
}
|
|
6843
7609
|
async glob(pattern, extension) {
|
|
6844
7610
|
const basePath = path6.join(this.outputPath, ...pattern.split("/"));
|
|
@@ -6850,19 +7616,19 @@ var FilesystemBridge = class {
|
|
|
6850
7616
|
}
|
|
6851
7617
|
);
|
|
6852
7618
|
const posixRootPath = normalize(this.outputPath);
|
|
6853
|
-
return items.map(
|
|
6854
|
-
|
|
6855
|
-
|
|
7619
|
+
return items.map(
|
|
7620
|
+
(item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
|
|
7621
|
+
);
|
|
6856
7622
|
}
|
|
6857
7623
|
async delete(filepath) {
|
|
6858
7624
|
await fs2.remove(path6.join(this.outputPath, filepath));
|
|
6859
7625
|
}
|
|
6860
7626
|
async get(filepath) {
|
|
6861
|
-
return fs2.
|
|
7627
|
+
return (await fs2.readFile(path6.join(this.outputPath, filepath))).toString();
|
|
6862
7628
|
}
|
|
6863
7629
|
async put(filepath, data, basePathOverride) {
|
|
6864
7630
|
const basePath = basePathOverride || this.outputPath;
|
|
6865
|
-
await fs2.
|
|
7631
|
+
await fs2.outputFile(path6.join(basePath, filepath), data);
|
|
6866
7632
|
}
|
|
6867
7633
|
};
|
|
6868
7634
|
var AuditFileSystemBridge = class extends FilesystemBridge {
|
|
@@ -6932,17 +7698,26 @@ var IsomorphicBridge = class {
|
|
|
6932
7698
|
getAuthor() {
|
|
6933
7699
|
return {
|
|
6934
7700
|
...this.author,
|
|
6935
|
-
timestamp: Math.round(new Date().getTime() / 1e3),
|
|
7701
|
+
timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
|
|
6936
7702
|
timezoneOffset: 0
|
|
6937
7703
|
};
|
|
6938
7704
|
}
|
|
6939
7705
|
getCommitter() {
|
|
6940
7706
|
return {
|
|
6941
7707
|
...this.committer,
|
|
6942
|
-
timestamp: Math.round(new Date().getTime() / 1e3),
|
|
7708
|
+
timestamp: Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3),
|
|
6943
7709
|
timezoneOffset: 0
|
|
6944
7710
|
};
|
|
6945
7711
|
}
|
|
7712
|
+
/**
|
|
7713
|
+
* Recursively populate paths matching `pattern` for the given `entry`
|
|
7714
|
+
*
|
|
7715
|
+
* @param pattern - pattern to filter paths by
|
|
7716
|
+
* @param entry - TreeEntry to start building list from
|
|
7717
|
+
* @param path - base path
|
|
7718
|
+
* @param results
|
|
7719
|
+
* @private
|
|
7720
|
+
*/
|
|
6946
7721
|
async listEntries({
|
|
6947
7722
|
pattern,
|
|
6948
7723
|
entry,
|
|
@@ -6975,6 +7750,15 @@ var IsomorphicBridge = class {
|
|
|
6975
7750
|
});
|
|
6976
7751
|
}
|
|
6977
7752
|
}
|
|
7753
|
+
/**
|
|
7754
|
+
* For the specified path, returns an object with an array containing the parts of the path (pathParts)
|
|
7755
|
+
* and an array containing the WalkerEntry objects for the path parts (pathEntries). Any null elements in the
|
|
7756
|
+
* pathEntries are placeholders for non-existent entries.
|
|
7757
|
+
*
|
|
7758
|
+
* @param path - path being resolved
|
|
7759
|
+
* @param ref - ref to resolve path entries for
|
|
7760
|
+
* @private
|
|
7761
|
+
*/
|
|
6978
7762
|
async resolvePathEntries(path7, ref) {
|
|
6979
7763
|
let pathParts = path7.split("/");
|
|
6980
7764
|
const result = await git2.walk({
|
|
@@ -7005,6 +7789,17 @@ var IsomorphicBridge = class {
|
|
|
7005
7789
|
}
|
|
7006
7790
|
return { pathParts, pathEntries };
|
|
7007
7791
|
}
|
|
7792
|
+
/**
|
|
7793
|
+
* Updates tree entry and associated parent tree entries
|
|
7794
|
+
*
|
|
7795
|
+
* @param existingOid - the existing OID
|
|
7796
|
+
* @param updatedOid - the updated OID
|
|
7797
|
+
* @param path - the path of the entry being updated
|
|
7798
|
+
* @param type - the type of the entry being updated (blob or tree)
|
|
7799
|
+
* @param pathEntries - parent path entries
|
|
7800
|
+
* @param pathParts - parent path parts
|
|
7801
|
+
* @private
|
|
7802
|
+
*/
|
|
7008
7803
|
async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
|
|
7009
7804
|
const lastIdx = pathEntries.length - 1;
|
|
7010
7805
|
const parentEntry = pathEntries[lastIdx];
|
|
@@ -7060,6 +7855,13 @@ var IsomorphicBridge = class {
|
|
|
7060
7855
|
);
|
|
7061
7856
|
}
|
|
7062
7857
|
}
|
|
7858
|
+
/**
|
|
7859
|
+
* Creates a commit for the specified tree and updates the specified ref to point to the commit
|
|
7860
|
+
*
|
|
7861
|
+
* @param treeSha - sha of the new tree
|
|
7862
|
+
* @param ref - the ref that should be updated
|
|
7863
|
+
* @private
|
|
7864
|
+
*/
|
|
7063
7865
|
async commitTree(treeSha, ref) {
|
|
7064
7866
|
const commitSha = await git2.writeCommit({
|
|
7065
7867
|
...this.isomorphicConfig,
|
|
@@ -7072,6 +7874,7 @@ var IsomorphicBridge = class {
|
|
|
7072
7874
|
})
|
|
7073
7875
|
],
|
|
7074
7876
|
message: this.commitMessage,
|
|
7877
|
+
// TODO these should be configurable
|
|
7075
7878
|
author: this.getAuthor(),
|
|
7076
7879
|
committer: this.getCommitter()
|
|
7077
7880
|
}
|
|
@@ -7309,5 +8112,5 @@ export {
|
|
|
7309
8112
|
transformDocument,
|
|
7310
8113
|
transformDocumentIntoPayload
|
|
7311
8114
|
};
|
|
7312
|
-
//! Replaces _.flattenDeep()
|
|
7313
8115
|
//! Replaces _.get()
|
|
8116
|
+
//! Replaces _.flattenDeep()
|