@tinacms/graphql 1.4.28 → 1.4.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast-builder/index.d.ts +1 -0
- package/dist/auth/utils.d.ts +22 -0
- package/dist/builder/index.d.ts +5 -0
- package/dist/database/datalayer.d.ts +1 -1
- package/dist/database/index.d.ts +36 -7
- package/dist/index.d.ts +4 -2
- package/dist/index.js +810 -194
- package/dist/index.mjs +800 -192
- package/dist/resolve.d.ts +4 -1
- package/dist/resolver/index.d.ts +18 -4
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -458,6 +458,7 @@ var astBuilder = {
|
|
|
458
458
|
CollectionDocumentUnion: "DocumentUnion",
|
|
459
459
|
Folder: "Folder",
|
|
460
460
|
String: "String",
|
|
461
|
+
Password: "Password",
|
|
461
462
|
Reference: "Reference",
|
|
462
463
|
Collection: "Collection",
|
|
463
464
|
ID: "ID",
|
|
@@ -1268,6 +1269,125 @@ var scalarDefinitions = [
|
|
|
1268
1269
|
];
|
|
1269
1270
|
var staticDefinitions = [...scalarDefinitions, interfaceDefinitions];
|
|
1270
1271
|
|
|
1272
|
+
// src/auth/utils.ts
|
|
1273
|
+
import crypto from "crypto";
|
|
1274
|
+
import scmp from "scmp";
|
|
1275
|
+
var DEFAULT_SALT_LENGTH = 32;
|
|
1276
|
+
var DEFAULT_KEY_LENGTH = 512;
|
|
1277
|
+
var DEFAULT_ITERATIONS = 25e3;
|
|
1278
|
+
var DEFAULT_DIGEST = "sha256";
|
|
1279
|
+
var generatePasswordHash = async ({
|
|
1280
|
+
password,
|
|
1281
|
+
opts: {
|
|
1282
|
+
saltLength = DEFAULT_SALT_LENGTH,
|
|
1283
|
+
keyLength = DEFAULT_KEY_LENGTH,
|
|
1284
|
+
iterations = DEFAULT_ITERATIONS,
|
|
1285
|
+
digest = DEFAULT_DIGEST
|
|
1286
|
+
} = {
|
|
1287
|
+
saltLength: DEFAULT_SALT_LENGTH,
|
|
1288
|
+
keyLength: DEFAULT_KEY_LENGTH,
|
|
1289
|
+
iterations: DEFAULT_ITERATIONS,
|
|
1290
|
+
digest: DEFAULT_DIGEST
|
|
1291
|
+
}
|
|
1292
|
+
}) => {
|
|
1293
|
+
if (!password) {
|
|
1294
|
+
throw new Error("Password is required");
|
|
1295
|
+
}
|
|
1296
|
+
if (password.length < 3) {
|
|
1297
|
+
throw new Error("Password must be at least 3 characters");
|
|
1298
|
+
}
|
|
1299
|
+
const salt = (await new Promise((resolve2, reject) => {
|
|
1300
|
+
crypto.randomBytes(saltLength, (err, saltBuffer) => {
|
|
1301
|
+
if (err) {
|
|
1302
|
+
reject(err);
|
|
1303
|
+
}
|
|
1304
|
+
resolve2(saltBuffer);
|
|
1305
|
+
});
|
|
1306
|
+
})).toString("hex");
|
|
1307
|
+
const hash = (await new Promise((resolve2, reject) => {
|
|
1308
|
+
crypto.pbkdf2(
|
|
1309
|
+
password,
|
|
1310
|
+
salt,
|
|
1311
|
+
iterations,
|
|
1312
|
+
keyLength,
|
|
1313
|
+
digest,
|
|
1314
|
+
(err, hashBuffer) => {
|
|
1315
|
+
if (err) {
|
|
1316
|
+
reject(err);
|
|
1317
|
+
}
|
|
1318
|
+
resolve2(hashBuffer);
|
|
1319
|
+
}
|
|
1320
|
+
);
|
|
1321
|
+
})).toString("hex");
|
|
1322
|
+
return `${salt}${hash}`;
|
|
1323
|
+
};
|
|
1324
|
+
var checkPasswordHash = async ({
|
|
1325
|
+
saltedHash,
|
|
1326
|
+
password,
|
|
1327
|
+
opts: {
|
|
1328
|
+
saltLength = DEFAULT_SALT_LENGTH,
|
|
1329
|
+
keyLength = DEFAULT_KEY_LENGTH,
|
|
1330
|
+
iterations = DEFAULT_ITERATIONS,
|
|
1331
|
+
digest = DEFAULT_DIGEST
|
|
1332
|
+
} = {
|
|
1333
|
+
saltLength: DEFAULT_SALT_LENGTH,
|
|
1334
|
+
keyLength: DEFAULT_KEY_LENGTH,
|
|
1335
|
+
iterations: DEFAULT_ITERATIONS,
|
|
1336
|
+
digest: DEFAULT_DIGEST
|
|
1337
|
+
}
|
|
1338
|
+
}) => {
|
|
1339
|
+
const salt = saltedHash.slice(0, saltLength * 2);
|
|
1340
|
+
const hash = saltedHash.slice(saltLength * 2);
|
|
1341
|
+
try {
|
|
1342
|
+
await new Promise((resolve2, reject) => {
|
|
1343
|
+
crypto.pbkdf2(
|
|
1344
|
+
password,
|
|
1345
|
+
salt,
|
|
1346
|
+
iterations,
|
|
1347
|
+
keyLength,
|
|
1348
|
+
digest,
|
|
1349
|
+
(err, hashBuffer) => {
|
|
1350
|
+
if (err) {
|
|
1351
|
+
reject(null);
|
|
1352
|
+
}
|
|
1353
|
+
if (scmp(hashBuffer, Buffer.from(hash, "hex"))) {
|
|
1354
|
+
resolve2();
|
|
1355
|
+
}
|
|
1356
|
+
reject(null);
|
|
1357
|
+
}
|
|
1358
|
+
);
|
|
1359
|
+
});
|
|
1360
|
+
} catch (e) {
|
|
1361
|
+
return false;
|
|
1362
|
+
}
|
|
1363
|
+
return true;
|
|
1364
|
+
};
|
|
1365
|
+
var mapUserFields = (collectable, prefix = []) => {
|
|
1366
|
+
const results = [];
|
|
1367
|
+
const passwordFields = collectable.fields?.filter((field) => field.type === "password") || [];
|
|
1368
|
+
if (passwordFields.length > 1) {
|
|
1369
|
+
throw new Error("Only one password field is allowed");
|
|
1370
|
+
}
|
|
1371
|
+
const idFields = collectable.fields?.filter((field) => field.uid) || [];
|
|
1372
|
+
if (idFields.length > 1) {
|
|
1373
|
+
throw new Error("Only one uid field is allowed");
|
|
1374
|
+
}
|
|
1375
|
+
if (passwordFields.length || idFields.length) {
|
|
1376
|
+
results.push({
|
|
1377
|
+
path: prefix,
|
|
1378
|
+
collectable,
|
|
1379
|
+
idFieldName: idFields[0]?.name,
|
|
1380
|
+
passwordFieldName: passwordFields[0]?.name
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
collectable.fields?.forEach((field) => {
|
|
1384
|
+
if (field.type === "object" && field.fields) {
|
|
1385
|
+
results.push(...mapUserFields(field, [...prefix, field.name]));
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
return results;
|
|
1389
|
+
};
|
|
1390
|
+
|
|
1271
1391
|
// src/builder/index.ts
|
|
1272
1392
|
var createBuilder = async ({
|
|
1273
1393
|
tinaSchema
|
|
@@ -1368,7 +1488,7 @@ var Builder = class {
|
|
|
1368
1488
|
type: astBuilder.TYPES.String
|
|
1369
1489
|
})
|
|
1370
1490
|
];
|
|
1371
|
-
|
|
1491
|
+
this.addToLookupMap({
|
|
1372
1492
|
type: astBuilder.TYPES.Node,
|
|
1373
1493
|
resolveType: "nodeDocument"
|
|
1374
1494
|
});
|
|
@@ -1511,7 +1631,7 @@ var Builder = class {
|
|
|
1511
1631
|
type: astBuilder.TYPES.String
|
|
1512
1632
|
})
|
|
1513
1633
|
];
|
|
1514
|
-
|
|
1634
|
+
this.addToLookupMap({
|
|
1515
1635
|
type: type.name.value,
|
|
1516
1636
|
resolveType: "collectionDocument",
|
|
1517
1637
|
collection: collection.name,
|
|
@@ -1525,6 +1645,43 @@ var Builder = class {
|
|
|
1525
1645
|
required: true
|
|
1526
1646
|
});
|
|
1527
1647
|
};
|
|
1648
|
+
this.authenticationCollectionDocument = async (collection) => {
|
|
1649
|
+
const name = "authenticate";
|
|
1650
|
+
const type = await this._buildAuthDocumentType(collection);
|
|
1651
|
+
const args = [
|
|
1652
|
+
astBuilder.InputValueDefinition({
|
|
1653
|
+
name: "sub",
|
|
1654
|
+
type: astBuilder.TYPES.String,
|
|
1655
|
+
required: true
|
|
1656
|
+
}),
|
|
1657
|
+
astBuilder.InputValueDefinition({
|
|
1658
|
+
name: "password",
|
|
1659
|
+
type: astBuilder.TYPES.String,
|
|
1660
|
+
required: true
|
|
1661
|
+
})
|
|
1662
|
+
];
|
|
1663
|
+
return astBuilder.FieldDefinition({ type, name, args, required: false });
|
|
1664
|
+
};
|
|
1665
|
+
this.updatePasswordMutation = async (collection) => {
|
|
1666
|
+
return astBuilder.FieldDefinition({
|
|
1667
|
+
type: astBuilder.TYPES.Boolean,
|
|
1668
|
+
name: "updatePassword",
|
|
1669
|
+
required: true,
|
|
1670
|
+
args: [
|
|
1671
|
+
astBuilder.InputValueDefinition({
|
|
1672
|
+
name: "password",
|
|
1673
|
+
required: true,
|
|
1674
|
+
type: astBuilder.TYPES.String
|
|
1675
|
+
})
|
|
1676
|
+
]
|
|
1677
|
+
});
|
|
1678
|
+
};
|
|
1679
|
+
this.authorizationCollectionDocument = async (collection) => {
|
|
1680
|
+
const name = "authorize";
|
|
1681
|
+
const type = await this._buildAuthDocumentType(collection);
|
|
1682
|
+
const args = [];
|
|
1683
|
+
return astBuilder.FieldDefinition({ type, name, args, required: false });
|
|
1684
|
+
};
|
|
1528
1685
|
this.collectionFragment = async (collection) => {
|
|
1529
1686
|
const name = NAMER.dataTypeName(collection.namespace);
|
|
1530
1687
|
const fragmentName = NAMER.fragmentName(collection.namespace);
|
|
@@ -1567,6 +1724,29 @@ var Builder = class {
|
|
|
1567
1724
|
case "boolean":
|
|
1568
1725
|
case "rich-text":
|
|
1569
1726
|
return astBuilder.FieldNodeDefinition(field);
|
|
1727
|
+
case "password":
|
|
1728
|
+
const passwordValue = await this._buildFieldNodeForFragments(
|
|
1729
|
+
{
|
|
1730
|
+
name: "value",
|
|
1731
|
+
namespace: [...field.namespace, "value"],
|
|
1732
|
+
type: "string",
|
|
1733
|
+
required: true
|
|
1734
|
+
},
|
|
1735
|
+
depth
|
|
1736
|
+
);
|
|
1737
|
+
const passwordChangeRequired = await this._buildFieldNodeForFragments(
|
|
1738
|
+
{
|
|
1739
|
+
name: "passwordChangeRequired",
|
|
1740
|
+
namespace: [...field.namespace, "passwordChangeRequired"],
|
|
1741
|
+
type: "boolean",
|
|
1742
|
+
required: false
|
|
1743
|
+
},
|
|
1744
|
+
depth
|
|
1745
|
+
);
|
|
1746
|
+
return astBuilder.FieldWithSelectionSetDefinition({
|
|
1747
|
+
name: field.name,
|
|
1748
|
+
selections: filterSelections([passwordValue, passwordChangeRequired])
|
|
1749
|
+
});
|
|
1570
1750
|
case "object":
|
|
1571
1751
|
if (field.fields?.length > 0) {
|
|
1572
1752
|
const selections2 = [];
|
|
@@ -1780,6 +1960,34 @@ var Builder = class {
|
|
|
1780
1960
|
]
|
|
1781
1961
|
});
|
|
1782
1962
|
};
|
|
1963
|
+
this._buildAuthDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
|
|
1964
|
+
const usersFields = mapUserFields(collection, []);
|
|
1965
|
+
if (!usersFields.length) {
|
|
1966
|
+
throw new Error("Auth collection must have a user field");
|
|
1967
|
+
}
|
|
1968
|
+
if (usersFields.length > 1) {
|
|
1969
|
+
throw new Error("Auth collection cannot have more than one user field");
|
|
1970
|
+
}
|
|
1971
|
+
const usersField = usersFields[0].collectable;
|
|
1972
|
+
const documentTypeName = NAMER.documentTypeName(usersField.namespace);
|
|
1973
|
+
const templateInfo = this.tinaSchema.getTemplatesForCollectable(usersField);
|
|
1974
|
+
if (templateInfo.type === "union") {
|
|
1975
|
+
throw new Error("Auth collection user field cannot be a union");
|
|
1976
|
+
}
|
|
1977
|
+
const fields = templateInfo.template.fields;
|
|
1978
|
+
const templateFields = await sequential(fields, async (field) => {
|
|
1979
|
+
return this._buildDataField(field);
|
|
1980
|
+
});
|
|
1981
|
+
return astBuilder.ObjectTypeDefinition({
|
|
1982
|
+
name: documentTypeName + suffix,
|
|
1983
|
+
interfaces: [
|
|
1984
|
+
astBuilder.NamedType({ name: astBuilder.TYPES.Node }),
|
|
1985
|
+
astBuilder.NamedType({ name: astBuilder.TYPES.Document }),
|
|
1986
|
+
...extraInterfaces
|
|
1987
|
+
],
|
|
1988
|
+
fields: [...templateFields]
|
|
1989
|
+
});
|
|
1990
|
+
};
|
|
1783
1991
|
this._filterCollectionDocumentType = async (collection) => {
|
|
1784
1992
|
const t = this.tinaSchema.getTemplatesForCollectable(collection);
|
|
1785
1993
|
if (t.type === "union") {
|
|
@@ -2038,9 +2246,7 @@ var Builder = class {
|
|
|
2038
2246
|
const filter = await this._connectionFilterBuilder({
|
|
2039
2247
|
fieldName: field.name,
|
|
2040
2248
|
namespace: field.namespace,
|
|
2041
|
-
collections:
|
|
2042
|
-
field.collections
|
|
2043
|
-
)
|
|
2249
|
+
collections: this.tinaSchema.getCollectionsByName(field.collections)
|
|
2044
2250
|
});
|
|
2045
2251
|
return astBuilder.InputValueDefinition({
|
|
2046
2252
|
name: field.name,
|
|
@@ -2073,6 +2279,8 @@ var Builder = class {
|
|
|
2073
2279
|
list: field.list,
|
|
2074
2280
|
type: astBuilder.TYPES.String
|
|
2075
2281
|
});
|
|
2282
|
+
case "password":
|
|
2283
|
+
return this._buildPasswordMutation(field);
|
|
2076
2284
|
case "object":
|
|
2077
2285
|
return astBuilder.InputValueDefinition({
|
|
2078
2286
|
name: field.name,
|
|
@@ -2107,6 +2315,27 @@ var Builder = class {
|
|
|
2107
2315
|
)
|
|
2108
2316
|
});
|
|
2109
2317
|
};
|
|
2318
|
+
this._buildPasswordMutation = async (field) => {
|
|
2319
|
+
return astBuilder.InputValueDefinition({
|
|
2320
|
+
name: field.name,
|
|
2321
|
+
list: field.list,
|
|
2322
|
+
type: astBuilder.InputObjectTypeDefinition({
|
|
2323
|
+
name: NAMER.dataMutationTypeName(field.namespace),
|
|
2324
|
+
fields: [
|
|
2325
|
+
astBuilder.InputValueDefinition({
|
|
2326
|
+
name: "value",
|
|
2327
|
+
type: astBuilder.TYPES.String,
|
|
2328
|
+
required: false
|
|
2329
|
+
}),
|
|
2330
|
+
astBuilder.InputValueDefinition({
|
|
2331
|
+
name: "passwordChangeRequired",
|
|
2332
|
+
type: astBuilder.TYPES.Boolean,
|
|
2333
|
+
required: true
|
|
2334
|
+
})
|
|
2335
|
+
]
|
|
2336
|
+
})
|
|
2337
|
+
});
|
|
2338
|
+
};
|
|
2110
2339
|
this._buildUpdateDocumentMutationParams = async (field) => {
|
|
2111
2340
|
const fields = await sequential(
|
|
2112
2341
|
this.tinaSchema.getCollectionsByName(field.collections),
|
|
@@ -2271,6 +2500,29 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
|
|
|
2271
2500
|
required: field.required,
|
|
2272
2501
|
type: astBuilder.TYPES.Scalar(field.type)
|
|
2273
2502
|
});
|
|
2503
|
+
case "password":
|
|
2504
|
+
return astBuilder.FieldDefinition({
|
|
2505
|
+
name: field.name,
|
|
2506
|
+
list: field.list,
|
|
2507
|
+
required: field.required,
|
|
2508
|
+
type: astBuilder.ObjectTypeDefinition({
|
|
2509
|
+
name: NAMER.dataTypeName(field.namespace),
|
|
2510
|
+
fields: [
|
|
2511
|
+
await this._buildDataField({
|
|
2512
|
+
name: "value",
|
|
2513
|
+
namespace: [...field.namespace, "value"],
|
|
2514
|
+
type: "string",
|
|
2515
|
+
required: true
|
|
2516
|
+
}),
|
|
2517
|
+
await this._buildDataField({
|
|
2518
|
+
name: "passwordChangeRequired",
|
|
2519
|
+
namespace: [...field.namespace, "passwordChangeRequired"],
|
|
2520
|
+
type: "boolean",
|
|
2521
|
+
required: false
|
|
2522
|
+
})
|
|
2523
|
+
]
|
|
2524
|
+
})
|
|
2525
|
+
});
|
|
2274
2526
|
case "object":
|
|
2275
2527
|
return astBuilder.FieldDefinition({
|
|
2276
2528
|
name: field.name,
|
|
@@ -2395,7 +2647,8 @@ var FIELD_TYPES = [
|
|
|
2395
2647
|
"image",
|
|
2396
2648
|
"reference",
|
|
2397
2649
|
"object",
|
|
2398
|
-
"rich-text"
|
|
2650
|
+
"rich-text",
|
|
2651
|
+
"password"
|
|
2399
2652
|
];
|
|
2400
2653
|
var validateSchema = async (schema) => {
|
|
2401
2654
|
const schema2 = addNamespaceToSchema(
|
|
@@ -2535,7 +2788,7 @@ var validateField = async (field) => {
|
|
|
2535
2788
|
// package.json
|
|
2536
2789
|
var package_default = {
|
|
2537
2790
|
name: "@tinacms/graphql",
|
|
2538
|
-
version: "1.4.
|
|
2791
|
+
version: "1.4.30",
|
|
2539
2792
|
main: "dist/index.js",
|
|
2540
2793
|
module: "dist/index.mjs",
|
|
2541
2794
|
typings: "dist/index.d.ts",
|
|
@@ -2590,6 +2843,7 @@ var package_default = {
|
|
|
2590
2843
|
micromatch: "4.0.5",
|
|
2591
2844
|
"normalize-path": "^3.0.0",
|
|
2592
2845
|
"readable-stream": "^4.3.0",
|
|
2846
|
+
scmp: "^2.1.0",
|
|
2593
2847
|
yup: "^0.32.9"
|
|
2594
2848
|
},
|
|
2595
2849
|
publishConfig: {
|
|
@@ -2775,6 +3029,17 @@ var _buildSchema = async (builder, tinaSchema) => {
|
|
|
2775
3029
|
);
|
|
2776
3030
|
await sequential(collections, async (collection) => {
|
|
2777
3031
|
queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
|
|
3032
|
+
if (collection.isAuthCollection) {
|
|
3033
|
+
queryTypeDefinitionFields.push(
|
|
3034
|
+
await builder.authenticationCollectionDocument(collection)
|
|
3035
|
+
);
|
|
3036
|
+
queryTypeDefinitionFields.push(
|
|
3037
|
+
await builder.authorizationCollectionDocument(collection)
|
|
3038
|
+
);
|
|
3039
|
+
mutationTypeDefinitionFields.push(
|
|
3040
|
+
await builder.updatePasswordMutation(collection)
|
|
3041
|
+
);
|
|
3042
|
+
}
|
|
2778
3043
|
mutationTypeDefinitionFields.push(
|
|
2779
3044
|
await builder.updateCollectionDocumentMutation(collection)
|
|
2780
3045
|
);
|
|
@@ -4081,6 +4346,12 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
|
|
|
4081
4346
|
accumulator[field.name] = value;
|
|
4082
4347
|
}
|
|
4083
4348
|
break;
|
|
4349
|
+
case "password":
|
|
4350
|
+
accumulator[field.name] = {
|
|
4351
|
+
value: void 0,
|
|
4352
|
+
passwordChangeRequired: value["passwordChangeRequired"] ?? false
|
|
4353
|
+
};
|
|
4354
|
+
break;
|
|
4084
4355
|
case "image":
|
|
4085
4356
|
accumulator[field.name] = resolveMediaRelativeToCloud(
|
|
4086
4357
|
value,
|
|
@@ -4114,7 +4385,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
|
|
|
4114
4385
|
(yup3) => yup3.array().of(yup3.object().required())
|
|
4115
4386
|
);
|
|
4116
4387
|
accumulator[field.name] = await sequential(value, async (item) => {
|
|
4117
|
-
const template =
|
|
4388
|
+
const template = tinaSchema.getTemplateForData({
|
|
4118
4389
|
data: item,
|
|
4119
4390
|
collection: {
|
|
4120
4391
|
namespace,
|
|
@@ -4142,7 +4413,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
|
|
|
4142
4413
|
if (!value) {
|
|
4143
4414
|
return;
|
|
4144
4415
|
}
|
|
4145
|
-
const template =
|
|
4416
|
+
const template = tinaSchema.getTemplateForData({
|
|
4146
4417
|
data: value,
|
|
4147
4418
|
collection: {
|
|
4148
4419
|
namespace,
|
|
@@ -4305,43 +4576,71 @@ var Resolver = class {
|
|
|
4305
4576
|
}
|
|
4306
4577
|
await this.database.delete(fullPath);
|
|
4307
4578
|
};
|
|
4308
|
-
this.buildObjectMutations = (fieldValue, field) => {
|
|
4579
|
+
this.buildObjectMutations = async (fieldValue, field, existingData) => {
|
|
4309
4580
|
if (field.fields) {
|
|
4310
4581
|
const objectTemplate = field;
|
|
4311
4582
|
if (Array.isArray(fieldValue)) {
|
|
4312
|
-
|
|
4313
|
-
|
|
4583
|
+
const idField = objectTemplate.fields.find((field2) => field2.uid);
|
|
4584
|
+
if (idField) {
|
|
4585
|
+
const ids = fieldValue.map((d) => d[idField.name]);
|
|
4586
|
+
const duplicateIds = ids.filter(
|
|
4587
|
+
(id, index) => ids.indexOf(id) !== index
|
|
4588
|
+
);
|
|
4589
|
+
if (duplicateIds.length > 0) {
|
|
4590
|
+
throw new Error(
|
|
4591
|
+
`Duplicate ids found in array for field marked as identifier: ${idField.name}`
|
|
4592
|
+
);
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
return Promise.all(
|
|
4596
|
+
fieldValue.map(
|
|
4597
|
+
async (item) => {
|
|
4598
|
+
return this.buildFieldMutations(
|
|
4599
|
+
item,
|
|
4600
|
+
objectTemplate,
|
|
4601
|
+
idField && existingData && existingData?.find(
|
|
4602
|
+
(d) => d[idField.name] === item[idField.name]
|
|
4603
|
+
)
|
|
4604
|
+
);
|
|
4605
|
+
}
|
|
4606
|
+
)
|
|
4314
4607
|
);
|
|
4315
4608
|
} else {
|
|
4316
4609
|
return this.buildFieldMutations(
|
|
4317
4610
|
fieldValue,
|
|
4318
|
-
objectTemplate
|
|
4611
|
+
objectTemplate,
|
|
4612
|
+
existingData
|
|
4319
4613
|
);
|
|
4320
4614
|
}
|
|
4321
4615
|
}
|
|
4322
4616
|
if (field.templates) {
|
|
4323
4617
|
if (Array.isArray(fieldValue)) {
|
|
4324
|
-
return
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4618
|
+
return Promise.all(
|
|
4619
|
+
fieldValue.map(async (item) => {
|
|
4620
|
+
if (typeof item === "string") {
|
|
4621
|
+
throw new Error(
|
|
4622
|
+
`Expected object for template value for field ${field.name}`
|
|
4623
|
+
);
|
|
4624
|
+
}
|
|
4625
|
+
const templates = field.templates.map((templateOrTemplateName) => {
|
|
4626
|
+
return templateOrTemplateName;
|
|
4627
|
+
});
|
|
4628
|
+
const [templateName] = Object.entries(item)[0];
|
|
4629
|
+
const template = templates.find(
|
|
4630
|
+
(template2) => template2.name === templateName
|
|
4328
4631
|
);
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
}
|
|
4340
|
-
|
|
4341
|
-
...this.buildFieldMutations(item[template.name], template),
|
|
4342
|
-
_template: template.name
|
|
4343
|
-
};
|
|
4344
|
-
});
|
|
4632
|
+
if (!template) {
|
|
4633
|
+
throw new Error(`Expected to find template ${templateName}`);
|
|
4634
|
+
}
|
|
4635
|
+
return {
|
|
4636
|
+
...await this.buildFieldMutations(
|
|
4637
|
+
item[template.name],
|
|
4638
|
+
template
|
|
4639
|
+
),
|
|
4640
|
+
_template: template.name
|
|
4641
|
+
};
|
|
4642
|
+
})
|
|
4643
|
+
);
|
|
4345
4644
|
} else {
|
|
4346
4645
|
if (typeof fieldValue === "string") {
|
|
4347
4646
|
throw new Error(
|
|
@@ -4359,7 +4658,10 @@ var Resolver = class {
|
|
|
4359
4658
|
throw new Error(`Expected to find template ${templateName}`);
|
|
4360
4659
|
}
|
|
4361
4660
|
return {
|
|
4362
|
-
...this.buildFieldMutations(
|
|
4661
|
+
...await this.buildFieldMutations(
|
|
4662
|
+
fieldValue[template.name],
|
|
4663
|
+
template
|
|
4664
|
+
),
|
|
4363
4665
|
_template: template.name
|
|
4364
4666
|
};
|
|
4365
4667
|
}
|
|
@@ -4398,7 +4700,7 @@ var Resolver = class {
|
|
|
4398
4700
|
}
|
|
4399
4701
|
return this.getDocument(realPath);
|
|
4400
4702
|
}
|
|
4401
|
-
const params = this.buildObjectMutations(
|
|
4703
|
+
const params = await this.buildObjectMutations(
|
|
4402
4704
|
args.params[collection.name],
|
|
4403
4705
|
collection
|
|
4404
4706
|
);
|
|
@@ -4420,9 +4722,10 @@ var Resolver = class {
|
|
|
4420
4722
|
switch (templateInfo.type) {
|
|
4421
4723
|
case "object":
|
|
4422
4724
|
if (params2) {
|
|
4423
|
-
const values = this.buildFieldMutations(
|
|
4725
|
+
const values = await this.buildFieldMutations(
|
|
4424
4726
|
params2,
|
|
4425
|
-
templateInfo.template
|
|
4727
|
+
templateInfo.template,
|
|
4728
|
+
doc?._rawData
|
|
4426
4729
|
);
|
|
4427
4730
|
await this.database.put(
|
|
4428
4731
|
realPath,
|
|
@@ -4442,7 +4745,11 @@ var Resolver = class {
|
|
|
4442
4745
|
}
|
|
4443
4746
|
const values = {
|
|
4444
4747
|
...oldDoc,
|
|
4445
|
-
...this.buildFieldMutations(
|
|
4748
|
+
...await this.buildFieldMutations(
|
|
4749
|
+
templateParams,
|
|
4750
|
+
template,
|
|
4751
|
+
doc?._rawData
|
|
4752
|
+
),
|
|
4446
4753
|
_template: lastItem(template.namespace)
|
|
4447
4754
|
};
|
|
4448
4755
|
await this.database.put(realPath, values, collection.name);
|
|
@@ -4451,9 +4758,10 @@ var Resolver = class {
|
|
|
4451
4758
|
}
|
|
4452
4759
|
return this.getDocument(realPath);
|
|
4453
4760
|
}
|
|
4454
|
-
const params = this.buildObjectMutations(
|
|
4761
|
+
const params = await this.buildObjectMutations(
|
|
4455
4762
|
isCollectionSpecific ? args.params : args.params[collection.name],
|
|
4456
|
-
collection
|
|
4763
|
+
collection,
|
|
4764
|
+
doc?._rawData
|
|
4457
4765
|
);
|
|
4458
4766
|
await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
|
|
4459
4767
|
return this.getDocument(realPath);
|
|
@@ -4682,13 +4990,23 @@ var Resolver = class {
|
|
|
4682
4990
|
}
|
|
4683
4991
|
};
|
|
4684
4992
|
};
|
|
4685
|
-
this.buildFieldMutations = (fieldParams, template) => {
|
|
4993
|
+
this.buildFieldMutations = async (fieldParams, template, existingData) => {
|
|
4686
4994
|
const accum = {};
|
|
4687
|
-
|
|
4995
|
+
for (const passwordField of template.fields.filter(
|
|
4996
|
+
(f) => f.type === "password"
|
|
4997
|
+
)) {
|
|
4998
|
+
if (!fieldParams[passwordField.name]["value"]) {
|
|
4999
|
+
fieldParams[passwordField.name] = {
|
|
5000
|
+
...fieldParams[passwordField.name],
|
|
5001
|
+
value: ""
|
|
5002
|
+
};
|
|
5003
|
+
}
|
|
5004
|
+
}
|
|
5005
|
+
for (const [fieldName, fieldValue] of Object.entries(fieldParams)) {
|
|
4688
5006
|
if (Array.isArray(fieldValue)) {
|
|
4689
5007
|
if (fieldValue.length === 0) {
|
|
4690
5008
|
accum[fieldName] = [];
|
|
4691
|
-
|
|
5009
|
+
break;
|
|
4692
5010
|
}
|
|
4693
5011
|
}
|
|
4694
5012
|
const field = template.fields.find((field2) => field2.name === fieldName);
|
|
@@ -4712,7 +5030,31 @@ var Resolver = class {
|
|
|
4712
5030
|
);
|
|
4713
5031
|
break;
|
|
4714
5032
|
case "object":
|
|
4715
|
-
accum[fieldName] = this.buildObjectMutations(
|
|
5033
|
+
accum[fieldName] = await this.buildObjectMutations(
|
|
5034
|
+
fieldValue,
|
|
5035
|
+
field,
|
|
5036
|
+
existingData?.[fieldName]
|
|
5037
|
+
);
|
|
5038
|
+
break;
|
|
5039
|
+
case "password":
|
|
5040
|
+
if (typeof fieldValue !== "object") {
|
|
5041
|
+
throw new Error(
|
|
5042
|
+
`Expected to find object for password field ${fieldName}. Found ${typeof accum[fieldName]}`
|
|
5043
|
+
);
|
|
5044
|
+
}
|
|
5045
|
+
if (fieldValue["value"]) {
|
|
5046
|
+
accum[fieldName] = {
|
|
5047
|
+
...fieldValue,
|
|
5048
|
+
value: await generatePasswordHash({
|
|
5049
|
+
password: fieldValue["value"]
|
|
5050
|
+
})
|
|
5051
|
+
};
|
|
5052
|
+
} else {
|
|
5053
|
+
accum[fieldName] = {
|
|
5054
|
+
...fieldValue,
|
|
5055
|
+
value: existingData?.[fieldName]?.["value"]
|
|
5056
|
+
};
|
|
5057
|
+
}
|
|
4716
5058
|
break;
|
|
4717
5059
|
case "rich-text":
|
|
4718
5060
|
accum[fieldName] = stringifyMDX(
|
|
@@ -4731,7 +5073,7 @@ var Resolver = class {
|
|
|
4731
5073
|
default:
|
|
4732
5074
|
throw new Error(`No mutation builder for field type ${field.type}`);
|
|
4733
5075
|
}
|
|
4734
|
-
}
|
|
5076
|
+
}
|
|
4735
5077
|
return accum;
|
|
4736
5078
|
};
|
|
4737
5079
|
this.buildParams = (args) => {
|
|
@@ -4801,6 +5143,9 @@ var resolveDateInput = (value) => {
|
|
|
4801
5143
|
return date;
|
|
4802
5144
|
};
|
|
4803
5145
|
|
|
5146
|
+
// src/resolve.ts
|
|
5147
|
+
import _4 from "lodash";
|
|
5148
|
+
|
|
4804
5149
|
// src/error.ts
|
|
4805
5150
|
import { GraphQLError as GraphQLError3 } from "graphql";
|
|
4806
5151
|
var NotFoundError = class extends GraphQLError3 {
|
|
@@ -4818,7 +5163,8 @@ var resolve = async ({
|
|
|
4818
5163
|
database,
|
|
4819
5164
|
silenceErrors,
|
|
4820
5165
|
verbose,
|
|
4821
|
-
isAudit
|
|
5166
|
+
isAudit,
|
|
5167
|
+
ctxUser
|
|
4822
5168
|
}) => {
|
|
4823
5169
|
try {
|
|
4824
5170
|
const verboseValue = verbose ?? true;
|
|
@@ -4832,7 +5178,7 @@ var resolve = async ({
|
|
|
4832
5178
|
schema: tinaConfig,
|
|
4833
5179
|
flags: tinaConfig?.meta?.flags
|
|
4834
5180
|
});
|
|
4835
|
-
const resolver =
|
|
5181
|
+
const resolver = createResolver({
|
|
4836
5182
|
config,
|
|
4837
5183
|
database,
|
|
4838
5184
|
tinaSchema,
|
|
@@ -4907,6 +5253,121 @@ var resolve = async ({
|
|
|
4907
5253
|
);
|
|
4908
5254
|
}
|
|
4909
5255
|
}
|
|
5256
|
+
if (info.fieldName === "authenticate" || info.fieldName === "authorize") {
|
|
5257
|
+
const sub = args.sub || ctxUser?.sub;
|
|
5258
|
+
const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
|
|
5259
|
+
if (!collection) {
|
|
5260
|
+
throw new Error(`Auth collection not found`);
|
|
5261
|
+
}
|
|
5262
|
+
const userFields = mapUserFields(collection, ["_rawData"]);
|
|
5263
|
+
if (!userFields.length) {
|
|
5264
|
+
throw new Error(
|
|
5265
|
+
`No user field found in collection ${collection.name}`
|
|
5266
|
+
);
|
|
5267
|
+
}
|
|
5268
|
+
if (userFields.length > 1) {
|
|
5269
|
+
throw new Error(
|
|
5270
|
+
`Multiple user fields found in collection ${collection.name}`
|
|
5271
|
+
);
|
|
5272
|
+
}
|
|
5273
|
+
const userField = userFields[0];
|
|
5274
|
+
const realPath = `${collection.path}/index.json`;
|
|
5275
|
+
const userDoc = await resolver.getDocument(realPath);
|
|
5276
|
+
const users = _4.get(userDoc, userField.path);
|
|
5277
|
+
if (!users) {
|
|
5278
|
+
throw new Error("No users found");
|
|
5279
|
+
}
|
|
5280
|
+
const { idFieldName, passwordFieldName } = userField;
|
|
5281
|
+
if (!idFieldName) {
|
|
5282
|
+
throw new Error("No uid field found on user field");
|
|
5283
|
+
}
|
|
5284
|
+
const user = users.find((u) => u[idFieldName] === sub);
|
|
5285
|
+
if (!user) {
|
|
5286
|
+
return null;
|
|
5287
|
+
}
|
|
5288
|
+
if (info.fieldName === "authenticate") {
|
|
5289
|
+
const saltedHash = _4.get(user, [passwordFieldName || "", "value"]);
|
|
5290
|
+
if (!saltedHash) {
|
|
5291
|
+
throw new Error("No password field found on user field");
|
|
5292
|
+
}
|
|
5293
|
+
const matches = await checkPasswordHash({
|
|
5294
|
+
saltedHash,
|
|
5295
|
+
password: args.password
|
|
5296
|
+
});
|
|
5297
|
+
if (matches) {
|
|
5298
|
+
return user;
|
|
5299
|
+
} else {
|
|
5300
|
+
return null;
|
|
5301
|
+
}
|
|
5302
|
+
} else {
|
|
5303
|
+
return user;
|
|
5304
|
+
}
|
|
5305
|
+
}
|
|
5306
|
+
if (info.fieldName === "updatePassword") {
|
|
5307
|
+
if (!ctxUser?.sub) {
|
|
5308
|
+
throw new Error("Not authorized");
|
|
5309
|
+
}
|
|
5310
|
+
if (!args.password) {
|
|
5311
|
+
throw new Error("No password provided");
|
|
5312
|
+
}
|
|
5313
|
+
const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
|
|
5314
|
+
if (!collection) {
|
|
5315
|
+
throw new Error(`Auth collection not found`);
|
|
5316
|
+
}
|
|
5317
|
+
const userFields = mapUserFields(collection, ["_rawData"]);
|
|
5318
|
+
if (!userFields.length) {
|
|
5319
|
+
throw new Error(
|
|
5320
|
+
`No user field found in collection ${collection.name}`
|
|
5321
|
+
);
|
|
5322
|
+
}
|
|
5323
|
+
if (userFields.length > 1) {
|
|
5324
|
+
throw new Error(
|
|
5325
|
+
`Multiple user fields found in collection ${collection.name}`
|
|
5326
|
+
);
|
|
5327
|
+
}
|
|
5328
|
+
const userField = userFields[0];
|
|
5329
|
+
const realPath = `${collection.path}/index.json`;
|
|
5330
|
+
const userDoc = await resolver.getDocument(realPath);
|
|
5331
|
+
const users = _4.get(userDoc, userField.path);
|
|
5332
|
+
if (!users) {
|
|
5333
|
+
throw new Error("No users found");
|
|
5334
|
+
}
|
|
5335
|
+
const { idFieldName, passwordFieldName } = userField;
|
|
5336
|
+
const user = users.find((u) => u[idFieldName] === ctxUser.sub);
|
|
5337
|
+
if (!user) {
|
|
5338
|
+
throw new Error("Not authorized");
|
|
5339
|
+
}
|
|
5340
|
+
user[passwordFieldName] = {
|
|
5341
|
+
value: args.password,
|
|
5342
|
+
passwordChangeRequired: false
|
|
5343
|
+
};
|
|
5344
|
+
const params = {};
|
|
5345
|
+
_4.set(
|
|
5346
|
+
params,
|
|
5347
|
+
userField.path.slice(1),
|
|
5348
|
+
users.map((u) => {
|
|
5349
|
+
if (user[idFieldName] === u[idFieldName]) {
|
|
5350
|
+
return user;
|
|
5351
|
+
} else {
|
|
5352
|
+
return {
|
|
5353
|
+
...u,
|
|
5354
|
+
[passwordFieldName]: {
|
|
5355
|
+
...u[passwordFieldName],
|
|
5356
|
+
value: ""
|
|
5357
|
+
}
|
|
5358
|
+
};
|
|
5359
|
+
}
|
|
5360
|
+
})
|
|
5361
|
+
);
|
|
5362
|
+
await resolver.updateResolveDocument({
|
|
5363
|
+
collection,
|
|
5364
|
+
args: { params },
|
|
5365
|
+
realPath,
|
|
5366
|
+
isCollectionSpecific: true,
|
|
5367
|
+
isAddPendingDocument: false
|
|
5368
|
+
});
|
|
5369
|
+
return true;
|
|
5370
|
+
}
|
|
4910
5371
|
if (!lookup) {
|
|
4911
5372
|
return value;
|
|
4912
5373
|
}
|
|
@@ -5047,12 +5508,78 @@ var resolve = async ({
|
|
|
5047
5508
|
}
|
|
5048
5509
|
};
|
|
5049
5510
|
|
|
5511
|
+
// src/level/tinaLevel.ts
|
|
5512
|
+
import { ManyLevelGuest } from "many-level";
|
|
5513
|
+
import { pipeline } from "readable-stream";
|
|
5514
|
+
import { connect } from "net";
|
|
5515
|
+
var TinaLevelClient = class extends ManyLevelGuest {
|
|
5516
|
+
constructor(port) {
|
|
5517
|
+
super();
|
|
5518
|
+
this._connected = false;
|
|
5519
|
+
this.port = port || 9e3;
|
|
5520
|
+
}
|
|
5521
|
+
openConnection() {
|
|
5522
|
+
if (this._connected)
|
|
5523
|
+
return;
|
|
5524
|
+
const socket = connect(this.port);
|
|
5525
|
+
pipeline(socket, this.createRpcStream(), socket, () => {
|
|
5526
|
+
this._connected = false;
|
|
5527
|
+
});
|
|
5528
|
+
this._connected = true;
|
|
5529
|
+
}
|
|
5530
|
+
};
|
|
5531
|
+
|
|
5050
5532
|
// src/database/index.ts
|
|
5051
5533
|
import path4 from "path";
|
|
5052
5534
|
import { GraphQLError as GraphQLError5 } from "graphql";
|
|
5053
5535
|
import micromatch2 from "micromatch";
|
|
5054
5536
|
import sha2 from "js-sha1";
|
|
5537
|
+
import _5 from "lodash";
|
|
5538
|
+
var createLocalDatabase = (config) => {
|
|
5539
|
+
const level = new TinaLevelClient(config?.port);
|
|
5540
|
+
level.openConnection();
|
|
5541
|
+
const fsBridge = new FilesystemBridge(config?.rootPath || process.cwd());
|
|
5542
|
+
return new Database({
|
|
5543
|
+
bridge: fsBridge,
|
|
5544
|
+
...config || {},
|
|
5545
|
+
level
|
|
5546
|
+
});
|
|
5547
|
+
};
|
|
5055
5548
|
var createDatabase = (config) => {
|
|
5549
|
+
if (config.onPut && config.onDelete) {
|
|
5550
|
+
console.warn(
|
|
5551
|
+
"onPut and onDelete are deprecated. Please use gitProvider.onPut and gitProvider.onDelete instead."
|
|
5552
|
+
);
|
|
5553
|
+
}
|
|
5554
|
+
if (config.level) {
|
|
5555
|
+
console.warn("level is deprecated. Please use databaseAdapter instead.");
|
|
5556
|
+
}
|
|
5557
|
+
if (config.onPut && config.onDelete && config.level && !config.databaseAdapter && !config.gitProvider) {
|
|
5558
|
+
return new Database({
|
|
5559
|
+
...config,
|
|
5560
|
+
level: config.level
|
|
5561
|
+
});
|
|
5562
|
+
}
|
|
5563
|
+
if (!config.gitProvider) {
|
|
5564
|
+
throw new Error(
|
|
5565
|
+
"createDatabase requires a gitProvider. Please provide a gitProvider."
|
|
5566
|
+
);
|
|
5567
|
+
}
|
|
5568
|
+
if (!config.databaseAdapter) {
|
|
5569
|
+
throw new Error(
|
|
5570
|
+
"createDatabase requires a databaseAdapter. Please provide a databaseAdapter."
|
|
5571
|
+
);
|
|
5572
|
+
}
|
|
5573
|
+
return new Database({
|
|
5574
|
+
...config,
|
|
5575
|
+
bridge: config.bridge,
|
|
5576
|
+
level: config.databaseAdapter,
|
|
5577
|
+
onPut: config.gitProvider.onPut.bind(config.gitProvider),
|
|
5578
|
+
onDelete: config.gitProvider.onDelete.bind(config.gitProvider),
|
|
5579
|
+
namespace: config.namespace || "tinacms"
|
|
5580
|
+
});
|
|
5581
|
+
};
|
|
5582
|
+
var createDatabaseInternal = (config) => {
|
|
5056
5583
|
return new Database({
|
|
5057
5584
|
...config,
|
|
5058
5585
|
bridge: config.bridge,
|
|
@@ -5067,7 +5594,7 @@ var Database = class {
|
|
|
5067
5594
|
constructor(config) {
|
|
5068
5595
|
this.config = config;
|
|
5069
5596
|
this.collectionForPath = async (filepath) => {
|
|
5070
|
-
const tinaSchema = await this.getSchema(this.
|
|
5597
|
+
const tinaSchema = await this.getSchema(this.contentLevel);
|
|
5071
5598
|
try {
|
|
5072
5599
|
return tinaSchema.getCollectionByFullPath(filepath);
|
|
5073
5600
|
} catch (e) {
|
|
@@ -5076,13 +5603,25 @@ var Database = class {
|
|
|
5076
5603
|
this.getGeneratedFolder = () => path4.join(this.tinaDirectory, "__generated__");
|
|
5077
5604
|
this.getMetadata = async (key) => {
|
|
5078
5605
|
await this.initLevel();
|
|
5079
|
-
|
|
5606
|
+
let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
|
|
5607
|
+
if (this.contentNamespace) {
|
|
5608
|
+
metadataLevel = metadataLevel.sublevel(
|
|
5609
|
+
this.contentNamespace,
|
|
5610
|
+
SUBLEVEL_OPTIONS
|
|
5611
|
+
);
|
|
5612
|
+
}
|
|
5080
5613
|
const metadata = await metadataLevel.get(`metadata_${key}`);
|
|
5081
5614
|
return metadata?.value;
|
|
5082
5615
|
};
|
|
5083
5616
|
this.setMetadata = async (key, value) => {
|
|
5084
5617
|
await this.initLevel();
|
|
5085
|
-
|
|
5618
|
+
let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
|
|
5619
|
+
if (this.contentNamespace) {
|
|
5620
|
+
metadataLevel = metadataLevel.sublevel(
|
|
5621
|
+
this.contentNamespace,
|
|
5622
|
+
SUBLEVEL_OPTIONS
|
|
5623
|
+
);
|
|
5624
|
+
}
|
|
5086
5625
|
return metadataLevel.put(`metadata_${key}`, { value });
|
|
5087
5626
|
};
|
|
5088
5627
|
this.get = async (filepath) => {
|
|
@@ -5090,7 +5629,15 @@ var Database = class {
|
|
|
5090
5629
|
if (SYSTEM_FILES.includes(filepath)) {
|
|
5091
5630
|
throw new Error(`Unexpected get for config file ${filepath}`);
|
|
5092
5631
|
} else {
|
|
5093
|
-
|
|
5632
|
+
let collection;
|
|
5633
|
+
let level = this.contentLevel;
|
|
5634
|
+
if (this.appLevel) {
|
|
5635
|
+
collection = await this.collectionForPath(filepath);
|
|
5636
|
+
if (collection?.isDetached) {
|
|
5637
|
+
level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
|
|
5638
|
+
}
|
|
5639
|
+
}
|
|
5640
|
+
const contentObject = await level.sublevel(
|
|
5094
5641
|
CONTENT_ROOT_PREFIX,
|
|
5095
5642
|
SUBLEVEL_OPTIONS
|
|
5096
5643
|
).get(normalizePath(filepath));
|
|
@@ -5100,7 +5647,7 @@ var Database = class {
|
|
|
5100
5647
|
return transformDocument(
|
|
5101
5648
|
filepath,
|
|
5102
5649
|
contentObject,
|
|
5103
|
-
await this.getSchema(this.
|
|
5650
|
+
await this.getSchema(this.contentLevel)
|
|
5104
5651
|
);
|
|
5105
5652
|
}
|
|
5106
5653
|
};
|
|
@@ -5116,23 +5663,29 @@ var Database = class {
|
|
|
5116
5663
|
dataFields,
|
|
5117
5664
|
collection
|
|
5118
5665
|
);
|
|
5119
|
-
const indexDefinitions = await this.getIndexDefinitions(this.
|
|
5666
|
+
const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
|
|
5120
5667
|
const collectionIndexDefinitions = indexDefinitions?.[collection.name];
|
|
5121
5668
|
const normalizedPath = normalizePath(filepath);
|
|
5122
|
-
if (
|
|
5123
|
-
|
|
5669
|
+
if (!collection?.isDetached) {
|
|
5670
|
+
if (this.bridge) {
|
|
5671
|
+
await this.bridge.put(normalizedPath, stringifiedFile);
|
|
5672
|
+
}
|
|
5673
|
+
try {
|
|
5674
|
+
await this.onPut(normalizedPath, stringifiedFile);
|
|
5675
|
+
} catch (e) {
|
|
5676
|
+
throw new GraphQLError5(
|
|
5677
|
+
`Error running onPut hook for ${filepath}: ${e}`,
|
|
5678
|
+
null,
|
|
5679
|
+
null,
|
|
5680
|
+
null,
|
|
5681
|
+
null,
|
|
5682
|
+
e
|
|
5683
|
+
);
|
|
5684
|
+
}
|
|
5124
5685
|
}
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
throw new GraphQLError5(
|
|
5129
|
-
`Error running onPut hook for ${filepath}: ${e}`,
|
|
5130
|
-
null,
|
|
5131
|
-
null,
|
|
5132
|
-
null,
|
|
5133
|
-
null,
|
|
5134
|
-
e
|
|
5135
|
-
);
|
|
5686
|
+
let level = this.contentLevel;
|
|
5687
|
+
if (collection?.isDetached) {
|
|
5688
|
+
level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
|
|
5136
5689
|
}
|
|
5137
5690
|
const folderTreeBuilder = new FolderTreeBuilder();
|
|
5138
5691
|
const folderKey = folderTreeBuilder.update(filepath, collection.path || "");
|
|
@@ -5143,7 +5696,7 @@ var Database = class {
|
|
|
5143
5696
|
collectionIndexDefinitions,
|
|
5144
5697
|
dataFields,
|
|
5145
5698
|
"put",
|
|
5146
|
-
|
|
5699
|
+
level
|
|
5147
5700
|
),
|
|
5148
5701
|
...makeIndexOpsForDocument(
|
|
5149
5702
|
normalizedPath,
|
|
@@ -5151,10 +5704,10 @@ var Database = class {
|
|
|
5151
5704
|
collectionIndexDefinitions,
|
|
5152
5705
|
dataFields,
|
|
5153
5706
|
"put",
|
|
5154
|
-
|
|
5707
|
+
level
|
|
5155
5708
|
)
|
|
5156
5709
|
];
|
|
5157
|
-
const existingItem = await
|
|
5710
|
+
const existingItem = await level.sublevel(
|
|
5158
5711
|
CONTENT_ROOT_PREFIX,
|
|
5159
5712
|
SUBLEVEL_OPTIONS
|
|
5160
5713
|
).get(normalizedPath);
|
|
@@ -5165,7 +5718,7 @@ var Database = class {
|
|
|
5165
5718
|
collectionIndexDefinitions,
|
|
5166
5719
|
existingItem,
|
|
5167
5720
|
"del",
|
|
5168
|
-
|
|
5721
|
+
level
|
|
5169
5722
|
),
|
|
5170
5723
|
...makeIndexOpsForDocument(
|
|
5171
5724
|
normalizedPath,
|
|
@@ -5173,7 +5726,7 @@ var Database = class {
|
|
|
5173
5726
|
collectionIndexDefinitions,
|
|
5174
5727
|
existingItem,
|
|
5175
5728
|
"del",
|
|
5176
|
-
|
|
5729
|
+
level
|
|
5177
5730
|
)
|
|
5178
5731
|
] : [];
|
|
5179
5732
|
const ops = [
|
|
@@ -5183,13 +5736,13 @@ var Database = class {
|
|
|
5183
5736
|
type: "put",
|
|
5184
5737
|
key: normalizedPath,
|
|
5185
5738
|
value: dataFields,
|
|
5186
|
-
sublevel:
|
|
5739
|
+
sublevel: level.sublevel(
|
|
5187
5740
|
CONTENT_ROOT_PREFIX,
|
|
5188
5741
|
SUBLEVEL_OPTIONS
|
|
5189
5742
|
)
|
|
5190
5743
|
}
|
|
5191
5744
|
];
|
|
5192
|
-
await
|
|
5745
|
+
await level.batch(ops);
|
|
5193
5746
|
};
|
|
5194
5747
|
this.put = async (filepath, data, collectionName) => {
|
|
5195
5748
|
await this.initLevel();
|
|
@@ -5199,7 +5752,9 @@ var Database = class {
|
|
|
5199
5752
|
} else {
|
|
5200
5753
|
let collectionIndexDefinitions;
|
|
5201
5754
|
if (collectionName) {
|
|
5202
|
-
const indexDefinitions = await this.getIndexDefinitions(
|
|
5755
|
+
const indexDefinitions = await this.getIndexDefinitions(
|
|
5756
|
+
this.contentLevel
|
|
5757
|
+
);
|
|
5203
5758
|
collectionIndexDefinitions = indexDefinitions?.[collectionName];
|
|
5204
5759
|
}
|
|
5205
5760
|
const normalizedPath = normalizePath(filepath);
|
|
@@ -5224,26 +5779,29 @@ var Database = class {
|
|
|
5224
5779
|
dataFields,
|
|
5225
5780
|
collection
|
|
5226
5781
|
);
|
|
5227
|
-
if (
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5782
|
+
if (!collection?.isDetached) {
|
|
5783
|
+
if (this.bridge) {
|
|
5784
|
+
await this.bridge.put(normalizedPath, stringifiedFile);
|
|
5785
|
+
}
|
|
5786
|
+
try {
|
|
5787
|
+
await this.onPut(normalizedPath, stringifiedFile);
|
|
5788
|
+
} catch (e) {
|
|
5789
|
+
throw new GraphQLError5(
|
|
5790
|
+
`Error running onPut hook for ${filepath}: ${e}`,
|
|
5791
|
+
null,
|
|
5792
|
+
null,
|
|
5793
|
+
null,
|
|
5794
|
+
null,
|
|
5795
|
+
e
|
|
5796
|
+
);
|
|
5797
|
+
}
|
|
5241
5798
|
}
|
|
5242
5799
|
const folderTreeBuilder = new FolderTreeBuilder();
|
|
5243
5800
|
const folderKey = folderTreeBuilder.update(
|
|
5244
5801
|
filepath,
|
|
5245
5802
|
collection.path || ""
|
|
5246
5803
|
);
|
|
5804
|
+
const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
|
|
5247
5805
|
const putOps = [
|
|
5248
5806
|
...makeIndexOpsForDocument(
|
|
5249
5807
|
normalizedPath,
|
|
@@ -5251,7 +5809,7 @@ var Database = class {
|
|
|
5251
5809
|
collectionIndexDefinitions,
|
|
5252
5810
|
dataFields,
|
|
5253
5811
|
"put",
|
|
5254
|
-
|
|
5812
|
+
level
|
|
5255
5813
|
),
|
|
5256
5814
|
...makeIndexOpsForDocument(
|
|
5257
5815
|
normalizedPath,
|
|
@@ -5259,10 +5817,10 @@ var Database = class {
|
|
|
5259
5817
|
collectionIndexDefinitions,
|
|
5260
5818
|
dataFields,
|
|
5261
5819
|
"put",
|
|
5262
|
-
|
|
5820
|
+
level
|
|
5263
5821
|
)
|
|
5264
5822
|
];
|
|
5265
|
-
const existingItem = await
|
|
5823
|
+
const existingItem = await level.sublevel(
|
|
5266
5824
|
CONTENT_ROOT_PREFIX,
|
|
5267
5825
|
SUBLEVEL_OPTIONS
|
|
5268
5826
|
).get(normalizedPath);
|
|
@@ -5273,7 +5831,7 @@ var Database = class {
|
|
|
5273
5831
|
collectionIndexDefinitions,
|
|
5274
5832
|
existingItem,
|
|
5275
5833
|
"del",
|
|
5276
|
-
|
|
5834
|
+
level
|
|
5277
5835
|
),
|
|
5278
5836
|
...makeIndexOpsForDocument(
|
|
5279
5837
|
normalizedPath,
|
|
@@ -5281,7 +5839,7 @@ var Database = class {
|
|
|
5281
5839
|
collectionIndexDefinitions,
|
|
5282
5840
|
existingItem,
|
|
5283
5841
|
"del",
|
|
5284
|
-
|
|
5842
|
+
level
|
|
5285
5843
|
)
|
|
5286
5844
|
] : [];
|
|
5287
5845
|
const ops = [
|
|
@@ -5291,13 +5849,13 @@ var Database = class {
|
|
|
5291
5849
|
type: "put",
|
|
5292
5850
|
key: normalizedPath,
|
|
5293
5851
|
value: dataFields,
|
|
5294
|
-
sublevel:
|
|
5852
|
+
sublevel: level.sublevel(
|
|
5295
5853
|
CONTENT_ROOT_PREFIX,
|
|
5296
5854
|
SUBLEVEL_OPTIONS
|
|
5297
5855
|
)
|
|
5298
5856
|
}
|
|
5299
5857
|
];
|
|
5300
|
-
await
|
|
5858
|
+
await level.batch(ops);
|
|
5301
5859
|
}
|
|
5302
5860
|
return true;
|
|
5303
5861
|
} catch (error) {
|
|
@@ -5347,7 +5905,7 @@ var Database = class {
|
|
|
5347
5905
|
const writeTemplateKey = templateDetails.info.type === "union";
|
|
5348
5906
|
const aliasedData = applyNameOverrides(templateDetails.template, payload);
|
|
5349
5907
|
const extension = path4.extname(filepath);
|
|
5350
|
-
|
|
5908
|
+
return stringifyFile(
|
|
5351
5909
|
aliasedData,
|
|
5352
5910
|
extension,
|
|
5353
5911
|
writeTemplateKey,
|
|
@@ -5356,7 +5914,6 @@ var Database = class {
|
|
|
5356
5914
|
frontmatterDelimiters: collection?.frontmatterDelimiters
|
|
5357
5915
|
}
|
|
5358
5916
|
);
|
|
5359
|
-
return stringifiedFile;
|
|
5360
5917
|
};
|
|
5361
5918
|
this.flush = async (filepath) => {
|
|
5362
5919
|
const data = await this.get(filepath);
|
|
@@ -5365,12 +5922,7 @@ var Database = class {
|
|
|
5365
5922
|
if (!collection) {
|
|
5366
5923
|
throw new Error(`Unable to find collection for path ${filepath}`);
|
|
5367
5924
|
}
|
|
5368
|
-
|
|
5369
|
-
filepath,
|
|
5370
|
-
dataFields,
|
|
5371
|
-
collection
|
|
5372
|
-
);
|
|
5373
|
-
return stringifiedFile;
|
|
5925
|
+
return this.stringifyFile(filepath, dataFields, collection);
|
|
5374
5926
|
};
|
|
5375
5927
|
this.getLookup = async (returnType) => {
|
|
5376
5928
|
await this.initLevel();
|
|
@@ -5378,11 +5930,10 @@ var Database = class {
|
|
|
5378
5930
|
path4.join(this.getGeneratedFolder(), `_lookup.json`)
|
|
5379
5931
|
);
|
|
5380
5932
|
if (!this._lookup) {
|
|
5381
|
-
|
|
5933
|
+
this._lookup = await this.contentLevel.sublevel(
|
|
5382
5934
|
CONTENT_ROOT_PREFIX,
|
|
5383
5935
|
SUBLEVEL_OPTIONS
|
|
5384
5936
|
).get(lookupPath);
|
|
5385
|
-
this._lookup = _lookup;
|
|
5386
5937
|
}
|
|
5387
5938
|
return this._lookup[returnType];
|
|
5388
5939
|
};
|
|
@@ -5391,7 +5942,7 @@ var Database = class {
|
|
|
5391
5942
|
const graphqlPath = normalizePath(
|
|
5392
5943
|
path4.join(this.getGeneratedFolder(), `_graphql.json`)
|
|
5393
5944
|
);
|
|
5394
|
-
return await this.
|
|
5945
|
+
return await this.contentLevel.sublevel(
|
|
5395
5946
|
CONTENT_ROOT_PREFIX,
|
|
5396
5947
|
SUBLEVEL_OPTIONS
|
|
5397
5948
|
).get(graphqlPath);
|
|
@@ -5411,7 +5962,7 @@ var Database = class {
|
|
|
5411
5962
|
const schemaPath = normalizePath(
|
|
5412
5963
|
path4.join(this.getGeneratedFolder(), `_schema.json`)
|
|
5413
5964
|
);
|
|
5414
|
-
return await (level || this.
|
|
5965
|
+
return await (level || this.contentLevel).sublevel(
|
|
5415
5966
|
CONTENT_ROOT_PREFIX,
|
|
5416
5967
|
SUBLEVEL_OPTIONS
|
|
5417
5968
|
).get(schemaPath);
|
|
@@ -5421,7 +5972,7 @@ var Database = class {
|
|
|
5421
5972
|
return this.tinaSchema;
|
|
5422
5973
|
}
|
|
5423
5974
|
await this.initLevel();
|
|
5424
|
-
const schema = existingSchema || await this.getTinaSchema(level || this.
|
|
5975
|
+
const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
|
|
5425
5976
|
if (!schema) {
|
|
5426
5977
|
throw new Error(
|
|
5427
5978
|
`Unable to get schema from level db: ${normalizePath(
|
|
@@ -5437,7 +5988,7 @@ var Database = class {
|
|
|
5437
5988
|
await new Promise(async (resolve2, reject) => {
|
|
5438
5989
|
await this.initLevel();
|
|
5439
5990
|
try {
|
|
5440
|
-
const schema = await this.getSchema(level || this.
|
|
5991
|
+
const schema = await this.getSchema(level || this.contentLevel);
|
|
5441
5992
|
const collections = schema.getCollections();
|
|
5442
5993
|
for (const collection of collections) {
|
|
5443
5994
|
const indexDefinitions = {
|
|
@@ -5503,7 +6054,6 @@ var Database = class {
|
|
|
5503
6054
|
last,
|
|
5504
6055
|
before,
|
|
5505
6056
|
sort = DEFAULT_COLLECTION_SORT_KEY,
|
|
5506
|
-
collection,
|
|
5507
6057
|
filterChain: rawFilterChain,
|
|
5508
6058
|
folder
|
|
5509
6059
|
} = queryOptions;
|
|
@@ -5519,22 +6069,25 @@ var Database = class {
|
|
|
5519
6069
|
} else if (before) {
|
|
5520
6070
|
query.lt = atob(before);
|
|
5521
6071
|
}
|
|
5522
|
-
const
|
|
5523
|
-
const
|
|
6072
|
+
const tinaSchema = await this.getSchema(this.contentLevel);
|
|
6073
|
+
const collection = tinaSchema.getCollection(queryOptions.collection);
|
|
6074
|
+
const allIndexDefinitions = await this.getIndexDefinitions(
|
|
6075
|
+
this.contentLevel
|
|
6076
|
+
);
|
|
6077
|
+
const indexDefinitions = allIndexDefinitions?.[collection.name];
|
|
5524
6078
|
if (!indexDefinitions) {
|
|
5525
|
-
throw new Error(
|
|
5526
|
-
`No indexDefinitions for collection ${queryOptions.collection}`
|
|
5527
|
-
);
|
|
6079
|
+
throw new Error(`No indexDefinitions for collection ${collection.name}`);
|
|
5528
6080
|
}
|
|
5529
6081
|
const filterChain = coerceFilterChainOperands(rawFilterChain);
|
|
5530
6082
|
const indexDefinition = sort && indexDefinitions?.[sort];
|
|
5531
6083
|
const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
|
|
5532
|
-
const
|
|
6084
|
+
const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
|
|
6085
|
+
const rootLevel = level.sublevel(
|
|
5533
6086
|
CONTENT_ROOT_PREFIX,
|
|
5534
6087
|
SUBLEVEL_OPTIONS
|
|
5535
6088
|
);
|
|
5536
|
-
const sublevel = indexDefinition ?
|
|
5537
|
-
`${collection}${folder ? `_${folder === FOLDER_ROOT ? folder : sha2.hex(folder)}` : ""}`,
|
|
6089
|
+
const sublevel = indexDefinition ? level.sublevel(
|
|
6090
|
+
`${collection.name}${folder ? `_${folder === FOLDER_ROOT ? folder : sha2.hex(folder)}` : ""}`,
|
|
5538
6091
|
SUBLEVEL_OPTIONS
|
|
5539
6092
|
).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
|
|
5540
6093
|
if (!query.gt && !query.gte) {
|
|
@@ -5606,7 +6159,7 @@ var Database = class {
|
|
|
5606
6159
|
throw new TinaQueryError({
|
|
5607
6160
|
originalError: error,
|
|
5608
6161
|
file: edge.path,
|
|
5609
|
-
collection,
|
|
6162
|
+
collection: collection.name,
|
|
5610
6163
|
stack: error.stack
|
|
5611
6164
|
});
|
|
5612
6165
|
} else {
|
|
@@ -5654,8 +6207,8 @@ var Database = class {
|
|
|
5654
6207
|
}
|
|
5655
6208
|
let nextVersion;
|
|
5656
6209
|
if (!this.config.version) {
|
|
5657
|
-
await this.
|
|
5658
|
-
nextLevel = this.
|
|
6210
|
+
await this.contentLevel.clear();
|
|
6211
|
+
nextLevel = this.contentLevel;
|
|
5659
6212
|
} else {
|
|
5660
6213
|
const version = await this.getDatabaseVersion();
|
|
5661
6214
|
nextVersion = version ? `${parseInt(version) + 1}` : "0";
|
|
@@ -5685,10 +6238,10 @@ var Database = class {
|
|
|
5685
6238
|
},
|
|
5686
6239
|
async () => {
|
|
5687
6240
|
if (this.config.version) {
|
|
5688
|
-
if (this.
|
|
5689
|
-
await this.
|
|
6241
|
+
if (this.contentLevel) {
|
|
6242
|
+
await this.contentLevel.clear();
|
|
5690
6243
|
}
|
|
5691
|
-
this.
|
|
6244
|
+
this.contentLevel = nextLevel;
|
|
5692
6245
|
}
|
|
5693
6246
|
}
|
|
5694
6247
|
);
|
|
@@ -5699,10 +6252,10 @@ var Database = class {
|
|
|
5699
6252
|
const enqueueOps = async (ops) => {
|
|
5700
6253
|
operations.push(...ops);
|
|
5701
6254
|
while (operations.length >= 25) {
|
|
5702
|
-
await this.
|
|
6255
|
+
await this.contentLevel.batch(operations.splice(0, 25));
|
|
5703
6256
|
}
|
|
5704
6257
|
};
|
|
5705
|
-
const tinaSchema = await this.getSchema(this.
|
|
6258
|
+
const tinaSchema = await this.getSchema(this.contentLevel);
|
|
5706
6259
|
await this.indexStatusCallbackWrapper(async () => {
|
|
5707
6260
|
const { pathsByCollection, nonCollectionPaths, collections } = await partitionPathsByCollection(tinaSchema, documentPaths);
|
|
5708
6261
|
for (const collection of Object.keys(pathsByCollection)) {
|
|
@@ -5718,7 +6271,7 @@ var Database = class {
|
|
|
5718
6271
|
}
|
|
5719
6272
|
});
|
|
5720
6273
|
while (operations.length) {
|
|
5721
|
-
await this.
|
|
6274
|
+
await this.contentLevel.batch(operations.splice(0, 25));
|
|
5722
6275
|
}
|
|
5723
6276
|
};
|
|
5724
6277
|
this.indexContentByPaths = async (documentPaths) => {
|
|
@@ -5727,31 +6280,29 @@ var Database = class {
|
|
|
5727
6280
|
const enqueueOps = async (ops) => {
|
|
5728
6281
|
operations.push(...ops);
|
|
5729
6282
|
while (operations.length >= 25) {
|
|
5730
|
-
await this.
|
|
6283
|
+
await this.contentLevel.batch(operations.splice(0, 25));
|
|
5731
6284
|
}
|
|
5732
6285
|
};
|
|
5733
|
-
const tinaSchema = await this.getSchema(this.
|
|
6286
|
+
const tinaSchema = await this.getSchema(this.contentLevel);
|
|
5734
6287
|
await this.indexStatusCallbackWrapper(async () => {
|
|
5735
6288
|
await scanContentByPaths(
|
|
5736
6289
|
tinaSchema,
|
|
5737
6290
|
documentPaths,
|
|
5738
6291
|
async (collection, documentPaths2) => {
|
|
5739
|
-
if (collection) {
|
|
6292
|
+
if (collection && !collection.isDetached) {
|
|
5740
6293
|
await _indexContent(
|
|
5741
6294
|
this,
|
|
5742
|
-
this.
|
|
6295
|
+
this.contentLevel,
|
|
5743
6296
|
documentPaths2,
|
|
5744
6297
|
enqueueOps,
|
|
5745
6298
|
collection
|
|
5746
6299
|
);
|
|
5747
|
-
} else {
|
|
5748
|
-
await _indexContent(this, this.level, documentPaths2, enqueueOps);
|
|
5749
6300
|
}
|
|
5750
6301
|
}
|
|
5751
6302
|
);
|
|
5752
6303
|
});
|
|
5753
6304
|
while (operations.length) {
|
|
5754
|
-
await this.
|
|
6305
|
+
await this.contentLevel.batch(operations.splice(0, 25));
|
|
5755
6306
|
}
|
|
5756
6307
|
};
|
|
5757
6308
|
this.delete = async (filepath) => {
|
|
@@ -5760,14 +6311,14 @@ var Database = class {
|
|
|
5760
6311
|
if (!collection) {
|
|
5761
6312
|
throw new Error(`No collection found for path: ${filepath}`);
|
|
5762
6313
|
}
|
|
5763
|
-
const indexDefinitions = await this.getIndexDefinitions(this.
|
|
6314
|
+
const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
|
|
5764
6315
|
const collectionIndexDefinitions = indexDefinitions?.[collection.name];
|
|
5765
|
-
this.
|
|
5766
|
-
|
|
5767
|
-
SUBLEVEL_OPTIONS
|
|
5768
|
-
|
|
6316
|
+
let level = this.contentLevel;
|
|
6317
|
+
if (collection?.isDetached) {
|
|
6318
|
+
level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
|
|
6319
|
+
}
|
|
5769
6320
|
const itemKey = normalizePath(filepath);
|
|
5770
|
-
const rootSublevel =
|
|
6321
|
+
const rootSublevel = level.sublevel(
|
|
5771
6322
|
CONTENT_ROOT_PREFIX,
|
|
5772
6323
|
SUBLEVEL_OPTIONS
|
|
5773
6324
|
);
|
|
@@ -5778,14 +6329,14 @@ var Database = class {
|
|
|
5778
6329
|
filepath,
|
|
5779
6330
|
collection.path || ""
|
|
5780
6331
|
);
|
|
5781
|
-
await this.
|
|
6332
|
+
await this.contentLevel.batch([
|
|
5782
6333
|
...makeIndexOpsForDocument(
|
|
5783
6334
|
filepath,
|
|
5784
6335
|
collection.name,
|
|
5785
6336
|
collectionIndexDefinitions,
|
|
5786
6337
|
item,
|
|
5787
6338
|
"del",
|
|
5788
|
-
|
|
6339
|
+
level
|
|
5789
6340
|
),
|
|
5790
6341
|
...makeIndexOpsForDocument(
|
|
5791
6342
|
filepath,
|
|
@@ -5793,7 +6344,7 @@ var Database = class {
|
|
|
5793
6344
|
collectionIndexDefinitions,
|
|
5794
6345
|
item,
|
|
5795
6346
|
"del",
|
|
5796
|
-
|
|
6347
|
+
level
|
|
5797
6348
|
),
|
|
5798
6349
|
{
|
|
5799
6350
|
type: "del",
|
|
@@ -5802,20 +6353,22 @@ var Database = class {
|
|
|
5802
6353
|
}
|
|
5803
6354
|
]);
|
|
5804
6355
|
}
|
|
5805
|
-
if (
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
6356
|
+
if (!collection?.isDetached) {
|
|
6357
|
+
if (this.bridge) {
|
|
6358
|
+
await this.bridge.delete(normalizePath(filepath));
|
|
6359
|
+
}
|
|
6360
|
+
try {
|
|
6361
|
+
await this.onDelete(normalizePath(filepath));
|
|
6362
|
+
} catch (e) {
|
|
6363
|
+
throw new GraphQLError5(
|
|
6364
|
+
`Error running onDelete hook for ${filepath}: ${e}`,
|
|
6365
|
+
null,
|
|
6366
|
+
null,
|
|
6367
|
+
null,
|
|
6368
|
+
null,
|
|
6369
|
+
e
|
|
6370
|
+
);
|
|
6371
|
+
}
|
|
5819
6372
|
}
|
|
5820
6373
|
};
|
|
5821
6374
|
this._indexAllContent = async (level, schema) => {
|
|
@@ -5832,7 +6385,29 @@ var Database = class {
|
|
|
5832
6385
|
tinaSchema,
|
|
5833
6386
|
this.bridge,
|
|
5834
6387
|
async (collection, contentPaths) => {
|
|
5835
|
-
|
|
6388
|
+
const userFields = mapUserFields(collection, []);
|
|
6389
|
+
if (collection.isDetached) {
|
|
6390
|
+
const level2 = this.appLevel.sublevel(
|
|
6391
|
+
collection.name,
|
|
6392
|
+
SUBLEVEL_OPTIONS
|
|
6393
|
+
);
|
|
6394
|
+
const doc = await level2.keys({ limit: 1 }).next();
|
|
6395
|
+
if (!doc) {
|
|
6396
|
+
await _indexContent(
|
|
6397
|
+
this,
|
|
6398
|
+
level2,
|
|
6399
|
+
contentPaths,
|
|
6400
|
+
enqueueOps,
|
|
6401
|
+
collection,
|
|
6402
|
+
userFields.map((field) => [
|
|
6403
|
+
...field.path,
|
|
6404
|
+
field.passwordFieldName
|
|
6405
|
+
])
|
|
6406
|
+
);
|
|
6407
|
+
}
|
|
6408
|
+
} else {
|
|
6409
|
+
await _indexContent(this, level, contentPaths, enqueueOps, collection);
|
|
6410
|
+
}
|
|
5836
6411
|
}
|
|
5837
6412
|
);
|
|
5838
6413
|
while (operations.length) {
|
|
@@ -5846,22 +6421,36 @@ var Database = class {
|
|
|
5846
6421
|
this.indexStatusCallback = config.indexStatusCallback || defaultStatusCallback;
|
|
5847
6422
|
this.onPut = config.onPut || defaultOnPut;
|
|
5848
6423
|
this.onDelete = config.onDelete || defaultOnDelete;
|
|
6424
|
+
this.contentNamespace = config.namespace;
|
|
5849
6425
|
}
|
|
5850
6426
|
async updateDatabaseVersion(version) {
|
|
5851
|
-
|
|
6427
|
+
let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
|
|
6428
|
+
if (this.contentNamespace) {
|
|
6429
|
+
metadataLevel = metadataLevel.sublevel(
|
|
6430
|
+
this.contentNamespace,
|
|
6431
|
+
SUBLEVEL_OPTIONS
|
|
6432
|
+
);
|
|
6433
|
+
}
|
|
5852
6434
|
await metadataLevel.put("metadata", { version });
|
|
5853
6435
|
}
|
|
5854
6436
|
async getDatabaseVersion() {
|
|
5855
|
-
|
|
6437
|
+
let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
|
|
6438
|
+
if (this.contentNamespace) {
|
|
6439
|
+
metadataLevel = metadataLevel.sublevel(
|
|
6440
|
+
this.contentNamespace,
|
|
6441
|
+
SUBLEVEL_OPTIONS
|
|
6442
|
+
);
|
|
6443
|
+
}
|
|
5856
6444
|
const metadata = await metadataLevel.get("metadata");
|
|
5857
6445
|
return metadata?.version;
|
|
5858
6446
|
}
|
|
5859
6447
|
async initLevel() {
|
|
5860
|
-
if (this.
|
|
6448
|
+
if (this.contentLevel) {
|
|
5861
6449
|
return;
|
|
5862
6450
|
}
|
|
6451
|
+
this.appLevel = this.rootLevel.sublevel("_appData", SUBLEVEL_OPTIONS);
|
|
5863
6452
|
if (!this.config.version) {
|
|
5864
|
-
this.
|
|
6453
|
+
this.contentLevel = this.contentNamespace ? this.rootLevel.sublevel("_content", SUBLEVEL_OPTIONS).sublevel(this.contentNamespace, SUBLEVEL_OPTIONS) : this.rootLevel.sublevel("_content", SUBLEVEL_OPTIONS);
|
|
5865
6454
|
} else {
|
|
5866
6455
|
let version = await this.getDatabaseVersion();
|
|
5867
6456
|
if (!version) {
|
|
@@ -5871,9 +6460,9 @@ var Database = class {
|
|
|
5871
6460
|
} catch (e) {
|
|
5872
6461
|
}
|
|
5873
6462
|
}
|
|
5874
|
-
this.
|
|
6463
|
+
this.contentLevel = this.contentNamespace ? this.rootLevel.sublevel("_content").sublevel(this.contentNamespace, SUBLEVEL_OPTIONS).sublevel(version, SUBLEVEL_OPTIONS) : this.rootLevel.sublevel(version, SUBLEVEL_OPTIONS);
|
|
5875
6464
|
}
|
|
5876
|
-
if (!this.
|
|
6465
|
+
if (!this.contentLevel) {
|
|
5877
6466
|
throw new GraphQLError5("Error initializing LevelDB instance");
|
|
5878
6467
|
}
|
|
5879
6468
|
}
|
|
@@ -5922,7 +6511,36 @@ var Database = class {
|
|
|
5922
6511
|
}
|
|
5923
6512
|
}
|
|
5924
6513
|
};
|
|
5925
|
-
var
|
|
6514
|
+
var hashPasswordVisitor = async (node, path7) => {
|
|
6515
|
+
const passwordValuePath = [...path7, "value"];
|
|
6516
|
+
const plaintextPassword = _5.get(node, passwordValuePath);
|
|
6517
|
+
if (plaintextPassword) {
|
|
6518
|
+
_5.set(
|
|
6519
|
+
node,
|
|
6520
|
+
passwordValuePath,
|
|
6521
|
+
await generatePasswordHash({ password: plaintextPassword })
|
|
6522
|
+
);
|
|
6523
|
+
}
|
|
6524
|
+
};
|
|
6525
|
+
var visitNodes = async (node, path7, callback) => {
|
|
6526
|
+
const [currentLevel, ...remainingLevels] = path7;
|
|
6527
|
+
if (!remainingLevels?.length) {
|
|
6528
|
+
return callback(node, path7);
|
|
6529
|
+
}
|
|
6530
|
+
if (Array.isArray(node[currentLevel])) {
|
|
6531
|
+
for (const item of node[currentLevel]) {
|
|
6532
|
+
await visitNodes(item, remainingLevels, callback);
|
|
6533
|
+
}
|
|
6534
|
+
} else {
|
|
6535
|
+
await visitNodes(node[currentLevel], remainingLevels, callback);
|
|
6536
|
+
}
|
|
6537
|
+
};
|
|
6538
|
+
var hashPasswordValues = async (data, passwordFields) => Promise.all(
|
|
6539
|
+
passwordFields.map(
|
|
6540
|
+
async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
|
|
6541
|
+
)
|
|
6542
|
+
);
|
|
6543
|
+
var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
|
|
5926
6544
|
let collectionIndexDefinitions;
|
|
5927
6545
|
let collectionPath;
|
|
5928
6546
|
if (collection) {
|
|
@@ -5950,6 +6568,9 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
|
|
|
5950
6568
|
if (!aliasedData) {
|
|
5951
6569
|
return;
|
|
5952
6570
|
}
|
|
6571
|
+
if (passwordFields?.length) {
|
|
6572
|
+
await hashPasswordValues(aliasedData, passwordFields);
|
|
6573
|
+
}
|
|
5953
6574
|
const normalizedPath = normalizePath(filepath);
|
|
5954
6575
|
const folderKey = folderTreeBuilder.update(
|
|
5955
6576
|
normalizedPath,
|
|
@@ -6009,7 +6630,9 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6009
6630
|
}
|
|
6010
6631
|
let collectionIndexDefinitions;
|
|
6011
6632
|
if (collection) {
|
|
6012
|
-
const indexDefinitions = await database.getIndexDefinitions(
|
|
6633
|
+
const indexDefinitions = await database.getIndexDefinitions(
|
|
6634
|
+
database.contentLevel
|
|
6635
|
+
);
|
|
6013
6636
|
collectionIndexDefinitions = indexDefinitions?.[collection.name];
|
|
6014
6637
|
if (!collectionIndexDefinitions) {
|
|
6015
6638
|
throw new Error(`No indexDefinitions for collection ${collection.name}`);
|
|
@@ -6018,9 +6641,9 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6018
6641
|
const tinaSchema = await database.getSchema();
|
|
6019
6642
|
let templateInfo = null;
|
|
6020
6643
|
if (collection) {
|
|
6021
|
-
templateInfo =
|
|
6644
|
+
templateInfo = tinaSchema.getTemplatesForCollectable(collection);
|
|
6022
6645
|
}
|
|
6023
|
-
const rootLevel = database.
|
|
6646
|
+
const rootLevel = database.contentLevel.sublevel(
|
|
6024
6647
|
CONTENT_ROOT_PREFIX,
|
|
6025
6648
|
SUBLEVEL_OPTIONS
|
|
6026
6649
|
);
|
|
@@ -6044,7 +6667,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6044
6667
|
collectionIndexDefinitions,
|
|
6045
6668
|
aliasedData,
|
|
6046
6669
|
"del",
|
|
6047
|
-
database.
|
|
6670
|
+
database.contentLevel
|
|
6048
6671
|
),
|
|
6049
6672
|
...makeIndexOpsForDocument(
|
|
6050
6673
|
itemKey,
|
|
@@ -6052,7 +6675,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6052
6675
|
collectionIndexDefinitions,
|
|
6053
6676
|
aliasedData,
|
|
6054
6677
|
"del",
|
|
6055
|
-
database.
|
|
6678
|
+
database.contentLevel
|
|
6056
6679
|
),
|
|
6057
6680
|
{ type: "del", key: itemKey, sublevel: rootLevel }
|
|
6058
6681
|
]);
|
|
@@ -6065,33 +6688,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
|
|
|
6065
6688
|
collection,
|
|
6066
6689
|
collectionIndexDefinitions,
|
|
6067
6690
|
"del",
|
|
6068
|
-
database.
|
|
6691
|
+
database.contentLevel
|
|
6069
6692
|
)
|
|
6070
6693
|
);
|
|
6071
6694
|
}
|
|
6072
6695
|
};
|
|
6073
6696
|
|
|
6074
|
-
// src/level/tinaLevel.ts
|
|
6075
|
-
import { ManyLevelGuest } from "many-level";
|
|
6076
|
-
import { pipeline } from "readable-stream";
|
|
6077
|
-
import { connect } from "net";
|
|
6078
|
-
var TinaLevelClient = class extends ManyLevelGuest {
|
|
6079
|
-
constructor(port) {
|
|
6080
|
-
super();
|
|
6081
|
-
this._connected = false;
|
|
6082
|
-
this.port = port || 9e3;
|
|
6083
|
-
}
|
|
6084
|
-
openConnection() {
|
|
6085
|
-
if (this._connected)
|
|
6086
|
-
return;
|
|
6087
|
-
const socket = connect(this.port);
|
|
6088
|
-
pipeline(socket, this.createRpcStream(), socket, () => {
|
|
6089
|
-
this._connected = false;
|
|
6090
|
-
});
|
|
6091
|
-
this._connected = true;
|
|
6092
|
-
}
|
|
6093
|
-
};
|
|
6094
|
-
|
|
6095
6697
|
// src/git/index.ts
|
|
6096
6698
|
import git from "isomorphic-git";
|
|
6097
6699
|
import fs from "fs-extra";
|
|
@@ -6627,6 +7229,7 @@ var buildSchema = async (config, flags) => {
|
|
|
6627
7229
|
};
|
|
6628
7230
|
export {
|
|
6629
7231
|
AuditFileSystemBridge,
|
|
7232
|
+
Database,
|
|
6630
7233
|
FilesystemBridge,
|
|
6631
7234
|
IsomorphicBridge,
|
|
6632
7235
|
TinaFetchError,
|
|
@@ -6637,12 +7240,17 @@ export {
|
|
|
6637
7240
|
assertShape,
|
|
6638
7241
|
buildDotTinaFiles,
|
|
6639
7242
|
buildSchema,
|
|
7243
|
+
checkPasswordHash,
|
|
6640
7244
|
createDatabase,
|
|
7245
|
+
createDatabaseInternal,
|
|
7246
|
+
createLocalDatabase,
|
|
6641
7247
|
createSchema,
|
|
7248
|
+
generatePasswordHash,
|
|
6642
7249
|
getChangedFiles,
|
|
6643
7250
|
getSha,
|
|
6644
7251
|
handleFetchErrorError,
|
|
6645
7252
|
loadAndParseWithAliases,
|
|
7253
|
+
mapUserFields,
|
|
6646
7254
|
parseFile,
|
|
6647
7255
|
resolve,
|
|
6648
7256
|
scanAllContent,
|