@tinacms/graphql 0.0.0-d7c745e-20250102002342 → 0.0.0-d9487bf-20251119052214

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,7 +62,7 @@ __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");
@@ -1095,41 +1095,6 @@ function* walk(maybeNode, visited = /* @__PURE__ */ new WeakSet()) {
1095
1095
  yield maybeNode;
1096
1096
  visited.add(maybeNode);
1097
1097
  }
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
1098
  var generateNamespacedFieldName = (names, suffix = "") => {
1134
1099
  return (suffix ? [...names, suffix] : names).map(capitalize).join("");
1135
1100
  };
@@ -1470,13 +1435,12 @@ var checkPasswordHash = async ({
1470
1435
  return true;
1471
1436
  };
1472
1437
  var mapUserFields = (collectable, prefix = []) => {
1473
- var _a, _b, _c, _d, _e;
1474
1438
  const results = [];
1475
- const passwordFields = ((_a = collectable.fields) == null ? void 0 : _a.filter((field) => field.type === "password")) || [];
1439
+ const passwordFields = collectable.fields?.filter((field) => field.type === "password") || [];
1476
1440
  if (passwordFields.length > 1) {
1477
1441
  throw new Error("Only one password field is allowed");
1478
1442
  }
1479
- const idFields = ((_b = collectable.fields) == null ? void 0 : _b.filter((field) => field.uid)) || [];
1443
+ const idFields = collectable.fields?.filter((field) => field.uid) || [];
1480
1444
  if (idFields.length > 1) {
1481
1445
  throw new Error("Only one uid field is allowed");
1482
1446
  }
@@ -1484,11 +1448,11 @@ var mapUserFields = (collectable, prefix = []) => {
1484
1448
  results.push({
1485
1449
  path: prefix,
1486
1450
  collectable,
1487
- idFieldName: (_c = idFields[0]) == null ? void 0 : _c.name,
1488
- passwordFieldName: (_d = passwordFields[0]) == null ? void 0 : _d.name
1451
+ idFieldName: idFields[0]?.name,
1452
+ passwordFieldName: passwordFields[0]?.name
1489
1453
  });
1490
1454
  }
1491
- (_e = collectable.fields) == null ? void 0 : _e.forEach((field) => {
1455
+ collectable.fields?.forEach((field) => {
1492
1456
  if (field.type === "object" && field.fields) {
1493
1457
  results.push(...mapUserFields(field, [...prefix, field.name]));
1494
1458
  }
@@ -1949,7 +1913,7 @@ var Builder = class {
1949
1913
  * ```
1950
1914
  *
1951
1915
  * @public
1952
- * @param collection a Tina Cloud collection
1916
+ * @param collection a TinaCloud collection
1953
1917
  */
1954
1918
  this.collectionFragment = async (collection) => {
1955
1919
  const name = NAMER.dataTypeName(collection.namespace);
@@ -1979,13 +1943,12 @@ var Builder = class {
1979
1943
  *
1980
1944
  * */
1981
1945
  this._getCollectionFragmentSelections = async (collection, depth) => {
1982
- var _a;
1983
1946
  const selections = [];
1984
1947
  selections.push({
1985
1948
  name: { kind: "Name", value: "__typename" },
1986
1949
  kind: "Field"
1987
1950
  });
1988
- if (((_a = collection.fields) == null ? void 0 : _a.length) > 0) {
1951
+ if (collection.fields?.length > 0) {
1989
1952
  await sequential(collection.fields, async (x) => {
1990
1953
  const field = await this._buildFieldNodeForFragments(x, depth);
1991
1954
  selections.push(field);
@@ -2000,7 +1963,6 @@ var Builder = class {
2000
1963
  return selections;
2001
1964
  };
2002
1965
  this._buildFieldNodeForFragments = async (field, depth) => {
2003
- var _a, _b;
2004
1966
  switch (field.type) {
2005
1967
  case "string":
2006
1968
  case "image":
@@ -2033,7 +1995,7 @@ var Builder = class {
2033
1995
  selections: filterSelections([passwordValue, passwordChangeRequired])
2034
1996
  });
2035
1997
  case "object":
2036
- if (((_a = field.fields) == null ? void 0 : _a.length) > 0) {
1998
+ if (field.fields?.length > 0) {
2037
1999
  const selections2 = [];
2038
2000
  await sequential(field.fields, async (item) => {
2039
2001
  const field2 = await this._buildFieldNodeForFragments(item, depth);
@@ -2046,7 +2008,7 @@ var Builder = class {
2046
2008
  ...filterSelections(selections2)
2047
2009
  ]
2048
2010
  });
2049
- } else if (((_b = field.templates) == null ? void 0 : _b.length) > 0) {
2011
+ } else if (field.templates?.length > 0) {
2050
2012
  const selections2 = [];
2051
2013
  await sequential(field.templates, async (tem) => {
2052
2014
  if (typeof tem === "object") {
@@ -2708,7 +2670,7 @@ var Builder = class {
2708
2670
  this.addToLookupMap({
2709
2671
  type: name,
2710
2672
  resolveType: "unionData",
2711
- collection: collection == null ? void 0 : collection.name,
2673
+ collection: collection?.name,
2712
2674
  typeMap
2713
2675
  });
2714
2676
  return astBuilder.UnionTypeDefinition({ name, types });
@@ -2815,7 +2777,7 @@ var Builder = class {
2815
2777
  this._buildDataField = async (field) => {
2816
2778
  const listWarningMsg = `
2817
2779
  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
2780
+ Visit https://tina.io/docs/r/content-fields/#list-fields/ for more information
2819
2781
 
2820
2782
  `;
2821
2783
  switch (field.type) {
@@ -2918,9 +2880,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2918
2880
  ]
2919
2881
  });
2920
2882
  };
2921
- var _a, _b, _c, _d;
2922
2883
  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;
2884
+ config?.tinaSchema.schema?.config?.client?.referenceDepth ?? 2;
2924
2885
  this.tinaSchema = config.tinaSchema;
2925
2886
  this.lookupMap = {};
2926
2887
  }
@@ -2965,12 +2926,13 @@ var filterSelections = (arr) => {
2965
2926
  };
2966
2927
 
2967
2928
  // src/schema/createSchema.ts
2968
- var import_schema_tools2 = require("@tinacms/schema-tools");
2929
+ var import_schema_tools3 = require("@tinacms/schema-tools");
2969
2930
 
2970
2931
  // src/schema/validate.ts
2932
+ var import_schema_tools = require("@tinacms/schema-tools");
2971
2933
  var import_lodash2 = __toESM(require("lodash.clonedeep"));
2972
2934
  var yup2 = __toESM(require("yup"));
2973
- var import_schema_tools = require("@tinacms/schema-tools");
2935
+ var import_schema_tools2 = require("@tinacms/schema-tools");
2974
2936
  var FIELD_TYPES = [
2975
2937
  "string",
2976
2938
  "number",
@@ -2983,7 +2945,7 @@ var FIELD_TYPES = [
2983
2945
  "password"
2984
2946
  ];
2985
2947
  var validateSchema = async (schema) => {
2986
- const schema2 = addNamespaceToSchema(
2948
+ const schema2 = (0, import_schema_tools.addNamespaceToSchema)(
2987
2949
  (0, import_lodash2.default)(schema)
2988
2950
  );
2989
2951
  const collections = await sequential(
@@ -2992,7 +2954,7 @@ var validateSchema = async (schema) => {
2992
2954
  );
2993
2955
  validationCollectionsPathAndMatch(collections);
2994
2956
  if (schema2.config) {
2995
- const config = (0, import_schema_tools.validateTinaCloudSchemaConfig)(schema2.config);
2957
+ const config = (0, import_schema_tools2.validateTinaCloudSchemaConfig)(schema2.config);
2996
2958
  return {
2997
2959
  collections,
2998
2960
  config
@@ -3008,7 +2970,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3008
2970
  return;
3009
2971
  }
3010
2972
  const noMatchCollections = collections.filter((x) => {
3011
- return typeof (x == null ? void 0 : x.match) === "undefined";
2973
+ return typeof x?.match === "undefined";
3012
2974
  }).map((x) => `${x.path}${x.format || "md"}`);
3013
2975
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
3014
2976
  throw new Error(
@@ -3019,10 +2981,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3019
2981
  const hasMatchAndPath = collections.filter((x) => {
3020
2982
  return typeof x.path !== "undefined" && typeof x.match !== "undefined";
3021
2983
  }).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
- }
2984
+ (x) => `${x.path}|${x?.match?.exclude || ""}|${x?.match?.include || ""}|${x.format || "md"}`
3026
2985
  );
3027
2986
  if (hasMatchAndPath.length !== new Set(hasMatchAndPath).size) {
3028
2987
  throw new Error(
@@ -3046,7 +3005,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3046
3005
  );
3047
3006
  }
3048
3007
  const matches = collectionsArr.map(
3049
- (x) => typeof (x == null ? void 0 : x.match) === "object" ? JSON.stringify(x.match) : ""
3008
+ (x) => typeof x?.match === "object" ? JSON.stringify(x.match) : ""
3050
3009
  );
3051
3010
  if (matches.length === new Set(matches).size) {
3052
3011
  return;
@@ -3124,7 +3083,7 @@ var validateField = async (field) => {
3124
3083
  // package.json
3125
3084
  var package_default = {
3126
3085
  name: "@tinacms/graphql",
3127
- version: "1.5.9",
3086
+ version: "1.6.1",
3128
3087
  main: "dist/index.js",
3129
3088
  module: "dist/index.mjs",
3130
3089
  typings: "dist/index.d.ts",
@@ -3150,33 +3109,32 @@ var package_default = {
3150
3109
  types: "pnpm tsc",
3151
3110
  build: "tinacms-scripts build",
3152
3111
  docs: "pnpm typedoc",
3153
- serve: "pnpm nodemon dist/server.js",
3154
- test: "jest",
3155
- "test-watch": "jest --watch"
3112
+ test: "vitest run",
3113
+ "test-watch": "vitest"
3156
3114
  },
3157
3115
  dependencies: {
3158
- "@iarna/toml": "^2.2.5",
3116
+ "@iarna/toml": "catalog:",
3159
3117
  "@tinacms/mdx": "workspace:*",
3160
3118
  "@tinacms/schema-tools": "workspace:*",
3161
- "abstract-level": "^1.0.4",
3119
+ "abstract-level": "catalog:",
3162
3120
  "date-fns": "^2.30.0",
3163
- "fast-glob": "^3.3.2",
3164
- "fs-extra": "^11.2.0",
3165
- "glob-parent": "^6.0.2",
3121
+ "fast-glob": "catalog:",
3122
+ "fs-extra": "catalog:",
3123
+ "glob-parent": "catalog:",
3166
3124
  graphql: "15.8.0",
3167
- "gray-matter": "^4.0.3",
3168
- "isomorphic-git": "^1.27.1",
3169
- "js-sha1": "^0.6.0",
3125
+ "gray-matter": "catalog:",
3126
+ "isomorphic-git": "catalog:",
3127
+ "js-sha1": "catalog:",
3170
3128
  "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",
3129
+ "jsonpath-plus": "catalog:",
3130
+ "lodash.clonedeep": "catalog:",
3131
+ "lodash.set": "catalog:",
3132
+ "lodash.uniqby": "catalog:",
3133
+ "many-level": "catalog:",
3134
+ micromatch: "catalog:",
3135
+ "normalize-path": "catalog:",
3136
+ "readable-stream": "catalog:",
3137
+ scmp: "catalog:",
3180
3138
  yup: "^0.32.11"
3181
3139
  },
3182
3140
  publishConfig: {
@@ -3191,26 +3149,24 @@ var package_default = {
3191
3149
  "@tinacms/scripts": "workspace:*",
3192
3150
  "@types/cors": "^2.8.17",
3193
3151
  "@types/estree": "^0.0.50",
3194
- "@types/express": "^4.17.21",
3152
+ "@types/express": "catalog:",
3195
3153
  "@types/fs-extra": "^9.0.13",
3196
- "@types/jest": "^26.0.24",
3197
3154
  "@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",
3155
+ "@types/lodash.camelcase": "catalog:",
3156
+ "@types/lodash.upperfirst": "catalog:",
3157
+ "@types/lru-cache": "catalog:",
3158
+ "@types/mdast": "catalog:",
3159
+ "@types/micromatch": "catalog:",
3160
+ "@types/node": "^22.13.1",
3161
+ "@types/normalize-path": "catalog:",
3162
+ "@types/ws": "catalog:",
3206
3163
  "@types/yup": "^0.29.14",
3207
- jest: "^29.7.0",
3208
- "jest-diff": "^29.7.0",
3209
3164
  "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"
3165
+ "memory-level": "catalog:",
3166
+ typescript: "^5.7.3",
3167
+ vite: "^4.5.9",
3168
+ vitest: "^0.32.4",
3169
+ zod: "catalog:"
3214
3170
  }
3215
3171
  };
3216
3172
 
@@ -3225,7 +3181,7 @@ var createSchema = async ({
3225
3181
  if (flags && flags.length > 0) {
3226
3182
  meta["flags"] = flags;
3227
3183
  }
3228
- return new import_schema_tools2.TinaSchema({
3184
+ return new import_schema_tools3.TinaSchema({
3229
3185
  version: {
3230
3186
  fullVersion: package_default.version,
3231
3187
  major,
@@ -3292,7 +3248,6 @@ var _buildQueries = async (builder, tinaSchema) => {
3292
3248
  const operationsDefinitions = [];
3293
3249
  const collections = tinaSchema.getCollections();
3294
3250
  await sequential(collections, async (collection) => {
3295
- var _a, _b, _c;
3296
3251
  const queryName = NAMER.queryName(collection.namespace);
3297
3252
  const queryListName = NAMER.generateQueryListName(collection.namespace);
3298
3253
  const queryFilterTypeName = NAMER.dataFilterTypeName(collection.namespace);
@@ -3307,7 +3262,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3307
3262
  filterType: queryFilterTypeName,
3308
3263
  // look for flag to see if the data layer is enabled
3309
3264
  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")
3265
+ tinaSchema.config?.meta?.flags?.find((x) => x === "experimentalData")
3311
3266
  )
3312
3267
  })
3313
3268
  );
@@ -3367,7 +3322,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3367
3322
  await builder.buildCreateCollectionFolderMutation()
3368
3323
  );
3369
3324
  await sequential(collections, async (collection) => {
3370
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3325
+ queryTypeDefinitionFields.push(
3326
+ await builder.collectionDocument(collection)
3327
+ );
3371
3328
  if (collection.isAuthCollection) {
3372
3329
  queryTypeDefinitionFields.push(
3373
3330
  await builder.authenticationCollectionDocument(collection)
@@ -3417,251 +3374,11 @@ var import_graphql5 = require("graphql");
3417
3374
  // src/resolver/index.ts
3418
3375
  var import_path3 = __toESM(require("path"));
3419
3376
  var import_isValid = __toESM(require("date-fns/isValid/index.js"));
3377
+ var import_jsonpath_plus2 = require("jsonpath-plus");
3420
3378
 
3421
3379
  // src/mdx/index.ts
3422
3380
  var import_mdx = require("@tinacms/mdx");
3423
3381
 
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
3382
  // src/resolver/index.ts
3666
3383
  var import_graphql3 = require("graphql");
3667
3384
 
@@ -3683,7 +3400,9 @@ var LevelProxyHandler = {
3683
3400
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3684
3401
  }
3685
3402
  if (typeof target[property] !== "function") {
3686
- throw new Error(`The property, ${property.toString()}, is not a function`);
3403
+ throw new Error(
3404
+ `The property, ${property.toString()}, is not a function`
3405
+ );
3687
3406
  }
3688
3407
  if (property === "get") {
3689
3408
  return async (...args) => {
@@ -3721,11 +3440,11 @@ var import_path2 = __toESM(require("path"));
3721
3440
 
3722
3441
  // src/database/util.ts
3723
3442
  var import_toml = __toESM(require("@iarna/toml"));
3724
- var import_js_yaml = __toESM(require("js-yaml"));
3443
+ var import_schema_tools4 = require("@tinacms/schema-tools");
3725
3444
  var import_gray_matter = __toESM(require("gray-matter"));
3726
- var import_schema_tools3 = require("@tinacms/schema-tools");
3727
- var import_micromatch = __toESM(require("micromatch"));
3445
+ var import_js_yaml = __toESM(require("js-yaml"));
3728
3446
  var import_path = __toESM(require("path"));
3447
+ var import_micromatch = __toESM(require("micromatch"));
3729
3448
 
3730
3449
  // src/database/alias-utils.ts
3731
3450
  var replaceBlockAliases = (template, item) => {
@@ -3762,22 +3481,20 @@ var replaceNameOverrides = (template, obj) => {
3762
3481
  }
3763
3482
  };
3764
3483
  function isBlockField(field) {
3765
- var _a;
3766
- return field && field.type === "object" && ((_a = field.templates) == null ? void 0 : _a.length) > 0;
3484
+ return field && field.type === "object" && field.templates?.length > 0;
3767
3485
  }
3768
3486
  var _replaceNameOverrides = (fields, obj) => {
3769
3487
  const output = {};
3770
3488
  Object.keys(obj).forEach((key) => {
3771
3489
  const field = fields.find(
3772
- (fieldWithMatchingAlias) => ((fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.nameOverride) || (fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.name)) === key
3490
+ (fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
3773
3491
  );
3774
- output[(field == null ? void 0 : field.name) || key] = (field == null ? void 0 : field.type) == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
3492
+ output[field?.name || key] = field?.type == "object" ? replaceNameOverrides(field, obj[key]) : obj[key];
3775
3493
  });
3776
3494
  return output;
3777
3495
  };
3778
3496
  var getTemplateForData = (field, data) => {
3779
- var _a;
3780
- if ((_a = field.templates) == null ? void 0 : _a.length) {
3497
+ if (field.templates?.length) {
3781
3498
  const templateKey = "_template";
3782
3499
  if (data[templateKey]) {
3783
3500
  const result = field.templates.find(
@@ -3835,8 +3552,8 @@ var _applyNameOverrides = (fields, obj) => {
3835
3552
  const output = {};
3836
3553
  Object.keys(obj).forEach((key) => {
3837
3554
  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];
3555
+ const outputKey = field?.nameOverride || key;
3556
+ output[outputKey] = field?.type === "object" ? applyNameOverrides(field, obj[key]) : obj[key];
3840
3557
  });
3841
3558
  return output;
3842
3559
  };
@@ -3849,7 +3566,6 @@ var matterEngines = {
3849
3566
  }
3850
3567
  };
3851
3568
  var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3852
- var _a, _b;
3853
3569
  const {
3854
3570
  _relativePath,
3855
3571
  _keepTemplateKey,
@@ -3873,9 +3589,9 @@ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3873
3589
  ${$_body}`,
3874
3590
  strippedContent,
3875
3591
  {
3876
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3592
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3877
3593
  engines: matterEngines,
3878
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
3594
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
3879
3595
  }
3880
3596
  );
3881
3597
  return ok;
@@ -3891,15 +3607,14 @@ ${$_body}`,
3891
3607
  }
3892
3608
  };
3893
3609
  var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3894
- var _a, _b;
3895
3610
  try {
3896
3611
  switch (format) {
3897
3612
  case ".markdown":
3898
3613
  case ".mdx":
3899
3614
  case ".md":
3900
3615
  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 : "---",
3616
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3617
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
3903
3618
  engines: matterEngines
3904
3619
  });
3905
3620
  const markdownData = {
@@ -3936,7 +3651,7 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3936
3651
  const filesSeen = /* @__PURE__ */ new Map();
3937
3652
  const duplicateFiles = /* @__PURE__ */ new Set();
3938
3653
  await sequential(tinaSchema.getCollections(), async (collection) => {
3939
- const normalPath = (0, import_schema_tools3.normalizePath)(collection.path);
3654
+ const normalPath = (0, import_schema_tools4.normalizePath)(collection.path);
3940
3655
  const format = collection.format || "md";
3941
3656
  const documentPaths = await bridge.glob(normalPath, format);
3942
3657
  const matches = tinaSchema.getMatches({ collection });
@@ -3998,7 +3713,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3998
3713
  ),
3999
3714
  template: void 0
4000
3715
  } : tinaSchema.getCollectionAndTemplateByFullPath(filepath, templateName);
4001
- const field = template == null ? void 0 : template.fields.find((field2) => {
3716
+ const field = template?.fields.find((field2) => {
4002
3717
  if (field2.type === "string" || field2.type === "rich-text") {
4003
3718
  if (field2.isBody) {
4004
3719
  return true;
@@ -4018,7 +3733,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
4018
3733
  ...data,
4019
3734
  _collection: collection.name,
4020
3735
  _keepTemplateKey: !!collection.templates,
4021
- _template: (template == null ? void 0 : template.namespace) ? lastItem(template == null ? void 0 : template.namespace) : void 0,
3736
+ _template: template?.namespace ? lastItem(template?.namespace) : void 0,
4022
3737
  _relativePath: filepath.replace(collection.path, "").replace(/^\/|\/$/g, ""),
4023
3738
  _id: filepath
4024
3739
  };
@@ -4027,10 +3742,10 @@ function hasOwnProperty(obj, prop) {
4027
3742
  return obj.hasOwnProperty(prop);
4028
3743
  }
4029
3744
  var getTemplateForFile = (templateInfo, data) => {
4030
- if ((templateInfo == null ? void 0 : templateInfo.type) === "object") {
3745
+ if (templateInfo?.type === "object") {
4031
3746
  return templateInfo.template;
4032
3747
  }
4033
- if ((templateInfo == null ? void 0 : templateInfo.type) === "union") {
3748
+ if (templateInfo?.type === "union") {
4034
3749
  if (hasOwnProperty(data, "_template")) {
4035
3750
  const template = templateInfo.templates.find(
4036
3751
  (t) => lastItem(t.namespace) === data._template
@@ -4048,14 +3763,14 @@ var getTemplateForFile = (templateInfo, data) => {
4048
3763
  throw new Error(`Unable to determine template`);
4049
3764
  };
4050
3765
  var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo) => {
4051
- const dataString = await bridge.get((0, import_schema_tools3.normalizePath)(filepath));
3766
+ const dataString = await bridge.get((0, import_schema_tools4.normalizePath)(filepath));
4052
3767
  const data = parseFile(
4053
3768
  dataString,
4054
3769
  import_path.default.extname(filepath),
4055
3770
  (yup3) => yup3.object({}),
4056
3771
  {
4057
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
4058
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
3772
+ frontmatterDelimiters: collection?.frontmatterDelimiters,
3773
+ frontmatterFormat: collection?.frontmatterFormat
4059
3774
  }
4060
3775
  );
4061
3776
  const template = getTemplateForFile(templateInfo, data);
@@ -4070,6 +3785,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
4070
3785
 
4071
3786
  // src/database/datalayer.ts
4072
3787
  var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
3788
+ var REFS_COLLECTIONS_SORT_KEY = "__refs__";
3789
+ var REFS_REFERENCE_FIELD = "__tina_ref__";
3790
+ var REFS_PATH_FIELD = "__tina_ref_path__";
4073
3791
  var DEFAULT_NUMERIC_LPAD = 4;
4074
3792
  var applyPadding = (input, pad) => {
4075
3793
  if (pad) {
@@ -4527,7 +4245,7 @@ var FolderTreeBuilder = class {
4527
4245
  return this._tree;
4528
4246
  }
4529
4247
  update(documentPath, collectionPath) {
4530
- let folderPath = import_path2.default.dirname((0, import_schema_tools3.normalizePath)(documentPath));
4248
+ let folderPath = import_path2.default.dirname((0, import_schema_tools4.normalizePath)(documentPath));
4531
4249
  if (folderPath === ".") {
4532
4250
  folderPath = "";
4533
4251
  }
@@ -4540,7 +4258,7 @@ var FolderTreeBuilder = class {
4540
4258
  if (!this._tree[current2]) {
4541
4259
  this._tree[current2] = /* @__PURE__ */ new Set();
4542
4260
  }
4543
- this._tree[current2].add((0, import_schema_tools3.normalizePath)(import_path2.default.join(current2, part)));
4261
+ this._tree[current2].add((0, import_schema_tools4.normalizePath)(import_path2.default.join(current2, part)));
4544
4262
  parent.push(part);
4545
4263
  });
4546
4264
  const current = parent.join("/");
@@ -4643,6 +4361,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4643
4361
  }
4644
4362
  return result;
4645
4363
  };
4364
+ var makeRefOpsForDocument = (filepath, collection, references, data, opType, level) => {
4365
+ const result = [];
4366
+ if (collection) {
4367
+ for (const [c, referencePaths] of Object.entries(references || {})) {
4368
+ if (!referencePaths.length) {
4369
+ continue;
4370
+ }
4371
+ const collectionSublevel = level.sublevel(c, SUBLEVEL_OPTIONS);
4372
+ const refSublevel = collectionSublevel.sublevel(
4373
+ REFS_COLLECTIONS_SORT_KEY,
4374
+ SUBLEVEL_OPTIONS
4375
+ );
4376
+ const references2 = {};
4377
+ for (const path7 of referencePaths) {
4378
+ const ref = (0, import_jsonpath_plus.JSONPath)({ path: path7, json: data });
4379
+ if (!ref) {
4380
+ continue;
4381
+ }
4382
+ if (Array.isArray(ref)) {
4383
+ for (const r of ref) {
4384
+ if (!r) {
4385
+ continue;
4386
+ }
4387
+ if (references2[r]) {
4388
+ references2[r].push(path7);
4389
+ } else {
4390
+ references2[r] = [path7];
4391
+ }
4392
+ }
4393
+ } else {
4394
+ if (references2[ref]) {
4395
+ references2[ref].push(path7);
4396
+ } else {
4397
+ references2[ref] = [path7];
4398
+ }
4399
+ }
4400
+ }
4401
+ for (const ref of Object.keys(references2)) {
4402
+ for (const path7 of references2[ref]) {
4403
+ result.push({
4404
+ type: opType,
4405
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4406
+ sublevel: refSublevel,
4407
+ value: opType === "put" ? {} : void 0
4408
+ });
4409
+ }
4410
+ }
4411
+ }
4412
+ }
4413
+ return result;
4414
+ };
4646
4415
  var makeStringEscaper = (regex, replacement) => {
4647
4416
  return (input) => {
4648
4417
  if (Array.isArray(input)) {
@@ -4656,19 +4425,254 @@ var makeStringEscaper = (regex, replacement) => {
4656
4425
  return input;
4657
4426
  }
4658
4427
  }
4659
- };
4428
+ };
4429
+ };
4430
+ var stringEscaper = makeStringEscaper(
4431
+ new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
4432
+ encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
4433
+ );
4434
+
4435
+ // src/resolver/error.ts
4436
+ var TinaGraphQLError = class extends Error {
4437
+ constructor(message, extensions) {
4438
+ super(message);
4439
+ if (!this.name) {
4440
+ Object.defineProperty(this, "name", { value: "TinaGraphQLError" });
4441
+ }
4442
+ this.extensions = { ...extensions };
4443
+ }
4444
+ };
4445
+ var TinaFetchError = class extends Error {
4446
+ constructor(message, args) {
4447
+ super(message);
4448
+ this.name = "TinaFetchError";
4449
+ this.collection = args.collection;
4450
+ this.file = args.file;
4451
+ this.originalError = args.originalError;
4452
+ }
4453
+ };
4454
+ var TinaQueryError = class extends TinaFetchError {
4455
+ constructor(args) {
4456
+ super(
4457
+ `Error querying file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
4458
+ args
4459
+ );
4460
+ }
4461
+ };
4462
+ var TinaParseDocumentError = class extends TinaFetchError {
4463
+ constructor(args) {
4464
+ super(
4465
+ `Error parsing file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
4466
+ args
4467
+ );
4468
+ }
4469
+ toString() {
4470
+ return super.toString() + "\n OriginalError: \n" + this.originalError.toString();
4471
+ }
4472
+ };
4473
+ var auditMessage = (includeAuditMessage = true) => includeAuditMessage ? `Please run "tinacms audit" or add the --verbose option for more info` : "";
4474
+ var handleFetchErrorError = (e, verbose) => {
4475
+ if (e instanceof Error) {
4476
+ if (e instanceof TinaFetchError) {
4477
+ if (verbose) {
4478
+ console.log(e.toString());
4479
+ console.log(e);
4480
+ console.log(e.stack);
4481
+ }
4482
+ }
4483
+ } else {
4484
+ console.error(e);
4485
+ }
4486
+ throw e;
4487
+ };
4488
+
4489
+ // src/resolver/filter-utils.ts
4490
+ var resolveReferences = async (filter, fields, resolver) => {
4491
+ for (const fieldKey of Object.keys(filter)) {
4492
+ const fieldDefinition = fields.find(
4493
+ (f) => f.name === fieldKey
4494
+ );
4495
+ if (fieldDefinition) {
4496
+ if (fieldDefinition.type === "reference") {
4497
+ const { edges, values } = await resolver(filter, fieldDefinition);
4498
+ if (edges.length === 1) {
4499
+ filter[fieldKey] = {
4500
+ eq: values[0]
4501
+ };
4502
+ } else if (edges.length > 1) {
4503
+ filter[fieldKey] = {
4504
+ in: values
4505
+ };
4506
+ } else {
4507
+ filter[fieldKey] = {
4508
+ eq: "___null___"
4509
+ };
4510
+ }
4511
+ } else if (fieldDefinition.type === "object") {
4512
+ if (fieldDefinition.templates) {
4513
+ for (const templateName of Object.keys(filter[fieldKey])) {
4514
+ const template = fieldDefinition.templates.find(
4515
+ (template2) => !(typeof template2 === "string") && template2.name === templateName
4516
+ );
4517
+ if (template) {
4518
+ await resolveReferences(
4519
+ filter[fieldKey][templateName],
4520
+ template.fields,
4521
+ resolver
4522
+ );
4523
+ } else {
4524
+ throw new Error(`Template ${templateName} not found`);
4525
+ }
4526
+ }
4527
+ } else {
4528
+ await resolveReferences(
4529
+ filter[fieldKey],
4530
+ fieldDefinition.fields,
4531
+ resolver
4532
+ );
4533
+ }
4534
+ }
4535
+ } else {
4536
+ throw new Error(`Unable to find field ${fieldKey}`);
4537
+ }
4538
+ }
4539
+ };
4540
+ var collectConditionsForChildFields = (filterNode, fields, pathExpression, collectCondition) => {
4541
+ for (const childFieldName of Object.keys(filterNode)) {
4542
+ const childField = fields.find((field) => field.name === childFieldName);
4543
+ if (!childField) {
4544
+ throw new Error(`Unable to find type for field ${childFieldName}`);
4545
+ }
4546
+ collectConditionsForField(
4547
+ childFieldName,
4548
+ childField,
4549
+ filterNode[childFieldName],
4550
+ pathExpression,
4551
+ collectCondition
4552
+ );
4553
+ }
4554
+ };
4555
+ var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
4556
+ if (field.list && field.templates) {
4557
+ for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
4558
+ const template = field.templates.find(
4559
+ (template2) => !(typeof template2 === "string") && template2.name === filterKey
4560
+ );
4561
+ const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
4562
+ const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
4563
+ collectConditionsForChildFields(
4564
+ childFilterNode,
4565
+ template.fields,
4566
+ filterPath,
4567
+ collectCondition
4568
+ );
4569
+ }
4570
+ } else {
4571
+ const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
4572
+ const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
4573
+ collectConditionsForChildFields(
4574
+ filterNode,
4575
+ field.fields,
4576
+ filterPath,
4577
+ collectCondition
4578
+ );
4579
+ }
4580
+ };
4581
+ var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
4582
+ if (field.type === "object") {
4583
+ collectConditionsForObjectField(
4584
+ fieldName,
4585
+ field,
4586
+ filterNode,
4587
+ pathExpression,
4588
+ collectCondition
4589
+ );
4590
+ } else {
4591
+ collectCondition({
4592
+ filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
4593
+ filterExpression: {
4594
+ _type: field.type,
4595
+ _list: !!field.list,
4596
+ ...filterNode
4597
+ }
4598
+ });
4599
+ }
4600
+ };
4601
+
4602
+ // src/resolver/media-utils.ts
4603
+ var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, schema) => {
4604
+ if (config && value) {
4605
+ if (config.useRelativeMedia === true) {
4606
+ return value;
4607
+ }
4608
+ if (hasTinaMediaConfig(schema) === true) {
4609
+ const assetsURL = `https://${config.assetsHost}/${config.clientId}`;
4610
+ if (typeof value === "string" && value.includes(assetsURL)) {
4611
+ const cleanMediaRoot = cleanUpSlashes(
4612
+ schema.config.media.tina.mediaRoot
4613
+ );
4614
+ const strippedURL = value.replace(assetsURL, "");
4615
+ return `${cleanMediaRoot}${strippedURL}`;
4616
+ }
4617
+ if (Array.isArray(value)) {
4618
+ return value.map((v) => {
4619
+ if (!v || typeof v !== "string") return v;
4620
+ const cleanMediaRoot = cleanUpSlashes(
4621
+ schema.config.media.tina.mediaRoot
4622
+ );
4623
+ const strippedURL = v.replace(assetsURL, "");
4624
+ return `${cleanMediaRoot}${strippedURL}`;
4625
+ });
4626
+ }
4627
+ return value;
4628
+ }
4629
+ return value;
4630
+ } else {
4631
+ return value;
4632
+ }
4633
+ };
4634
+ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, schema) => {
4635
+ if (config && value) {
4636
+ if (config.useRelativeMedia === true) {
4637
+ return value;
4638
+ }
4639
+ if (hasTinaMediaConfig(schema) === true) {
4640
+ const cleanMediaRoot = cleanUpSlashes(schema.config.media.tina.mediaRoot);
4641
+ if (typeof value === "string") {
4642
+ const strippedValue = value.replace(cleanMediaRoot, "");
4643
+ return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
4644
+ }
4645
+ if (Array.isArray(value)) {
4646
+ return value.map((v) => {
4647
+ if (!v || typeof v !== "string") return v;
4648
+ const strippedValue = v.replace(cleanMediaRoot, "");
4649
+ return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
4650
+ });
4651
+ }
4652
+ }
4653
+ return value;
4654
+ } else {
4655
+ return value;
4656
+ }
4657
+ };
4658
+ var cleanUpSlashes = (path7) => {
4659
+ if (path7) {
4660
+ return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
4661
+ }
4662
+ return "";
4663
+ };
4664
+ var hasTinaMediaConfig = (schema) => {
4665
+ if (!schema.config?.media?.tina) return false;
4666
+ if (typeof schema.config?.media?.tina?.publicFolder !== "string" && typeof schema.config?.media?.tina?.mediaRoot !== "string")
4667
+ return false;
4668
+ return true;
4660
4669
  };
4661
- var stringEscaper = makeStringEscaper(
4662
- new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
4663
- encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
4664
- );
4665
4670
 
4666
4671
  // src/resolver/index.ts
4667
4672
  var createResolver = (args) => {
4668
4673
  return new Resolver(args);
4669
4674
  };
4670
4675
  var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4671
- var _a, _b;
4672
4676
  if (!rawData) {
4673
4677
  return void 0;
4674
4678
  }
@@ -4696,7 +4700,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4696
4700
  accumulator[field.name] = {
4697
4701
  value: void 0,
4698
4702
  // never resolve the password hash
4699
- passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4703
+ passwordChangeRequired: value["passwordChangeRequired"] ?? false
4700
4704
  };
4701
4705
  break;
4702
4706
  case "image":
@@ -4712,11 +4716,11 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4712
4716
  field,
4713
4717
  (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4714
4718
  );
4715
- if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4719
+ if (tree?.children[0]?.type === "invalid_markdown") {
4716
4720
  if (isAudit) {
4717
- const invalidNode = tree == null ? void 0 : tree.children[0];
4721
+ const invalidNode = tree?.children[0];
4718
4722
  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}` : ""}`
4723
+ `${invalidNode?.message}${invalidNode.position ? ` at line ${invalidNode.position.start.line}, column ${invalidNode.position.start.column}` : ""}`
4720
4724
  );
4721
4725
  }
4722
4726
  }
@@ -4824,16 +4828,15 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4824
4828
  originalError: e,
4825
4829
  collection: collection.name,
4826
4830
  includeAuditMessage: !isAudit,
4827
- file: relativePath,
4828
- stack: e.stack
4831
+ file: relativePath
4829
4832
  });
4830
4833
  }
4831
4834
  const titleField = template.fields.find((x) => {
4832
- if (x.type === "string" && (x == null ? void 0 : x.isTitle)) {
4835
+ if (x.type === "string" && x?.isTitle) {
4833
4836
  return true;
4834
4837
  }
4835
4838
  });
4836
- const titleFieldName = titleField == null ? void 0 : titleField.name;
4839
+ const titleFieldName = titleField?.name;
4837
4840
  const title = data[titleFieldName || " "] || null;
4838
4841
  return {
4839
4842
  __typename: collection.fields ? NAMER.documentTypeName(collection.namespace) : NAMER.documentTypeName(template.namespace),
@@ -4864,24 +4867,33 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4864
4867
  throw e;
4865
4868
  }
4866
4869
  };
4867
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4870
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4871
+ let updated = false;
4868
4872
  if (!path7.includes(".") && !path7.includes("[")) {
4869
- if (path7 in obj) {
4873
+ if (path7 in obj && obj[path7] === oldValue) {
4870
4874
  obj[path7] = newValue;
4875
+ updated = true;
4871
4876
  }
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" });
4877
+ return { object: obj, updated };
4878
+ }
4879
+ const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4880
+ const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4881
+ const parents = (0, import_jsonpath_plus2.JSONPath)({
4882
+ path: parentPath,
4883
+ json: obj,
4884
+ resultType: "value"
4885
+ });
4877
4886
  if (parents.length > 0) {
4878
4887
  parents.forEach((parent) => {
4879
4888
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4880
- parent[keyToUpdate] = newValue;
4889
+ if (parent[keyToUpdate] === oldValue) {
4890
+ parent[keyToUpdate] = newValue;
4891
+ updated = true;
4892
+ }
4881
4893
  }
4882
4894
  });
4883
4895
  }
4884
- return obj;
4896
+ return { object: obj, updated };
4885
4897
  };
4886
4898
  var Resolver = class {
4887
4899
  constructor(init) {
@@ -4898,7 +4910,9 @@ var Resolver = class {
4898
4910
  };
4899
4911
  this.getRaw = async (fullPath) => {
4900
4912
  if (typeof fullPath !== "string") {
4901
- throw new Error(`fullPath must be of type string for getDocument request`);
4913
+ throw new Error(
4914
+ `fullPath must be of type string for getDocument request`
4915
+ );
4902
4916
  }
4903
4917
  return this.database.get(fullPath);
4904
4918
  };
@@ -4927,10 +4941,12 @@ var Resolver = class {
4927
4941
  };
4928
4942
  this.getDocument = async (fullPath, opts = {}) => {
4929
4943
  if (typeof fullPath !== "string") {
4930
- throw new Error(`fullPath must be of type string for getDocument request`);
4944
+ throw new Error(
4945
+ `fullPath must be of type string for getDocument request`
4946
+ );
4931
4947
  }
4932
4948
  const rawData = await this.getRaw(fullPath);
4933
- const hasReferences = (opts == null ? void 0 : opts.checkReferences) ? await this.hasReferences(fullPath, opts.collection) : void 0;
4949
+ const hasReferences = opts?.checkReferences ? await this.hasReferences(fullPath, opts.collection) : void 0;
4934
4950
  return transformDocumentIntoPayload(
4935
4951
  fullPath,
4936
4952
  rawData,
@@ -4942,7 +4958,9 @@ var Resolver = class {
4942
4958
  };
4943
4959
  this.deleteDocument = async (fullPath) => {
4944
4960
  if (typeof fullPath !== "string") {
4945
- throw new Error(`fullPath must be of type string for getDocument request`);
4961
+ throw new Error(
4962
+ `fullPath must be of type string for getDocument request`
4963
+ );
4946
4964
  }
4947
4965
  await this.database.delete(fullPath);
4948
4966
  };
@@ -4968,9 +4986,9 @@ var Resolver = class {
4968
4986
  return this.buildFieldMutations(
4969
4987
  item,
4970
4988
  objectTemplate,
4971
- idField && existingData && (existingData == null ? void 0 : existingData.find(
4989
+ idField && existingData && existingData?.find(
4972
4990
  (d) => d[idField.name] === item[idField.name]
4973
- ))
4991
+ )
4974
4992
  );
4975
4993
  }
4976
4994
  )
@@ -5096,7 +5114,7 @@ var Resolver = class {
5096
5114
  isCollectionSpecific
5097
5115
  }) => {
5098
5116
  const doc = await this.getDocument(realPath);
5099
- const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5117
+ const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5100
5118
  if (isAddPendingDocument === true) {
5101
5119
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5102
5120
  const params2 = this.buildParams(args);
@@ -5106,7 +5124,7 @@ var Resolver = class {
5106
5124
  const values = await this.buildFieldMutations(
5107
5125
  params2,
5108
5126
  templateInfo.template,
5109
- doc == null ? void 0 : doc._rawData
5127
+ doc?._rawData
5110
5128
  );
5111
5129
  await this.database.put(
5112
5130
  realPath,
@@ -5130,7 +5148,7 @@ var Resolver = class {
5130
5148
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
5131
5149
  templateParams,
5132
5150
  template,
5133
- doc == null ? void 0 : doc._rawData
5151
+ doc?._rawData
5134
5152
  ),
5135
5153
  _template: lastItem(template.namespace)
5136
5154
  };
@@ -5144,9 +5162,13 @@ var Resolver = class {
5144
5162
  //@ts-ignore
5145
5163
  isCollectionSpecific ? args.params : args.params[collection.name],
5146
5164
  collection,
5147
- doc == null ? void 0 : doc._rawData
5165
+ doc?._rawData
5166
+ );
5167
+ await this.database.put(
5168
+ realPath,
5169
+ { ...oldDoc, ...params },
5170
+ collection.name
5148
5171
  );
5149
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
5150
5172
  return this.getDocument(realPath);
5151
5173
  };
5152
5174
  /**
@@ -5156,7 +5178,6 @@ var Resolver = class {
5156
5178
  this.resolveLegacyValues = (oldDoc, collection) => {
5157
5179
  const legacyValues = {};
5158
5180
  Object.entries(oldDoc).forEach(([key, value]) => {
5159
- var _a;
5160
5181
  const reservedKeys = [
5161
5182
  "$_body",
5162
5183
  "_collection",
@@ -5169,7 +5190,7 @@ var Resolver = class {
5169
5190
  return;
5170
5191
  }
5171
5192
  if (oldDoc._template && collection.templates) {
5172
- const template = (_a = collection.templates) == null ? void 0 : _a.find(
5193
+ const template = collection.templates?.find(
5173
5194
  ({ name }) => name === oldDoc._template
5174
5195
  );
5175
5196
  if (template) {
@@ -5216,7 +5237,7 @@ var Resolver = class {
5216
5237
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5217
5238
  );
5218
5239
  const collection = await this.tinaSchema.getCollection(collectionLookup);
5219
- let realPath = import_path3.default.join(collection == null ? void 0 : collection.path, args.relativePath);
5240
+ let realPath = import_path3.default.join(collection?.path, args.relativePath);
5220
5241
  if (isFolderCreation) {
5221
5242
  realPath = `${realPath}/.gitkeep.${collection.format || "md"}`;
5222
5243
  }
@@ -5260,17 +5281,35 @@ var Resolver = class {
5260
5281
  await this.deleteDocument(realPath);
5261
5282
  if (await this.hasReferences(realPath, collection)) {
5262
5283
  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(
5284
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5285
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5286
+ docsWithRefs
5287
+ )) {
5288
+ let refDoc = await this.getRaw(pathToDocWithRef);
5289
+ let hasUpdate = false;
5290
+ for (const path7 of referencePaths) {
5291
+ const { object: object2, updated } = updateObjectWithJsonPath(
5268
5292
  refDoc,
5269
- ref.path.join("."),
5293
+ path7,
5294
+ realPath,
5270
5295
  null
5271
5296
  );
5297
+ refDoc = object2;
5298
+ hasUpdate = updated || hasUpdate;
5299
+ }
5300
+ if (hasUpdate) {
5301
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5302
+ if (!collectionWithRef) {
5303
+ throw new Error(
5304
+ `Unable to find collection for ${pathToDocWithRef}`
5305
+ );
5306
+ }
5307
+ await this.database.put(
5308
+ pathToDocWithRef,
5309
+ refDoc,
5310
+ collectionWithRef.name
5311
+ );
5272
5312
  }
5273
- await this.database.put(refPath, refDoc, collection2);
5274
5313
  }
5275
5314
  }
5276
5315
  }
@@ -5282,34 +5321,57 @@ var Resolver = class {
5282
5321
  (yup3) => yup3.object({ params: yup3.object().required() })
5283
5322
  );
5284
5323
  assertShape(
5285
- args == null ? void 0 : args.params,
5324
+ args?.params,
5286
5325
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5287
5326
  );
5288
5327
  const doc = await this.getDocument(realPath);
5289
5328
  const newRealPath = import_path3.default.join(
5290
- collection == null ? void 0 : collection.path,
5329
+ collection?.path,
5291
5330
  args.params.relativePath
5292
5331
  );
5332
+ if (newRealPath === realPath) {
5333
+ return doc;
5334
+ }
5293
5335
  await this.database.put(newRealPath, doc._rawData, collection.name);
5294
5336
  await this.deleteDocument(realPath);
5295
5337
  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("."),
5338
+ for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5339
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5340
+ docsWithRefs
5341
+ )) {
5342
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5343
+ let hasUpdate = false;
5344
+ for (const path7 of referencePaths) {
5345
+ const { object: object2, updated } = updateObjectWithJsonPath(
5346
+ docWithRef,
5347
+ path7,
5348
+ realPath,
5303
5349
  newRealPath
5304
5350
  );
5351
+ docWithRef = object2;
5352
+ hasUpdate = updated || hasUpdate;
5353
+ }
5354
+ if (hasUpdate) {
5355
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5356
+ if (!collectionWithRef) {
5357
+ throw new Error(
5358
+ `Unable to find collection for ${pathToDocWithRef}`
5359
+ );
5360
+ }
5361
+ await this.database.put(
5362
+ pathToDocWithRef,
5363
+ docWithRef,
5364
+ collectionWithRef.name
5365
+ );
5305
5366
  }
5306
- await this.database.put(refPath, refDoc, collection2);
5307
5367
  }
5308
5368
  }
5309
5369
  return this.getDocument(newRealPath);
5310
5370
  }
5311
5371
  if (alreadyExists === false) {
5312
- throw new Error(`Unable to update document, ${realPath} does not exist`);
5372
+ throw new Error(
5373
+ `Unable to update document, ${realPath} does not exist`
5374
+ );
5313
5375
  }
5314
5376
  return this.updateResolveDocument({
5315
5377
  collection,
@@ -5435,35 +5497,30 @@ var Resolver = class {
5435
5497
  */
5436
5498
  this.hasReferences = async (id, c) => {
5437
5499
  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
- }
5500
+ await this.database.query(
5501
+ {
5502
+ collection: c.name,
5503
+ filterChain: makeFilterChain({
5504
+ conditions: [
5505
+ {
5506
+ filterPath: REFS_REFERENCE_FIELD,
5507
+ filterExpression: {
5508
+ _type: "string",
5509
+ _list: false,
5510
+ eq: id
5511
+ }
5512
+ }
5513
+ ]
5514
+ }),
5515
+ sort: REFS_COLLECTIONS_SORT_KEY
5516
+ },
5517
+ (refId) => {
5518
+ count++;
5519
+ return refId;
5466
5520
  }
5521
+ );
5522
+ if (count) {
5523
+ return true;
5467
5524
  }
5468
5525
  return false;
5469
5526
  };
@@ -5471,50 +5528,44 @@ var Resolver = class {
5471
5528
  * Finds references to a document
5472
5529
  * @param id the id of the document to find references to
5473
5530
  * @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
5531
+ * @returns a map of references to the document
5475
5532
  */
5476
5533
  this.findReferences = async (id, c) => {
5477
5534
  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] = [];
5535
+ await this.database.query(
5536
+ {
5537
+ collection: c.name,
5538
+ filterChain: makeFilterChain({
5539
+ conditions: [
5540
+ {
5541
+ filterPath: REFS_REFERENCE_FIELD,
5542
+ filterExpression: {
5543
+ _type: "string",
5544
+ _list: false,
5545
+ eq: id
5546
+ }
5504
5547
  }
5505
- references[collection][refId].push({
5506
- path: ref.path,
5507
- field: ref.field
5508
- });
5509
- return refId;
5510
- }
5511
- );
5548
+ ]
5549
+ }),
5550
+ sort: REFS_COLLECTIONS_SORT_KEY
5551
+ },
5552
+ (refId, rawItem) => {
5553
+ if (!references[c.name]) {
5554
+ references[c.name] = {};
5555
+ }
5556
+ if (!references[c.name][refId]) {
5557
+ references[c.name][refId] = [];
5558
+ }
5559
+ const referencePath = rawItem?.[REFS_PATH_FIELD];
5560
+ if (referencePath) {
5561
+ references[c.name][refId].push(referencePath);
5562
+ }
5563
+ return refId;
5512
5564
  }
5513
- }
5565
+ );
5514
5566
  return references;
5515
5567
  };
5516
5568
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5517
- var _a;
5518
5569
  const accum = {};
5519
5570
  for (const passwordField of template.fields.filter(
5520
5571
  (f) => f.type === "password"
@@ -5557,7 +5608,7 @@ var Resolver = class {
5557
5608
  accum[fieldName] = await this.buildObjectMutations(
5558
5609
  fieldValue,
5559
5610
  field,
5560
- existingData == null ? void 0 : existingData[fieldName]
5611
+ existingData?.[fieldName]
5561
5612
  );
5562
5613
  break;
5563
5614
  case "password":
@@ -5576,12 +5627,12 @@ var Resolver = class {
5576
5627
  } else {
5577
5628
  accum[fieldName] = {
5578
5629
  ...fieldValue,
5579
- value: (_a = existingData == null ? void 0 : existingData[fieldName]) == null ? void 0 : _a["value"]
5630
+ value: existingData?.[fieldName]?.["value"]
5580
5631
  };
5581
5632
  }
5582
5633
  break;
5583
5634
  case "rich-text":
5584
- accum[fieldName] = (0, import_mdx.stringifyMDX)(
5635
+ accum[fieldName] = (0, import_mdx.serializeMDX)(
5585
5636
  fieldValue,
5586
5637
  field,
5587
5638
  (fieldValue2) => resolveMediaCloudToRelative(
@@ -5688,8 +5739,129 @@ var resolveDateInput = (value) => {
5688
5739
  return date;
5689
5740
  };
5690
5741
 
5691
- // src/resolve.ts
5742
+ // src/resolver/auth-fields.ts
5692
5743
  var import_lodash4 = __toESM(require("lodash.set"));
5744
+ async function getUserDocumentContext(tinaSchema, resolver) {
5745
+ const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5746
+ if (!collection) {
5747
+ throw new Error("Auth collection not found");
5748
+ }
5749
+ const userFields = mapUserFields(collection, ["_rawData"]);
5750
+ if (!userFields.length) {
5751
+ throw new Error(`No user field found in collection ${collection.name}`);
5752
+ }
5753
+ if (userFields.length > 1) {
5754
+ throw new Error(
5755
+ `Multiple user fields found in collection ${collection.name}`
5756
+ );
5757
+ }
5758
+ const userField = userFields[0];
5759
+ const realPath = `${collection.path}/index.json`;
5760
+ const userDoc = await resolver.getDocument(realPath);
5761
+ const users = get(userDoc, userField.path);
5762
+ if (!users) {
5763
+ throw new Error("No users found");
5764
+ }
5765
+ return { collection, userField, users, userDoc, realPath };
5766
+ }
5767
+ function findUserInCollection(users, userField, userSub) {
5768
+ const { idFieldName } = userField;
5769
+ if (!idFieldName) {
5770
+ throw new Error("No uid field found on user field");
5771
+ }
5772
+ return users.find((u) => u[idFieldName] === userSub) || null;
5773
+ }
5774
+ async function handleAuthenticate({
5775
+ tinaSchema,
5776
+ resolver,
5777
+ sub,
5778
+ password,
5779
+ ctxUser
5780
+ }) {
5781
+ const userSub = sub || ctxUser?.sub;
5782
+ const { userField, users } = await getUserDocumentContext(
5783
+ tinaSchema,
5784
+ resolver
5785
+ );
5786
+ const user = findUserInCollection(users, userField, userSub);
5787
+ if (!user) {
5788
+ return null;
5789
+ }
5790
+ const { passwordFieldName } = userField;
5791
+ const saltedHash = get(user, [passwordFieldName || "", "value"]);
5792
+ if (!saltedHash) {
5793
+ throw new Error("No password field found on user field");
5794
+ }
5795
+ const matches = await checkPasswordHash({
5796
+ saltedHash,
5797
+ password
5798
+ });
5799
+ return matches ? user : null;
5800
+ }
5801
+ async function handleAuthorize({
5802
+ tinaSchema,
5803
+ resolver,
5804
+ sub,
5805
+ ctxUser
5806
+ }) {
5807
+ const userSub = sub || ctxUser?.sub;
5808
+ const { userField, users } = await getUserDocumentContext(
5809
+ tinaSchema,
5810
+ resolver
5811
+ );
5812
+ const user = findUserInCollection(users, userField, userSub);
5813
+ return user ? user : null;
5814
+ }
5815
+ async function handleUpdatePassword({
5816
+ tinaSchema,
5817
+ resolver,
5818
+ password,
5819
+ ctxUser
5820
+ }) {
5821
+ if (!ctxUser?.sub) {
5822
+ throw new Error("Not authorized");
5823
+ }
5824
+ if (!password) {
5825
+ throw new Error("No password provided");
5826
+ }
5827
+ const { collection, userField, users, realPath } = await getUserDocumentContext(tinaSchema, resolver);
5828
+ const { idFieldName, passwordFieldName } = userField;
5829
+ const user = users.find((u) => u[idFieldName] === ctxUser.sub);
5830
+ if (!user) {
5831
+ throw new Error("Not authorized");
5832
+ }
5833
+ user[passwordFieldName] = {
5834
+ value: password,
5835
+ passwordChangeRequired: false
5836
+ };
5837
+ const params = {};
5838
+ (0, import_lodash4.default)(
5839
+ params,
5840
+ userField.path.slice(1),
5841
+ // remove _rawData from users path
5842
+ users.map((u) => {
5843
+ if (user[idFieldName] === u[idFieldName]) {
5844
+ return user;
5845
+ }
5846
+ return {
5847
+ // don't overwrite other users' passwords
5848
+ ...u,
5849
+ [passwordFieldName]: {
5850
+ ...u[passwordFieldName],
5851
+ value: ""
5852
+ }
5853
+ };
5854
+ })
5855
+ );
5856
+ await resolver.updateResolveDocument({
5857
+ collection,
5858
+ args: { params },
5859
+ realPath,
5860
+ isCollectionSpecific: true,
5861
+ isAddPendingDocument: false
5862
+ });
5863
+ return true;
5864
+ }
5693
5865
 
5694
5866
  // src/error.ts
5695
5867
  var import_graphql4 = require("graphql");
@@ -5711,9 +5883,8 @@ var resolve = async ({
5711
5883
  isAudit,
5712
5884
  ctxUser
5713
5885
  }) => {
5714
- var _a;
5715
5886
  try {
5716
- const verboseValue = verbose != null ? verbose : true;
5887
+ const verboseValue = verbose ?? true;
5717
5888
  const graphQLSchemaAst = await database.getGraphQLSchema();
5718
5889
  if (!graphQLSchemaAst) {
5719
5890
  throw new import_graphql5.GraphQLError("GraphQL schema not found");
@@ -5725,7 +5896,7 @@ var resolve = async ({
5725
5896
  // @ts-ignore
5726
5897
  schema: tinaConfig,
5727
5898
  // @ts-ignore
5728
- flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
5899
+ flags: tinaConfig?.meta?.flags
5729
5900
  });
5730
5901
  const resolver = createResolver({
5731
5902
  config,
@@ -5750,7 +5921,6 @@ var resolve = async ({
5750
5921
  throw new Error(`Unable to find lookup key for ${namedType}`);
5751
5922
  },
5752
5923
  fieldResolver: async (source = {}, _args = {}, _context, info) => {
5753
- var _a2, _b, _c, _d;
5754
5924
  try {
5755
5925
  const args = JSON.parse(JSON.stringify(_args));
5756
5926
  const returnType = (0, import_graphql5.getNamedType)(info.returnType).toString();
@@ -5767,8 +5937,7 @@ var resolve = async ({
5767
5937
  );
5768
5938
  const hasDocuments2 = collectionNode2.selectionSet.selections.find(
5769
5939
  (x) => {
5770
- var _a3;
5771
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5940
+ return x?.name?.value === "documents";
5772
5941
  }
5773
5942
  );
5774
5943
  return tinaSchema.getCollections().map((collection) => {
@@ -5784,8 +5953,7 @@ var resolve = async ({
5784
5953
  );
5785
5954
  const hasDocuments = collectionNode.selectionSet.selections.find(
5786
5955
  (x) => {
5787
- var _a3;
5788
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5956
+ return x?.name?.value === "documents";
5789
5957
  }
5790
5958
  );
5791
5959
  return resolver.resolveCollection(
@@ -5803,119 +5971,33 @@ var resolve = async ({
5803
5971
  );
5804
5972
  }
5805
5973
  }
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;
5974
+ if (info.fieldName === "authenticate") {
5975
+ return handleAuthenticate({
5976
+ tinaSchema,
5977
+ resolver,
5978
+ sub: args.sub,
5979
+ password: args.password,
5980
+ info,
5981
+ ctxUser
5982
+ });
5983
+ }
5984
+ if (info.fieldName === "authorize") {
5985
+ return handleAuthorize({
5986
+ tinaSchema,
5987
+ resolver,
5988
+ sub: args.sub,
5989
+ info,
5990
+ ctxUser
5991
+ });
5853
5992
  }
5854
5993
  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
5994
+ return handleUpdatePassword({
5995
+ tinaSchema,
5996
+ resolver,
5997
+ password: args.password,
5998
+ info,
5999
+ ctxUser
5917
6000
  });
5918
- return true;
5919
6001
  }
5920
6002
  if (!lookup) {
5921
6003
  return value;
@@ -5935,7 +6017,7 @@ var resolve = async ({
5935
6017
  if (typeof value === "string" && value !== "") {
5936
6018
  return resolver.getDocument(value);
5937
6019
  }
5938
- if ((args == null ? void 0 : args.collection) && info.fieldName === "addPendingDocument") {
6020
+ if (args?.collection && info.fieldName === "addPendingDocument") {
5939
6021
  return resolver.resolveDocument({
5940
6022
  args: { ...args, params: {} },
5941
6023
  collection: args.collection,
@@ -5959,7 +6041,7 @@ var resolve = async ({
5959
6041
  // Right now this is the only case for deletion
5960
6042
  isDeletion: info.fieldName === "deleteDocument",
5961
6043
  isFolderCreation: info.fieldName === "createFolder",
5962
- isUpdateName: Boolean((_a2 = args == null ? void 0 : args.params) == null ? void 0 : _a2.relativePath),
6044
+ isUpdateName: Boolean(args?.params?.relativePath),
5963
6045
  isAddPendingDocument: false,
5964
6046
  isCollectionSpecific: false
5965
6047
  });
@@ -5978,16 +6060,16 @@ var resolve = async ({
5978
6060
  })
5979
6061
  };
5980
6062
  }
5981
- if (info.fieldName === "documents" && (value == null ? void 0 : value.collection) && (value == null ? void 0 : value.hasDocuments)) {
6063
+ if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
5982
6064
  let filter = args.filter;
5983
6065
  if (
5984
6066
  // 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
6067
+ typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
5986
6068
  // @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
6069
+ typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
5988
6070
  // @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"
6071
+ Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
6072
+ typeof args.filter[value?.collection?.name] !== "undefined"
5991
6073
  ) {
5992
6074
  filter = args.filter[value.collection.name];
5993
6075
  }
@@ -6124,15 +6206,15 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
6124
6206
  };
6125
6207
 
6126
6208
  // src/database/index.ts
6127
- var import_node_path = __toESM(require("path"));
6209
+ var import_node_path = __toESM(require("node:path"));
6128
6210
  var import_graphql6 = require("graphql");
6129
6211
  var import_micromatch2 = __toESM(require("micromatch"));
6130
6212
  var import_js_sha12 = __toESM(require("js-sha1"));
6131
6213
  var import_lodash5 = __toESM(require("lodash.set"));
6132
6214
  var createLocalDatabase = (config) => {
6133
- const level = new TinaLevelClient(config == null ? void 0 : config.port);
6215
+ const level = new TinaLevelClient(config?.port);
6134
6216
  level.openConnection();
6135
- const fsBridge = new FilesystemBridge((config == null ? void 0 : config.rootPath) || process.cwd());
6217
+ const fsBridge = new FilesystemBridge(config?.rootPath || process.cwd());
6136
6218
  return new Database({
6137
6219
  bridge: fsBridge,
6138
6220
  ...config || {},
@@ -6205,7 +6287,7 @@ var Database = class {
6205
6287
  );
6206
6288
  }
6207
6289
  const metadata = await metadataLevel.get(`metadata_${key}`);
6208
- return metadata == null ? void 0 : metadata.value;
6290
+ return metadata?.value;
6209
6291
  };
6210
6292
  this.setMetadata = async (key, value) => {
6211
6293
  await this.initLevel();
@@ -6227,14 +6309,14 @@ var Database = class {
6227
6309
  let level = this.contentLevel;
6228
6310
  if (this.appLevel) {
6229
6311
  collection = await this.collectionForPath(filepath);
6230
- if (collection == null ? void 0 : collection.isDetached) {
6312
+ if (collection?.isDetached) {
6231
6313
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
6232
6314
  }
6233
6315
  }
6234
6316
  const contentObject = await level.sublevel(
6235
6317
  CONTENT_ROOT_PREFIX,
6236
6318
  SUBLEVEL_OPTIONS
6237
- ).get((0, import_schema_tools3.normalizePath)(filepath));
6319
+ ).get((0, import_schema_tools4.normalizePath)(filepath));
6238
6320
  if (!contentObject) {
6239
6321
  throw new NotFoundError(`Unable to find record ${filepath}`);
6240
6322
  }
@@ -6258,9 +6340,10 @@ var Database = class {
6258
6340
  collection
6259
6341
  );
6260
6342
  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)) {
6343
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6344
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6345
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6346
+ if (!collection?.isDetached) {
6264
6347
  if (this.bridge) {
6265
6348
  await this.bridge.put(normalizedPath, stringifiedFile);
6266
6349
  }
@@ -6278,7 +6361,7 @@ var Database = class {
6278
6361
  }
6279
6362
  }
6280
6363
  let level = this.contentLevel;
6281
- if (collection == null ? void 0 : collection.isDetached) {
6364
+ if (collection?.isDetached) {
6282
6365
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
6283
6366
  }
6284
6367
  const folderTreeBuilder = new FolderTreeBuilder();
@@ -6287,9 +6370,17 @@ var Database = class {
6287
6370
  let delOps = [];
6288
6371
  if (!isGitKeep(normalizedPath, collection)) {
6289
6372
  putOps = [
6373
+ ...makeRefOpsForDocument(
6374
+ normalizedPath,
6375
+ collection?.name,
6376
+ collectionReferences,
6377
+ dataFields,
6378
+ "put",
6379
+ level
6380
+ ),
6290
6381
  ...makeIndexOpsForDocument(
6291
6382
  normalizedPath,
6292
- collection == null ? void 0 : collection.name,
6383
+ collection?.name,
6293
6384
  collectionIndexDefinitions,
6294
6385
  dataFields,
6295
6386
  "put",
@@ -6298,7 +6389,7 @@ var Database = class {
6298
6389
  // folder indices
6299
6390
  ...makeIndexOpsForDocument(
6300
6391
  normalizedPath,
6301
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6392
+ `${collection?.name}_${folderKey}`,
6302
6393
  collectionIndexDefinitions,
6303
6394
  dataFields,
6304
6395
  "put",
@@ -6310,9 +6401,17 @@ var Database = class {
6310
6401
  SUBLEVEL_OPTIONS
6311
6402
  ).get(normalizedPath);
6312
6403
  delOps = existingItem ? [
6404
+ ...makeRefOpsForDocument(
6405
+ normalizedPath,
6406
+ collection?.name,
6407
+ collectionReferences,
6408
+ existingItem,
6409
+ "del",
6410
+ level
6411
+ ),
6313
6412
  ...makeIndexOpsForDocument(
6314
6413
  normalizedPath,
6315
- collection == null ? void 0 : collection.name,
6414
+ collection?.name,
6316
6415
  collectionIndexDefinitions,
6317
6416
  existingItem,
6318
6417
  "del",
@@ -6321,7 +6420,7 @@ var Database = class {
6321
6420
  // folder indices
6322
6421
  ...makeIndexOpsForDocument(
6323
6422
  normalizedPath,
6324
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6423
+ `${collection?.name}_${folderKey}`,
6325
6424
  collectionIndexDefinitions,
6326
6425
  existingItem,
6327
6426
  "del",
@@ -6345,7 +6444,6 @@ var Database = class {
6345
6444
  await level.batch(ops);
6346
6445
  };
6347
6446
  this.put = async (filepath, data, collectionName) => {
6348
- var _a, _b;
6349
6447
  await this.initLevel();
6350
6448
  try {
6351
6449
  if (SYSTEM_FILES.includes(filepath)) {
@@ -6356,15 +6454,16 @@ var Database = class {
6356
6454
  const indexDefinitions = await this.getIndexDefinitions(
6357
6455
  this.contentLevel
6358
6456
  );
6359
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6457
+ collectionIndexDefinitions = indexDefinitions?.[collectionName];
6360
6458
  }
6361
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
6459
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6460
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6362
6461
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6363
6462
  const collection = await this.collectionForPath(filepath);
6364
6463
  if (!collection) {
6365
6464
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
6366
6465
  }
6367
- if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
6466
+ if (collection.match?.exclude || collection.match?.include) {
6368
6467
  const matches = this.tinaSchema.getMatches({ collection });
6369
6468
  const match = import_micromatch2.default.isMatch(filepath, matches);
6370
6469
  if (!match) {
@@ -6378,7 +6477,7 @@ var Database = class {
6378
6477
  const stringifiedFile = filepath.endsWith(
6379
6478
  `.gitkeep.${collection.format || "md"}`
6380
6479
  ) ? "" : await this.stringifyFile(filepath, dataFields, collection);
6381
- if (!(collection == null ? void 0 : collection.isDetached)) {
6480
+ if (!collection?.isDetached) {
6382
6481
  if (this.bridge) {
6383
6482
  await this.bridge.put(normalizedPath, stringifiedFile);
6384
6483
  }
@@ -6400,11 +6499,19 @@ var Database = class {
6400
6499
  filepath,
6401
6500
  collection.path || ""
6402
6501
  );
6403
- const level = (collection == null ? void 0 : collection.isDetached) ? this.appLevel.sublevel(collection == null ? void 0 : collection.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6502
+ const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6404
6503
  let putOps = [];
6405
6504
  let delOps = [];
6406
6505
  if (!isGitKeep(normalizedPath, collection)) {
6407
6506
  putOps = [
6507
+ ...makeRefOpsForDocument(
6508
+ normalizedPath,
6509
+ collectionName,
6510
+ collectionReferences,
6511
+ dataFields,
6512
+ "put",
6513
+ level
6514
+ ),
6408
6515
  ...makeIndexOpsForDocument(
6409
6516
  normalizedPath,
6410
6517
  collectionName,
@@ -6416,7 +6523,7 @@ var Database = class {
6416
6523
  // folder indices
6417
6524
  ...makeIndexOpsForDocument(
6418
6525
  normalizedPath,
6419
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6526
+ `${collection?.name}_${folderKey}`,
6420
6527
  collectionIndexDefinitions,
6421
6528
  dataFields,
6422
6529
  "put",
@@ -6428,6 +6535,14 @@ var Database = class {
6428
6535
  SUBLEVEL_OPTIONS
6429
6536
  ).get(normalizedPath);
6430
6537
  delOps = existingItem ? [
6538
+ ...makeRefOpsForDocument(
6539
+ normalizedPath,
6540
+ collectionName,
6541
+ collectionReferences,
6542
+ existingItem,
6543
+ "del",
6544
+ level
6545
+ ),
6431
6546
  ...makeIndexOpsForDocument(
6432
6547
  normalizedPath,
6433
6548
  collectionName,
@@ -6439,7 +6554,7 @@ var Database = class {
6439
6554
  // folder indices
6440
6555
  ...makeIndexOpsForDocument(
6441
6556
  normalizedPath,
6442
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6557
+ `${collection?.name}_${folderKey}`,
6443
6558
  collectionIndexDefinitions,
6444
6559
  existingItem,
6445
6560
  "del",
@@ -6470,8 +6585,7 @@ var Database = class {
6470
6585
  throw new TinaFetchError(`Error in PUT for ${filepath}`, {
6471
6586
  originalError: error,
6472
6587
  file: filepath,
6473
- collection: collectionName,
6474
- stack: error.stack
6588
+ collection: collectionName
6475
6589
  });
6476
6590
  }
6477
6591
  };
@@ -6516,8 +6630,8 @@ var Database = class {
6516
6630
  writeTemplateKey,
6517
6631
  //templateInfo.type === 'union',
6518
6632
  {
6519
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat,
6520
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
6633
+ frontmatterFormat: collection?.frontmatterFormat,
6634
+ frontmatterDelimiters: collection?.frontmatterDelimiters
6521
6635
  }
6522
6636
  );
6523
6637
  };
@@ -6532,7 +6646,7 @@ var Database = class {
6532
6646
  };
6533
6647
  this.getLookup = async (returnType) => {
6534
6648
  await this.initLevel();
6535
- const lookupPath = (0, import_schema_tools3.normalizePath)(
6649
+ const lookupPath = (0, import_schema_tools4.normalizePath)(
6536
6650
  import_node_path.default.join(this.getGeneratedFolder(), `_lookup.json`)
6537
6651
  );
6538
6652
  if (!this._lookup) {
@@ -6545,7 +6659,7 @@ var Database = class {
6545
6659
  };
6546
6660
  this.getGraphQLSchema = async () => {
6547
6661
  await this.initLevel();
6548
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6662
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6549
6663
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6550
6664
  );
6551
6665
  return await this.contentLevel.sublevel(
@@ -6558,7 +6672,7 @@ var Database = class {
6558
6672
  if (!this.bridge) {
6559
6673
  throw new Error(`No bridge configured`);
6560
6674
  }
6561
- const graphqlPath = (0, import_schema_tools3.normalizePath)(
6675
+ const graphqlPath = (0, import_schema_tools4.normalizePath)(
6562
6676
  import_node_path.default.join(this.getGeneratedFolder(), `_graphql.json`)
6563
6677
  );
6564
6678
  const _graphql = await this.bridge.get(graphqlPath);
@@ -6566,7 +6680,7 @@ var Database = class {
6566
6680
  };
6567
6681
  this.getTinaSchema = async (level) => {
6568
6682
  await this.initLevel();
6569
- const schemaPath = (0, import_schema_tools3.normalizePath)(
6683
+ const schemaPath = (0, import_schema_tools4.normalizePath)(
6570
6684
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6571
6685
  );
6572
6686
  return await (level || this.contentLevel).sublevel(
@@ -6582,7 +6696,7 @@ var Database = class {
6582
6696
  const schema = existingSchema || await this.getTinaSchema(level || this.contentLevel);
6583
6697
  if (!schema) {
6584
6698
  throw new Error(
6585
- `Unable to get schema from level db: ${(0, import_schema_tools3.normalizePath)(
6699
+ `Unable to get schema from level db: ${(0, import_schema_tools4.normalizePath)(
6586
6700
  import_node_path.default.join(this.getGeneratedFolder(), `_schema.json`)
6587
6701
  )}`
6588
6702
  );
@@ -6590,6 +6704,22 @@ var Database = class {
6590
6704
  this.tinaSchema = await createSchema({ schema });
6591
6705
  return this.tinaSchema;
6592
6706
  };
6707
+ this.getCollectionReferences = async (level) => {
6708
+ if (this.collectionReferences) {
6709
+ return this.collectionReferences;
6710
+ }
6711
+ const result = {};
6712
+ const schema = await this.getSchema(level || this.contentLevel);
6713
+ const collections = schema.getCollections();
6714
+ for (const collection of collections) {
6715
+ const collectionReferences = this.tinaSchema.findReferencesFromCollection(
6716
+ collection.name
6717
+ );
6718
+ result[collection.name] = collectionReferences;
6719
+ }
6720
+ this.collectionReferences = result;
6721
+ return result;
6722
+ };
6593
6723
  this.getIndexDefinitions = async (level) => {
6594
6724
  if (!this.collectionIndexDefinitions) {
6595
6725
  await new Promise(async (resolve2, reject) => {
@@ -6599,11 +6729,53 @@ var Database = class {
6599
6729
  const collections = schema.getCollections();
6600
6730
  for (const collection of collections) {
6601
6731
  const indexDefinitions = {
6602
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6732
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6603
6733
  // provide a default sort key which is the file sort
6734
+ // pseudo-index for the collection's references
6735
+ [REFS_COLLECTIONS_SORT_KEY]: {
6736
+ fields: [
6737
+ {
6738
+ name: REFS_REFERENCE_FIELD,
6739
+ type: "string",
6740
+ list: false
6741
+ },
6742
+ {
6743
+ name: REFS_PATH_FIELD,
6744
+ type: "string",
6745
+ list: false
6746
+ }
6747
+ ]
6748
+ }
6604
6749
  };
6605
- if (collection.fields) {
6606
- for (const field of collection.fields) {
6750
+ let fields = [];
6751
+ if (collection.templates) {
6752
+ const templateFieldMap = {};
6753
+ const conflictedFields = /* @__PURE__ */ new Set();
6754
+ for (const template of collection.templates) {
6755
+ for (const field of template.fields) {
6756
+ if (!templateFieldMap[field.name]) {
6757
+ templateFieldMap[field.name] = field;
6758
+ } else {
6759
+ if (templateFieldMap[field.name].type !== field.type) {
6760
+ console.warn(
6761
+ `Field ${field.name} has conflicting types in templates - skipping index`
6762
+ );
6763
+ conflictedFields.add(field.name);
6764
+ }
6765
+ }
6766
+ }
6767
+ }
6768
+ for (const conflictedField in conflictedFields) {
6769
+ delete templateFieldMap[conflictedField];
6770
+ }
6771
+ for (const field of Object.values(templateFieldMap)) {
6772
+ fields.push(field);
6773
+ }
6774
+ } else if (collection.fields) {
6775
+ fields = collection.fields;
6776
+ }
6777
+ if (fields) {
6778
+ for (const field of fields) {
6607
6779
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6608
6780
  continue;
6609
6781
  }
@@ -6628,8 +6800,8 @@ var Database = class {
6628
6800
  );
6629
6801
  return {
6630
6802
  name: indexField.name,
6631
- type: field == null ? void 0 : field.type,
6632
- list: !!(field == null ? void 0 : field.list)
6803
+ type: field?.type,
6804
+ list: !!field?.list
6633
6805
  };
6634
6806
  })
6635
6807
  };
@@ -6655,7 +6827,6 @@ var Database = class {
6655
6827
  return true;
6656
6828
  };
6657
6829
  this.query = async (queryOptions, hydrator) => {
6658
- var _a;
6659
6830
  await this.initLevel();
6660
6831
  const {
6661
6832
  first,
@@ -6683,14 +6854,14 @@ var Database = class {
6683
6854
  const allIndexDefinitions = await this.getIndexDefinitions(
6684
6855
  this.contentLevel
6685
6856
  );
6686
- const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[collection.name];
6857
+ const indexDefinitions = allIndexDefinitions?.[collection.name];
6687
6858
  if (!indexDefinitions) {
6688
6859
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6689
6860
  }
6690
6861
  const filterChain = coerceFilterChainOperands(rawFilterChain);
6691
- const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
6862
+ const indexDefinition = sort && indexDefinitions?.[sort];
6692
6863
  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;
6864
+ const level = collection?.isDetached ? this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS) : this.contentLevel;
6694
6865
  const rootLevel = level.sublevel(
6695
6866
  CONTENT_ROOT_PREFIX,
6696
6867
  SUBLEVEL_OPTIONS
@@ -6700,17 +6871,17 @@ var Database = class {
6700
6871
  SUBLEVEL_OPTIONS
6701
6872
  ).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
6702
6873
  if (!query.gt && !query.gte) {
6703
- query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? filterSuffixes.left : "";
6874
+ query.gte = filterSuffixes?.left ? filterSuffixes.left : "";
6704
6875
  }
6705
6876
  if (!query.lt && !query.lte) {
6706
- query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6877
+ query.lte = filterSuffixes?.right ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6707
6878
  }
6708
6879
  let edges = [];
6709
6880
  let startKey = "";
6710
6881
  let endKey = "";
6711
6882
  let hasPreviousPage = false;
6712
6883
  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("")}` : "";
6884
+ const fieldsPattern = indexDefinition?.fields?.length ? `${indexDefinition.fields.map((p) => `(?<${p.name}>.+)${INDEX_KEY_FIELD_SEPARATOR}`).join("")}` : "";
6714
6885
  const valuesRegex = indexDefinition ? new RegExp(`^${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^(?<_filepath_>.+)`);
6715
6886
  const itemFilter = makeFilter({ filterChain });
6716
6887
  const iterator = sublevel.iterator(query);
@@ -6752,29 +6923,35 @@ var Database = class {
6752
6923
  }
6753
6924
  startKey = startKey || key || "";
6754
6925
  endKey = key || "";
6755
- edges = [...edges, { cursor: key, path: filepath }];
6926
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6756
6927
  }
6757
6928
  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
- });
6929
+ edges: await sequential(
6930
+ edges,
6931
+ async ({
6932
+ cursor,
6933
+ path: path7,
6934
+ value
6935
+ }) => {
6936
+ try {
6937
+ const node = await hydrator(path7, value);
6938
+ return {
6939
+ node,
6940
+ cursor: btoa(cursor)
6941
+ };
6942
+ } catch (error) {
6943
+ console.log(error);
6944
+ if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
6945
+ throw new TinaQueryError({
6946
+ originalError: error,
6947
+ file: path7,
6948
+ collection: collection.name
6949
+ });
6950
+ }
6951
+ throw error;
6774
6952
  }
6775
- throw error;
6776
6953
  }
6777
- }),
6954
+ ),
6778
6955
  pageInfo: {
6779
6956
  hasPreviousPage,
6780
6957
  hasNextPage,
@@ -6799,7 +6976,7 @@ var Database = class {
6799
6976
  try {
6800
6977
  lookup = lookupFromLockFile || JSON.parse(
6801
6978
  await this.bridge.get(
6802
- (0, import_schema_tools3.normalizePath)(
6979
+ (0, import_schema_tools4.normalizePath)(
6803
6980
  import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")
6804
6981
  )
6805
6982
  )
@@ -6824,15 +7001,15 @@ var Database = class {
6824
7001
  }
6825
7002
  const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
6826
7003
  await contentRootLevel.put(
6827
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
7004
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_graphql.json")),
6828
7005
  graphQLSchema
6829
7006
  );
6830
7007
  await contentRootLevel.put(
6831
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
7008
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_schema.json")),
6832
7009
  tinaSchema.schema
6833
7010
  );
6834
7011
  await contentRootLevel.put(
6835
- (0, import_schema_tools3.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
7012
+ (0, import_schema_tools4.normalizePath)(import_node_path.default.join(this.getGeneratedFolder(), "_lookup.json")),
6836
7013
  lookup
6837
7014
  );
6838
7015
  const result = await this._indexAllContent(
@@ -6898,13 +7075,14 @@ var Database = class {
6898
7075
  documentPaths,
6899
7076
  async (collection, documentPaths2) => {
6900
7077
  if (collection && !collection.isDetached) {
6901
- await _indexContent(
6902
- this,
6903
- this.contentLevel,
6904
- documentPaths2,
7078
+ await _indexContent({
7079
+ database: this,
7080
+ level: this.contentLevel,
7081
+ documentPaths: documentPaths2,
6905
7082
  enqueueOps,
6906
- collection
6907
- );
7083
+ collection,
7084
+ isPartialReindex: true
7085
+ });
6908
7086
  }
6909
7087
  }
6910
7088
  );
@@ -6920,12 +7098,13 @@ var Database = class {
6920
7098
  throw new Error(`No collection found for path: ${filepath}`);
6921
7099
  }
6922
7100
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6923
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7101
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
7102
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6924
7103
  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);
7104
+ if (collection?.isDetached) {
7105
+ level = this.appLevel.sublevel(collection?.name, SUBLEVEL_OPTIONS);
6927
7106
  }
6928
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
7107
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6929
7108
  const rootSublevel = level.sublevel(
6930
7109
  CONTENT_ROOT_PREFIX,
6931
7110
  SUBLEVEL_OPTIONS
@@ -6938,6 +7117,14 @@ var Database = class {
6938
7117
  collection.path || ""
6939
7118
  );
6940
7119
  await this.contentLevel.batch([
7120
+ ...makeRefOpsForDocument(
7121
+ normalizedPath,
7122
+ collection.name,
7123
+ collectionReferences,
7124
+ item,
7125
+ "del",
7126
+ level
7127
+ ),
6941
7128
  ...makeIndexOpsForDocument(
6942
7129
  normalizedPath,
6943
7130
  collection.name,
@@ -6962,7 +7149,7 @@ var Database = class {
6962
7149
  }
6963
7150
  ]);
6964
7151
  }
6965
- if (!(collection == null ? void 0 : collection.isDetached)) {
7152
+ if (!collection?.isDetached) {
6966
7153
  if (this.bridge) {
6967
7154
  await this.bridge.delete(normalizedPath);
6968
7155
  }
@@ -7002,20 +7189,26 @@ var Database = class {
7002
7189
  );
7003
7190
  const doc = await level2.keys({ limit: 1 }).next();
7004
7191
  if (!doc) {
7005
- await _indexContent(
7006
- this,
7007
- level2,
7008
- contentPaths,
7192
+ await _indexContent({
7193
+ database: this,
7194
+ level: level2,
7195
+ documentPaths: contentPaths,
7009
7196
  enqueueOps,
7010
7197
  collection,
7011
- userFields.map((field) => [
7198
+ passwordFields: userFields.map((field) => [
7012
7199
  ...field.path,
7013
7200
  field.passwordFieldName
7014
7201
  ])
7015
- );
7202
+ });
7016
7203
  }
7017
7204
  } else {
7018
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7205
+ await _indexContent({
7206
+ database: this,
7207
+ level,
7208
+ documentPaths: contentPaths,
7209
+ enqueueOps,
7210
+ collection
7211
+ });
7019
7212
  }
7020
7213
  }
7021
7214
  );
@@ -7051,7 +7244,7 @@ var Database = class {
7051
7244
  );
7052
7245
  }
7053
7246
  const metadata = await metadataLevel.get("metadata");
7054
- return metadata == null ? void 0 : metadata.version;
7247
+ return metadata?.version;
7055
7248
  }
7056
7249
  async initLevel() {
7057
7250
  if (this.contentLevel) {
@@ -7137,7 +7330,7 @@ var hashPasswordVisitor = async (node, path7) => {
7137
7330
  };
7138
7331
  var visitNodes = async (node, path7, callback) => {
7139
7332
  const [currentLevel, ...remainingLevels] = path7;
7140
- if (!(remainingLevels == null ? void 0 : remainingLevels.length)) {
7333
+ if (!remainingLevels?.length) {
7141
7334
  return callback(node, path7);
7142
7335
  }
7143
7336
  if (Array.isArray(node[currentLevel])) {
@@ -7153,18 +7346,27 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
7153
7346
  async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
7154
7347
  )
7155
7348
  );
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) => {
7349
+ var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${collection?.format || "md"}`);
7350
+ var _indexContent = async ({
7351
+ database,
7352
+ level,
7353
+ documentPaths,
7354
+ enqueueOps,
7355
+ collection,
7356
+ passwordFields,
7357
+ isPartialReindex
7358
+ }) => {
7158
7359
  let collectionIndexDefinitions;
7159
7360
  let collectionPath;
7160
7361
  if (collection) {
7161
7362
  const indexDefinitions = await database.getIndexDefinitions(level);
7162
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7363
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
7163
7364
  if (!collectionIndexDefinitions) {
7164
7365
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7165
7366
  }
7166
7367
  collectionPath = collection.path;
7167
7368
  }
7369
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7168
7370
  const tinaSchema = await database.getSchema();
7169
7371
  let templateInfo = null;
7170
7372
  if (collection) {
@@ -7182,19 +7384,68 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7182
7384
  if (!aliasedData) {
7183
7385
  return;
7184
7386
  }
7185
- if (passwordFields == null ? void 0 : passwordFields.length) {
7387
+ if (passwordFields?.length) {
7186
7388
  await hashPasswordValues(aliasedData, passwordFields);
7187
7389
  }
7188
- const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
7390
+ const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
7391
+ const rootSublevel = level.sublevel(
7392
+ CONTENT_ROOT_PREFIX,
7393
+ SUBLEVEL_OPTIONS
7394
+ );
7189
7395
  const folderKey = folderTreeBuilder.update(
7190
7396
  normalizedPath,
7191
7397
  collectionPath || ""
7192
7398
  );
7399
+ if (isPartialReindex) {
7400
+ const item = await rootSublevel.get(normalizedPath);
7401
+ if (item) {
7402
+ await database.contentLevel.batch([
7403
+ ...makeRefOpsForDocument(
7404
+ normalizedPath,
7405
+ collection?.name,
7406
+ collectionReferences,
7407
+ item,
7408
+ "del",
7409
+ level
7410
+ ),
7411
+ ...makeIndexOpsForDocument(
7412
+ normalizedPath,
7413
+ collection.name,
7414
+ collectionIndexDefinitions,
7415
+ item,
7416
+ "del",
7417
+ level
7418
+ ),
7419
+ // folder indices
7420
+ ...makeIndexOpsForDocument(
7421
+ normalizedPath,
7422
+ `${collection.name}_${folderKey}`,
7423
+ collectionIndexDefinitions,
7424
+ item,
7425
+ "del",
7426
+ level
7427
+ ),
7428
+ {
7429
+ type: "del",
7430
+ key: normalizedPath,
7431
+ sublevel: rootSublevel
7432
+ }
7433
+ ]);
7434
+ }
7435
+ }
7193
7436
  if (!isGitKeep(filepath, collection)) {
7194
7437
  await enqueueOps([
7438
+ ...makeRefOpsForDocument(
7439
+ normalizedPath,
7440
+ collection?.name,
7441
+ collectionReferences,
7442
+ aliasedData,
7443
+ "put",
7444
+ level
7445
+ ),
7195
7446
  ...makeIndexOpsForDocument(
7196
7447
  normalizedPath,
7197
- collection == null ? void 0 : collection.name,
7448
+ collection?.name,
7198
7449
  collectionIndexDefinitions,
7199
7450
  aliasedData,
7200
7451
  "put",
@@ -7203,7 +7454,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7203
7454
  // folder indexes
7204
7455
  ...makeIndexOpsForDocument(
7205
7456
  normalizedPath,
7206
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7457
+ `${collection?.name}_${folderKey}`,
7207
7458
  collectionIndexDefinitions,
7208
7459
  aliasedData,
7209
7460
  "put",
@@ -7224,8 +7475,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7224
7475
  throw new TinaFetchError(`Unable to seed ${filepath}`, {
7225
7476
  originalError: error,
7226
7477
  file: filepath,
7227
- collection: collection == null ? void 0 : collection.name,
7228
- stack: error.stack
7478
+ collection: collection?.name
7229
7479
  });
7230
7480
  }
7231
7481
  });
@@ -7250,11 +7500,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7250
7500
  const indexDefinitions = await database.getIndexDefinitions(
7251
7501
  database.contentLevel
7252
7502
  );
7253
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7503
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
7254
7504
  if (!collectionIndexDefinitions) {
7255
7505
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7256
7506
  }
7257
7507
  }
7508
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7258
7509
  const tinaSchema = await database.getSchema();
7259
7510
  let templateInfo = null;
7260
7511
  if (collection) {
@@ -7266,18 +7517,26 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7266
7517
  );
7267
7518
  const folderTreeBuilder = new FolderTreeBuilder();
7268
7519
  await sequential(documentPaths, async (filepath) => {
7269
- const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
7520
+ const itemKey = (0, import_schema_tools4.normalizePath)(filepath);
7270
7521
  const item = await rootLevel.get(itemKey);
7271
7522
  if (item) {
7272
7523
  const folderKey = folderTreeBuilder.update(
7273
7524
  itemKey,
7274
- (collection == null ? void 0 : collection.path) || ""
7525
+ collection?.path || ""
7275
7526
  );
7276
7527
  const aliasedData = templateInfo ? replaceNameOverrides(
7277
7528
  getTemplateForFile(templateInfo, item),
7278
7529
  item
7279
7530
  ) : item;
7280
7531
  await enqueueOps([
7532
+ ...makeRefOpsForDocument(
7533
+ itemKey,
7534
+ collection?.name,
7535
+ collectionReferences,
7536
+ aliasedData,
7537
+ "del",
7538
+ database.contentLevel
7539
+ ),
7281
7540
  ...makeIndexOpsForDocument(
7282
7541
  itemKey,
7283
7542
  collection.name,
@@ -7289,7 +7548,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7289
7548
  // folder indexes
7290
7549
  ...makeIndexOpsForDocument(
7291
7550
  itemKey,
7292
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7551
+ `${collection?.name}_${folderKey}`,
7293
7552
  collectionIndexDefinitions,
7294
7553
  aliasedData,
7295
7554
  "del",
@@ -7353,14 +7612,14 @@ var getChangedFiles = async ({
7353
7612
  const rootDir = await findGitRoot(dir);
7354
7613
  let pathPrefix = "";
7355
7614
  if (rootDir !== dir) {
7356
- pathPrefix = (0, import_schema_tools3.normalizePath)(dir.substring(rootDir.length + 1));
7615
+ pathPrefix = (0, import_schema_tools4.normalizePath)(dir.substring(rootDir.length + 1));
7357
7616
  }
7358
7617
  await import_isomorphic_git.default.walk({
7359
7618
  fs: fs4,
7360
7619
  dir: rootDir,
7361
7620
  trees: [import_isomorphic_git.default.TREE({ ref: from }), import_isomorphic_git.default.TREE({ ref: to })],
7362
7621
  map: async function(filename, [A, B]) {
7363
- const relativePath = (0, import_schema_tools3.normalizePath)(filename).substring(pathPrefix.length);
7622
+ const relativePath = (0, import_schema_tools4.normalizePath)(filename).substring(pathPrefix.length);
7364
7623
  let matches = false;
7365
7624
  for (const [key, matcher] of Object.entries(pathFilter)) {
7366
7625
  if (relativePath.startsWith(key)) {
@@ -7374,12 +7633,12 @@ var getChangedFiles = async ({
7374
7633
  }
7375
7634
  }
7376
7635
  }
7377
- if (await (B == null ? void 0 : B.type()) === "tree") {
7636
+ if (await B?.type() === "tree") {
7378
7637
  return;
7379
7638
  }
7380
7639
  if (matches) {
7381
- const oidA = await (A == null ? void 0 : A.oid());
7382
- const oidB = await (B == null ? void 0 : B.oid());
7640
+ const oidA = await A?.oid();
7641
+ const oidB = await B?.oid();
7383
7642
  if (oidA !== oidB) {
7384
7643
  if (oidA === void 0) {
7385
7644
  results.added.push(relativePath);
@@ -7407,8 +7666,8 @@ var import_path5 = __toESM(require("path"));
7407
7666
  var import_normalize_path = __toESM(require("normalize-path"));
7408
7667
  var FilesystemBridge = class {
7409
7668
  constructor(rootPath, outputPath) {
7410
- this.rootPath = rootPath || "";
7411
- this.outputPath = outputPath || rootPath;
7669
+ this.rootPath = import_path5.default.resolve(rootPath);
7670
+ this.outputPath = outputPath ? import_path5.default.resolve(outputPath) : this.rootPath;
7412
7671
  }
7413
7672
  async glob(pattern, extension) {
7414
7673
  const basePath = import_path5.default.join(this.outputPath, ...pattern.split("/"));
@@ -7420,19 +7679,19 @@ var FilesystemBridge = class {
7420
7679
  }
7421
7680
  );
7422
7681
  const posixRootPath = (0, import_normalize_path.default)(this.outputPath);
7423
- return items.map((item) => {
7424
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
7425
- });
7682
+ return items.map(
7683
+ (item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
7684
+ );
7426
7685
  }
7427
7686
  async delete(filepath) {
7428
7687
  await import_fs_extra2.default.remove(import_path5.default.join(this.outputPath, filepath));
7429
7688
  }
7430
7689
  async get(filepath) {
7431
- return import_fs_extra2.default.readFileSync(import_path5.default.join(this.outputPath, filepath)).toString();
7690
+ return (await import_fs_extra2.default.readFile(import_path5.default.join(this.outputPath, filepath))).toString();
7432
7691
  }
7433
7692
  async put(filepath, data, basePathOverride) {
7434
7693
  const basePath = basePathOverride || this.outputPath;
7435
- await import_fs_extra2.default.outputFileSync(import_path5.default.join(basePath, filepath), data);
7694
+ await import_fs_extra2.default.outputFile(import_path5.default.join(basePath, filepath), data);
7436
7695
  }
7437
7696
  };
7438
7697
  var AuditFileSystemBridge = class extends FilesystemBridge {