@tinacms/graphql 1.4.27 → 1.4.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
26
26
  var src_exports = {};
27
27
  __export(src_exports, {
28
28
  AuditFileSystemBridge: () => AuditFileSystemBridge,
29
+ Database: () => Database,
29
30
  FilesystemBridge: () => FilesystemBridge,
30
31
  IsomorphicBridge: () => IsomorphicBridge,
31
32
  TinaFetchError: () => TinaFetchError,
@@ -36,12 +37,17 @@ __export(src_exports, {
36
37
  assertShape: () => assertShape,
37
38
  buildDotTinaFiles: () => buildDotTinaFiles,
38
39
  buildSchema: () => buildSchema,
40
+ checkPasswordHash: () => checkPasswordHash,
39
41
  createDatabase: () => createDatabase,
42
+ createDatabaseInternal: () => createDatabaseInternal,
43
+ createLocalDatabase: () => createLocalDatabase,
40
44
  createSchema: () => createSchema,
45
+ generatePasswordHash: () => generatePasswordHash,
41
46
  getChangedFiles: () => getChangedFiles,
42
47
  getSha: () => getSha,
43
48
  handleFetchErrorError: () => handleFetchErrorError,
44
49
  loadAndParseWithAliases: () => loadAndParseWithAliases,
50
+ mapUserFields: () => mapUserFields,
45
51
  parseFile: () => parseFile,
46
52
  resolve: () => resolve,
47
53
  scanAllContent: () => scanAllContent,
@@ -514,6 +520,7 @@ var astBuilder = {
514
520
  CollectionDocumentUnion: "DocumentUnion",
515
521
  Folder: "Folder",
516
522
  String: "String",
523
+ Password: "Password",
517
524
  Reference: "Reference",
518
525
  Collection: "Collection",
519
526
  ID: "ID",
@@ -1324,6 +1331,126 @@ var scalarDefinitions = [
1324
1331
  ];
1325
1332
  var staticDefinitions = [...scalarDefinitions, interfaceDefinitions];
1326
1333
 
1334
+ // src/auth/utils.ts
1335
+ var import_crypto = __toESM(require("crypto"));
1336
+ var import_scmp = __toESM(require("scmp"));
1337
+ var DEFAULT_SALT_LENGTH = 32;
1338
+ var DEFAULT_KEY_LENGTH = 512;
1339
+ var DEFAULT_ITERATIONS = 25e3;
1340
+ var DEFAULT_DIGEST = "sha256";
1341
+ var generatePasswordHash = async ({
1342
+ password,
1343
+ opts: {
1344
+ saltLength = DEFAULT_SALT_LENGTH,
1345
+ keyLength = DEFAULT_KEY_LENGTH,
1346
+ iterations = DEFAULT_ITERATIONS,
1347
+ digest = DEFAULT_DIGEST
1348
+ } = {
1349
+ saltLength: DEFAULT_SALT_LENGTH,
1350
+ keyLength: DEFAULT_KEY_LENGTH,
1351
+ iterations: DEFAULT_ITERATIONS,
1352
+ digest: DEFAULT_DIGEST
1353
+ }
1354
+ }) => {
1355
+ if (!password) {
1356
+ throw new Error("Password is required");
1357
+ }
1358
+ if (password.length < 3) {
1359
+ throw new Error("Password must be at least 3 characters");
1360
+ }
1361
+ const salt = (await new Promise((resolve2, reject) => {
1362
+ import_crypto.default.randomBytes(saltLength, (err, saltBuffer) => {
1363
+ if (err) {
1364
+ reject(err);
1365
+ }
1366
+ resolve2(saltBuffer);
1367
+ });
1368
+ })).toString("hex");
1369
+ const hash = (await new Promise((resolve2, reject) => {
1370
+ import_crypto.default.pbkdf2(
1371
+ password,
1372
+ salt,
1373
+ iterations,
1374
+ keyLength,
1375
+ digest,
1376
+ (err, hashBuffer) => {
1377
+ if (err) {
1378
+ reject(err);
1379
+ }
1380
+ resolve2(hashBuffer);
1381
+ }
1382
+ );
1383
+ })).toString("hex");
1384
+ return `${salt}${hash}`;
1385
+ };
1386
+ var checkPasswordHash = async ({
1387
+ saltedHash,
1388
+ password,
1389
+ opts: {
1390
+ saltLength = DEFAULT_SALT_LENGTH,
1391
+ keyLength = DEFAULT_KEY_LENGTH,
1392
+ iterations = DEFAULT_ITERATIONS,
1393
+ digest = DEFAULT_DIGEST
1394
+ } = {
1395
+ saltLength: DEFAULT_SALT_LENGTH,
1396
+ keyLength: DEFAULT_KEY_LENGTH,
1397
+ iterations: DEFAULT_ITERATIONS,
1398
+ digest: DEFAULT_DIGEST
1399
+ }
1400
+ }) => {
1401
+ const salt = saltedHash.slice(0, saltLength * 2);
1402
+ const hash = saltedHash.slice(saltLength * 2);
1403
+ try {
1404
+ await new Promise((resolve2, reject) => {
1405
+ import_crypto.default.pbkdf2(
1406
+ password,
1407
+ salt,
1408
+ iterations,
1409
+ keyLength,
1410
+ digest,
1411
+ (err, hashBuffer) => {
1412
+ if (err) {
1413
+ reject(null);
1414
+ }
1415
+ if ((0, import_scmp.default)(hashBuffer, Buffer.from(hash, "hex"))) {
1416
+ resolve2();
1417
+ }
1418
+ reject(null);
1419
+ }
1420
+ );
1421
+ });
1422
+ } catch (e) {
1423
+ return false;
1424
+ }
1425
+ return true;
1426
+ };
1427
+ var mapUserFields = (collectable, prefix = []) => {
1428
+ var _a, _b, _c, _d, _e;
1429
+ const results = [];
1430
+ const passwordFields = ((_a = collectable.fields) == null ? void 0 : _a.filter((field) => field.type === "password")) || [];
1431
+ if (passwordFields.length > 1) {
1432
+ throw new Error("Only one password field is allowed");
1433
+ }
1434
+ const idFields = ((_b = collectable.fields) == null ? void 0 : _b.filter((field) => field.uid)) || [];
1435
+ if (idFields.length > 1) {
1436
+ throw new Error("Only one uid field is allowed");
1437
+ }
1438
+ if (passwordFields.length || idFields.length) {
1439
+ results.push({
1440
+ path: prefix,
1441
+ collectable,
1442
+ idFieldName: (_c = idFields[0]) == null ? void 0 : _c.name,
1443
+ passwordFieldName: (_d = passwordFields[0]) == null ? void 0 : _d.name
1444
+ });
1445
+ }
1446
+ (_e = collectable.fields) == null ? void 0 : _e.forEach((field) => {
1447
+ if (field.type === "object" && field.fields) {
1448
+ results.push(...mapUserFields(field, [...prefix, field.name]));
1449
+ }
1450
+ });
1451
+ return results;
1452
+ };
1453
+
1327
1454
  // src/builder/index.ts
1328
1455
  var createBuilder = async ({
1329
1456
  tinaSchema
@@ -1424,7 +1551,7 @@ var Builder = class {
1424
1551
  type: astBuilder.TYPES.String
1425
1552
  })
1426
1553
  ];
1427
- await this.addToLookupMap({
1554
+ this.addToLookupMap({
1428
1555
  type: astBuilder.TYPES.Node,
1429
1556
  resolveType: "nodeDocument"
1430
1557
  });
@@ -1567,7 +1694,7 @@ var Builder = class {
1567
1694
  type: astBuilder.TYPES.String
1568
1695
  })
1569
1696
  ];
1570
- await this.addToLookupMap({
1697
+ this.addToLookupMap({
1571
1698
  type: type.name.value,
1572
1699
  resolveType: "collectionDocument",
1573
1700
  collection: collection.name,
@@ -1581,6 +1708,43 @@ var Builder = class {
1581
1708
  required: true
1582
1709
  });
1583
1710
  };
1711
+ this.authenticationCollectionDocument = async (collection) => {
1712
+ const name = "authenticate";
1713
+ const type = await this._buildAuthDocumentType(collection);
1714
+ const args = [
1715
+ astBuilder.InputValueDefinition({
1716
+ name: "sub",
1717
+ type: astBuilder.TYPES.String,
1718
+ required: true
1719
+ }),
1720
+ astBuilder.InputValueDefinition({
1721
+ name: "password",
1722
+ type: astBuilder.TYPES.String,
1723
+ required: true
1724
+ })
1725
+ ];
1726
+ return astBuilder.FieldDefinition({ type, name, args, required: false });
1727
+ };
1728
+ this.updatePasswordMutation = async (collection) => {
1729
+ return astBuilder.FieldDefinition({
1730
+ type: astBuilder.TYPES.Boolean,
1731
+ name: "updatePassword",
1732
+ required: true,
1733
+ args: [
1734
+ astBuilder.InputValueDefinition({
1735
+ name: "password",
1736
+ required: true,
1737
+ type: astBuilder.TYPES.String
1738
+ })
1739
+ ]
1740
+ });
1741
+ };
1742
+ this.authorizationCollectionDocument = async (collection) => {
1743
+ const name = "authorize";
1744
+ const type = await this._buildAuthDocumentType(collection);
1745
+ const args = [];
1746
+ return astBuilder.FieldDefinition({ type, name, args, required: false });
1747
+ };
1584
1748
  this.collectionFragment = async (collection) => {
1585
1749
  const name = NAMER.dataTypeName(collection.namespace);
1586
1750
  const fragmentName = NAMER.fragmentName(collection.namespace);
@@ -1625,6 +1789,29 @@ var Builder = class {
1625
1789
  case "boolean":
1626
1790
  case "rich-text":
1627
1791
  return astBuilder.FieldNodeDefinition(field);
1792
+ case "password":
1793
+ const passwordValue = await this._buildFieldNodeForFragments(
1794
+ {
1795
+ name: "value",
1796
+ namespace: [...field.namespace, "value"],
1797
+ type: "string",
1798
+ required: true
1799
+ },
1800
+ depth
1801
+ );
1802
+ const passwordChangeRequired = await this._buildFieldNodeForFragments(
1803
+ {
1804
+ name: "passwordChangeRequired",
1805
+ namespace: [...field.namespace, "passwordChangeRequired"],
1806
+ type: "boolean",
1807
+ required: false
1808
+ },
1809
+ depth
1810
+ );
1811
+ return astBuilder.FieldWithSelectionSetDefinition({
1812
+ name: field.name,
1813
+ selections: filterSelections([passwordValue, passwordChangeRequired])
1814
+ });
1628
1815
  case "object":
1629
1816
  if (((_a = field.fields) == null ? void 0 : _a.length) > 0) {
1630
1817
  const selections2 = [];
@@ -1838,6 +2025,34 @@ var Builder = class {
1838
2025
  ]
1839
2026
  });
1840
2027
  };
2028
+ this._buildAuthDocumentType = async (collection, suffix = "", extraFields = [], extraInterfaces = []) => {
2029
+ const usersFields = mapUserFields(collection, []);
2030
+ if (!usersFields.length) {
2031
+ throw new Error("Auth collection must have a user field");
2032
+ }
2033
+ if (usersFields.length > 1) {
2034
+ throw new Error("Auth collection cannot have more than one user field");
2035
+ }
2036
+ const usersField = usersFields[0].collectable;
2037
+ const documentTypeName = NAMER.documentTypeName(usersField.namespace);
2038
+ const templateInfo = this.tinaSchema.getTemplatesForCollectable(usersField);
2039
+ if (templateInfo.type === "union") {
2040
+ throw new Error("Auth collection user field cannot be a union");
2041
+ }
2042
+ const fields = templateInfo.template.fields;
2043
+ const templateFields = await sequential(fields, async (field) => {
2044
+ return this._buildDataField(field);
2045
+ });
2046
+ return astBuilder.ObjectTypeDefinition({
2047
+ name: documentTypeName + suffix,
2048
+ interfaces: [
2049
+ astBuilder.NamedType({ name: astBuilder.TYPES.Node }),
2050
+ astBuilder.NamedType({ name: astBuilder.TYPES.Document }),
2051
+ ...extraInterfaces
2052
+ ],
2053
+ fields: [...templateFields]
2054
+ });
2055
+ };
1841
2056
  this._filterCollectionDocumentType = async (collection) => {
1842
2057
  const t = this.tinaSchema.getTemplatesForCollectable(collection);
1843
2058
  if (t.type === "union") {
@@ -2096,9 +2311,7 @@ var Builder = class {
2096
2311
  const filter = await this._connectionFilterBuilder({
2097
2312
  fieldName: field.name,
2098
2313
  namespace: field.namespace,
2099
- collections: await this.tinaSchema.getCollectionsByName(
2100
- field.collections
2101
- )
2314
+ collections: this.tinaSchema.getCollectionsByName(field.collections)
2102
2315
  });
2103
2316
  return astBuilder.InputValueDefinition({
2104
2317
  name: field.name,
@@ -2131,6 +2344,8 @@ var Builder = class {
2131
2344
  list: field.list,
2132
2345
  type: astBuilder.TYPES.String
2133
2346
  });
2347
+ case "password":
2348
+ return this._buildPasswordMutation(field);
2134
2349
  case "object":
2135
2350
  return astBuilder.InputValueDefinition({
2136
2351
  name: field.name,
@@ -2165,6 +2380,27 @@ var Builder = class {
2165
2380
  )
2166
2381
  });
2167
2382
  };
2383
+ this._buildPasswordMutation = async (field) => {
2384
+ return astBuilder.InputValueDefinition({
2385
+ name: field.name,
2386
+ list: field.list,
2387
+ type: astBuilder.InputObjectTypeDefinition({
2388
+ name: NAMER.dataMutationTypeName(field.namespace),
2389
+ fields: [
2390
+ astBuilder.InputValueDefinition({
2391
+ name: "value",
2392
+ type: astBuilder.TYPES.String,
2393
+ required: false
2394
+ }),
2395
+ astBuilder.InputValueDefinition({
2396
+ name: "passwordChangeRequired",
2397
+ type: astBuilder.TYPES.Boolean,
2398
+ required: true
2399
+ })
2400
+ ]
2401
+ })
2402
+ });
2403
+ };
2168
2404
  this._buildUpdateDocumentMutationParams = async (field) => {
2169
2405
  const fields = await sequential(
2170
2406
  this.tinaSchema.getCollectionsByName(field.collections),
@@ -2329,6 +2565,29 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2329
2565
  required: field.required,
2330
2566
  type: astBuilder.TYPES.Scalar(field.type)
2331
2567
  });
2568
+ case "password":
2569
+ return astBuilder.FieldDefinition({
2570
+ name: field.name,
2571
+ list: field.list,
2572
+ required: field.required,
2573
+ type: astBuilder.ObjectTypeDefinition({
2574
+ name: NAMER.dataTypeName(field.namespace),
2575
+ fields: [
2576
+ await this._buildDataField({
2577
+ name: "value",
2578
+ namespace: [...field.namespace, "value"],
2579
+ type: "string",
2580
+ required: true
2581
+ }),
2582
+ await this._buildDataField({
2583
+ name: "passwordChangeRequired",
2584
+ namespace: [...field.namespace, "passwordChangeRequired"],
2585
+ type: "boolean",
2586
+ required: false
2587
+ })
2588
+ ]
2589
+ })
2590
+ });
2332
2591
  case "object":
2333
2592
  return astBuilder.FieldDefinition({
2334
2593
  name: field.name,
@@ -2452,7 +2711,8 @@ var FIELD_TYPES = [
2452
2711
  "image",
2453
2712
  "reference",
2454
2713
  "object",
2455
- "rich-text"
2714
+ "rich-text",
2715
+ "password"
2456
2716
  ];
2457
2717
  var validateSchema = async (schema) => {
2458
2718
  const schema2 = addNamespaceToSchema(
@@ -2595,7 +2855,7 @@ var validateField = async (field) => {
2595
2855
  // package.json
2596
2856
  var package_default = {
2597
2857
  name: "@tinacms/graphql",
2598
- version: "1.4.27",
2858
+ version: "1.4.29",
2599
2859
  main: "dist/index.js",
2600
2860
  module: "dist/index.mjs",
2601
2861
  typings: "dist/index.d.ts",
@@ -2650,6 +2910,7 @@ var package_default = {
2650
2910
  micromatch: "4.0.5",
2651
2911
  "normalize-path": "^3.0.0",
2652
2912
  "readable-stream": "^4.3.0",
2913
+ scmp: "^2.1.0",
2653
2914
  yup: "^0.32.9"
2654
2915
  },
2655
2916
  publishConfig: {
@@ -2836,6 +3097,17 @@ var _buildSchema = async (builder, tinaSchema) => {
2836
3097
  );
2837
3098
  await sequential(collections, async (collection) => {
2838
3099
  queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3100
+ if (collection.isAuthCollection) {
3101
+ queryTypeDefinitionFields.push(
3102
+ await builder.authenticationCollectionDocument(collection)
3103
+ );
3104
+ queryTypeDefinitionFields.push(
3105
+ await builder.authorizationCollectionDocument(collection)
3106
+ );
3107
+ mutationTypeDefinitionFields.push(
3108
+ await builder.updatePasswordMutation(collection)
3109
+ );
3110
+ }
2839
3111
  mutationTypeDefinitionFields.push(
2840
3112
  await builder.updateCollectionDocumentMutation(collection)
2841
3113
  );
@@ -3516,7 +3788,7 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
3516
3788
  const template = getTemplateForFile(templateInfo, data);
3517
3789
  if (!template) {
3518
3790
  console.warn(
3519
- `Document: ${filepath} has an ambiguous template, skipping from indexing`
3791
+ `Document: ${filepath} has an ambiguous template, skipping from indexing. See https://tina.io/docs/errors/ambiguous-template/ for more info.`
3520
3792
  );
3521
3793
  return;
3522
3794
  }
@@ -4122,7 +4394,7 @@ var createResolver = (args) => {
4122
4394
  return new Resolver(args);
4123
4395
  };
4124
4396
  var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4125
- var _a;
4397
+ var _a, _b;
4126
4398
  if (!rawData) {
4127
4399
  return void 0;
4128
4400
  }
@@ -4146,6 +4418,12 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4146
4418
  accumulator[field.name] = value;
4147
4419
  }
4148
4420
  break;
4421
+ case "password":
4422
+ accumulator[field.name] = {
4423
+ value: void 0,
4424
+ passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4425
+ };
4426
+ break;
4149
4427
  case "image":
4150
4428
  accumulator[field.name] = resolveMediaRelativeToCloud(
4151
4429
  value,
@@ -4159,7 +4437,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4159
4437
  field,
4160
4438
  (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4161
4439
  );
4162
- if (((_a = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _a.type) === "invalid_markdown") {
4440
+ if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4163
4441
  if (isAudit) {
4164
4442
  const invalidNode = tree == null ? void 0 : tree.children[0];
4165
4443
  throw new import_graphql3.GraphQLError(
@@ -4179,7 +4457,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4179
4457
  (yup3) => yup3.array().of(yup3.object().required())
4180
4458
  );
4181
4459
  accumulator[field.name] = await sequential(value, async (item) => {
4182
- const template = await tinaSchema.getTemplateForData({
4460
+ const template = tinaSchema.getTemplateForData({
4183
4461
  data: item,
4184
4462
  collection: {
4185
4463
  namespace,
@@ -4207,7 +4485,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4207
4485
  if (!value) {
4208
4486
  return;
4209
4487
  }
4210
- const template = await tinaSchema.getTemplateForData({
4488
+ const template = tinaSchema.getTemplateForData({
4211
4489
  data: value,
4212
4490
  collection: {
4213
4491
  namespace,
@@ -4370,43 +4648,71 @@ var Resolver = class {
4370
4648
  }
4371
4649
  await this.database.delete(fullPath);
4372
4650
  };
4373
- this.buildObjectMutations = (fieldValue, field) => {
4651
+ this.buildObjectMutations = async (fieldValue, field, existingData) => {
4374
4652
  if (field.fields) {
4375
4653
  const objectTemplate = field;
4376
4654
  if (Array.isArray(fieldValue)) {
4377
- return fieldValue.map(
4378
- (item) => this.buildFieldMutations(item, objectTemplate)
4655
+ const idField = objectTemplate.fields.find((field2) => field2.uid);
4656
+ if (idField) {
4657
+ const ids = fieldValue.map((d) => d[idField.name]);
4658
+ const duplicateIds = ids.filter(
4659
+ (id, index) => ids.indexOf(id) !== index
4660
+ );
4661
+ if (duplicateIds.length > 0) {
4662
+ throw new Error(
4663
+ `Duplicate ids found in array for field marked as identifier: ${idField.name}`
4664
+ );
4665
+ }
4666
+ }
4667
+ return Promise.all(
4668
+ fieldValue.map(
4669
+ async (item) => {
4670
+ return this.buildFieldMutations(
4671
+ item,
4672
+ objectTemplate,
4673
+ idField && existingData && (existingData == null ? void 0 : existingData.find(
4674
+ (d) => d[idField.name] === item[idField.name]
4675
+ ))
4676
+ );
4677
+ }
4678
+ )
4379
4679
  );
4380
4680
  } else {
4381
4681
  return this.buildFieldMutations(
4382
4682
  fieldValue,
4383
- objectTemplate
4683
+ objectTemplate,
4684
+ existingData
4384
4685
  );
4385
4686
  }
4386
4687
  }
4387
4688
  if (field.templates) {
4388
4689
  if (Array.isArray(fieldValue)) {
4389
- return fieldValue.map((item) => {
4390
- if (typeof item === "string") {
4391
- throw new Error(
4392
- `Expected object for template value for field ${field.name}`
4690
+ return Promise.all(
4691
+ fieldValue.map(async (item) => {
4692
+ if (typeof item === "string") {
4693
+ throw new Error(
4694
+ `Expected object for template value for field ${field.name}`
4695
+ );
4696
+ }
4697
+ const templates = field.templates.map((templateOrTemplateName) => {
4698
+ return templateOrTemplateName;
4699
+ });
4700
+ const [templateName] = Object.entries(item)[0];
4701
+ const template = templates.find(
4702
+ (template2) => template2.name === templateName
4393
4703
  );
4394
- }
4395
- const templates = field.templates.map((templateOrTemplateName) => {
4396
- return templateOrTemplateName;
4397
- });
4398
- const [templateName] = Object.entries(item)[0];
4399
- const template = templates.find(
4400
- (template2) => template2.name === templateName
4401
- );
4402
- if (!template) {
4403
- throw new Error(`Expected to find template ${templateName}`);
4404
- }
4405
- return {
4406
- ...this.buildFieldMutations(item[template.name], template),
4407
- _template: template.name
4408
- };
4409
- });
4704
+ if (!template) {
4705
+ throw new Error(`Expected to find template ${templateName}`);
4706
+ }
4707
+ return {
4708
+ ...await this.buildFieldMutations(
4709
+ item[template.name],
4710
+ template
4711
+ ),
4712
+ _template: template.name
4713
+ };
4714
+ })
4715
+ );
4410
4716
  } else {
4411
4717
  if (typeof fieldValue === "string") {
4412
4718
  throw new Error(
@@ -4424,7 +4730,10 @@ var Resolver = class {
4424
4730
  throw new Error(`Expected to find template ${templateName}`);
4425
4731
  }
4426
4732
  return {
4427
- ...this.buildFieldMutations(fieldValue[template.name], template),
4733
+ ...await this.buildFieldMutations(
4734
+ fieldValue[template.name],
4735
+ template
4736
+ ),
4428
4737
  _template: template.name
4429
4738
  };
4430
4739
  }
@@ -4463,7 +4772,7 @@ var Resolver = class {
4463
4772
  }
4464
4773
  return this.getDocument(realPath);
4465
4774
  }
4466
- const params = this.buildObjectMutations(
4775
+ const params = await this.buildObjectMutations(
4467
4776
  args.params[collection.name],
4468
4777
  collection
4469
4778
  );
@@ -4485,9 +4794,10 @@ var Resolver = class {
4485
4794
  switch (templateInfo.type) {
4486
4795
  case "object":
4487
4796
  if (params2) {
4488
- const values = this.buildFieldMutations(
4797
+ const values = await this.buildFieldMutations(
4489
4798
  params2,
4490
- templateInfo.template
4799
+ templateInfo.template,
4800
+ doc == null ? void 0 : doc._rawData
4491
4801
  );
4492
4802
  await this.database.put(
4493
4803
  realPath,
@@ -4507,7 +4817,11 @@ var Resolver = class {
4507
4817
  }
4508
4818
  const values = {
4509
4819
  ...oldDoc,
4510
- ...this.buildFieldMutations(templateParams, template),
4820
+ ...await this.buildFieldMutations(
4821
+ templateParams,
4822
+ template,
4823
+ doc == null ? void 0 : doc._rawData
4824
+ ),
4511
4825
  _template: lastItem(template.namespace)
4512
4826
  };
4513
4827
  await this.database.put(realPath, values, collection.name);
@@ -4516,9 +4830,10 @@ var Resolver = class {
4516
4830
  }
4517
4831
  return this.getDocument(realPath);
4518
4832
  }
4519
- const params = this.buildObjectMutations(
4833
+ const params = await this.buildObjectMutations(
4520
4834
  isCollectionSpecific ? args.params : args.params[collection.name],
4521
- collection
4835
+ collection,
4836
+ doc == null ? void 0 : doc._rawData
4522
4837
  );
4523
4838
  await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
4524
4839
  return this.getDocument(realPath);
@@ -4748,9 +5063,20 @@ var Resolver = class {
4748
5063
  }
4749
5064
  };
4750
5065
  };
4751
- this.buildFieldMutations = (fieldParams, template) => {
5066
+ this.buildFieldMutations = async (fieldParams, template, existingData) => {
5067
+ var _a;
4752
5068
  const accum = {};
4753
- Object.entries(fieldParams).forEach(([fieldName, fieldValue]) => {
5069
+ for (const passwordField of template.fields.filter(
5070
+ (f) => f.type === "password"
5071
+ )) {
5072
+ if (!fieldParams[passwordField.name]["value"]) {
5073
+ fieldParams[passwordField.name] = {
5074
+ ...fieldParams[passwordField.name],
5075
+ value: ""
5076
+ };
5077
+ }
5078
+ }
5079
+ for (const [fieldName, fieldValue] of Object.entries(fieldParams)) {
4754
5080
  if (Array.isArray(fieldValue)) {
4755
5081
  if (fieldValue.length === 0) {
4756
5082
  accum[fieldName] = [];
@@ -4778,7 +5104,31 @@ var Resolver = class {
4778
5104
  );
4779
5105
  break;
4780
5106
  case "object":
4781
- accum[fieldName] = this.buildObjectMutations(fieldValue, field);
5107
+ accum[fieldName] = await this.buildObjectMutations(
5108
+ fieldValue,
5109
+ field,
5110
+ existingData == null ? void 0 : existingData[fieldName]
5111
+ );
5112
+ break;
5113
+ case "password":
5114
+ if (typeof fieldValue !== "object") {
5115
+ throw new Error(
5116
+ `Expected to find object for password field ${fieldName}. Found ${typeof accum[fieldName]}`
5117
+ );
5118
+ }
5119
+ if (fieldValue["value"]) {
5120
+ accum[fieldName] = {
5121
+ ...fieldValue,
5122
+ value: await generatePasswordHash({
5123
+ password: fieldValue["value"]
5124
+ })
5125
+ };
5126
+ } else {
5127
+ accum[fieldName] = {
5128
+ ...fieldValue,
5129
+ value: (_a = existingData == null ? void 0 : existingData[fieldName]) == null ? void 0 : _a["value"]
5130
+ };
5131
+ }
4782
5132
  break;
4783
5133
  case "rich-text":
4784
5134
  accum[fieldName] = (0, import_mdx.stringifyMDX)(
@@ -4797,7 +5147,7 @@ var Resolver = class {
4797
5147
  default:
4798
5148
  throw new Error(`No mutation builder for field type ${field.type}`);
4799
5149
  }
4800
- });
5150
+ }
4801
5151
  return accum;
4802
5152
  };
4803
5153
  this.buildParams = (args) => {
@@ -4867,6 +5217,9 @@ var resolveDateInput = (value) => {
4867
5217
  return date;
4868
5218
  };
4869
5219
 
5220
+ // src/resolve.ts
5221
+ var import_lodash4 = __toESM(require("lodash"));
5222
+
4870
5223
  // src/error.ts
4871
5224
  var import_graphql4 = require("graphql");
4872
5225
  var NotFoundError = class extends import_graphql4.GraphQLError {
@@ -4884,7 +5237,8 @@ var resolve = async ({
4884
5237
  database,
4885
5238
  silenceErrors,
4886
5239
  verbose,
4887
- isAudit
5240
+ isAudit,
5241
+ ctxUser
4888
5242
  }) => {
4889
5243
  var _a;
4890
5244
  try {
@@ -4899,7 +5253,7 @@ var resolve = async ({
4899
5253
  schema: tinaConfig,
4900
5254
  flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
4901
5255
  });
4902
- const resolver = await createResolver({
5256
+ const resolver = createResolver({
4903
5257
  config,
4904
5258
  database,
4905
5259
  tinaSchema,
@@ -4977,6 +5331,121 @@ var resolve = async ({
4977
5331
  );
4978
5332
  }
4979
5333
  }
5334
+ if (info.fieldName === "authenticate" || info.fieldName === "authorize") {
5335
+ const sub = args.sub || (ctxUser == null ? void 0 : ctxUser.sub);
5336
+ const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5337
+ if (!collection) {
5338
+ throw new Error(`Auth collection not found`);
5339
+ }
5340
+ const userFields = mapUserFields(collection, ["_rawData"]);
5341
+ if (!userFields.length) {
5342
+ throw new Error(
5343
+ `No user field found in collection ${collection.name}`
5344
+ );
5345
+ }
5346
+ if (userFields.length > 1) {
5347
+ throw new Error(
5348
+ `Multiple user fields found in collection ${collection.name}`
5349
+ );
5350
+ }
5351
+ const userField = userFields[0];
5352
+ const realPath = `${collection.path}/index.json`;
5353
+ const userDoc = await resolver.getDocument(realPath);
5354
+ const users = import_lodash4.default.get(userDoc, userField.path);
5355
+ if (!users) {
5356
+ throw new Error("No users found");
5357
+ }
5358
+ const { idFieldName, passwordFieldName } = userField;
5359
+ if (!idFieldName) {
5360
+ throw new Error("No uid field found on user field");
5361
+ }
5362
+ const user = users.find((u) => u[idFieldName] === sub);
5363
+ if (!user) {
5364
+ return null;
5365
+ }
5366
+ if (info.fieldName === "authenticate") {
5367
+ const saltedHash = import_lodash4.default.get(user, [passwordFieldName || "", "value"]);
5368
+ if (!saltedHash) {
5369
+ throw new Error("No password field found on user field");
5370
+ }
5371
+ const matches = await checkPasswordHash({
5372
+ saltedHash,
5373
+ password: args.password
5374
+ });
5375
+ if (matches) {
5376
+ return user;
5377
+ } else {
5378
+ return null;
5379
+ }
5380
+ } else {
5381
+ return user;
5382
+ }
5383
+ }
5384
+ if (info.fieldName === "updatePassword") {
5385
+ if (!(ctxUser == null ? void 0 : ctxUser.sub)) {
5386
+ throw new Error("Not authorized");
5387
+ }
5388
+ if (!args.password) {
5389
+ throw new Error("No password provided");
5390
+ }
5391
+ const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5392
+ if (!collection) {
5393
+ throw new Error(`Auth collection not found`);
5394
+ }
5395
+ const userFields = mapUserFields(collection, ["_rawData"]);
5396
+ if (!userFields.length) {
5397
+ throw new Error(
5398
+ `No user field found in collection ${collection.name}`
5399
+ );
5400
+ }
5401
+ if (userFields.length > 1) {
5402
+ throw new Error(
5403
+ `Multiple user fields found in collection ${collection.name}`
5404
+ );
5405
+ }
5406
+ const userField = userFields[0];
5407
+ const realPath = `${collection.path}/index.json`;
5408
+ const userDoc = await resolver.getDocument(realPath);
5409
+ const users = import_lodash4.default.get(userDoc, userField.path);
5410
+ if (!users) {
5411
+ throw new Error("No users found");
5412
+ }
5413
+ const { idFieldName, passwordFieldName } = userField;
5414
+ const user = users.find((u) => u[idFieldName] === ctxUser.sub);
5415
+ if (!user) {
5416
+ throw new Error("Not authorized");
5417
+ }
5418
+ user[passwordFieldName] = {
5419
+ value: args.password,
5420
+ passwordChangeRequired: false
5421
+ };
5422
+ const params = {};
5423
+ import_lodash4.default.set(
5424
+ params,
5425
+ userField.path.slice(1),
5426
+ users.map((u) => {
5427
+ if (user[idFieldName] === u[idFieldName]) {
5428
+ return user;
5429
+ } else {
5430
+ return {
5431
+ ...u,
5432
+ [passwordFieldName]: {
5433
+ ...u[passwordFieldName],
5434
+ value: ""
5435
+ }
5436
+ };
5437
+ }
5438
+ })
5439
+ );
5440
+ await resolver.updateResolveDocument({
5441
+ collection,
5442
+ args: { params },
5443
+ realPath,
5444
+ isCollectionSpecific: true,
5445
+ isAddPendingDocument: false
5446
+ });
5447
+ return true;
5448
+ }
4980
5449
  if (!lookup) {
4981
5450
  return value;
4982
5451
  }
@@ -5117,12 +5586,78 @@ var resolve = async ({
5117
5586
  }
5118
5587
  };
5119
5588
 
5589
+ // src/level/tinaLevel.ts
5590
+ var import_many_level = require("many-level");
5591
+ var import_readable_stream = require("readable-stream");
5592
+ var import_net = require("net");
5593
+ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5594
+ constructor(port) {
5595
+ super();
5596
+ this._connected = false;
5597
+ this.port = port || 9e3;
5598
+ }
5599
+ openConnection() {
5600
+ if (this._connected)
5601
+ return;
5602
+ const socket = (0, import_net.connect)(this.port);
5603
+ (0, import_readable_stream.pipeline)(socket, this.createRpcStream(), socket, () => {
5604
+ this._connected = false;
5605
+ });
5606
+ this._connected = true;
5607
+ }
5608
+ };
5609
+
5120
5610
  // src/database/index.ts
5121
5611
  var import_path4 = __toESM(require("path"));
5122
5612
  var import_graphql6 = require("graphql");
5123
5613
  var import_micromatch2 = __toESM(require("micromatch"));
5124
5614
  var import_js_sha12 = __toESM(require("js-sha1"));
5615
+ var import_lodash5 = __toESM(require("lodash"));
5616
+ var createLocalDatabase = (config) => {
5617
+ const level = new TinaLevelClient(config == null ? void 0 : config.port);
5618
+ level.openConnection();
5619
+ const fsBridge = new FilesystemBridge((config == null ? void 0 : config.rootPath) || process.cwd());
5620
+ return new Database({
5621
+ bridge: fsBridge,
5622
+ ...config || {},
5623
+ level
5624
+ });
5625
+ };
5125
5626
  var createDatabase = (config) => {
5627
+ if (config.onPut && config.onDelete) {
5628
+ console.warn(
5629
+ "onPut and onDelete are deprecated. Please use gitProvider.onPut and gitProvider.onDelete instead."
5630
+ );
5631
+ }
5632
+ if (config.level) {
5633
+ console.warn("level is deprecated. Please use databaseAdapter instead.");
5634
+ }
5635
+ if (config.onPut && config.onDelete && config.level && !config.databaseAdapter && !config.gitProvider) {
5636
+ return new Database({
5637
+ ...config,
5638
+ level: config.level
5639
+ });
5640
+ }
5641
+ if (!config.gitProvider) {
5642
+ throw new Error(
5643
+ "createDatabase requires a gitProvider. Please provide a gitProvider."
5644
+ );
5645
+ }
5646
+ if (!config.databaseAdapter) {
5647
+ throw new Error(
5648
+ "createDatabase requires a databaseAdapter. Please provide a databaseAdapter."
5649
+ );
5650
+ }
5651
+ return new Database({
5652
+ ...config,
5653
+ bridge: config.bridge,
5654
+ level: config.databaseAdapter,
5655
+ onPut: config.gitProvider.onPut.bind(config.gitProvider),
5656
+ onDelete: config.gitProvider.onDelete.bind(config.gitProvider),
5657
+ namespace: config.namespace || "tinacms"
5658
+ });
5659
+ };
5660
+ var createDatabaseInternal = (config) => {
5126
5661
  return new Database({
5127
5662
  ...config,
5128
5663
  bridge: config.bridge,
@@ -5137,7 +5672,7 @@ var Database = class {
5137
5672
  constructor(config) {
5138
5673
  this.config = config;
5139
5674
  this.collectionForPath = async (filepath) => {
5140
- const tinaSchema = await this.getSchema(this.level);
5675
+ const tinaSchema = await this.getSchema(this.contentLevel);
5141
5676
  try {
5142
5677
  return tinaSchema.getCollectionByFullPath(filepath);
5143
5678
  } catch (e) {
@@ -5146,13 +5681,25 @@ var Database = class {
5146
5681
  this.getGeneratedFolder = () => import_path4.default.join(this.tinaDirectory, "__generated__");
5147
5682
  this.getMetadata = async (key) => {
5148
5683
  await this.initLevel();
5149
- const metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
5684
+ let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
5685
+ if (this.contentNamespace) {
5686
+ metadataLevel = metadataLevel.sublevel(
5687
+ this.contentNamespace,
5688
+ SUBLEVEL_OPTIONS
5689
+ );
5690
+ }
5150
5691
  const metadata = await metadataLevel.get(`metadata_${key}`);
5151
5692
  return metadata == null ? void 0 : metadata.value;
5152
5693
  };
5153
5694
  this.setMetadata = async (key, value) => {
5154
5695
  await this.initLevel();
5155
- const metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
5696
+ let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
5697
+ if (this.contentNamespace) {
5698
+ metadataLevel = metadataLevel.sublevel(
5699
+ this.contentNamespace,
5700
+ SUBLEVEL_OPTIONS
5701
+ );
5702
+ }
5156
5703
  return metadataLevel.put(`metadata_${key}`, { value });
5157
5704
  };
5158
5705
  this.get = async (filepath) => {
@@ -5160,7 +5707,15 @@ var Database = class {
5160
5707
  if (SYSTEM_FILES.includes(filepath)) {
5161
5708
  throw new Error(`Unexpected get for config file ${filepath}`);
5162
5709
  } else {
5163
- const contentObject = await this.level.sublevel(
5710
+ let collection;
5711
+ let level = this.contentLevel;
5712
+ if (this.appLevel) {
5713
+ collection = await this.collectionForPath(filepath);
5714
+ if (collection == null ? void 0 : collection.isDetached) {
5715
+ level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
5716
+ }
5717
+ }
5718
+ const contentObject = await level.sublevel(
5164
5719
  CONTENT_ROOT_PREFIX,
5165
5720
  SUBLEVEL_OPTIONS
5166
5721
  ).get((0, import_schema_tools3.normalizePath)(filepath));
@@ -5170,7 +5725,7 @@ var Database = class {
5170
5725
  return transformDocument(
5171
5726
  filepath,
5172
5727
  contentObject,
5173
- await this.getSchema(this.level)
5728
+ await this.getSchema(this.contentLevel)
5174
5729
  );
5175
5730
  }
5176
5731
  };
@@ -5186,23 +5741,29 @@ var Database = class {
5186
5741
  dataFields,
5187
5742
  collection
5188
5743
  );
5189
- const indexDefinitions = await this.getIndexDefinitions(this.level);
5744
+ const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
5190
5745
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
5191
5746
  const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
5192
- if (this.bridge) {
5193
- await this.bridge.put(normalizedPath, stringifiedFile);
5747
+ if (!(collection == null ? void 0 : collection.isDetached)) {
5748
+ if (this.bridge) {
5749
+ await this.bridge.put(normalizedPath, stringifiedFile);
5750
+ }
5751
+ try {
5752
+ await this.onPut(normalizedPath, stringifiedFile);
5753
+ } catch (e) {
5754
+ throw new import_graphql6.GraphQLError(
5755
+ `Error running onPut hook for ${filepath}: ${e}`,
5756
+ null,
5757
+ null,
5758
+ null,
5759
+ null,
5760
+ e
5761
+ );
5762
+ }
5194
5763
  }
5195
- try {
5196
- await this.onPut(normalizedPath, stringifiedFile);
5197
- } catch (e) {
5198
- throw new import_graphql6.GraphQLError(
5199
- `Error running onPut hook for ${filepath}: ${e}`,
5200
- null,
5201
- null,
5202
- null,
5203
- null,
5204
- e
5205
- );
5764
+ let level = this.contentLevel;
5765
+ if (collection == null ? void 0 : collection.isDetached) {
5766
+ level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
5206
5767
  }
5207
5768
  const folderTreeBuilder = new FolderTreeBuilder();
5208
5769
  const folderKey = folderTreeBuilder.update(filepath, collection.path || "");
@@ -5213,7 +5774,7 @@ var Database = class {
5213
5774
  collectionIndexDefinitions,
5214
5775
  dataFields,
5215
5776
  "put",
5216
- this.level
5777
+ level
5217
5778
  ),
5218
5779
  ...makeIndexOpsForDocument(
5219
5780
  normalizedPath,
@@ -5221,10 +5782,10 @@ var Database = class {
5221
5782
  collectionIndexDefinitions,
5222
5783
  dataFields,
5223
5784
  "put",
5224
- this.level
5785
+ level
5225
5786
  )
5226
5787
  ];
5227
- const existingItem = await this.level.sublevel(
5788
+ const existingItem = await level.sublevel(
5228
5789
  CONTENT_ROOT_PREFIX,
5229
5790
  SUBLEVEL_OPTIONS
5230
5791
  ).get(normalizedPath);
@@ -5235,7 +5796,7 @@ var Database = class {
5235
5796
  collectionIndexDefinitions,
5236
5797
  existingItem,
5237
5798
  "del",
5238
- this.level
5799
+ level
5239
5800
  ),
5240
5801
  ...makeIndexOpsForDocument(
5241
5802
  normalizedPath,
@@ -5243,7 +5804,7 @@ var Database = class {
5243
5804
  collectionIndexDefinitions,
5244
5805
  existingItem,
5245
5806
  "del",
5246
- this.level
5807
+ level
5247
5808
  )
5248
5809
  ] : [];
5249
5810
  const ops = [
@@ -5253,13 +5814,13 @@ var Database = class {
5253
5814
  type: "put",
5254
5815
  key: normalizedPath,
5255
5816
  value: dataFields,
5256
- sublevel: this.level.sublevel(
5817
+ sublevel: level.sublevel(
5257
5818
  CONTENT_ROOT_PREFIX,
5258
5819
  SUBLEVEL_OPTIONS
5259
5820
  )
5260
5821
  }
5261
5822
  ];
5262
- await this.level.batch(ops);
5823
+ await level.batch(ops);
5263
5824
  };
5264
5825
  this.put = async (filepath, data, collectionName) => {
5265
5826
  var _a, _b;
@@ -5270,7 +5831,9 @@ var Database = class {
5270
5831
  } else {
5271
5832
  let collectionIndexDefinitions;
5272
5833
  if (collectionName) {
5273
- const indexDefinitions = await this.getIndexDefinitions(this.level);
5834
+ const indexDefinitions = await this.getIndexDefinitions(
5835
+ this.contentLevel
5836
+ );
5274
5837
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
5275
5838
  }
5276
5839
  const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
@@ -5295,26 +5858,29 @@ var Database = class {
5295
5858
  dataFields,
5296
5859
  collection
5297
5860
  );
5298
- if (this.bridge) {
5299
- await this.bridge.put(normalizedPath, stringifiedFile);
5300
- }
5301
- try {
5302
- await this.onPut(normalizedPath, stringifiedFile);
5303
- } catch (e) {
5304
- throw new import_graphql6.GraphQLError(
5305
- `Error running onPut hook for ${filepath}: ${e}`,
5306
- null,
5307
- null,
5308
- null,
5309
- null,
5310
- e
5311
- );
5861
+ if (!(collection == null ? void 0 : collection.isDetached)) {
5862
+ if (this.bridge) {
5863
+ await this.bridge.put(normalizedPath, stringifiedFile);
5864
+ }
5865
+ try {
5866
+ await this.onPut(normalizedPath, stringifiedFile);
5867
+ } catch (e) {
5868
+ throw new import_graphql6.GraphQLError(
5869
+ `Error running onPut hook for ${filepath}: ${e}`,
5870
+ null,
5871
+ null,
5872
+ null,
5873
+ null,
5874
+ e
5875
+ );
5876
+ }
5312
5877
  }
5313
5878
  const folderTreeBuilder = new FolderTreeBuilder();
5314
5879
  const folderKey = folderTreeBuilder.update(
5315
5880
  filepath,
5316
5881
  collection.path || ""
5317
5882
  );
5883
+ const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
5318
5884
  const putOps = [
5319
5885
  ...makeIndexOpsForDocument(
5320
5886
  normalizedPath,
@@ -5322,7 +5888,7 @@ var Database = class {
5322
5888
  collectionIndexDefinitions,
5323
5889
  dataFields,
5324
5890
  "put",
5325
- this.level
5891
+ level
5326
5892
  ),
5327
5893
  ...makeIndexOpsForDocument(
5328
5894
  normalizedPath,
@@ -5330,10 +5896,10 @@ var Database = class {
5330
5896
  collectionIndexDefinitions,
5331
5897
  dataFields,
5332
5898
  "put",
5333
- this.level
5899
+ level
5334
5900
  )
5335
5901
  ];
5336
- const existingItem = await this.level.sublevel(
5902
+ const existingItem = await level.sublevel(
5337
5903
  CONTENT_ROOT_PREFIX,
5338
5904
  SUBLEVEL_OPTIONS
5339
5905
  ).get(normalizedPath);
@@ -5344,7 +5910,7 @@ var Database = class {
5344
5910
  collectionIndexDefinitions,
5345
5911
  existingItem,
5346
5912
  "del",
5347
- this.level
5913
+ level
5348
5914
  ),
5349
5915
  ...makeIndexOpsForDocument(
5350
5916
  normalizedPath,
@@ -5352,7 +5918,7 @@ var Database = class {
5352
5918
  collectionIndexDefinitions,
5353
5919
  existingItem,
5354
5920
  "del",
5355
- this.level
5921
+ level
5356
5922
  )
5357
5923
  ] : [];
5358
5924
  const ops = [
@@ -5362,13 +5928,13 @@ var Database = class {
5362
5928
  type: "put",
5363
5929
  key: normalizedPath,
5364
5930
  value: dataFields,
5365
- sublevel: this.level.sublevel(
5931
+ sublevel: level.sublevel(
5366
5932
  CONTENT_ROOT_PREFIX,
5367
5933
  SUBLEVEL_OPTIONS
5368
5934
  )
5369
5935
  }
5370
5936
  ];
5371
- await this.level.batch(ops);
5937
+ await level.batch(ops);
5372
5938
  }
5373
5939
  return true;
5374
5940
  } catch (error) {
@@ -5418,7 +5984,7 @@ var Database = class {
5418
5984
  const writeTemplateKey = templateDetails.info.type === "union";
5419
5985
  const aliasedData = applyNameOverrides(templateDetails.template, payload);
5420
5986
  const extension = import_path4.default.extname(filepath);
5421
- const stringifiedFile = stringifyFile(
5987
+ return stringifyFile(
5422
5988
  aliasedData,
5423
5989
  extension,
5424
5990
  writeTemplateKey,
@@ -5427,7 +5993,6 @@ var Database = class {
5427
5993
  frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
5428
5994
  }
5429
5995
  );
5430
- return stringifiedFile;
5431
5996
  };
5432
5997
  this.flush = async (filepath) => {
5433
5998
  const data = await this.get(filepath);
@@ -5436,12 +6001,7 @@ var Database = class {
5436
6001
  if (!collection) {
5437
6002
  throw new Error(`Unable to find collection for path ${filepath}`);
5438
6003
  }
5439
- const stringifiedFile = await this.stringifyFile(
5440
- filepath,
5441
- dataFields,
5442
- collection
5443
- );
5444
- return stringifiedFile;
6004
+ return this.stringifyFile(filepath, dataFields, collection);
5445
6005
  };
5446
6006
  this.getLookup = async (returnType) => {
5447
6007
  await this.initLevel();
@@ -5449,11 +6009,10 @@ var Database = class {
5449
6009
  import_path4.default.join(this.getGeneratedFolder(), `_lookup.json`)
5450
6010
  );
5451
6011
  if (!this._lookup) {
5452
- const _lookup = await this.level.sublevel(
6012
+ this._lookup = await this.contentLevel.sublevel(
5453
6013
  CONTENT_ROOT_PREFIX,
5454
6014
  SUBLEVEL_OPTIONS
5455
6015
  ).get(lookupPath);
5456
- this._lookup = _lookup;
5457
6016
  }
5458
6017
  return this._lookup[returnType];
5459
6018
  };
@@ -5462,7 +6021,7 @@ var Database = class {
5462
6021
  const graphqlPath = (0, import_schema_tools3.normalizePath)(
5463
6022
  import_path4.default.join(this.getGeneratedFolder(), `_graphql.json`)
5464
6023
  );
5465
- return await this.level.sublevel(
6024
+ return await this.contentLevel.sublevel(
5466
6025
  CONTENT_ROOT_PREFIX,
5467
6026
  SUBLEVEL_OPTIONS
5468
6027
  ).get(graphqlPath);
@@ -5482,7 +6041,7 @@ var Database = class {
5482
6041
  const schemaPath = (0, import_schema_tools3.normalizePath)(
5483
6042
  import_path4.default.join(this.getGeneratedFolder(), `_schema.json`)
5484
6043
  );
5485
- return await (level || this.level).sublevel(
6044
+ return await (level || this.contentLevel).sublevel(
5486
6045
  CONTENT_ROOT_PREFIX,
5487
6046
  SUBLEVEL_OPTIONS
5488
6047
  ).get(schemaPath);
@@ -5492,7 +6051,7 @@ var Database = class {
5492
6051
  return this.tinaSchema;
5493
6052
  }
5494
6053
  await this.initLevel();
5495
- const schema = existingSchema || await this.getTinaSchema(level || this.level);
6054
+ const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
5496
6055
  if (!schema) {
5497
6056
  throw new Error(
5498
6057
  `Unable to get schema from level db: ${(0, import_schema_tools3.normalizePath)(
@@ -5508,7 +6067,7 @@ var Database = class {
5508
6067
  await new Promise(async (resolve2, reject) => {
5509
6068
  await this.initLevel();
5510
6069
  try {
5511
- const schema = await this.getSchema(level || this.level);
6070
+ const schema = await this.getSchema(level || this.contentLevel);
5512
6071
  const collections = schema.getCollections();
5513
6072
  for (const collection of collections) {
5514
6073
  const indexDefinitions = {
@@ -5575,7 +6134,6 @@ var Database = class {
5575
6134
  last,
5576
6135
  before,
5577
6136
  sort = DEFAULT_COLLECTION_SORT_KEY,
5578
- collection,
5579
6137
  filterChain: rawFilterChain,
5580
6138
  folder
5581
6139
  } = queryOptions;
@@ -5591,22 +6149,25 @@ var Database = class {
5591
6149
  } else if (before) {
5592
6150
  query.lt = atob(before);
5593
6151
  }
5594
- const allIndexDefinitions = await this.getIndexDefinitions(this.level);
5595
- const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[queryOptions.collection];
6152
+ const tinaSchema = await this.getSchema(this.contentLevel);
6153
+ const collection = tinaSchema.getCollection(queryOptions.collection);
6154
+ const allIndexDefinitions = await this.getIndexDefinitions(
6155
+ this.contentLevel
6156
+ );
6157
+ const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[collection.name];
5596
6158
  if (!indexDefinitions) {
5597
- throw new Error(
5598
- `No indexDefinitions for collection ${queryOptions.collection}`
5599
- );
6159
+ throw new Error(`No indexDefinitions for collection ${collection.name}`);
5600
6160
  }
5601
6161
  const filterChain = coerceFilterChainOperands(rawFilterChain);
5602
6162
  const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
5603
6163
  const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
5604
- const rootLevel = this.level.sublevel(
6164
+ const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6165
+ const rootLevel = level.sublevel(
5605
6166
  CONTENT_ROOT_PREFIX,
5606
6167
  SUBLEVEL_OPTIONS
5607
6168
  );
5608
- const sublevel = indexDefinition ? this.level.sublevel(
5609
- `${collection}${folder ? `_${folder === FOLDER_ROOT ? folder : import_js_sha12.default.hex(folder)}` : ""}`,
6169
+ const sublevel = indexDefinition ? level.sublevel(
6170
+ `${collection.name}${folder ? `_${folder === FOLDER_ROOT ? folder : import_js_sha12.default.hex(folder)}` : ""}`,
5610
6171
  SUBLEVEL_OPTIONS
5611
6172
  ).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
5612
6173
  if (!query.gt && !query.gte) {
@@ -5678,7 +6239,7 @@ var Database = class {
5678
6239
  throw new TinaQueryError({
5679
6240
  originalError: error,
5680
6241
  file: edge.path,
5681
- collection,
6242
+ collection: collection.name,
5682
6243
  stack: error.stack
5683
6244
  });
5684
6245
  } else {
@@ -5726,8 +6287,8 @@ var Database = class {
5726
6287
  }
5727
6288
  let nextVersion;
5728
6289
  if (!this.config.version) {
5729
- await this.level.clear();
5730
- nextLevel = this.level;
6290
+ await this.contentLevel.clear();
6291
+ nextLevel = this.contentLevel;
5731
6292
  } else {
5732
6293
  const version = await this.getDatabaseVersion();
5733
6294
  nextVersion = version ? `${parseInt(version) + 1}` : "0";
@@ -5757,10 +6318,10 @@ var Database = class {
5757
6318
  },
5758
6319
  async () => {
5759
6320
  if (this.config.version) {
5760
- if (this.level) {
5761
- await this.level.clear();
6321
+ if (this.contentLevel) {
6322
+ await this.contentLevel.clear();
5762
6323
  }
5763
- this.level = nextLevel;
6324
+ this.contentLevel = nextLevel;
5764
6325
  }
5765
6326
  }
5766
6327
  );
@@ -5771,10 +6332,10 @@ var Database = class {
5771
6332
  const enqueueOps = async (ops) => {
5772
6333
  operations.push(...ops);
5773
6334
  while (operations.length >= 25) {
5774
- await this.level.batch(operations.splice(0, 25));
6335
+ await this.contentLevel.batch(operations.splice(0, 25));
5775
6336
  }
5776
6337
  };
5777
- const tinaSchema = await this.getSchema(this.level);
6338
+ const tinaSchema = await this.getSchema(this.contentLevel);
5778
6339
  await this.indexStatusCallbackWrapper(async () => {
5779
6340
  const { pathsByCollection, nonCollectionPaths, collections } = await partitionPathsByCollection(tinaSchema, documentPaths);
5780
6341
  for (const collection of Object.keys(pathsByCollection)) {
@@ -5790,7 +6351,7 @@ var Database = class {
5790
6351
  }
5791
6352
  });
5792
6353
  while (operations.length) {
5793
- await this.level.batch(operations.splice(0, 25));
6354
+ await this.contentLevel.batch(operations.splice(0, 25));
5794
6355
  }
5795
6356
  };
5796
6357
  this.indexContentByPaths = async (documentPaths) => {
@@ -5799,31 +6360,29 @@ var Database = class {
5799
6360
  const enqueueOps = async (ops) => {
5800
6361
  operations.push(...ops);
5801
6362
  while (operations.length >= 25) {
5802
- await this.level.batch(operations.splice(0, 25));
6363
+ await this.contentLevel.batch(operations.splice(0, 25));
5803
6364
  }
5804
6365
  };
5805
- const tinaSchema = await this.getSchema(this.level);
6366
+ const tinaSchema = await this.getSchema(this.contentLevel);
5806
6367
  await this.indexStatusCallbackWrapper(async () => {
5807
6368
  await scanContentByPaths(
5808
6369
  tinaSchema,
5809
6370
  documentPaths,
5810
6371
  async (collection, documentPaths2) => {
5811
- if (collection) {
6372
+ if (collection && !collection.isDetached) {
5812
6373
  await _indexContent(
5813
6374
  this,
5814
- this.level,
6375
+ this.contentLevel,
5815
6376
  documentPaths2,
5816
6377
  enqueueOps,
5817
6378
  collection
5818
6379
  );
5819
- } else {
5820
- await _indexContent(this, this.level, documentPaths2, enqueueOps);
5821
6380
  }
5822
6381
  }
5823
6382
  );
5824
6383
  });
5825
6384
  while (operations.length) {
5826
- await this.level.batch(operations.splice(0, 25));
6385
+ await this.contentLevel.batch(operations.splice(0, 25));
5827
6386
  }
5828
6387
  };
5829
6388
  this.delete = async (filepath) => {
@@ -5832,14 +6391,14 @@ var Database = class {
5832
6391
  if (!collection) {
5833
6392
  throw new Error(`No collection found for path: ${filepath}`);
5834
6393
  }
5835
- const indexDefinitions = await this.getIndexDefinitions(this.level);
6394
+ const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
5836
6395
  const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
5837
- this.level.sublevel(
5838
- CONTENT_ROOT_PREFIX,
5839
- SUBLEVEL_OPTIONS
5840
- );
6396
+ let level = this.contentLevel;
6397
+ if (collection == null ? void 0 : collection.isDetached) {
6398
+ level = this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS);
6399
+ }
5841
6400
  const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
5842
- const rootSublevel = this.level.sublevel(
6401
+ const rootSublevel = level.sublevel(
5843
6402
  CONTENT_ROOT_PREFIX,
5844
6403
  SUBLEVEL_OPTIONS
5845
6404
  );
@@ -5850,14 +6409,14 @@ var Database = class {
5850
6409
  filepath,
5851
6410
  collection.path || ""
5852
6411
  );
5853
- await this.level.batch([
6412
+ await this.contentLevel.batch([
5854
6413
  ...makeIndexOpsForDocument(
5855
6414
  filepath,
5856
6415
  collection.name,
5857
6416
  collectionIndexDefinitions,
5858
6417
  item,
5859
6418
  "del",
5860
- this.level
6419
+ level
5861
6420
  ),
5862
6421
  ...makeIndexOpsForDocument(
5863
6422
  filepath,
@@ -5865,7 +6424,7 @@ var Database = class {
5865
6424
  collectionIndexDefinitions,
5866
6425
  item,
5867
6426
  "del",
5868
- this.level
6427
+ level
5869
6428
  ),
5870
6429
  {
5871
6430
  type: "del",
@@ -5874,20 +6433,22 @@ var Database = class {
5874
6433
  }
5875
6434
  ]);
5876
6435
  }
5877
- if (this.bridge) {
5878
- await this.bridge.delete((0, import_schema_tools3.normalizePath)(filepath));
5879
- }
5880
- try {
5881
- await this.onDelete((0, import_schema_tools3.normalizePath)(filepath));
5882
- } catch (e) {
5883
- throw new import_graphql6.GraphQLError(
5884
- `Error running onDelete hook for ${filepath}: ${e}`,
5885
- null,
5886
- null,
5887
- null,
5888
- null,
5889
- e
5890
- );
6436
+ if (!(collection == null ? void 0 : collection.isDetached)) {
6437
+ if (this.bridge) {
6438
+ await this.bridge.delete((0, import_schema_tools3.normalizePath)(filepath));
6439
+ }
6440
+ try {
6441
+ await this.onDelete((0, import_schema_tools3.normalizePath)(filepath));
6442
+ } catch (e) {
6443
+ throw new import_graphql6.GraphQLError(
6444
+ `Error running onDelete hook for ${filepath}: ${e}`,
6445
+ null,
6446
+ null,
6447
+ null,
6448
+ null,
6449
+ e
6450
+ );
6451
+ }
5891
6452
  }
5892
6453
  };
5893
6454
  this._indexAllContent = async (level, schema) => {
@@ -5904,7 +6465,29 @@ var Database = class {
5904
6465
  tinaSchema,
5905
6466
  this.bridge,
5906
6467
  async (collection, contentPaths) => {
5907
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
6468
+ const userFields = mapUserFields(collection, []);
6469
+ if (collection.isDetached) {
6470
+ const level2 = this.appLevel.sublevel(
6471
+ collection.name,
6472
+ SUBLEVEL_OPTIONS
6473
+ );
6474
+ const doc = await level2.keys({ limit: 1 }).next();
6475
+ if (!doc) {
6476
+ await _indexContent(
6477
+ this,
6478
+ level2,
6479
+ contentPaths,
6480
+ enqueueOps,
6481
+ collection,
6482
+ userFields.map((field) => [
6483
+ ...field.path,
6484
+ field.passwordFieldName
6485
+ ])
6486
+ );
6487
+ }
6488
+ } else {
6489
+ await _indexContent(this, level, contentPaths, enqueueOps, collection);
6490
+ }
5908
6491
  }
5909
6492
  );
5910
6493
  while (operations.length) {
@@ -5918,22 +6501,36 @@ var Database = class {
5918
6501
  this.indexStatusCallback = config.indexStatusCallback || defaultStatusCallback;
5919
6502
  this.onPut = config.onPut || defaultOnPut;
5920
6503
  this.onDelete = config.onDelete || defaultOnDelete;
6504
+ this.contentNamespace = config.namespace;
5921
6505
  }
5922
6506
  async updateDatabaseVersion(version) {
5923
- const metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
6507
+ let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
6508
+ if (this.contentNamespace) {
6509
+ metadataLevel = metadataLevel.sublevel(
6510
+ this.contentNamespace,
6511
+ SUBLEVEL_OPTIONS
6512
+ );
6513
+ }
5924
6514
  await metadataLevel.put("metadata", { version });
5925
6515
  }
5926
6516
  async getDatabaseVersion() {
5927
- const metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
6517
+ let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
6518
+ if (this.contentNamespace) {
6519
+ metadataLevel = metadataLevel.sublevel(
6520
+ this.contentNamespace,
6521
+ SUBLEVEL_OPTIONS
6522
+ );
6523
+ }
5928
6524
  const metadata = await metadataLevel.get("metadata");
5929
6525
  return metadata == null ? void 0 : metadata.version;
5930
6526
  }
5931
6527
  async initLevel() {
5932
- if (this.level) {
6528
+ if (this.contentLevel) {
5933
6529
  return;
5934
6530
  }
6531
+ this.appLevel = this.rootLevel.sublevel("_appData", SUBLEVEL_OPTIONS);
5935
6532
  if (!this.config.version) {
5936
- this.level = this.rootLevel;
6533
+ this.contentLevel = this.contentNamespace ? this.rootLevel.sublevel("_content", SUBLEVEL_OPTIONS).sublevel(this.contentNamespace, SUBLEVEL_OPTIONS) : this.rootLevel.sublevel("_content", SUBLEVEL_OPTIONS);
5937
6534
  } else {
5938
6535
  let version = await this.getDatabaseVersion();
5939
6536
  if (!version) {
@@ -5943,9 +6540,9 @@ var Database = class {
5943
6540
  } catch (e) {
5944
6541
  }
5945
6542
  }
5946
- this.level = this.rootLevel.sublevel(version, SUBLEVEL_OPTIONS);
6543
+ this.contentLevel = this.contentNamespace ? this.rootLevel.sublevel("_content").sublevel(this.contentNamespace, SUBLEVEL_OPTIONS).sublevel(version, SUBLEVEL_OPTIONS) : this.rootLevel.sublevel(version, SUBLEVEL_OPTIONS);
5947
6544
  }
5948
- if (!this.level) {
6545
+ if (!this.contentLevel) {
5949
6546
  throw new import_graphql6.GraphQLError("Error initializing LevelDB instance");
5950
6547
  }
5951
6548
  }
@@ -5994,7 +6591,36 @@ var Database = class {
5994
6591
  }
5995
6592
  }
5996
6593
  };
5997
- var _indexContent = async (database, level, documentPaths, enqueueOps, collection) => {
6594
+ var hashPasswordVisitor = async (node, path7) => {
6595
+ const passwordValuePath = [...path7, "value"];
6596
+ const plaintextPassword = import_lodash5.default.get(node, passwordValuePath);
6597
+ if (plaintextPassword) {
6598
+ import_lodash5.default.set(
6599
+ node,
6600
+ passwordValuePath,
6601
+ await generatePasswordHash({ password: plaintextPassword })
6602
+ );
6603
+ }
6604
+ };
6605
+ var visitNodes = async (node, path7, callback) => {
6606
+ const [currentLevel, ...remainingLevels] = path7;
6607
+ if (!(remainingLevels == null ? void 0 : remainingLevels.length)) {
6608
+ return callback(node, path7);
6609
+ }
6610
+ if (Array.isArray(node[currentLevel])) {
6611
+ for (const item of node[currentLevel]) {
6612
+ await visitNodes(item, remainingLevels, callback);
6613
+ }
6614
+ } else {
6615
+ await visitNodes(node[currentLevel], remainingLevels, callback);
6616
+ }
6617
+ };
6618
+ var hashPasswordValues = async (data, passwordFields) => Promise.all(
6619
+ passwordFields.map(
6620
+ async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
6621
+ )
6622
+ );
6623
+ var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
5998
6624
  let collectionIndexDefinitions;
5999
6625
  let collectionPath;
6000
6626
  if (collection) {
@@ -6022,6 +6648,9 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
6022
6648
  if (!aliasedData) {
6023
6649
  return;
6024
6650
  }
6651
+ if (passwordFields == null ? void 0 : passwordFields.length) {
6652
+ await hashPasswordValues(aliasedData, passwordFields);
6653
+ }
6025
6654
  const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6026
6655
  const folderKey = folderTreeBuilder.update(
6027
6656
  normalizedPath,
@@ -6081,7 +6710,9 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6081
6710
  }
6082
6711
  let collectionIndexDefinitions;
6083
6712
  if (collection) {
6084
- const indexDefinitions = await database.getIndexDefinitions(database.level);
6713
+ const indexDefinitions = await database.getIndexDefinitions(
6714
+ database.contentLevel
6715
+ );
6085
6716
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6086
6717
  if (!collectionIndexDefinitions) {
6087
6718
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
@@ -6090,9 +6721,9 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6090
6721
  const tinaSchema = await database.getSchema();
6091
6722
  let templateInfo = null;
6092
6723
  if (collection) {
6093
- templateInfo = await tinaSchema.getTemplatesForCollectable(collection);
6724
+ templateInfo = tinaSchema.getTemplatesForCollectable(collection);
6094
6725
  }
6095
- const rootLevel = database.level.sublevel(
6726
+ const rootLevel = database.contentLevel.sublevel(
6096
6727
  CONTENT_ROOT_PREFIX,
6097
6728
  SUBLEVEL_OPTIONS
6098
6729
  );
@@ -6116,7 +6747,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6116
6747
  collectionIndexDefinitions,
6117
6748
  aliasedData,
6118
6749
  "del",
6119
- database.level
6750
+ database.contentLevel
6120
6751
  ),
6121
6752
  ...makeIndexOpsForDocument(
6122
6753
  itemKey,
@@ -6124,7 +6755,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6124
6755
  collectionIndexDefinitions,
6125
6756
  aliasedData,
6126
6757
  "del",
6127
- database.level
6758
+ database.contentLevel
6128
6759
  ),
6129
6760
  { type: "del", key: itemKey, sublevel: rootLevel }
6130
6761
  ]);
@@ -6137,33 +6768,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
6137
6768
  collection,
6138
6769
  collectionIndexDefinitions,
6139
6770
  "del",
6140
- database.level
6771
+ database.contentLevel
6141
6772
  )
6142
6773
  );
6143
6774
  }
6144
6775
  };
6145
6776
 
6146
- // src/level/tinaLevel.ts
6147
- var import_many_level = require("many-level");
6148
- var import_readable_stream = require("readable-stream");
6149
- var import_net = require("net");
6150
- var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
6151
- constructor(port) {
6152
- super();
6153
- this._connected = false;
6154
- this.port = port || 9e3;
6155
- }
6156
- openConnection() {
6157
- if (this._connected)
6158
- return;
6159
- const socket = (0, import_net.connect)(this.port);
6160
- (0, import_readable_stream.pipeline)(socket, this.createRpcStream(), socket, () => {
6161
- this._connected = false;
6162
- });
6163
- this._connected = true;
6164
- }
6165
- };
6166
-
6167
6777
  // src/git/index.ts
6168
6778
  var import_isomorphic_git = __toESM(require("isomorphic-git"));
6169
6779
  var import_fs_extra = __toESM(require("fs-extra"));
@@ -6700,6 +7310,7 @@ var buildSchema = async (config, flags) => {
6700
7310
  // Annotate the CommonJS export names for ESM import in node:
6701
7311
  0 && (module.exports = {
6702
7312
  AuditFileSystemBridge,
7313
+ Database,
6703
7314
  FilesystemBridge,
6704
7315
  IsomorphicBridge,
6705
7316
  TinaFetchError,
@@ -6710,12 +7321,17 @@ var buildSchema = async (config, flags) => {
6710
7321
  assertShape,
6711
7322
  buildDotTinaFiles,
6712
7323
  buildSchema,
7324
+ checkPasswordHash,
6713
7325
  createDatabase,
7326
+ createDatabaseInternal,
7327
+ createLocalDatabase,
6714
7328
  createSchema,
7329
+ generatePasswordHash,
6715
7330
  getChangedFiles,
6716
7331
  getSha,
6717
7332
  handleFetchErrorError,
6718
7333
  loadAndParseWithAliases,
7334
+ mapUserFields,
6719
7335
  parseFile,
6720
7336
  resolve,
6721
7337
  scanAllContent,