@tinacms/graphql 0.0.0-b832ee4-20250102012112 → 0.0.0-bb1ad6a-20251201062640

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
@@ -27,8 +27,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/index.ts
30
- var src_exports = {};
31
- __export(src_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  AuditFileSystemBridge: () => AuditFileSystemBridge,
33
33
  Database: () => Database,
34
34
  FilesystemBridge: () => FilesystemBridge,
@@ -62,11 +62,11 @@ __export(src_exports, {
62
62
  transformDocument: () => transformDocument,
63
63
  transformDocumentIntoPayload: () => transformDocumentIntoPayload
64
64
  });
65
- module.exports = __toCommonJS(src_exports);
65
+ module.exports = __toCommonJS(index_exports);
66
66
 
67
67
  // src/build.ts
68
68
  var import_graphql2 = require("graphql");
69
- var import_lodash3 = __toESM(require("lodash.uniqby"));
69
+ var import_es_toolkit3 = require("es-toolkit");
70
70
 
71
71
  // src/util.ts
72
72
  var yup = __toESM(require("yup"));
@@ -122,7 +122,7 @@ var flattenDeep = (arr) => arr.flatMap(
122
122
  );
123
123
 
124
124
  // src/ast-builder/index.ts
125
- var import_lodash = __toESM(require("lodash.uniqby"));
125
+ var import_es_toolkit = require("es-toolkit");
126
126
  var SysFieldDefinition = {
127
127
  kind: "Field",
128
128
  name: {
@@ -1037,12 +1037,13 @@ var astBuilder = {
1037
1037
  };
1038
1038
  },
1039
1039
  toGraphQLAst: (ast) => {
1040
- const definitions = (0, import_lodash.default)(
1040
+ const definitions = (0, import_es_toolkit.uniqBy)(
1041
1041
  [
1042
1042
  ...extractInlineTypes(ast.query),
1043
1043
  ...extractInlineTypes(ast.globalTemplates),
1044
1044
  ...ast.definitions
1045
1045
  ],
1046
+ // @ts-ignore - all nodes have a name property in practice
1046
1047
  (field) => field.name.value
1047
1048
  );
1048
1049
  return {
@@ -1065,7 +1066,7 @@ var extractInlineTypes = (item) => {
1065
1066
  const accumulator = [item];
1066
1067
  for (const node of walk(item)) {
1067
1068
  if (node.kind === "UnionTypeDefinition") {
1068
- node.types = (0, import_lodash.default)(node.types, (type) => type.name.value);
1069
+ node.types = (0, import_es_toolkit.uniqBy)(node.types, (type) => type.name.value);
1069
1070
  }
1070
1071
  if (node.kind === "NamedType") {
1071
1072
  if (typeof node.name.value !== "string") {
@@ -1095,41 +1096,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1095
1096
  yield maybeNode;
1096
1097
  visited.add(maybeNode);
1097
1098
  }
1098
- function addNamespaceToSchema(maybeNode, namespace = []) {
1099
- if (typeof maybeNode === "string") {
1100
- return maybeNode;
1101
- }
1102
- if (typeof maybeNode === "boolean") {
1103
- return maybeNode;
1104
- }
1105
- const newNode = maybeNode;
1106
- const keys = Object.keys(maybeNode);
1107
- Object.values(maybeNode).map((m, index) => {
1108
- const key = keys[index];
1109
- if (Array.isArray(m)) {
1110
- newNode[key] = m.map((element) => {
1111
- if (!element) {
1112
- return;
1113
- }
1114
- if (!element.hasOwnProperty("name")) {
1115
- return element;
1116
- }
1117
- const value = element.name || element.value;
1118
- return addNamespaceToSchema(element, [...namespace, value]);
1119
- });
1120
- } else {
1121
- if (!m) {
1122
- return;
1123
- }
1124
- if (!m.hasOwnProperty("name")) {
1125
- newNode[key] = m;
1126
- } else {
1127
- newNode[key] = addNamespaceToSchema(m, [...namespace, m.name]);
1128
- }
1129
- }
1130
- });
1131
- return { ...newNode, namespace };
1132
- }
1133
1099
  var generateNamespacedFieldName = (names, suffix = "") => {
1134
1100
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1135
1101
  };
@@ -1470,13 +1436,12 @@ var checkPasswordHash = async ({
1470
1436
  return true;
1471
1437
  };
1472
1438
  var mapUserFields = (collectable, prefix = []) => {
1473
- var _a, _b, _c, _d, _e;
1474
1439
  const results = [];
1475
- const passwordFields = ((_a = collectable.fields) == null ? void 0 : _a.filter((field) => field.type === "password")) || [];
1440
+ const passwordFields = collectable.fields?.filter((field) => field.type === "password") || [];
1476
1441
  if (passwordFields.length > 1) {
1477
1442
  throw new Error("Only one password field is allowed");
1478
1443
  }
1479
- const idFields = ((_b = collectable.fields) == null ? void 0 : _b.filter((field) => field.uid)) || [];
1444
+ const idFields = collectable.fields?.filter((field) => field.uid) || [];
1480
1445
  if (idFields.length > 1) {
1481
1446
  throw new Error("Only one uid field is allowed");
1482
1447
  }
@@ -1484,11 +1449,11 @@ var mapUserFields = (collectable, prefix = []) => {
1484
1449
  results.push({
1485
1450
  path: prefix,
1486
1451
  collectable,
1487
- idFieldName: (_c = idFields[0]) == null ? void 0 : _c.name,
1488
- passwordFieldName: (_d = passwordFields[0]) == null ? void 0 : _d.name
1452
+ idFieldName: idFields[0]?.name,
1453
+ passwordFieldName: passwordFields[0]?.name
1489
1454
  });
1490
1455
  }
1491
- (_e = collectable.fields) == null ? void 0 : _e.forEach((field) => {
1456
+ collectable.fields?.forEach((field) => {
1492
1457
  if (field.type === "object" && field.fields) {
1493
1458
  results.push(...mapUserFields(field, [...prefix, field.name]));
1494
1459
  }
@@ -1949,7 +1914,7 @@ var Builder = class {
1949
1914
  * ```
1950
1915
  *
1951
1916
  * @public
1952
- * @param collection a Tina Cloud collection
1917
+ * @param collection a TinaCloud collection
1953
1918
  */
1954
1919
  this.collectionFragment = async (collection) => {
1955
1920
  const name = NAMER.dataTypeName(collection.namespace);
@@ -1979,13 +1944,12 @@ var Builder = class {
1979
1944
  *
1980
1945
  * */
1981
1946
  this._getCollectionFragmentSelections = async (collection, depth) => {
1982
- var _a;
1983
1947
  const selections = [];
1984
1948
  selections.push({
1985
1949
  name: { kind: "Name", value: "__typename" },
1986
1950
  kind: "Field"
1987
1951
  });
1988
- if (((_a = collection.fields) == null ? void 0 : _a.length) > 0) {
1952
+ if (collection.fields?.length > 0) {
1989
1953
  await sequential(collection.fields, async (x) => {
1990
1954
  const field = await this._buildFieldNodeForFragments(x, depth);
1991
1955
  selections.push(field);
@@ -2000,7 +1964,6 @@ var Builder = class {
2000
1964
  return selections;
2001
1965
  };
2002
1966
  this._buildFieldNodeForFragments = async (field, depth) => {
2003
- var _a, _b;
2004
1967
  switch (field.type) {
2005
1968
  case "string":
2006
1969
  case "image":
@@ -2033,7 +1996,7 @@ var Builder = class {
2033
1996
  selections: filterSelections([passwordValue, passwordChangeRequired])
2034
1997
  });
2035
1998
  case "object":
2036
- if (((_a = field.fields) == null ? void 0 : _a.length) > 0) {
1999
+ if (field.fields?.length > 0) {
2037
2000
  const selections2 = [];
2038
2001
  await sequential(field.fields, async (item) => {
2039
2002
  const field2 = await this._buildFieldNodeForFragments(item, depth);
@@ -2046,7 +2009,7 @@ var Builder = class {
2046
2009
  ...filterSelections(selections2)
2047
2010
  ]
2048
2011
  });
2049
- } else if (((_b = field.templates) == null ? void 0 : _b.length) > 0) {
2012
+ } else if (field.templates?.length > 0) {
2050
2013
  const selections2 = [];
2051
2014
  await sequential(field.templates, async (tem) => {
2052
2015
  if (typeof tem === "object") {
@@ -2708,7 +2671,7 @@ var Builder = class {
2708
2671
  this.addToLookupMap({
2709
2672
  type: name,
2710
2673
  resolveType: "unionData",
2711
- collection: collection == null ? void 0 : collection.name,
2674
+ collection: collection?.name,
2712
2675
  typeMap
2713
2676
  });
2714
2677
  return astBuilder.UnionTypeDefinition({ name, types });
@@ -2815,7 +2778,7 @@ var Builder = class {
2815
2778
  this._buildDataField = async (field) => {
2816
2779
  const listWarningMsg = `
2817
2780
  WARNING: The user interface for ${field.type} does not support \`list: true\`
2818
- Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2781
+ Visit https://tina.io/docs/r/content-fields/#list-fields/ for more information
2819
2782
 
2820
2783
  `;
2821
2784
  switch (field.type) {
@@ -2918,9 +2881,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2918
2881
  ]
2919
2882
  });
2920
2883
  };
2921
- var _a, _b, _c, _d;
2922
2884
  this.maxDepth = // @ts-ignore
2923
- (_d = (_c = (_b = (_a = config == null ? void 0 : config.tinaSchema.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.client) == null ? void 0 : _c.referenceDepth) != null ? _d : 2;
2885
+ config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2924
2886
  this.tinaSchema = config.tinaSchema;
2925
2887
  this.lookupMap = {};
2926
2888
  }
@@ -2965,12 +2927,13 @@ var filterSelections = (arr) => {
2965
2927
  };
2966
2928
 
2967
2929
  // src/schema/createSchema.ts
2968
- var import_schema_tools2 = require("@tinacms/schema-tools");
2930
+ var import_schema_tools3 = require("@tinacms/schema-tools");
2969
2931
 
2970
2932
  // src/schema/validate.ts
2971
- var import_lodash2 = __toESM(require("lodash.clonedeep"));
2972
- var yup2 = __toESM(require("yup"));
2973
2933
  var import_schema_tools = require("@tinacms/schema-tools");
2934
+ var yup2 = __toESM(require("yup"));
2935
+ var import_es_toolkit2 = require("es-toolkit");
2936
+ var import_schema_tools2 = require("@tinacms/schema-tools");
2974
2937
  var FIELD_TYPES = [
2975
2938
  "string",
2976
2939
  "number",
@@ -2983,8 +2946,8 @@ var FIELD_TYPES = [
2983
2946
  "password"
2984
2947
  ];
2985
2948
  var validateSchema = async (schema) => {
2986
- const schema2 = addNamespaceToSchema(
2987
- (0, import_lodash2.default)(schema)
2949
+ const schema2 = (0, import_schema_tools.addNamespaceToSchema)(
2950
+ (0, import_es_toolkit2.cloneDeep)(schema)
2988
2951
  );
2989
2952
  const collections = await sequential(
2990
2953
  schema2.collections,
@@ -2992,7 +2955,7 @@ var validateSchema = async (schema) => {
2992
2955
  );
2993
2956
  validationCollectionsPathAndMatch(collections);
2994
2957
  if (schema2.config) {
2995
- const config = (0, import_schema_tools.validateTinaCloudSchemaConfig)(schema2.config);
2958
+ const config = (0, import_schema_tools2.validateTinaCloudSchemaConfig)(schema2.config);
2996
2959
  return {
2997
2960
  collections,
2998
2961
  config
@@ -3008,7 +2971,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3008
2971
  return;
3009
2972
  }
3010
2973
  const noMatchCollections = collections.filter((x) => {
3011
- return typeof (x == null ? void 0 : x.match) === "undefined";
2974
+ return typeof x?.match === "undefined";
3012
2975
  }).map((x) => `${x.path}${x.format || "md"}`);
3013
2976
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
3014
2977
  throw new Error(
@@ -3019,10 +2982,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3019
2982
  const hasMatchAndPath = collections.filter((x) => {
3020
2983
  return typeof x.path !== "undefined" && typeof x.match !== "undefined";
3021
2984
  }).map(
3022
- (x) => {
3023
- var _a, _b;
3024
- return `${x.path}|${((_a = x == null ? void 0 : x.match) == null ? void 0 : _a.exclude) || ""}|${((_b = x == null ? void 0 : x.match) == null ? void 0 : _b.include) || ""}|${x.format || "md"}`;
3025
- }
2985
+ (x) => `${x.path}|${x?.match?.exclude || ""}|${x?.match?.include || ""}|${x.format || "md"}`
3026
2986
  );
3027
2987
  if (hasMatchAndPath.length !== new Set(hasMatchAndPath).size) {
3028
2988
  throw new Error(
@@ -3046,7 +3006,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3046
3006
  );
3047
3007
  }
3048
3008
  const matches = collectionsArr.map(
3049
- (x) => typeof (x == null ? void 0 : x.match) === "object" ? JSON.stringify(x.match) : ""
3009
+ (x) => typeof x?.match === "object" ? JSON.stringify(x.match) : ""
3050
3010
  );
3051
3011
  if (matches.length === new Set(matches).size) {
3052
3012
  return;
@@ -3124,7 +3084,7 @@ var validateField = async (field) => {
3124
3084
  // package.json
3125
3085
  var package_default = {
3126
3086
  name: "@tinacms/graphql",
3127
- version: "1.5.9",
3087
+ version: "1.6.3",
3128
3088
  main: "dist/index.js",
3129
3089
  module: "dist/index.mjs",
3130
3090
  typings: "dist/index.d.ts",
@@ -3150,34 +3110,31 @@ var package_default = {
3150
3110
  types: "pnpm tsc",
3151
3111
  build: "tinacms-scripts build",
3152
3112
  docs: "pnpm typedoc",
3153
- serve: "pnpm nodemon dist/server.js",
3154
- test: "jest",
3155
- "test-watch": "jest --watch"
3113
+ test: "vitest run",
3114
+ "test-watch": "vitest"
3156
3115
  },
3157
3116
  dependencies: {
3158
- "@iarna/toml": "^2.2.5",
3117
+ "@iarna/toml": "catalog:",
3159
3118
  "@tinacms/mdx": "workspace:*",
3160
3119
  "@tinacms/schema-tools": "workspace:*",
3161
- "abstract-level": "^1.0.4",
3120
+ "abstract-level": "catalog:",
3162
3121
  "date-fns": "^2.30.0",
3163
- "fast-glob": "^3.3.2",
3164
- "fs-extra": "^11.2.0",
3165
- "glob-parent": "^6.0.2",
3122
+ "es-toolkit": "^1.42.0",
3123
+ "fast-glob": "catalog:",
3124
+ "fs-extra": "catalog:",
3125
+ "glob-parent": "catalog:",
3166
3126
  graphql: "15.8.0",
3167
- "gray-matter": "^4.0.3",
3168
- "isomorphic-git": "^1.27.1",
3169
- "js-sha1": "^0.6.0",
3127
+ "gray-matter": "catalog:",
3128
+ "isomorphic-git": "catalog:",
3129
+ "js-sha1": "catalog:",
3170
3130
  "js-yaml": "^3.14.1",
3171
- "jsonpath-plus": "10.1.0",
3172
- "lodash.clonedeep": "^4.5.0",
3173
- "lodash.set": "^4.3.2",
3174
- "lodash.uniqby": "^4.7.0",
3175
- "many-level": "^2.0.0",
3176
- micromatch: "4.0.8",
3177
- "normalize-path": "^3.0.0",
3178
- "readable-stream": "^4.5.2",
3179
- scmp: "^2.1.0",
3180
- yup: "^0.32.11"
3131
+ "jsonpath-plus": "catalog:",
3132
+ "many-level": "catalog:",
3133
+ micromatch: "catalog:",
3134
+ "normalize-path": "catalog:",
3135
+ "readable-stream": "catalog:",
3136
+ scmp: "catalog:",
3137
+ yup: "^1.6.1"
3181
3138
  },
3182
3139
  publishConfig: {
3183
3140
  registry: "https://registry.npmjs.org"
@@ -3191,26 +3148,21 @@ var package_default = {
3191
3148
  "@tinacms/scripts": "workspace:*",
3192
3149
  "@types/cors": "^2.8.17",
3193
3150
  "@types/estree": "^0.0.50",
3194
- "@types/express": "^4.17.21",
3151
+ "@types/express": "catalog:",
3195
3152
  "@types/fs-extra": "^9.0.13",
3196
- "@types/jest": "^26.0.24",
3197
3153
  "@types/js-yaml": "^3.12.10",
3198
- "@types/lodash.camelcase": "^4.3.9",
3199
- "@types/lodash.upperfirst": "^4.3.9",
3200
- "@types/lru-cache": "^5.1.1",
3201
- "@types/mdast": "^3.0.15",
3202
- "@types/micromatch": "^4.0.9",
3203
- "@types/node": "^22.9.0",
3204
- "@types/normalize-path": "^3.0.2",
3205
- "@types/ws": "^7.4.7",
3206
- "@types/yup": "^0.29.14",
3207
- jest: "^29.7.0",
3208
- "jest-diff": "^29.7.0",
3154
+ "@types/lru-cache": "catalog:",
3155
+ "@types/mdast": "catalog:",
3156
+ "@types/micromatch": "catalog:",
3157
+ "@types/node": "^22.13.1",
3158
+ "@types/normalize-path": "catalog:",
3159
+ "@types/ws": "catalog:",
3209
3160
  "jest-file-snapshot": "^0.5.0",
3210
- "jest-matcher-utils": "^29.7.0",
3211
- "memory-level": "^1.0.0",
3212
- nodemon: "3.1.4",
3213
- typescript: "^5.6.3"
3161
+ "memory-level": "catalog:",
3162
+ typescript: "^5.7.3",
3163
+ vite: "^4.5.9",
3164
+ vitest: "^0.32.4",
3165
+ zod: "catalog:"
3214
3166
  }
3215
3167
  };
3216
3168
 
@@ -3225,7 +3177,7 @@ var createSchema = async ({
3225
3177
  if (flags && flags.length > 0) {
3226
3178
  meta["flags"] = flags;
3227
3179
  }
3228
- return new import_schema_tools2.TinaSchema({
3180
+ return new import_schema_tools3.TinaSchema({
3229
3181
  version: {
3230
3182
  fullVersion: package_default.version,
3231
3183
  major,
@@ -3280,9 +3232,9 @@ var _buildFragments = async (builder, tinaSchema) => {
3280
3232
  });
3281
3233
  const fragDoc = {
3282
3234
  kind: "Document",
3283
- definitions: (0, import_lodash3.default)(
3284
- // @ts-ignore
3235
+ definitions: (0, import_es_toolkit3.uniqBy)(
3285
3236
  extractInlineTypes(fragmentDefinitionsFields),
3237
+ // @ts-ignore - all nodes returned by extractInlineTypes have a name property
3286
3238
  (node) => node.name.value
3287
3239
  )
3288
3240
  };
@@ -3292,7 +3244,6 @@ var _buildQueries = async (builder, tinaSchema) => {
3292
3244
  const operationsDefinitions = [];
3293
3245
  const collections = tinaSchema.getCollections();
3294
3246
  await sequential(collections, async (collection) => {
3295
- var _a, _b, _c;
3296
3247
  const queryName = NAMER.queryName(collection.namespace);
3297
3248
  const queryListName = NAMER.generateQueryListName(collection.namespace);
3298
3249
  const queryFilterTypeName = NAMER.dataFilterTypeName(collection.namespace);
@@ -3307,16 +3258,16 @@ var _buildQueries = async (builder, tinaSchema) => {
3307
3258
  filterType: queryFilterTypeName,
3308
3259
  // look for flag to see if the data layer is enabled
3309
3260
  dataLayer: Boolean(
3310
- (_c = (_b = (_a = tinaSchema.config) == null ? void 0 : _a.meta) == null ? void 0 : _b.flags) == null ? void 0 : _c.find((x) => x === "experimentalData")
3261
+ tinaSchema.config?.meta?.flags?.find((x) => x === "experimentalData")
3311
3262
  )
3312
3263
  })
3313
3264
  );
3314
3265
  });
3315
3266
  const queryDoc = {
3316
3267
  kind: "Document",
3317
- definitions: (0, import_lodash3.default)(
3318
- // @ts-ignore
3268
+ definitions: (0, import_es_toolkit3.uniqBy)(
3319
3269
  extractInlineTypes(operationsDefinitions),
3270
+ // @ts-ignore - all nodes returned by extractInlineTypes have a name property
3320
3271
  (node) => node.name.value
3321
3272
  )
3322
3273
  };
@@ -3367,7 +3318,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3367
3318
  await builder.buildCreateCollectionFolderMutation()
3368
3319
  );
3369
3320
  await sequential(collections, async (collection) => {
3370
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3321
+ queryTypeDefinitionFields.push(
3322
+ await builder.collectionDocument(collection)
3323
+ );
3371
3324
  if (collection.isAuthCollection) {
3372
3325
  queryTypeDefinitionFields.push(
3373
3326
  await builder.authenticationCollectionDocument(collection)
@@ -3401,14 +3354,15 @@ var _buildSchema = async (builder, tinaSchema) => {
3401
3354
  fields: mutationTypeDefinitionFields
3402
3355
  })
3403
3356
  );
3404
- return {
3357
+ const schema = {
3405
3358
  kind: "Document",
3406
- definitions: (0, import_lodash3.default)(
3407
- // @ts-ignore
3359
+ definitions: (0, import_es_toolkit3.uniqBy)(
3408
3360
  extractInlineTypes(definitions),
3361
+ // @ts-ignore - all nodes returned by extractInlineTypes have a name property
3409
3362
  (node) => node.name.value
3410
3363
  )
3411
3364
  };
3365
+ return schema;
3412
3366
  };
3413
3367
 
3414
3368
  // src/resolve.ts
@@ -3417,251 +3371,11 @@ var import_graphql5 = require("graphql");
3417
3371
  // src/resolver/index.ts
3418
3372
  var import_path3 = __toESM(require("path"));
3419
3373
  var import_isValid = __toESM(require("date-fns/isValid/index.js"));
3374
+ var import_jsonpath_plus2 = require("jsonpath-plus");
3420
3375
 
3421
3376
  // src/mdx/index.ts
3422
3377
  var import_mdx = require("@tinacms/mdx");
3423
3378
 
3424
- // src/resolver/index.ts
3425
- var import_jsonpath_plus2 = require("jsonpath-plus");
3426
-
3427
- // src/resolver/error.ts
3428
- var TinaGraphQLError = class extends Error {
3429
- constructor(message, extensions) {
3430
- super(message);
3431
- if (!this.name) {
3432
- Object.defineProperty(this, "name", { value: "TinaGraphQLError" });
3433
- }
3434
- this.extensions = { ...extensions };
3435
- }
3436
- };
3437
- var TinaFetchError = class extends Error {
3438
- constructor(message, args) {
3439
- super(message);
3440
- this.name = "TinaFetchError";
3441
- this.collection = args.collection;
3442
- this.stack = args.stack;
3443
- this.file = args.file;
3444
- this.originalError = args.originalError;
3445
- }
3446
- };
3447
- var TinaQueryError = class extends TinaFetchError {
3448
- constructor(args) {
3449
- super(
3450
- `Error querying file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
3451
- args
3452
- );
3453
- }
3454
- };
3455
- var TinaParseDocumentError = class extends TinaFetchError {
3456
- constructor(args) {
3457
- super(
3458
- `Error parsing file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
3459
- args
3460
- );
3461
- }
3462
- toString() {
3463
- return super.toString() + "\n OriginalError: \n" + this.originalError.toString();
3464
- }
3465
- };
3466
- var auditMessage = (includeAuditMessage = true) => includeAuditMessage ? `Please run "tinacms audit" or add the --verbose option for more info` : "";
3467
- var handleFetchErrorError = (e, verbose) => {
3468
- if (e instanceof Error) {
3469
- if (e instanceof TinaFetchError) {
3470
- if (verbose) {
3471
- console.log(e.toString());
3472
- console.log(e);
3473
- console.log(e.stack);
3474
- }
3475
- }
3476
- } else {
3477
- console.error(e);
3478
- }
3479
- throw e;
3480
- };
3481
-
3482
- // src/resolver/filter-utils.ts
3483
- var resolveReferences = async (filter, fields, resolver) => {
3484
- for (const fieldKey of Object.keys(filter)) {
3485
- const fieldDefinition = fields.find(
3486
- (f) => f.name === fieldKey
3487
- );
3488
- if (fieldDefinition) {
3489
- if (fieldDefinition.type === "reference") {
3490
- const { edges, values } = await resolver(filter, fieldDefinition);
3491
- if (edges.length === 1) {
3492
- filter[fieldKey] = {
3493
- eq: values[0]
3494
- };
3495
- } else if (edges.length > 1) {
3496
- filter[fieldKey] = {
3497
- in: values
3498
- };
3499
- } else {
3500
- filter[fieldKey] = {
3501
- eq: "___null___"
3502
- };
3503
- }
3504
- } else if (fieldDefinition.type === "object") {
3505
- if (fieldDefinition.templates) {
3506
- for (const templateName of Object.keys(filter[fieldKey])) {
3507
- const template = fieldDefinition.templates.find(
3508
- (template2) => !(typeof template2 === "string") && template2.name === templateName
3509
- );
3510
- if (template) {
3511
- await resolveReferences(
3512
- filter[fieldKey][templateName],
3513
- template.fields,
3514
- resolver
3515
- );
3516
- } else {
3517
- throw new Error(`Template ${templateName} not found`);
3518
- }
3519
- }
3520
- } else {
3521
- await resolveReferences(
3522
- filter[fieldKey],
3523
- fieldDefinition.fields,
3524
- resolver
3525
- );
3526
- }
3527
- }
3528
- } else {
3529
- throw new Error(`Unable to find field ${fieldKey}`);
3530
- }
3531
- }
3532
- };
3533
- var collectConditionsForChildFields = (filterNode, fields, pathExpression, collectCondition) => {
3534
- for (const childFieldName of Object.keys(filterNode)) {
3535
- const childField = fields.find((field) => field.name === childFieldName);
3536
- if (!childField) {
3537
- throw new Error(`Unable to find type for field ${childFieldName}`);
3538
- }
3539
- collectConditionsForField(
3540
- childFieldName,
3541
- childField,
3542
- filterNode[childFieldName],
3543
- pathExpression,
3544
- collectCondition
3545
- );
3546
- }
3547
- };
3548
- var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
3549
- if (field.list && field.templates) {
3550
- for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
3551
- const template = field.templates.find(
3552
- (template2) => !(typeof template2 === "string") && template2.name === filterKey
3553
- );
3554
- const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
3555
- const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
3556
- collectConditionsForChildFields(
3557
- childFilterNode,
3558
- template.fields,
3559
- filterPath,
3560
- collectCondition
3561
- );
3562
- }
3563
- } else {
3564
- const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
3565
- const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
3566
- collectConditionsForChildFields(
3567
- filterNode,
3568
- field.fields,
3569
- filterPath,
3570
- collectCondition
3571
- );
3572
- }
3573
- };
3574
- var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
3575
- if (field.type === "object") {
3576
- collectConditionsForObjectField(
3577
- fieldName,
3578
- field,
3579
- filterNode,
3580
- pathExpression,
3581
- collectCondition
3582
- );
3583
- } else {
3584
- collectCondition({
3585
- filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
3586
- filterExpression: {
3587
- _type: field.type,
3588
- _list: !!field.list,
3589
- ...filterNode
3590
- }
3591
- });
3592
- }
3593
- };
3594
-
3595
- // src/resolver/media-utils.ts
3596
- var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, schema) => {
3597
- if (config && value) {
3598
- if (config.useRelativeMedia === true) {
3599
- return value;
3600
- }
3601
- if (hasTinaMediaConfig(schema) === true) {
3602
- const assetsURL = `https://${config.assetsHost}/${config.clientId}`;
3603
- if (typeof value === "string" && value.includes(assetsURL)) {
3604
- const cleanMediaRoot = cleanUpSlashes(
3605
- schema.config.media.tina.mediaRoot
3606
- );
3607
- const strippedURL = value.replace(assetsURL, "");
3608
- return `${cleanMediaRoot}${strippedURL}`;
3609
- }
3610
- if (Array.isArray(value)) {
3611
- return value.map((v) => {
3612
- if (!v || typeof v !== "string") return v;
3613
- const cleanMediaRoot = cleanUpSlashes(
3614
- schema.config.media.tina.mediaRoot
3615
- );
3616
- const strippedURL = v.replace(assetsURL, "");
3617
- return `${cleanMediaRoot}${strippedURL}`;
3618
- });
3619
- }
3620
- return value;
3621
- }
3622
- return value;
3623
- } else {
3624
- return value;
3625
- }
3626
- };
3627
- var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, schema) => {
3628
- if (config && value) {
3629
- if (config.useRelativeMedia === true) {
3630
- return value;
3631
- }
3632
- if (hasTinaMediaConfig(schema) === true) {
3633
- const cleanMediaRoot = cleanUpSlashes(schema.config.media.tina.mediaRoot);
3634
- if (typeof value === "string") {
3635
- const strippedValue = value.replace(cleanMediaRoot, "");
3636
- return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3637
- }
3638
- if (Array.isArray(value)) {
3639
- return value.map((v) => {
3640
- if (!v || typeof v !== "string") return v;
3641
- const strippedValue = v.replace(cleanMediaRoot, "");
3642
- return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3643
- });
3644
- }
3645
- }
3646
- return value;
3647
- } else {
3648
- return value;
3649
- }
3650
- };
3651
- var cleanUpSlashes = (path7) => {
3652
- if (path7) {
3653
- return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
3654
- }
3655
- return "";
3656
- };
3657
- var hasTinaMediaConfig = (schema) => {
3658
- var _a, _b, _c, _d, _e, _f, _g, _h;
3659
- if (!((_b = (_a = schema.config) == null ? void 0 : _a.media) == null ? void 0 : _b.tina)) return false;
3660
- if (typeof ((_e = (_d = (_c = schema.config) == null ? void 0 : _c.media) == null ? void 0 : _d.tina) == null ? void 0 : _e.publicFolder) !== "string" && typeof ((_h = (_g = (_f = schema.config) == null ? void 0 : _f.media) == null ? void 0 : _g.tina) == null ? void 0 : _h.mediaRoot) !== "string")
3661
- return false;
3662
- return true;
3663
- };
3664
-
3665
3379
  // src/resolver/index.ts
3666
3380
  var import_graphql3 = require("graphql");
3667
3381
 
@@ -3683,7 +3397,9 @@ var LevelProxyHandler = {
3683
3397
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3684
3398
  }
3685
3399
  if (typeof target[property] !== "function") {
3686
- throw new Error(`The property, ${property.toString()}, is not a function`);
3400
+ throw new Error(
3401
+ `The property, ${property.toString()}, is not a function`
3402
+ );
3687
3403
  }
3688
3404
  if (property === "get") {
3689
3405
  return async (...args) => {
@@ -3721,11 +3437,11 @@ var import_path2 = __toESM(require("path"));
3721
3437
 
3722
3438
  // src/database/util.ts
3723
3439
  var import_toml = __toESM(require("@iarna/toml"));
3724
- var import_js_yaml = __toESM(require("js-yaml"));
3440
+ var import_schema_tools4 = require("@tinacms/schema-tools");
3725
3441
  var import_gray_matter = __toESM(require("gray-matter"));
3726
- var import_schema_tools3 = require("@tinacms/schema-tools");
3727
- var import_micromatch = __toESM(require("micromatch"));
3442
+ var import_js_yaml = __toESM(require("js-yaml"));
3728
3443
  var import_path = __toESM(require("path"));
3444
+ var import_micromatch = __toESM(require("micromatch"));
3729
3445
 
3730
3446
  // src/database/alias-utils.ts
3731
3447
  var replaceBlockAliases = (template, item) => {
@@ -3762,22 +3478,20 @@ var replaceNameOverrides = (template, obj) => {
3762
3478
  }
3763
3479
  };
3764
3480
  function isBlockField(field) {
3765
- var _a;
3766
- return field && field.type === "object" && ((_a = field.templates) == null ? void 0 : _a.length) > 0;
3481
+ return field && field.type === "object" && field.templates?.length > 0;
3767
3482
  }
3768
3483
  var _replaceNameOverrides = (fields, obj) => {
3769
3484
  const output = {};
3770
3485
  Object.keys(obj).forEach((key) => {
3771
3486
  const field = fields.find(
3772
- (fieldWithMatchingAlias) => ((fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.nameOverride) || (fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.name)) === key
3487
+ (fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
3773
3488
  );
3774
- output[(field == null ? void 0 : field.name) || key] = (field == null ? void 0 : field.type) == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
3489
+ output[field?.name || key] = field?.type == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
3775
3490
  });
3776
3491
  return output;
3777
3492
  };
3778
3493
  var getTemplateForData = (field, data) => {
3779
- var _a;
3780
- if ((_a = field.templates) == null ? void 0 : _a.length) {
3494
+ if (field.templates?.length) {
3781
3495
  const templateKey = "_template";
3782
3496
  if (data[templateKey]) {
3783
3497
  const result = field.templates.find(
@@ -3835,8 +3549,8 @@ var _applyNameOverrides = (fields, obj) => {
3835
3549
  const output = {};
3836
3550
  Object.keys(obj).forEach((key) => {
3837
3551
  const field = fields.find((field2) => field2.name === key);
3838
- const outputKey = (field == null ? void 0 : field.nameOverride) || key;
3839
- output[outputKey] = (field == null ? void 0 : field.type) === "object" ? applyNameOverrides(field, obj[key]) : obj[key];
3552
+ const outputKey = field?.nameOverride || key;
3553
+ output[outputKey] = field?.type === "object" ? applyNameOverrides(field, obj[key]) : obj[key];
3840
3554
  });
3841
3555
  return output;
3842
3556
  };
@@ -3849,7 +3563,6 @@ var matterEngines = {
3849
3563
  }
3850
3564
  };
3851
3565
  var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3852
- var _a, _b;
3853
3566
  const {
3854
3567
  _relativePath,
3855
3568
  _keepTemplateKey,
@@ -3873,9 +3586,9 @@ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3873
3586
  ${$_body}`,
3874
3587
  strippedContent,
3875
3588
  {
3876
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3589
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3877
3590
  engines: matterEngines,
3878
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
3591
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
3879
3592
  }
3880
3593
  );
3881
3594
  return ok;
@@ -3891,15 +3604,14 @@ ${$_body}`,
3891
3604
  }
3892
3605
  };
3893
3606
  var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3894
- var _a, _b;
3895
3607
  try {
3896
3608
  switch (format) {
3897
3609
  case ".markdown":
3898
3610
  case ".mdx":
3899
3611
  case ".md":
3900
3612
  const contentJSON = (0, import_gray_matter.default)(content || "", {
3901
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3902
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---",
3613
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3614
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
3903
3615
  engines: matterEngines
3904
3616
  });
3905
3617
  const markdownData = {
@@ -3936,7 +3648,7 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3936
3648
  const filesSeen = /* @__PURE__ */ new Map();
3937
3649
  const duplicateFiles = /* @__PURE__ */ new Set();
3938
3650
  await sequential(tinaSchema.getCollections(), async (collection) => {
3939
- const normalPath = (0, import_schema_tools3.normalizePath)(collection.path);
3651
+ const normalPath = (0, import_schema_tools4.normalizePath)(collection.path);
3940
3652
  const format = collection.format || "md";
3941
3653
  const documentPaths = await bridge.glob(normalPath, format);
3942
3654
  const matches = tinaSchema.getMatches({ collection });
@@ -3998,7 +3710,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3998
3710
  ),
3999
3711
  template: void 0
4000
3712
  } : tinaSchema.getCollectionAndTemplateByFullPath(filepath, templateName);
4001
- const field = template == null ? void 0 : template.fields.find((field2) => {
3713
+ const field = template?.fields.find((field2) => {
4002
3714
  if (field2.type === "string" || field2.type === "rich-text") {
4003
3715
  if (field2.isBody) {
4004
3716
  return true;
@@ -4018,7 +3730,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
4018
3730
  ...data,
4019
3731
  _collection: collection.name,
4020
3732
  _keepTemplateKey: !!collection.templates,
4021
- _template: (template == null ? void 0 : template.namespace) ? lastItem(template == null ? void 0 : template.namespace) : void 0,
3733
+ _template: template?.namespace ? lastItem(template?.namespace) : void 0,
4022
3734
  _relativePath: filepath.replace(collection.path, "").replace(/^\/|\/$/g, ""),
4023
3735
  _id: filepath
4024
3736
  };
@@ -4027,10 +3739,10 @@ function hasOwnProperty(obj, prop) {
4027
3739
  return obj.hasOwnProperty(prop);
4028
3740
  }
4029
3741
  var getTemplateForFile = (templateInfo, data) => {
4030
- if ((templateInfo == null ? void 0 : templateInfo.type) === "object") {
3742
+ if (templateInfo?.type === "object") {
4031
3743
  return templateInfo.template;
4032
3744
  }
4033
- if ((templateInfo == null ? void 0 : templateInfo.type) === "union") {
3745
+ if (templateInfo?.type === "union") {
4034
3746
  if (hasOwnProperty(data, "_template")) {
4035
3747
  const template = templateInfo.templates.find(
4036
3748
  (t) => lastItem(t.namespace) === data._template
@@ -4048,14 +3760,14 @@ var getTemplateForFile = (templateInfo, data) => {
4048
3760
  throw new Error(`Unable to determine template`);
4049
3761
  };
4050
3762
  var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo) => {
4051
- const dataString = await bridge.get((0, import_schema_tools3.normalizePath)(filepath));
3763
+ const dataString = await bridge.get((0, import_schema_tools4.normalizePath)(filepath));
4052
3764
  const data = parseFile(
4053
3765
  dataString,
4054
3766
  import_path.default.extname(filepath),
4055
3767
  (yup3) => yup3.object({}),
4056
3768
  {
4057
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
4058
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
3769
+ frontmatterDelimiters: collection?.frontmatterDelimiters,
3770
+ frontmatterFormat: collection?.frontmatterFormat
4059
3771
  }
4060
3772
  );
4061
3773
  const template = getTemplateForFile(templateInfo, data);
@@ -4070,6 +3782,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
4070
3782
 
4071
3783
  // src/database/datalayer.ts
4072
3784
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
3785
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
3786
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
3787
+ var REFS_PATH_FIELD = "__tina_ref_path__";
4073
3788
  var DEFAULT_NUMERIC_LPAD = 4;
4074
3789
  var applyPadding = (input, pad) => {
4075
3790
  if (pad) {
@@ -4527,7 +4242,7 @@ var FolderTreeBuilder = class {
4527
4242
  return this._tree;
4528
4243
  }
4529
4244
  update(documentPath, collectionPath) {
4530
- let folderPath = import_path2.default.dirname((0, import_schema_tools3.normalizePath)(documentPath));
4245
+ let folderPath = import_path2.default.dirname((0, import_schema_tools4.normalizePath)(documentPath));
4531
4246
  if (folderPath === ".") {
4532
4247
  folderPath = "";
4533
4248
  }
@@ -4540,7 +4255,7 @@ var FolderTreeBuilder = class {
4540
4255
  if (!this._tree[current2]) {
4541
4256
  this._tree[current2] = /* @__PURE__ */ new Set();
4542
4257
  }
4543
- this._tree[current2].add((0, import_schema_tools3.normalizePath)(import_path2.default.join(current2, part)));
4258
+ this._tree[current2].add((0, import_schema_tools4.normalizePath)(import_path2.default.join(current2, part)));
4544
4259
  parent.push(part);
4545
4260
  });
4546
4261
  const current = parent.join("/");
@@ -4643,6 +4358,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4643
4358
  }
4644
4359
  return result;
4645
4360
  };
4361
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4362
+ const result = [];
4363
+ if (collection) {
4364
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4365
+ if (!referencePaths.length) {
4366
+ continue;
4367
+ }
4368
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4369
+ const refSublevel = collectionSublevel.sublevel(
4370
+ REFS_COLLECTIONS_SORT_KEY,
4371
+ SUBLEVEL_OPTIONS
4372
+ );
4373
+ const references2 = {};
4374
+ for (const path7 of referencePaths) {
4375
+ const ref = (0, import_jsonpath_plus.JSONPath)({ path: path7, json: data });
4376
+ if (!ref) {
4377
+ continue;
4378
+ }
4379
+ if (Array.isArray(ref)) {
4380
+ for (const r of ref) {
4381
+ if (!r) {
4382
+ continue;
4383
+ }
4384
+ if (references2[r]) {
4385
+ references2[r].push(path7);
4386
+ } else {
4387
+ references2[r] = [path7];
4388
+ }
4389
+ }
4390
+ } else {
4391
+ if (references2[ref]) {
4392
+ references2[ref].push(path7);
4393
+ } else {
4394
+ references2[ref] = [path7];
4395
+ }
4396
+ }
4397
+ }
4398
+ for (const ref of Object.keys(references2)) {
4399
+ for (const path7 of references2[ref]) {
4400
+ result.push({
4401
+ type: opType,
4402
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4403
+ sublevel: refSublevel,
4404
+ value: opType === "put" ? {} : void 0
4405
+ });
4406
+ }
4407
+ }
4408
+ }
4409
+ }
4410
+ return result;
4411
+ };
4646
4412
  var makeStringEscaper = (regex, replacement) => {
4647
4413
  return (input) => {
4648
4414
  if (Array.isArray(input)) {
@@ -4656,19 +4422,254 @@ var makeStringEscaper = (regex, replacement) => {
4656
4422
  return input;
4657
4423
  }
4658
4424
  }
4659
- };
4425
+ };
4426
+ };
4427
+ var stringEscaper = makeStringEscaper(
4428
+ new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
4429
+ encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
4430
+ );
4431
+
4432
+ // src/resolver/error.ts
4433
+ var TinaGraphQLError = class extends Error {
4434
+ constructor(message, extensions) {
4435
+ super(message);
4436
+ if (!this.name) {
4437
+ Object.defineProperty(this, "name", { value: "TinaGraphQLError" });
4438
+ }
4439
+ this.extensions = { ...extensions };
4440
+ }
4441
+ };
4442
+ var TinaFetchError = class extends Error {
4443
+ constructor(message, args) {
4444
+ super(message);
4445
+ this.name = "TinaFetchError";
4446
+ this.collection = args.collection;
4447
+ this.file = args.file;
4448
+ this.originalError = args.originalError;
4449
+ }
4450
+ };
4451
+ var TinaQueryError = class extends TinaFetchError {
4452
+ constructor(args) {
4453
+ super(
4454
+ `Error querying file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
4455
+ args
4456
+ );
4457
+ }
4458
+ };
4459
+ var TinaParseDocumentError = class extends TinaFetchError {
4460
+ constructor(args) {
4461
+ super(
4462
+ `Error parsing file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
4463
+ args
4464
+ );
4465
+ }
4466
+ toString() {
4467
+ return super.toString() + "\n OriginalError: \n" + this.originalError.toString();
4468
+ }
4469
+ };
4470
+ var auditMessage = (includeAuditMessage = true) => includeAuditMessage ? `Please run "tinacms audit" or add the --verbose option for more info` : "";
4471
+ var handleFetchErrorError = (e, verbose) => {
4472
+ if (e instanceof Error) {
4473
+ if (e instanceof TinaFetchError) {
4474
+ if (verbose) {
4475
+ console.log(e.toString());
4476
+ console.log(e);
4477
+ console.log(e.stack);
4478
+ }
4479
+ }
4480
+ } else {
4481
+ console.error(e);
4482
+ }
4483
+ throw e;
4484
+ };
4485
+
4486
+ // src/resolver/filter-utils.ts
4487
+ var resolveReferences = async (filter, fields, resolver) => {
4488
+ for (const fieldKey of Object.keys(filter)) {
4489
+ const fieldDefinition = fields.find(
4490
+ (f) => f.name === fieldKey
4491
+ );
4492
+ if (fieldDefinition) {
4493
+ if (fieldDefinition.type === "reference") {
4494
+ const { edges, values } = await resolver(filter, fieldDefinition);
4495
+ if (edges.length === 1) {
4496
+ filter[fieldKey] = {
4497
+ eq: values[0]
4498
+ };
4499
+ } else if (edges.length > 1) {
4500
+ filter[fieldKey] = {
4501
+ in: values
4502
+ };
4503
+ } else {
4504
+ filter[fieldKey] = {
4505
+ eq: "___null___"
4506
+ };
4507
+ }
4508
+ } else if (fieldDefinition.type === "object") {
4509
+ if (fieldDefinition.templates) {
4510
+ for (const templateName of Object.keys(filter[fieldKey])) {
4511
+ const template = fieldDefinition.templates.find(
4512
+ (template2) => !(typeof template2 === "string") && template2.name === templateName
4513
+ );
4514
+ if (template) {
4515
+ await resolveReferences(
4516
+ filter[fieldKey][templateName],
4517
+ template.fields,
4518
+ resolver
4519
+ );
4520
+ } else {
4521
+ throw new Error(`Template ${templateName} not found`);
4522
+ }
4523
+ }
4524
+ } else {
4525
+ await resolveReferences(
4526
+ filter[fieldKey],
4527
+ fieldDefinition.fields,
4528
+ resolver
4529
+ );
4530
+ }
4531
+ }
4532
+ } else {
4533
+ throw new Error(`Unable to find field ${fieldKey}`);
4534
+ }
4535
+ }
4536
+ };
4537
+ var collectConditionsForChildFields = (filterNode, fields, pathExpression, collectCondition) => {
4538
+ for (const childFieldName of Object.keys(filterNode)) {
4539
+ const childField = fields.find((field) => field.name === childFieldName);
4540
+ if (!childField) {
4541
+ throw new Error(`Unable to find type for field ${childFieldName}`);
4542
+ }
4543
+ collectConditionsForField(
4544
+ childFieldName,
4545
+ childField,
4546
+ filterNode[childFieldName],
4547
+ pathExpression,
4548
+ collectCondition
4549
+ );
4550
+ }
4551
+ };
4552
+ var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
4553
+ if (field.list && field.templates) {
4554
+ for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
4555
+ const template = field.templates.find(
4556
+ (template2) => !(typeof template2 === "string") && template2.name === filterKey
4557
+ );
4558
+ const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
4559
+ const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
4560
+ collectConditionsForChildFields(
4561
+ childFilterNode,
4562
+ template.fields,
4563
+ filterPath,
4564
+ collectCondition
4565
+ );
4566
+ }
4567
+ } else {
4568
+ const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
4569
+ const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
4570
+ collectConditionsForChildFields(
4571
+ filterNode,
4572
+ field.fields,
4573
+ filterPath,
4574
+ collectCondition
4575
+ );
4576
+ }
4577
+ };
4578
+ var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
4579
+ if (field.type === "object") {
4580
+ collectConditionsForObjectField(
4581
+ fieldName,
4582
+ field,
4583
+ filterNode,
4584
+ pathExpression,
4585
+ collectCondition
4586
+ );
4587
+ } else {
4588
+ collectCondition({
4589
+ filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
4590
+ filterExpression: {
4591
+ _type: field.type,
4592
+ _list: !!field.list,
4593
+ ...filterNode
4594
+ }
4595
+ });
4596
+ }
4597
+ };
4598
+
4599
+ // src/resolver/media-utils.ts
4600
+ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, schema) => {
4601
+ if (config && value) {
4602
+ if (config.useRelativeMedia === true) {
4603
+ return value;
4604
+ }
4605
+ if (hasTinaMediaConfig(schema) === true) {
4606
+ const assetsURL = `https://${config.assetsHost}/${config.clientId}`;
4607
+ if (typeof value === "string" && value.includes(assetsURL)) {
4608
+ const cleanMediaRoot = cleanUpSlashes(
4609
+ schema.config.media.tina.mediaRoot
4610
+ );
4611
+ const strippedURL = value.replace(assetsURL, "");
4612
+ return `${cleanMediaRoot}${strippedURL}`;
4613
+ }
4614
+ if (Array.isArray(value)) {
4615
+ return value.map((v) => {
4616
+ if (!v || typeof v !== "string") return v;
4617
+ const cleanMediaRoot = cleanUpSlashes(
4618
+ schema.config.media.tina.mediaRoot
4619
+ );
4620
+ const strippedURL = v.replace(assetsURL, "");
4621
+ return `${cleanMediaRoot}${strippedURL}`;
4622
+ });
4623
+ }
4624
+ return value;
4625
+ }
4626
+ return value;
4627
+ } else {
4628
+ return value;
4629
+ }
4630
+ };
4631
+ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, schema) => {
4632
+ if (config && value) {
4633
+ if (config.useRelativeMedia === true) {
4634
+ return value;
4635
+ }
4636
+ if (hasTinaMediaConfig(schema) === true) {
4637
+ const cleanMediaRoot = cleanUpSlashes(schema.config.media.tina.mediaRoot);
4638
+ if (typeof value === "string") {
4639
+ const strippedValue = value.replace(cleanMediaRoot, "");
4640
+ return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
4641
+ }
4642
+ if (Array.isArray(value)) {
4643
+ return value.map((v) => {
4644
+ if (!v || typeof v !== "string") return v;
4645
+ const strippedValue = v.replace(cleanMediaRoot, "");
4646
+ return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
4647
+ });
4648
+ }
4649
+ }
4650
+ return value;
4651
+ } else {
4652
+ return value;
4653
+ }
4654
+ };
4655
+ var cleanUpSlashes = (path7) => {
4656
+ if (path7) {
4657
+ return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
4658
+ }
4659
+ return "";
4660
+ };
4661
+ var hasTinaMediaConfig = (schema) => {
4662
+ if (!schema.config?.media?.tina) return false;
4663
+ if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
4664
+ return false;
4665
+ return true;
4660
4666
  };
4661
- var stringEscaper = makeStringEscaper(
4662
- new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
4663
- encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
4664
- );
4665
4667
 
4666
4668
  // src/resolver/index.ts
4667
4669
  var createResolver = (args) => {
4668
4670
  return new Resolver(args);
4669
4671
  };
4670
4672
  var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4671
- var _a, _b;
4672
4673
  if (!rawData) {
4673
4674
  return void 0;
4674
4675
  }
@@ -4696,7 +4697,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4696
4697
  accumulator[field.name] = {
4697
4698
  value: void 0,
4698
4699
  // never resolve the password hash
4699
- passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4700
+ passwordChangeRequired: value["passwordChangeRequired"] ?? false
4700
4701
  };
4701
4702
  break;
4702
4703
  case "image":
@@ -4712,11 +4713,11 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4712
4713
  field,
4713
4714
  (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4714
4715
  );
4715
- if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4716
+ if (tree?.children[0]?.type === "invalid_markdown") {
4716
4717
  if (isAudit) {
4717
- const invalidNode = tree == null ? void 0 : tree.children[0];
4718
+ const invalidNode = tree?.children[0];
4718
4719
  throw new import_graphql3.GraphQLError(
4719
- `${invalidNode == null ? void 0 : invalidNode.message}${invalidNode.position ? ` at line ${invalidNode.position.start.line}, column ${invalidNode.position.start.column}` : ""}`
4720
+ `${invalidNode?.message}${invalidNode.position ? ` at line ${invalidNode.position.start.line}, column ${invalidNode.position.start.column}` : ""}`
4720
4721
  );
4721
4722
  }
4722
4723
  }
@@ -4824,16 +4825,15 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4824
4825
  originalError: e,
4825
4826
  collection: collection.name,
4826
4827
  includeAuditMessage: !isAudit,
4827
- file: relativePath,
4828
- stack: e.stack
4828
+ file: relativePath
4829
4829
  });
4830
4830
  }
4831
4831
  const titleField = template.fields.find((x) => {
4832
- if (x.type === "string" && (x == null ? void 0 : x.isTitle)) {
4832
+ if (x.type === "string" && x?.isTitle) {
4833
4833
  return true;
4834
4834
  }
4835
4835
  });
4836
- const titleFieldName = titleField == null ? void 0 : titleField.name;
4836
+ const titleFieldName = titleField?.name;
4837
4837
  const title = data[titleFieldName || " "] || null;
4838
4838
  return {
4839
4839
  __typename: collection.fields ? NAMER.documentTypeName(collection.namespace) : NAMER.documentTypeName(template.namespace),
@@ -4864,24 +4864,33 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4864
4864
  throw e;
4865
4865
  }
4866
4866
  };
4867
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4867
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4868
+ let updated = false;
4868
4869
  if (!path7.includes(".") && !path7.includes("[")) {
4869
- if (path7 in obj) {
4870
+ if (path7 in obj && obj[path7] === oldValue) {
4870
4871
  obj[path7] = newValue;
4872
+ updated = true;
4871
4873
  }
4872
- return obj;
4873
- }
4874
- const parentPath = path7.replace(/\.[^.]+$/, "");
4875
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4876
- const parents = (0, import_jsonpath_plus2.JSONPath)({ path: parentPath, json: obj, resultType: "value" });
4874
+ return { object: obj, updated };
4875
+ }
4876
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4877
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4878
+ const parents = (0, import_jsonpath_plus2.JSONPath)({
4879
+ path: parentPath,
4880
+ json: obj,
4881
+ resultType: "value"
4882
+ });
4877
4883
  if (parents.length > 0) {
4878
4884
  parents.forEach((parent) => {
4879
4885
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4880
- parent[keyToUpdate] = newValue;
4886
+ if (parent[keyToUpdate] === oldValue) {
4887
+ parent[keyToUpdate] = newValue;
4888
+ updated = true;
4889
+ }
4881
4890
  }
4882
4891
  });
4883
4892
  }
4884
- return obj;
4893
+ return { object: obj, updated };
4885
4894
  };
4886
4895
  var Resolver = class {
4887
4896
  constructor(init) {
@@ -4898,7 +4907,9 @@ var Resolver = class {
4898
4907
  };
4899
4908
  this.getRaw = async (fullPath) => {
4900
4909
  if (typeof fullPath !== "string") {
4901
- throw new Error(`fullPath must be of type string for getDocument request`);
4910
+ throw new Error(
4911
+ `fullPath must be of type string for getDocument request`
4912
+ );
4902
4913
  }
4903
4914
  return this.database.get(fullPath);
4904
4915
  };
@@ -4927,10 +4938,12 @@ var Resolver = class {
4927
4938
  };
4928
4939
  this.getDocument = async (fullPath, opts = {}) => {
4929
4940
  if (typeof fullPath !== "string") {
4930
- throw new Error(`fullPath must be of type string for getDocument request`);
4941
+ throw new Error(
4942
+ `fullPath must be of type string for getDocument request`
4943
+ );
4931
4944
  }
4932
4945
  const rawData = await this.getRaw(fullPath);
4933
- const hasReferences = (opts == null ? void 0 : opts.checkReferences) ? await this.hasReferences(fullPath, opts.collection) : void 0;
4946
+ const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4934
4947
  return transformDocumentIntoPayload(
4935
4948
  fullPath,
4936
4949
  rawData,
@@ -4942,7 +4955,9 @@ var Resolver = class {
4942
4955
  };
4943
4956
  this.deleteDocument = async (fullPath) => {
4944
4957
  if (typeof fullPath !== "string") {
4945
- throw new Error(`fullPath must be of type string for getDocument request`);
4958
+ throw new Error(
4959
+ `fullPath must be of type string for getDocument request`
4960
+ );
4946
4961
  }
4947
4962
  await this.database.delete(fullPath);
4948
4963
  };
@@ -4968,9 +4983,9 @@ var Resolver = class {
4968
4983
  return this.buildFieldMutations(
4969
4984
  item,
4970
4985
  objectTemplate,
4971
- idField && existingData && (existingData == null ? void 0 : existingData.find(
4986
+ idField && existingData && existingData?.find(
4972
4987
  (d) => d[idField.name] === item[idField.name]
4973
- ))
4988
+ )
4974
4989
  );
4975
4990
  }
4976
4991
  )
@@ -5096,7 +5111,7 @@ var Resolver = class {
5096
5111
  isCollectionSpecific
5097
5112
  }) => {
5098
5113
  const doc = await this.getDocument(realPath);
5099
- const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5114
+ const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5100
5115
  if (isAddPendingDocument === true) {
5101
5116
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5102
5117
  const params2 = this.buildParams(args);
@@ -5106,7 +5121,7 @@ var Resolver = class {
5106
5121
  const values = await this.buildFieldMutations(
5107
5122
  params2,
5108
5123
  templateInfo.template,
5109
- doc == null ? void 0 : doc._rawData
5124
+ doc?._rawData
5110
5125
  );
5111
5126
  await this.database.put(
5112
5127
  realPath,
@@ -5130,7 +5145,7 @@ var Resolver = class {
5130
5145
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
5131
5146
  templateParams,
5132
5147
  template,
5133
- doc == null ? void 0 : doc._rawData
5148
+ doc?._rawData
5134
5149
  ),
5135
5150
  _template: lastItem(template.namespace)
5136
5151
  };
@@ -5144,9 +5159,13 @@ var Resolver = class {
5144
5159
  //@ts-ignore
5145
5160
  isCollectionSpecific ? args.params : args.params[collection.name],
5146
5161
  collection,
5147
- doc == null ? void 0 : doc._rawData
5162
+ doc?._rawData
5163
+ );
5164
+ await this.database.put(
5165
+ realPath,
5166
+ { ...oldDoc, ...params },
5167
+ collection.name
5148
5168
  );
5149
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
5150
5169
  return this.getDocument(realPath);
5151
5170
  };
5152
5171
  /**
@@ -5156,7 +5175,6 @@ var Resolver = class {
5156
5175
  this.resolveLegacyValues = (oldDoc, collection) => {
5157
5176
  const legacyValues = {};
5158
5177
  Object.entries(oldDoc).forEach(([key, value]) => {
5159
- var _a;
5160
5178
  const reservedKeys = [
5161
5179
  "$_body",
5162
5180
  "_collection",
@@ -5169,7 +5187,7 @@ var Resolver = class {
5169
5187
  return;
5170
5188
  }
5171
5189
  if (oldDoc._template && collection.templates) {
5172
- const template = (_a = collection.templates) == null ? void 0 : _a.find(
5190
+ const template = collection.templates?.find(
5173
5191
  ({ name }) => name === oldDoc._template
5174
5192
  );
5175
5193
  if (template) {
@@ -5216,7 +5234,7 @@ var Resolver = class {
5216
5234
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5217
5235
  );
5218
5236
  const collection = await this.tinaSchema.getCollection(collectionLookup);
5219
- let realPath = import_path3.default.join(collection == null ? void 0 : collection.path, args.relativePath);
5237
+ let realPath = import_path3.default.join(collection?.path, args.relativePath);
5220
5238
  if (isFolderCreation) {
5221
5239
  realPath = `${realPath}/.gitkeep.${collection.format || "md"}`;
5222
5240
  }
@@ -5260,17 +5278,35 @@ var Resolver = class {
5260
5278
  await this.deleteDocument(realPath);
5261
5279
  if (await this.hasReferences(realPath, collection)) {
5262
5280
  const collRefs = await this.findReferences(realPath, collection);
5263
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5264
- for (const [refPath, refs] of Object.entries(refFields)) {
5265
- let refDoc = await this.getRaw(refPath);
5266
- for (const ref of refs) {
5267
- refDoc = updateObjectWithJsonPath(
5281
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5282
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5283
+ docsWithRefs
5284
+ )) {
5285
+ let refDoc = await this.getRaw(pathToDocWithRef);
5286
+ let hasUpdate = false;
5287
+ for (const path7 of referencePaths) {
5288
+ const { object: object2, updated } = updateObjectWithJsonPath(
5268
5289
  refDoc,
5269
- ref.path.join("."),
5290
+ path7,
5291
+ realPath,
5270
5292
  null
5271
5293
  );
5294
+ refDoc = object2;
5295
+ hasUpdate = updated || hasUpdate;
5296
+ }
5297
+ if (hasUpdate) {
5298
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5299
+ if (!collectionWithRef) {
5300
+ throw new Error(
5301
+ `Unable to find collection for ${pathToDocWithRef}`
5302
+ );
5303
+ }
5304
+ await this.database.put(
5305
+ pathToDocWithRef,
5306
+ refDoc,
5307
+ collectionWithRef.name
5308
+ );
5272
5309
  }
5273
- await this.database.put(refPath, refDoc, collection2);
5274
5310
  }
5275
5311
  }
5276
5312
  }
@@ -5282,34 +5318,57 @@ var Resolver = class {
5282
5318
  (yup3) => yup3.object({ params: yup3.object().required() })
5283
5319
  );
5284
5320
  assertShape(
5285
- args == null ? void 0 : args.params,
5321
+ args?.params,
5286
5322
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5287
5323
  );
5288
5324
  const doc = await this.getDocument(realPath);
5289
5325
  const newRealPath = import_path3.default.join(
5290
- collection == null ? void 0 : collection.path,
5326
+ collection?.path,
5291
5327
  args.params.relativePath
5292
5328
  );
5329
+ if (newRealPath === realPath) {
5330
+ return doc;
5331
+ }
5293
5332
  await this.database.put(newRealPath, doc._rawData, collection.name);
5294
5333
  await this.deleteDocument(realPath);
5295
5334
  const collRefs = await this.findReferences(realPath, collection);
5296
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5297
- for (const [refPath, refs] of Object.entries(refFields)) {
5298
- let refDoc = await this.getRaw(refPath);
5299
- for (const ref of refs) {
5300
- refDoc = updateObjectWithJsonPath(
5301
- refDoc,
5302
- ref.path.join("."),
5335
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5336
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5337
+ docsWithRefs
5338
+ )) {
5339
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5340
+ let hasUpdate = false;
5341
+ for (const path7 of referencePaths) {
5342
+ const { object: object2, updated } = updateObjectWithJsonPath(
5343
+ docWithRef,
5344
+ path7,
5345
+ realPath,
5303
5346
  newRealPath
5304
5347
  );
5348
+ docWithRef = object2;
5349
+ hasUpdate = updated || hasUpdate;
5350
+ }
5351
+ if (hasUpdate) {
5352
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5353
+ if (!collectionWithRef) {
5354
+ throw new Error(
5355
+ `Unable to find collection for ${pathToDocWithRef}`
5356
+ );
5357
+ }
5358
+ await this.database.put(
5359
+ pathToDocWithRef,
5360
+ docWithRef,
5361
+ collectionWithRef.name
5362
+ );
5305
5363
  }
5306
- await this.database.put(refPath, refDoc, collection2);
5307
5364
  }
5308
5365
  }
5309
5366
  return this.getDocument(newRealPath);
5310
5367
  }
5311
5368
  if (alreadyExists === false) {
5312
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5369
+ throw new Error(
5370
+ `Unable to update document, ${realPath} does not exist`
5371
+ );
5313
5372
  }
5314
5373
  return this.updateResolveDocument({
5315
5374
  collection,
@@ -5435,35 +5494,30 @@ var Resolver = class {
5435
5494
  */
5436
5495
  this.hasReferences = async (id, c) => {
5437
5496
  let count = 0;
5438
- const deepRefs = this.tinaSchema.findReferences(c.name);
5439
- for (const [collection, refs] of Object.entries(deepRefs)) {
5440
- for (const ref of refs) {
5441
- await this.database.query(
5442
- {
5443
- collection,
5444
- filterChain: makeFilterChain({
5445
- conditions: [
5446
- {
5447
- filterPath: ref.path.join("."),
5448
- filterExpression: {
5449
- _type: "reference",
5450
- _list: false,
5451
- eq: id
5452
- }
5453
- }
5454
- ]
5455
- }),
5456
- sort: ref.field.name
5457
- },
5458
- (refId) => {
5459
- count++;
5460
- return refId;
5461
- }
5462
- );
5463
- if (count) {
5464
- return true;
5465
- }
5497
+ await this.database.query(
5498
+ {
5499
+ collection: c.name,
5500
+ filterChain: makeFilterChain({
5501
+ conditions: [
5502
+ {
5503
+ filterPath: REFS_REFERENCE_FIELD,
5504
+ filterExpression: {
5505
+ _type: "string",
5506
+ _list: false,
5507
+ eq: id
5508
+ }
5509
+ }
5510
+ ]
5511
+ }),
5512
+ sort: REFS_COLLECTIONS_SORT_KEY
5513
+ },
5514
+ (refId) => {
5515
+ count++;
5516
+ return refId;
5466
5517
  }
5518
+ );
5519
+ if (count) {
5520
+ return true;
5467
5521
  }
5468
5522
  return false;
5469
5523
  };
@@ -5471,50 +5525,44 @@ var Resolver = class {
5471
5525
  * Finds references to a document
5472
5526
  * @param id the id of the document to find references to
5473
5527
  * @param c the collection to find references in
5474
- * @returns references to the document in the form of a map of collection names to a list of fields that reference the document
5528
+ * @returns a map of references to the document
5475
5529
  */
5476
5530
  this.findReferences = async (id, c) => {
5477
5531
  const references = {};
5478
- const deepRefs = this.tinaSchema.findReferences(c.name);
5479
- for (const [collection, refs] of Object.entries(deepRefs)) {
5480
- for (const ref of refs) {
5481
- await this.database.query(
5482
- {
5483
- collection,
5484
- filterChain: makeFilterChain({
5485
- conditions: [
5486
- {
5487
- filterPath: ref.path.join("."),
5488
- filterExpression: {
5489
- _type: "reference",
5490
- _list: false,
5491
- eq: id
5492
- }
5493
- }
5494
- ]
5495
- }),
5496
- sort: ref.field.name
5497
- },
5498
- (refId) => {
5499
- if (!references[collection]) {
5500
- references[collection] = {};
5501
- }
5502
- if (!references[collection][refId]) {
5503
- references[collection][refId] = [];
5532
+ await this.database.query(
5533
+ {
5534
+ collection: c.name,
5535
+ filterChain: makeFilterChain({
5536
+ conditions: [
5537
+ {
5538
+ filterPath: REFS_REFERENCE_FIELD,
5539
+ filterExpression: {
5540
+ _type: "string",
5541
+ _list: false,
5542
+ eq: id
5543
+ }
5504
5544
  }
5505
- references[collection][refId].push({
5506
- path: ref.path,
5507
- field: ref.field
5508
- });
5509
- return refId;
5510
- }
5511
- );
5545
+ ]
5546
+ }),
5547
+ sort: REFS_COLLECTIONS_SORT_KEY
5548
+ },
5549
+ (refId, rawItem) => {
5550
+ if (!references[c.name]) {
5551
+ references[c.name] = {};
5552
+ }
5553
+ if (!references[c.name][refId]) {
5554
+ references[c.name][refId] = [];
5555
+ }
5556
+ const referencePath = rawItem?.[REFS_PATH_FIELD];
5557
+ if (referencePath) {
5558
+ references[c.name][refId].push(referencePath);
5559
+ }
5560
+ return refId;
5512
5561
  }
5513
- }
5562
+ );
5514
5563
  return references;
5515
5564
  };
5516
5565
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5517
- var _a;
5518
5566
  const accum = {};
5519
5567
  for (const passwordField of template.fields.filter(
5520
5568
  (f) => f.type === "password"
@@ -5557,7 +5605,7 @@ var Resolver = class {
5557
5605
  accum[fieldName] = await this.buildObjectMutations(
5558
5606
  fieldValue,
5559
5607
  field,
5560
- existingData == null ? void 0 : existingData[fieldName]
5608
+ existingData?.[fieldName]
5561
5609
  );
5562
5610
  break;
5563
5611
  case "password":
@@ -5576,12 +5624,12 @@ var Resolver = class {
5576
5624
  } else {
5577
5625
  accum[fieldName] = {
5578
5626
  ...fieldValue,
5579
- value: (_a = existingData == null ? void 0 : existingData[fieldName]) == null ? void 0 : _a["value"]
5627
+ value: existingData?.[fieldName]?.["value"]
5580
5628
  };
5581
5629
  }
5582
5630
  break;
5583
5631
  case "rich-text":
5584
- accum[fieldName] = (0, import_mdx.stringifyMDX)(
5632
+ accum[fieldName] = (0, import_mdx.serializeMDX)(
5585
5633
  fieldValue,
5586
5634
  field,
5587
5635
  (fieldValue2) => resolveMediaCloudToRelative(
@@ -5688,8 +5736,129 @@ var resolveDateInput = (value) => {
5688
5736
  return date;
5689
5737
  };
5690
5738
 
5691
- // src/resolve.ts
5692
- var import_lodash4 = __toESM(require("lodash.set"));
5739
+ // src/resolver/auth-fields.ts
5740
+ var import_compat = require("es-toolkit/compat");
5741
+ async function getUserDocumentContext(tinaSchema, resolver) {
5742
+ const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5743
+ if (!collection) {
5744
+ throw new Error("Auth collection not found");
5745
+ }
5746
+ const userFields = mapUserFields(collection, ["_rawData"]);
5747
+ if (!userFields.length) {
5748
+ throw new Error(`No user field found in collection ${collection.name}`);
5749
+ }
5750
+ if (userFields.length > 1) {
5751
+ throw new Error(
5752
+ `Multiple user fields found in collection ${collection.name}`
5753
+ );
5754
+ }
5755
+ const userField = userFields[0];
5756
+ const realPath = `${collection.path}/index.json`;
5757
+ const userDoc = await resolver.getDocument(realPath);
5758
+ const users = get(userDoc, userField.path);
5759
+ if (!users) {
5760
+ throw new Error("No users found");
5761
+ }
5762
+ return { collection, userField, users, userDoc, realPath };
5763
+ }
5764
+ function findUserInCollection(users, userField, userSub) {
5765
+ const { idFieldName } = userField;
5766
+ if (!idFieldName) {
5767
+ throw new Error("No uid field found on user field");
5768
+ }
5769
+ return users.find((u) => u[idFieldName] === userSub) || null;
5770
+ }
5771
+ async function handleAuthenticate({
5772
+ tinaSchema,
5773
+ resolver,
5774
+ sub,
5775
+ password,
5776
+ ctxUser
5777
+ }) {
5778
+ const userSub = sub || ctxUser?.sub;
5779
+ const { userField, users } = await getUserDocumentContext(
5780
+ tinaSchema,
5781
+ resolver
5782
+ );
5783
+ const user = findUserInCollection(users, userField, userSub);
5784
+ if (!user) {
5785
+ return null;
5786
+ }
5787
+ const { passwordFieldName } = userField;
5788
+ const saltedHash = get(user, [passwordFieldName || "", "value"]);
5789
+ if (!saltedHash) {
5790
+ throw new Error("No password field found on user field");
5791
+ }
5792
+ const matches = await checkPasswordHash({
5793
+ saltedHash,
5794
+ password
5795
+ });
5796
+ return matches ? user : null;
5797
+ }
5798
+ async function handleAuthorize({
5799
+ tinaSchema,
5800
+ resolver,
5801
+ sub,
5802
+ ctxUser
5803
+ }) {
5804
+ const userSub = sub || ctxUser?.sub;
5805
+ const { userField, users } = await getUserDocumentContext(
5806
+ tinaSchema,
5807
+ resolver
5808
+ );
5809
+ const user = findUserInCollection(users, userField, userSub);
5810
+ return user ? user : null;
5811
+ }
5812
+ async function handleUpdatePassword({
5813
+ tinaSchema,
5814
+ resolver,
5815
+ password,
5816
+ ctxUser
5817
+ }) {
5818
+ if (!ctxUser?.sub) {
5819
+ throw new Error("Not authorized");
5820
+ }
5821
+ if (!password) {
5822
+ throw new Error("No password provided");
5823
+ }
5824
+ const { collection, userField, users, realPath } = await getUserDocumentContext(tinaSchema, resolver);
5825
+ const { idFieldName, passwordFieldName } = userField;
5826
+ const user = users.find((u) => u[idFieldName] === ctxUser.sub);
5827
+ if (!user) {
5828
+ throw new Error("Not authorized");
5829
+ }
5830
+ user[passwordFieldName] = {
5831
+ value: password,
5832
+ passwordChangeRequired: false
5833
+ };
5834
+ const params = {};
5835
+ (0, import_compat.set)(
5836
+ params,
5837
+ userField.path.slice(1),
5838
+ // remove _rawData from users path
5839
+ users.map((u) => {
5840
+ if (user[idFieldName] === u[idFieldName]) {
5841
+ return user;
5842
+ }
5843
+ return {
5844
+ // don't overwrite other users' passwords
5845
+ ...u,
5846
+ [passwordFieldName]: {
5847
+ ...u[passwordFieldName],
5848
+ value: ""
5849
+ }
5850
+ };
5851
+ })
5852
+ );
5853
+ await resolver.updateResolveDocument({
5854
+ collection,
5855
+ args: { params },
5856
+ realPath,
5857
+ isCollectionSpecific: true,
5858
+ isAddPendingDocument: false
5859
+ });
5860
+ return true;
5861
+ }
5693
5862
 
5694
5863
  // src/error.ts
5695
5864
  var import_graphql4 = require("graphql");
@@ -5711,9 +5880,8 @@ var resolve = async ({
5711
5880
  isAudit,
5712
5881
  ctxUser
5713
5882
  }) => {
5714
- var _a;
5715
5883
  try {
5716
- const verboseValue = verbose != null ? verbose : true;
5884
+ const verboseValue = verbose ?? true;
5717
5885
  const graphQLSchemaAst = await database.getGraphQLSchema();
5718
5886
  if (!graphQLSchemaAst) {
5719
5887
  throw new import_graphql5.GraphQLError("GraphQL schema not found");
@@ -5725,7 +5893,7 @@ var resolve = async ({
5725
5893
  // @ts-ignore
5726
5894
  schema: tinaConfig,
5727
5895
  // @ts-ignore
5728
- flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
5896
+ flags: tinaConfig?.meta?.flags
5729
5897
  });
5730
5898
  const resolver = createResolver({
5731
5899
  config,
@@ -5750,7 +5918,6 @@ var resolve = async ({
5750
5918
  throw new Error(`Unable to find lookup key for ${namedType}`);
5751
5919
  },
5752
5920
  fieldResolver: async (source = {}, _args = {}, _context, info) => {
5753
- var _a2, _b, _c, _d;
5754
5921
  try {
5755
5922
  const args = JSON.parse(JSON.stringify(_args));
5756
5923
  const returnType = (0, import_graphql5.getNamedType)(info.returnType).toString();
@@ -5767,8 +5934,7 @@ var resolve = async ({
5767
5934
  );
5768
5935
  const hasDocuments2 = collectionNode2.selectionSet.selections.find(
5769
5936
  (x) => {
5770
- var _a3;
5771
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5937
+ return x?.name?.value === "documents";
5772
5938
  }
5773
5939
  );
5774
5940
  return tinaSchema.getCollections().map((collection) => {
@@ -5784,8 +5950,7 @@ var resolve = async ({
5784
5950
  );
5785
5951
  const hasDocuments = collectionNode.selectionSet.selections.find(
5786
5952
  (x) => {
5787
- var _a3;
5788
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5953
+ return x?.name?.value === "documents";
5789
5954
  }
5790
5955
  );
5791
5956
  return resolver.resolveCollection(
@@ -5803,119 +5968,33 @@ var resolve = async ({
5803
5968
  );
5804
5969
  }
5805
5970
  }
5806
- if (info.fieldName === "authenticate" || info.fieldName === "authorize") {
5807
- const sub = args.sub || (ctxUser == null ? void 0 : ctxUser.sub);
5808
- const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5809
- if (!collection) {
5810
- throw new Error("Auth collection not found");
5811
- }
5812
- const userFields = mapUserFields(collection, ["_rawData"]);
5813
- if (!userFields.length) {
5814
- throw new Error(
5815
- `No user field found in collection ${collection.name}`
5816
- );
5817
- }
5818
- if (userFields.length > 1) {
5819
- throw new Error(
5820
- `Multiple user fields found in collection ${collection.name}`
5821
- );
5822
- }
5823
- const userField = userFields[0];
5824
- const realPath = `${collection.path}/index.json`;
5825
- const userDoc = await resolver.getDocument(realPath);
5826
- const users = get(userDoc, userField.path);
5827
- if (!users) {
5828
- throw new Error("No users found");
5829
- }
5830
- const { idFieldName, passwordFieldName } = userField;
5831
- if (!idFieldName) {
5832
- throw new Error("No uid field found on user field");
5833
- }
5834
- const user = users.find((u) => u[idFieldName] === sub);
5835
- if (!user) {
5836
- return null;
5837
- }
5838
- if (info.fieldName === "authenticate") {
5839
- const saltedHash = get(user, [passwordFieldName || "", "value"]);
5840
- if (!saltedHash) {
5841
- throw new Error("No password field found on user field");
5842
- }
5843
- const matches = await checkPasswordHash({
5844
- saltedHash,
5845
- password: args.password
5846
- });
5847
- if (matches) {
5848
- return user;
5849
- }
5850
- return null;
5851
- }
5852
- return user;
5971
+ if (info.fieldName === "authenticate") {
5972
+ return handleAuthenticate({
5973
+ tinaSchema,
5974
+ resolver,
5975
+ sub: args.sub,
5976
+ password: args.password,
5977
+ info,
5978
+ ctxUser
5979
+ });
5980
+ }
5981
+ if (info.fieldName === "authorize") {
5982
+ return handleAuthorize({
5983
+ tinaSchema,
5984
+ resolver,
5985
+ sub: args.sub,
5986
+ info,
5987
+ ctxUser
5988
+ });
5853
5989
  }
5854
5990
  if (info.fieldName === "updatePassword") {
5855
- if (!(ctxUser == null ? void 0 : ctxUser.sub)) {
5856
- throw new Error("Not authorized");
5857
- }
5858
- if (!args.password) {
5859
- throw new Error("No password provided");
5860
- }
5861
- const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5862
- if (!collection) {
5863
- throw new Error("Auth collection not found");
5864
- }
5865
- const userFields = mapUserFields(collection, ["_rawData"]);
5866
- if (!userFields.length) {
5867
- throw new Error(
5868
- `No user field found in collection ${collection.name}`
5869
- );
5870
- }
5871
- if (userFields.length > 1) {
5872
- throw new Error(
5873
- `Multiple user fields found in collection ${collection.name}`
5874
- );
5875
- }
5876
- const userField = userFields[0];
5877
- const realPath = `${collection.path}/index.json`;
5878
- const userDoc = await resolver.getDocument(realPath);
5879
- const users = get(userDoc, userField.path);
5880
- if (!users) {
5881
- throw new Error("No users found");
5882
- }
5883
- const { idFieldName, passwordFieldName } = userField;
5884
- const user = users.find((u) => u[idFieldName] === ctxUser.sub);
5885
- if (!user) {
5886
- throw new Error("Not authorized");
5887
- }
5888
- user[passwordFieldName] = {
5889
- value: args.password,
5890
- passwordChangeRequired: false
5891
- };
5892
- const params = {};
5893
- (0, import_lodash4.default)(
5894
- params,
5895
- userField.path.slice(1),
5896
- // remove _rawData from users path
5897
- users.map((u) => {
5898
- if (user[idFieldName] === u[idFieldName]) {
5899
- return user;
5900
- }
5901
- return {
5902
- // don't overwrite other users' passwords
5903
- ...u,
5904
- [passwordFieldName]: {
5905
- ...u[passwordFieldName],
5906
- value: ""
5907
- }
5908
- };
5909
- })
5910
- );
5911
- await resolver.updateResolveDocument({
5912
- collection,
5913
- args: { params },
5914
- realPath,
5915
- isCollectionSpecific: true,
5916
- isAddPendingDocument: false
5991
+ return handleUpdatePassword({
5992
+ tinaSchema,
5993
+ resolver,
5994
+ password: args.password,
5995
+ info,
5996
+ ctxUser
5917
5997
  });
5918
- return true;
5919
5998
  }
5920
5999
  if (!lookup) {
5921
6000
  return value;
@@ -5935,7 +6014,7 @@ var resolve = async ({
5935
6014
  if (typeof value === "string" && value !== "") {
5936
6015
  return resolver.getDocument(value);
5937
6016
  }
5938
- if ((args == null ? void 0 : args.collection) && info.fieldName === "addPendingDocument") {
6017
+ if (args?.collection && info.fieldName === "addPendingDocument") {
5939
6018
  return resolver.resolveDocument({
5940
6019
  args: { ...args, params: {} },
5941
6020
  collection: args.collection,
@@ -5959,7 +6038,7 @@ var resolve = async ({
5959
6038
  // Right now this is the only case for deletion
5960
6039
  isDeletion: info.fieldName === "deleteDocument",
5961
6040
  isFolderCreation: info.fieldName === "createFolder",
5962
- isUpdateName: Boolean((_a2 = args == null ? void 0 : args.params) == null ? void 0 : _a2.relativePath),
6041
+ isUpdateName: Boolean(args?.params?.relativePath),
5963
6042
  isAddPendingDocument: false,
5964
6043
  isCollectionSpecific: false
5965
6044
  });
@@ -5978,16 +6057,16 @@ var resolve = async ({
5978
6057
  })
5979
6058
  };
5980
6059
  }
5981
- if (info.fieldName === "documents" && (value == null ? void 0 : value.collection) && (value == null ? void 0 : value.hasDocuments)) {
6060
+ if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
5982
6061
  let filter = args.filter;
5983
6062
  if (
5984
6063
  // 1. Make sure that the filter exists
5985
- typeof (args == null ? void 0 : args.filter) !== "undefined" && (args == null ? void 0 : args.filter) !== null && // 2. Make sure that the collection name exists
6064
+ typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
5986
6065
  // @ts-ignore
5987
- typeof ((_b = value == null ? void 0 : value.collection) == null ? void 0 : _b.name) === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
6066
+ typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
5988
6067
  // @ts-ignore
5989
- Object.keys(args.filter).includes((_c = value == null ? void 0 : value.collection) == null ? void 0 : _c.name) && // @ts-ignore
5990
- typeof args.filter[(_d = value == null ? void 0 : value.collection) == null ? void 0 : _d.name] !== "undefined"
6068
+ Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
6069
+ typeof args.filter[value?.collection?.name] !== "undefined"
5991
6070
  ) {
5992
6071
  filter = args.filter[value.collection.name];
5993
6072
  }
@@ -6124,15 +6203,15 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
6124
6203
  };
6125
6204
 
6126
6205
  // src/database/index.ts
6127
- var import_node_path = __toESM(require("path"));
6206
+ var import_node_path = __toESM(require("node:path"));
6128
6207
  var import_graphql6 = require("graphql");
6129
6208
  var import_micromatch2 = __toESM(require("micromatch"));
6130
6209
  var import_js_sha12 = __toESM(require("js-sha1"));
6131
- var import_lodash5 = __toESM(require("lodash.set"));
6210
+ var import_compat2 = require("es-toolkit/compat");
6132
6211
  var createLocalDatabase = (config) => {
6133
- const level = new TinaLevelClient(config == null ? void 0 : config.port);
6212
+ const level = new TinaLevelClient(config?.port);
6134
6213
  level.openConnection();
6135
- const fsBridge = new FilesystemBridge((config == null ? void 0 : config.rootPath) || process.cwd());
6214
+ const fsBridge = new FilesystemBridge(config?.rootPath || process.cwd());
6136
6215
  return new Database({
6137
6216
  bridge: fsBridge,
6138
6217
  ...config || {},
@@ -6205,7 +6284,7 @@ var Database = class {
6205
6284
  );
6206
6285
  }
6207
6286
  const metadata = await metadataLevel.get(`metadata_${key}`);
6208
- return metadata == null ? void 0 : metadata.value;
6287
+ return metadata?.value;
6209
6288
  };
6210
6289
  this.setMetadata = async (key, value) => {
6211
6290
  await this.initLevel();
@@ -6227,14 +6306,14 @@ var Database = class {
6227
6306
  let level = this.contentLevel;
6228
6307
  if (this.appLevel) {
6229
6308
  collection = await this.collectionForPath(filepath);
6230
- if (collection == null ? void 0 : collection.isDetached) {
6309
+ if (collection?.isDetached) {
6231
6310
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
6232
6311
  }
6233
6312
  }
6234
6313
  const contentObject = await level.sublevel(
6235
6314
  CONTENT_ROOT_PREFIX,
6236
6315
  SUBLEVEL_OPTIONS
6237
- ).get((0, import_schema_tools3.normalizePath)(filepath));
6316
+ ).get((0, import_schema_tools4.normalizePath)(filepath));
6238
6317
  if (!contentObject) {
6239
6318
  throw new NotFoundError(`Unable to find record ${filepath}`);
6240
6319
  }
@@ -6258,9 +6337,10 @@ var Database = class {
6258
6337
  collection
6259
6338
  );
6260
6339
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6261
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6262
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6263
- if (!(collection == null ? void 0 : collection.isDetached)) {
6340
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6341
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6342
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6343
+ if (!collection?.isDetached) {
6264
6344
  if (this.bridge) {
6265
6345
  await this.bridge.put(normalizedPath, stringifiedFile);
6266
6346
  }
@@ -6278,7 +6358,7 @@ var Database = class {
6278
6358
  }
6279
6359
  }
6280
6360
  let level = this.contentLevel;
6281
- if (collection == null ? void 0 : collection.isDetached) {
6361
+ if (collection?.isDetached) {
6282
6362
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
6283
6363
  }
6284
6364
  const folderTreeBuilder = new FolderTreeBuilder();
@@ -6287,9 +6367,17 @@ var Database = class {
6287
6367
  let delOps = [];
6288
6368
  if (!isGitKeep(normalizedPath, collection)) {
6289
6369
  putOps = [
6370
+ ...makeRefOpsForDocument(
6371
+ normalizedPath,
6372
+ collection?.name,
6373
+ collectionReferences,
6374
+ dataFields,
6375
+ "put",
6376
+ level
6377
+ ),
6290
6378
  ...makeIndexOpsForDocument(
6291
6379
  normalizedPath,
6292
- collection == null ? void 0 : collection.name,
6380
+ collection?.name,
6293
6381
  collectionIndexDefinitions,
6294
6382
  dataFields,
6295
6383
  "put",
@@ -6298,7 +6386,7 @@ var Database = class {
6298
6386
  // folder indices
6299
6387
  ...makeIndexOpsForDocument(
6300
6388
  normalizedPath,
6301
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6389
+ `${collection?.name}_${folderKey}`,
6302
6390
  collectionIndexDefinitions,
6303
6391
  dataFields,
6304
6392
  "put",
@@ -6310,9 +6398,17 @@ var Database = class {
6310
6398
  SUBLEVEL_OPTIONS
6311
6399
  ).get(normalizedPath);
6312
6400
  delOps = existingItem ? [
6401
+ ...makeRefOpsForDocument(
6402
+ normalizedPath,
6403
+ collection?.name,
6404
+ collectionReferences,
6405
+ existingItem,
6406
+ "del",
6407
+ level
6408
+ ),
6313
6409
  ...makeIndexOpsForDocument(
6314
6410
  normalizedPath,
6315
- collection == null ? void 0 : collection.name,
6411
+ collection?.name,
6316
6412
  collectionIndexDefinitions,
6317
6413
  existingItem,
6318
6414
  "del",
@@ -6321,7 +6417,7 @@ var Database = class {
6321
6417
  // folder indices
6322
6418
  ...makeIndexOpsForDocument(
6323
6419
  normalizedPath,
6324
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6420
+ `${collection?.name}_${folderKey}`,
6325
6421
  collectionIndexDefinitions,
6326
6422
  existingItem,
6327
6423
  "del",
@@ -6345,7 +6441,6 @@ var Database = class {
6345
6441
  await level.batch(ops);
6346
6442
  };
6347
6443
  this.put = async (filepath, data, collectionName) => {
6348
- var _a, _b;
6349
6444
  await this.initLevel();
6350
6445
  try {
6351
6446
  if (SYSTEM_FILES.includes(filepath)) {
@@ -6356,15 +6451,16 @@ var Database = class {
6356
6451
  const indexDefinitions = await this.getIndexDefinitions(
6357
6452
  this.contentLevel
6358
6453
  );
6359
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6454
+ collectionIndexDefinitions = indexDefinitions?.[collectionName];
6360
6455
  }
6361
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6456
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6457
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6362
6458
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6363
6459
  const collection = await this.collectionForPath(filepath);
6364
6460
  if (!collection) {
6365
6461
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
6366
6462
  }
6367
- if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
6463
+ if (collection.match?.exclude || collection.match?.include) {
6368
6464
  const matches = this.tinaSchema.getMatches({ collection });
6369
6465
  const match = import_micromatch2.default.isMatch(filepath, matches);
6370
6466
  if (!match) {
@@ -6378,7 +6474,7 @@ var Database = class {
6378
6474
  const stringifiedFile = filepath.endsWith(
6379
6475
  `.gitkeep.${collection.format || "md"}`
6380
6476
  ) ? "" : await this.stringifyFile(filepath, dataFields, collection);
6381
- if (!(collection == null ? void 0 : collection.isDetached)) {
6477
+ if (!collection?.isDetached) {
6382
6478
  if (this.bridge) {
6383
6479
  await this.bridge.put(normalizedPath, stringifiedFile);
6384
6480
  }
@@ -6400,11 +6496,19 @@ var Database = class {
6400
6496
  filepath,
6401
6497
  collection.path || ""
6402
6498
  );
6403
- const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6499
+ const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6404
6500
  let putOps = [];
6405
6501
  let delOps = [];
6406
6502
  if (!isGitKeep(normalizedPath, collection)) {
6407
6503
  putOps = [
6504
+ ...makeRefOpsForDocument(
6505
+ normalizedPath,
6506
+ collectionName,
6507
+ collectionReferences,
6508
+ dataFields,
6509
+ "put",
6510
+ level
6511
+ ),
6408
6512
  ...makeIndexOpsForDocument(
6409
6513
  normalizedPath,
6410
6514
  collectionName,
@@ -6416,7 +6520,7 @@ var Database = class {
6416
6520
  // folder indices
6417
6521
  ...makeIndexOpsForDocument(
6418
6522
  normalizedPath,
6419
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6523
+ `${collection?.name}_${folderKey}`,
6420
6524
  collectionIndexDefinitions,
6421
6525
  dataFields,
6422
6526
  "put",
@@ -6428,6 +6532,14 @@ var Database = class {
6428
6532
  SUBLEVEL_OPTIONS
6429
6533
  ).get(normalizedPath);
6430
6534
  delOps = existingItem ? [
6535
+ ...makeRefOpsForDocument(
6536
+ normalizedPath,
6537
+ collectionName,
6538
+ collectionReferences,
6539
+ existingItem,
6540
+ "del",
6541
+ level
6542
+ ),
6431
6543
  ...makeIndexOpsForDocument(
6432
6544
  normalizedPath,
6433
6545
  collectionName,
@@ -6439,7 +6551,7 @@ var Database = class {
6439
6551
  // folder indices
6440
6552
  ...makeIndexOpsForDocument(
6441
6553
  normalizedPath,
6442
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6554
+ `${collection?.name}_${folderKey}`,
6443
6555
  collectionIndexDefinitions,
6444
6556
  existingItem,
6445
6557
  "del",
@@ -6470,8 +6582,7 @@ var Database = class {
6470
6582
  throw new TinaFetchError(`Error in PUT for ${filepath}`, {
6471
6583
  originalError: error,
6472
6584
  file: filepath,
6473
- collection: collectionName,
6474
- stack: error.stack
6585
+ collection: collectionName
6475
6586
  });
6476
6587
  }
6477
6588
  };
@@ -6516,8 +6627,8 @@ var Database = class {
6516
6627
  writeTemplateKey,
6517
6628
  //templateInfo.type === 'union',
6518
6629
  {
6519
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat,
6520
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
6630
+ frontmatterFormat: collection?.frontmatterFormat,
6631
+ frontmatterDelimiters: collection?.frontmatterDelimiters
6521
6632
  }
6522
6633
  );
6523
6634
  };
@@ -6532,7 +6643,7 @@ var Database = class {
6532
6643
  };
6533
6644
  this.getLookup = async (returnType) => {
6534
6645
  await this.initLevel();
6535
- const lookupPath = (0, import_schema_tools3.normalizePath)(
6646
+ const lookupPath = (0, import_schema_tools4.normalizePath)(
6536
6647
  import_node_path.default.join(this.getGeneratedFolder(), `_lookup.json`)
6537
6648
  );
6538
6649
  if (!this._lookup) {
@@ -6545,7 +6656,7 @@ var Database = class {
6545
6656
  };
6546
6657
  this.getGraphQLSchema = async () => {
6547
6658
  await this.initLevel();
6548
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6659
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6549
6660
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6550
6661
  );
6551
6662
  return await this.contentLevel.sublevel(
@@ -6558,7 +6669,7 @@ var Database = class {
6558
6669
  if (!this.bridge) {
6559
6670
  throw new Error(`No bridge configured`);
6560
6671
  }
6561
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6672
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6562
6673
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6563
6674
  );
6564
6675
  const _graphql = await this.bridge.get(graphqlPath);
@@ -6566,7 +6677,7 @@ var Database = class {
6566
6677
  };
6567
6678
  this.getTinaSchema = async (level) => {
6568
6679
  await this.initLevel();
6569
- const schemaPath = (0, import_schema_tools3.normalizePath)(
6680
+ const schemaPath = (0, import_schema_tools4.normalizePath)(
6570
6681
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6571
6682
  );
6572
6683
  return await (level || this.contentLevel).sublevel(
@@ -6582,7 +6693,7 @@ var Database = class {
6582
6693
  const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
6583
6694
  if (!schema) {
6584
6695
  throw new Error(
6585
- `Unable to get schema from level db: ${(0, import_schema_tools3.normalizePath)(
6696
+ `Unable to get schema from level db: ${(0, import_schema_tools4.normalizePath)(
6586
6697
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6587
6698
  )}`
6588
6699
  );
@@ -6590,6 +6701,22 @@ var Database = class {
6590
6701
  this.tinaSchema = await createSchema({ schema });
6591
6702
  return this.tinaSchema;
6592
6703
  };
6704
+ this.getCollectionReferences = async (level) => {
6705
+ if (this.collectionReferences) {
6706
+ return this.collectionReferences;
6707
+ }
6708
+ const result = {};
6709
+ const schema = await this.getSchema(level || this.contentLevel);
6710
+ const collections = schema.getCollections();
6711
+ for (const collection of collections) {
6712
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6713
+ collection.name
6714
+ );
6715
+ result[collection.name] = collectionReferences;
6716
+ }
6717
+ this.collectionReferences = result;
6718
+ return result;
6719
+ };
6593
6720
  this.getIndexDefinitions = async (level) => {
6594
6721
  if (!this.collectionIndexDefinitions) {
6595
6722
  await new Promise(async (resolve2, reject) => {
@@ -6599,11 +6726,53 @@ var Database = class {
6599
6726
  const collections = schema.getCollections();
6600
6727
  for (const collection of collections) {
6601
6728
  const indexDefinitions = {
6602
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6729
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6603
6730
  // provide a default sort key which is the file sort
6731
+ // pseudo-index for the collection's references
6732
+ [REFS_COLLECTIONS_SORT_KEY]: {
6733
+ fields: [
6734
+ {
6735
+ name: REFS_REFERENCE_FIELD,
6736
+ type: "string",
6737
+ list: false
6738
+ },
6739
+ {
6740
+ name: REFS_PATH_FIELD,
6741
+ type: "string",
6742
+ list: false
6743
+ }
6744
+ ]
6745
+ }
6604
6746
  };
6605
- if (collection.fields) {
6606
- for (const field of collection.fields) {
6747
+ let fields = [];
6748
+ if (collection.templates) {
6749
+ const templateFieldMap = {};
6750
+ const conflictedFields = /* @__PURE__ */ new Set();
6751
+ for (const template of collection.templates) {
6752
+ for (const field of template.fields) {
6753
+ if (!templateFieldMap[field.name]) {
6754
+ templateFieldMap[field.name] = field;
6755
+ } else {
6756
+ if (templateFieldMap[field.name].type !== field.type) {
6757
+ console.warn(
6758
+ `Field ${field.name} has conflicting types in templates - skipping index`
6759
+ );
6760
+ conflictedFields.add(field.name);
6761
+ }
6762
+ }
6763
+ }
6764
+ }
6765
+ for (const conflictedField in conflictedFields) {
6766
+ delete templateFieldMap[conflictedField];
6767
+ }
6768
+ for (const field of Object.values(templateFieldMap)) {
6769
+ fields.push(field);
6770
+ }
6771
+ } else if (collection.fields) {
6772
+ fields = collection.fields;
6773
+ }
6774
+ if (fields) {
6775
+ for (const field of fields) {
6607
6776
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6608
6777
  continue;
6609
6778
  }
@@ -6628,8 +6797,8 @@ var Database = class {
6628
6797
  );
6629
6798
  return {
6630
6799
  name: indexField.name,
6631
- type: field == null ? void 0 : field.type,
6632
- list: !!(field == null ? void 0 : field.list)
6800
+ type: field?.type,
6801
+ list: !!field?.list
6633
6802
  };
6634
6803
  })
6635
6804
  };
@@ -6655,7 +6824,6 @@ var Database = class {
6655
6824
  return true;
6656
6825
  };
6657
6826
  this.query = async (queryOptions, hydrator) => {
6658
- var _a;
6659
6827
  await this.initLevel();
6660
6828
  const {
6661
6829
  first,
@@ -6683,14 +6851,14 @@ var Database = class {
6683
6851
  const allIndexDefinitions = await this.getIndexDefinitions(
6684
6852
  this.contentLevel
6685
6853
  );
6686
- const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[collection.name];
6854
+ const indexDefinitions = allIndexDefinitions?.[collection.name];
6687
6855
  if (!indexDefinitions) {
6688
6856
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6689
6857
  }
6690
6858
  const filterChain = coerceFilterChainOperands(rawFilterChain);
6691
- const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
6859
+ const indexDefinition = sort && indexDefinitions?.[sort];
6692
6860
  const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
6693
- const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6861
+ const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6694
6862
  const rootLevel = level.sublevel(
6695
6863
  CONTENT_ROOT_PREFIX,
6696
6864
  SUBLEVEL_OPTIONS
@@ -6700,17 +6868,17 @@ var Database = class {
6700
6868
  SUBLEVEL_OPTIONS
6701
6869
  ).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
6702
6870
  if (!query.gt && !query.gte) {
6703
- query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? filterSuffixes.left : "";
6871
+ query.gte = filterSuffixes?.left ? filterSuffixes.left : "";
6704
6872
  }
6705
6873
  if (!query.lt && !query.lte) {
6706
- query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6874
+ query.lte = filterSuffixes?.right ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6707
6875
  }
6708
6876
  let edges = [];
6709
6877
  let startKey = "";
6710
6878
  let endKey = "";
6711
6879
  let hasPreviousPage = false;
6712
6880
  let hasNextPage = false;
6713
- const fieldsPattern = ((_a = indexDefinition == null ? void 0 : indexDefinition.fields) == null ? void 0 : _a.length) ? `${indexDefinition.fields.map((p) => `(?<${p.name}>.+)${INDEX_KEY_FIELD_SEPARATOR}`).join("")}` : "";
6881
+ const fieldsPattern = indexDefinition?.fields?.length ? `${indexDefinition.fields.map((p) => `(?<${p.name}>.+)${INDEX_KEY_FIELD_SEPARATOR}`).join("")}` : "";
6714
6882
  const valuesRegex = indexDefinition ? new RegExp(`^${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^(?<_filepath_>.+)`);
6715
6883
  const itemFilter = makeFilter({ filterChain });
6716
6884
  const iterator = sublevel.iterator(query);
@@ -6752,29 +6920,35 @@ var Database = class {
6752
6920
  }
6753
6921
  startKey = startKey || key || "";
6754
6922
  endKey = key || "";
6755
- edges = [...edges, { cursor: key, path: filepath }];
6923
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6756
6924
  }
6757
6925
  return {
6758
- edges: await sequential(edges, async (edge) => {
6759
- try {
6760
- const node = await hydrator(edge.path);
6761
- return {
6762
- node,
6763
- cursor: btoa(edge.cursor)
6764
- };
6765
- } catch (error) {
6766
- console.log(error);
6767
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6768
- throw new TinaQueryError({
6769
- originalError: error,
6770
- file: edge.path,
6771
- collection: collection.name,
6772
- stack: error.stack
6773
- });
6926
+ edges: await sequential(
6927
+ edges,
6928
+ async ({
6929
+ cursor,
6930
+ path: path7,
6931
+ value
6932
+ }) => {
6933
+ try {
6934
+ const node = await hydrator(path7, value);
6935
+ return {
6936
+ node,
6937
+ cursor: btoa(cursor)
6938
+ };
6939
+ } catch (error) {
6940
+ console.log(error);
6941
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6942
+ throw new TinaQueryError({
6943
+ originalError: error,
6944
+ file: path7,
6945
+ collection: collection.name
6946
+ });
6947
+ }
6948
+ throw error;
6774
6949
  }
6775
- throw error;
6776
6950
  }
6777
- }),
6951
+ ),
6778
6952
  pageInfo: {
6779
6953
  hasPreviousPage,
6780
6954
  hasNextPage,
@@ -6799,7 +6973,7 @@ var Database = class {
6799
6973
  try {
6800
6974
  lookup = lookupFromLockFile || JSON.parse(
6801
6975
  await this.bridge.get(
6802
- (0, import_schema_tools3.normalizePath)(
6976
+ (0, import_schema_tools4.normalizePath)(
6803
6977
  import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")
6804
6978
  )
6805
6979
  )
@@ -6824,15 +6998,15 @@ var Database = class {
6824
6998
  }
6825
6999
  const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
6826
7000
  await contentRootLevel.put(
6827
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
7001
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
6828
7002
  graphQLSchema
6829
7003
  );
6830
7004
  await contentRootLevel.put(
6831
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
7005
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
6832
7006
  tinaSchema.schema
6833
7007
  );
6834
7008
  await contentRootLevel.put(
6835
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
7009
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
6836
7010
  lookup
6837
7011
  );
6838
7012
  const result = await this._indexAllContent(
@@ -6898,13 +7072,14 @@ var Database = class {
6898
7072
  documentPaths,
6899
7073
  async (collection, documentPaths2) => {
6900
7074
  if (collection && !collection.isDetached) {
6901
- await _indexContent(
6902
- this,
6903
- this.contentLevel,
6904
- documentPaths2,
7075
+ await _indexContent({
7076
+ database: this,
7077
+ level: this.contentLevel,
7078
+ documentPaths: documentPaths2,
6905
7079
  enqueueOps,
6906
- collection
6907
- );
7080
+ collection,
7081
+ isPartialReindex: true
7082
+ });
6908
7083
  }
6909
7084
  }
6910
7085
  );
@@ -6920,12 +7095,13 @@ var Database = class {
6920
7095
  throw new Error(`No collection found for path: ${filepath}`);
6921
7096
  }
6922
7097
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6923
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7098
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
7099
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6924
7100
  let level = this.contentLevel;
6925
- if (collection == null ? void 0 : collection.isDetached) {
6926
- level = this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS);
7101
+ if (collection?.isDetached) {
7102
+ level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
6927
7103
  }
6928
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
7104
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6929
7105
  const rootSublevel = level.sublevel(
6930
7106
  CONTENT_ROOT_PREFIX,
6931
7107
  SUBLEVEL_OPTIONS
@@ -6938,6 +7114,14 @@ var Database = class {
6938
7114
  collection.path || ""
6939
7115
  );
6940
7116
  await this.contentLevel.batch([
7117
+ ...makeRefOpsForDocument(
7118
+ normalizedPath,
7119
+ collection.name,
7120
+ collectionReferences,
7121
+ item,
7122
+ "del",
7123
+ level
7124
+ ),
6941
7125
  ...makeIndexOpsForDocument(
6942
7126
  normalizedPath,
6943
7127
  collection.name,
@@ -6962,7 +7146,7 @@ var Database = class {
6962
7146
  }
6963
7147
  ]);
6964
7148
  }
6965
- if (!(collection == null ? void 0 : collection.isDetached)) {
7149
+ if (!collection?.isDetached) {
6966
7150
  if (this.bridge) {
6967
7151
  await this.bridge.delete(normalizedPath);
6968
7152
  }
@@ -7002,20 +7186,26 @@ var Database = class {
7002
7186
  );
7003
7187
  const doc = await level2.keys({ limit: 1 }).next();
7004
7188
  if (!doc) {
7005
- await _indexContent(
7006
- this,
7007
- level2,
7008
- contentPaths,
7189
+ await _indexContent({
7190
+ database: this,
7191
+ level: level2,
7192
+ documentPaths: contentPaths,
7009
7193
  enqueueOps,
7010
7194
  collection,
7011
- userFields.map((field) => [
7195
+ passwordFields: userFields.map((field) => [
7012
7196
  ...field.path,
7013
7197
  field.passwordFieldName
7014
7198
  ])
7015
- );
7199
+ });
7016
7200
  }
7017
7201
  } else {
7018
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7202
+ await _indexContent({
7203
+ database: this,
7204
+ level,
7205
+ documentPaths: contentPaths,
7206
+ enqueueOps,
7207
+ collection
7208
+ });
7019
7209
  }
7020
7210
  }
7021
7211
  );
@@ -7051,7 +7241,7 @@ var Database = class {
7051
7241
  );
7052
7242
  }
7053
7243
  const metadata = await metadataLevel.get("metadata");
7054
- return metadata == null ? void 0 : metadata.version;
7244
+ return metadata?.version;
7055
7245
  }
7056
7246
  async initLevel() {
7057
7247
  if (this.contentLevel) {
@@ -7128,7 +7318,7 @@ var hashPasswordVisitor = async (node, path7) => {
7128
7318
  const passwordValuePath = [...path7, "value"];
7129
7319
  const plaintextPassword = get(node, passwordValuePath);
7130
7320
  if (plaintextPassword) {
7131
- (0, import_lodash5.default)(
7321
+ (0, import_compat2.set)(
7132
7322
  node,
7133
7323
  passwordValuePath,
7134
7324
  await generatePasswordHash({ password: plaintextPassword })
@@ -7137,7 +7327,7 @@ var hashPasswordVisitor = async (node, path7) => {
7137
7327
  };
7138
7328
  var visitNodes = async (node, path7, callback) => {
7139
7329
  const [currentLevel, ...remainingLevels] = path7;
7140
- if (!(remainingLevels == null ? void 0 : remainingLevels.length)) {
7330
+ if (!remainingLevels?.length) {
7141
7331
  return callback(node, path7);
7142
7332
  }
7143
7333
  if (Array.isArray(node[currentLevel])) {
@@ -7153,18 +7343,27 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
7153
7343
  async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
7154
7344
  )
7155
7345
  );
7156
- var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
7157
- var _indexContent = async (database, level, documentPaths, enqueueOps, collection, passwordFields) => {
7346
+ var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${collection?.format || "md"}`);
7347
+ var _indexContent = async ({
7348
+ database,
7349
+ level,
7350
+ documentPaths,
7351
+ enqueueOps,
7352
+ collection,
7353
+ passwordFields,
7354
+ isPartialReindex
7355
+ }) => {
7158
7356
  let collectionIndexDefinitions;
7159
7357
  let collectionPath;
7160
7358
  if (collection) {
7161
7359
  const indexDefinitions = await database.getIndexDefinitions(level);
7162
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7360
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
7163
7361
  if (!collectionIndexDefinitions) {
7164
7362
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7165
7363
  }
7166
7364
  collectionPath = collection.path;
7167
7365
  }
7366
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7168
7367
  const tinaSchema = await database.getSchema();
7169
7368
  let templateInfo = null;
7170
7369
  if (collection) {
@@ -7182,19 +7381,68 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7182
7381
  if (!aliasedData) {
7183
7382
  return;
7184
7383
  }
7185
- if (passwordFields == null ? void 0 : passwordFields.length) {
7384
+ if (passwordFields?.length) {
7186
7385
  await hashPasswordValues(aliasedData, passwordFields);
7187
7386
  }
7188
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
7387
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
7388
+ const rootSublevel = level.sublevel(
7389
+ CONTENT_ROOT_PREFIX,
7390
+ SUBLEVEL_OPTIONS
7391
+ );
7189
7392
  const folderKey = folderTreeBuilder.update(
7190
7393
  normalizedPath,
7191
7394
  collectionPath || ""
7192
7395
  );
7396
+ if (isPartialReindex) {
7397
+ const item = await rootSublevel.get(normalizedPath);
7398
+ if (item) {
7399
+ await database.contentLevel.batch([
7400
+ ...makeRefOpsForDocument(
7401
+ normalizedPath,
7402
+ collection?.name,
7403
+ collectionReferences,
7404
+ item,
7405
+ "del",
7406
+ level
7407
+ ),
7408
+ ...makeIndexOpsForDocument(
7409
+ normalizedPath,
7410
+ collection.name,
7411
+ collectionIndexDefinitions,
7412
+ item,
7413
+ "del",
7414
+ level
7415
+ ),
7416
+ // folder indices
7417
+ ...makeIndexOpsForDocument(
7418
+ normalizedPath,
7419
+ `${collection.name}_${folderKey}`,
7420
+ collectionIndexDefinitions,
7421
+ item,
7422
+ "del",
7423
+ level
7424
+ ),
7425
+ {
7426
+ type: "del",
7427
+ key: normalizedPath,
7428
+ sublevel: rootSublevel
7429
+ }
7430
+ ]);
7431
+ }
7432
+ }
7193
7433
  if (!isGitKeep(filepath, collection)) {
7194
7434
  await enqueueOps([
7435
+ ...makeRefOpsForDocument(
7436
+ normalizedPath,
7437
+ collection?.name,
7438
+ collectionReferences,
7439
+ aliasedData,
7440
+ "put",
7441
+ level
7442
+ ),
7195
7443
  ...makeIndexOpsForDocument(
7196
7444
  normalizedPath,
7197
- collection == null ? void 0 : collection.name,
7445
+ collection?.name,
7198
7446
  collectionIndexDefinitions,
7199
7447
  aliasedData,
7200
7448
  "put",
@@ -7203,7 +7451,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7203
7451
  // folder indexes
7204
7452
  ...makeIndexOpsForDocument(
7205
7453
  normalizedPath,
7206
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7454
+ `${collection?.name}_${folderKey}`,
7207
7455
  collectionIndexDefinitions,
7208
7456
  aliasedData,
7209
7457
  "put",
@@ -7224,8 +7472,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7224
7472
  throw new TinaFetchError(`Unable to seed ${filepath}`, {
7225
7473
  originalError: error,
7226
7474
  file: filepath,
7227
- collection: collection == null ? void 0 : collection.name,
7228
- stack: error.stack
7475
+ collection: collection?.name
7229
7476
  });
7230
7477
  }
7231
7478
  });
@@ -7250,11 +7497,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7250
7497
  const indexDefinitions = await database.getIndexDefinitions(
7251
7498
  database.contentLevel
7252
7499
  );
7253
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7500
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
7254
7501
  if (!collectionIndexDefinitions) {
7255
7502
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7256
7503
  }
7257
7504
  }
7505
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7258
7506
  const tinaSchema = await database.getSchema();
7259
7507
  let templateInfo = null;
7260
7508
  if (collection) {
@@ -7266,18 +7514,26 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7266
7514
  );
7267
7515
  const folderTreeBuilder = new FolderTreeBuilder();
7268
7516
  await sequential(documentPaths, async (filepath) => {
7269
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7517
+ const itemKey = (0, import_schema_tools4.normalizePath)(filepath);
7270
7518
  const item = await rootLevel.get(itemKey);
7271
7519
  if (item) {
7272
7520
  const folderKey = folderTreeBuilder.update(
7273
7521
  itemKey,
7274
- (collection == null ? void 0 : collection.path) || ""
7522
+ collection?.path || ""
7275
7523
  );
7276
7524
  const aliasedData = templateInfo ? replaceNameOverrides(
7277
7525
  getTemplateForFile(templateInfo, item),
7278
7526
  item
7279
7527
  ) : item;
7280
7528
  await enqueueOps([
7529
+ ...makeRefOpsForDocument(
7530
+ itemKey,
7531
+ collection?.name,
7532
+ collectionReferences,
7533
+ aliasedData,
7534
+ "del",
7535
+ database.contentLevel
7536
+ ),
7281
7537
  ...makeIndexOpsForDocument(
7282
7538
  itemKey,
7283
7539
  collection.name,
@@ -7289,7 +7545,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7289
7545
  // folder indexes
7290
7546
  ...makeIndexOpsForDocument(
7291
7547
  itemKey,
7292
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7548
+ `${collection?.name}_${folderKey}`,
7293
7549
  collectionIndexDefinitions,
7294
7550
  aliasedData,
7295
7551
  "del",
@@ -7353,14 +7609,14 @@ var getChangedFiles = async ({
7353
7609
  const rootDir = await findGitRoot(dir);
7354
7610
  let pathPrefix = "";
7355
7611
  if (rootDir !== dir) {
7356
- pathPrefix = (0, import_schema_tools3.normalizePath)(dir.substring(rootDir.length + 1));
7612
+ pathPrefix = (0, import_schema_tools4.normalizePath)(dir.substring(rootDir.length + 1));
7357
7613
  }
7358
7614
  await import_isomorphic_git.default.walk({
7359
7615
  fs: fs4,
7360
7616
  dir: rootDir,
7361
7617
  trees: [import_isomorphic_git.default.TREE({ ref: from }), import_isomorphic_git.default.TREE({ ref: to })],
7362
7618
  map: async function(filename, [A, B]) {
7363
- const relativePath = (0, import_schema_tools3.normalizePath)(filename).substring(pathPrefix.length);
7619
+ const relativePath = (0, import_schema_tools4.normalizePath)(filename).substring(pathPrefix.length);
7364
7620
  let matches = false;
7365
7621
  for (const [key, matcher] of Object.entries(pathFilter)) {
7366
7622
  if (relativePath.startsWith(key)) {
@@ -7374,12 +7630,12 @@ var getChangedFiles = async ({
7374
7630
  }
7375
7631
  }
7376
7632
  }
7377
- if (await (B == null ? void 0 : B.type()) === "tree") {
7633
+ if (await B?.type() === "tree") {
7378
7634
  return;
7379
7635
  }
7380
7636
  if (matches) {
7381
- const oidA = await (A == null ? void 0 : A.oid());
7382
- const oidB = await (B == null ? void 0 : B.oid());
7637
+ const oidA = await A?.oid();
7638
+ const oidB = await B?.oid();
7383
7639
  if (oidA !== oidB) {
7384
7640
  if (oidA === void 0) {
7385
7641
  results.added.push(relativePath);
@@ -7407,8 +7663,8 @@ var import_path5 = __toESM(require("path"));
7407
7663
  var import_normalize_path = __toESM(require("normalize-path"));
7408
7664
  var FilesystemBridge = class {
7409
7665
  constructor(rootPath, outputPath) {
7410
- this.rootPath = rootPath || "";
7411
- this.outputPath = outputPath || rootPath;
7666
+ this.rootPath = import_path5.default.resolve(rootPath);
7667
+ this.outputPath = outputPath ? import_path5.default.resolve(outputPath) : this.rootPath;
7412
7668
  }
7413
7669
  async glob(pattern, extension) {
7414
7670
  const basePath = import_path5.default.join(this.outputPath, ...pattern.split("/"));
@@ -7420,19 +7676,19 @@ var FilesystemBridge = class {
7420
7676
  }
7421
7677
  );
7422
7678
  const posixRootPath = (0, import_normalize_path.default)(this.outputPath);
7423
- return items.map((item) => {
7424
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
7425
- });
7679
+ return items.map(
7680
+ (item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
7681
+ );
7426
7682
  }
7427
7683
  async delete(filepath) {
7428
7684
  await import_fs_extra2.default.remove(import_path5.default.join(this.outputPath, filepath));
7429
7685
  }
7430
7686
  async get(filepath) {
7431
- return import_fs_extra2.default.readFileSync(import_path5.default.join(this.outputPath, filepath)).toString();
7687
+ return (await import_fs_extra2.default.readFile(import_path5.default.join(this.outputPath, filepath))).toString();
7432
7688
  }
7433
7689
  async put(filepath, data, basePathOverride) {
7434
7690
  const basePath = basePathOverride || this.outputPath;
7435
- await import_fs_extra2.default.outputFileSync(import_path5.default.join(basePath, filepath), data);
7691
+ await import_fs_extra2.default.outputFile(import_path5.default.join(basePath, filepath), data);
7436
7692
  }
7437
7693
  };
7438
7694
  var AuditFileSystemBridge = class extends FilesystemBridge {