@tinacms/graphql 0.0.0-d7c5ec1-20250219020924 → 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
@@ -1435,13 +1435,12 @@ var checkPasswordHash = async ({
1435
1435
  return true;
1436
1436
  };
1437
1437
  var mapUserFields = (collectable, prefix = []) => {
1438
- var _a, _b, _c, _d, _e;
1439
1438
  const results = [];
1440
- const passwordFields = ((_a = collectable.fields) == null ? void 0 : _a.filter((field) => field.type === "password")) || [];
1439
+ const passwordFields = collectable.fields?.filter((field) => field.type === "password") || [];
1441
1440
  if (passwordFields.length > 1) {
1442
1441
  throw new Error("Only one password field is allowed");
1443
1442
  }
1444
- const idFields = ((_b = collectable.fields) == null ? void 0 : _b.filter((field) => field.uid)) || [];
1443
+ const idFields = collectable.fields?.filter((field) => field.uid) || [];
1445
1444
  if (idFields.length > 1) {
1446
1445
  throw new Error("Only one uid field is allowed");
1447
1446
  }
@@ -1449,11 +1448,11 @@ var mapUserFields = (collectable, prefix = []) => {
1449
1448
  results.push({
1450
1449
  path: prefix,
1451
1450
  collectable,
1452
- idFieldName: (_c = idFields[0]) == null ? void 0 : _c.name,
1453
- passwordFieldName: (_d = passwordFields[0]) == null ? void 0 : _d.name
1451
+ idFieldName: idFields[0]?.name,
1452
+ passwordFieldName: passwordFields[0]?.name
1454
1453
  });
1455
1454
  }
1456
- (_e = collectable.fields) == null ? void 0 : _e.forEach((field) => {
1455
+ collectable.fields?.forEach((field) => {
1457
1456
  if (field.type === "object" && field.fields) {
1458
1457
  results.push(...mapUserFields(field, [...prefix, field.name]));
1459
1458
  }
@@ -1914,7 +1913,7 @@ var Builder = class {
1914
1913
  * ```
1915
1914
  *
1916
1915
  * @public
1917
- * @param collection a Tina Cloud collection
1916
+ * @param collection a TinaCloud collection
1918
1917
  */
1919
1918
  this.collectionFragment = async (collection) => {
1920
1919
  const name = NAMER.dataTypeName(collection.namespace);
@@ -1944,13 +1943,12 @@ var Builder = class {
1944
1943
  *
1945
1944
  * */
1946
1945
  this._getCollectionFragmentSelections = async (collection, depth) => {
1947
- var _a;
1948
1946
  const selections = [];
1949
1947
  selections.push({
1950
1948
  name: { kind: "Name", value: "__typename" },
1951
1949
  kind: "Field"
1952
1950
  });
1953
- if (((_a = collection.fields) == null ? void 0 : _a.length) > 0) {
1951
+ if (collection.fields?.length > 0) {
1954
1952
  await sequential(collection.fields, async (x) => {
1955
1953
  const field = await this._buildFieldNodeForFragments(x, depth);
1956
1954
  selections.push(field);
@@ -1965,7 +1963,6 @@ var Builder = class {
1965
1963
  return selections;
1966
1964
  };
1967
1965
  this._buildFieldNodeForFragments = async (field, depth) => {
1968
- var _a, _b;
1969
1966
  switch (field.type) {
1970
1967
  case "string":
1971
1968
  case "image":
@@ -1998,7 +1995,7 @@ var Builder = class {
1998
1995
  selections: filterSelections([passwordValue, passwordChangeRequired])
1999
1996
  });
2000
1997
  case "object":
2001
- if (((_a = field.fields) == null ? void 0 : _a.length) > 0) {
1998
+ if (field.fields?.length > 0) {
2002
1999
  const selections2 = [];
2003
2000
  await sequential(field.fields, async (item) => {
2004
2001
  const field2 = await this._buildFieldNodeForFragments(item, depth);
@@ -2011,7 +2008,7 @@ var Builder = class {
2011
2008
  ...filterSelections(selections2)
2012
2009
  ]
2013
2010
  });
2014
- } else if (((_b = field.templates) == null ? void 0 : _b.length) > 0) {
2011
+ } else if (field.templates?.length > 0) {
2015
2012
  const selections2 = [];
2016
2013
  await sequential(field.templates, async (tem) => {
2017
2014
  if (typeof tem === "object") {
@@ -2673,7 +2670,7 @@ var Builder = class {
2673
2670
  this.addToLookupMap({
2674
2671
  type: name,
2675
2672
  resolveType: "unionData",
2676
- collection: collection == null ? void 0 : collection.name,
2673
+ collection: collection?.name,
2677
2674
  typeMap
2678
2675
  });
2679
2676
  return astBuilder.UnionTypeDefinition({ name, types });
@@ -2780,7 +2777,7 @@ var Builder = class {
2780
2777
  this._buildDataField = async (field) => {
2781
2778
  const listWarningMsg = `
2782
2779
  WARNING: The user interface for ${field.type} does not support \`list: true\`
2783
- 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
2784
2781
 
2785
2782
  `;
2786
2783
  switch (field.type) {
@@ -2883,9 +2880,8 @@ Visit https://tina.io/docs/errors/ui-not-supported/ for more information
2883
2880
  ]
2884
2881
  });
2885
2882
  };
2886
- var _a, _b, _c, _d;
2887
2883
  this.maxDepth = // @ts-ignore
2888
- (_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;
2889
2885
  this.tinaSchema = config.tinaSchema;
2890
2886
  this.lookupMap = {};
2891
2887
  }
@@ -2974,7 +2970,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2974
2970
  return;
2975
2971
  }
2976
2972
  const noMatchCollections = collections.filter((x) => {
2977
- return typeof (x == null ? void 0 : x.match) === "undefined";
2973
+ return typeof x?.match === "undefined";
2978
2974
  }).map((x) => `${x.path}${x.format || "md"}`);
2979
2975
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2980
2976
  throw new Error(
@@ -2985,10 +2981,7 @@ var validationCollectionsPathAndMatch = (collections) => {
2985
2981
  const hasMatchAndPath = collections.filter((x) => {
2986
2982
  return typeof x.path !== "undefined" && typeof x.match !== "undefined";
2987
2983
  }).map(
2988
- (x) => {
2989
- var _a, _b;
2990
- 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"}`;
2991
- }
2984
+ (x) => `${x.path}|${x?.match?.exclude || ""}|${x?.match?.include || ""}|${x.format || "md"}`
2992
2985
  );
2993
2986
  if (hasMatchAndPath.length !== new Set(hasMatchAndPath).size) {
2994
2987
  throw new Error(
@@ -3012,7 +3005,7 @@ var validationCollectionsPathAndMatch = (collections) => {
3012
3005
  );
3013
3006
  }
3014
3007
  const matches = collectionsArr.map(
3015
- (x) => typeof (x == null ? void 0 : x.match) === "object" ? JSON.stringify(x.match) : ""
3008
+ (x) => typeof x?.match === "object" ? JSON.stringify(x.match) : ""
3016
3009
  );
3017
3010
  if (matches.length === new Set(matches).size) {
3018
3011
  return;
@@ -3090,7 +3083,7 @@ var validateField = async (field) => {
3090
3083
  // package.json
3091
3084
  var package_default = {
3092
3085
  name: "@tinacms/graphql",
3093
- version: "1.5.12",
3086
+ version: "1.6.1",
3094
3087
  main: "dist/index.js",
3095
3088
  module: "dist/index.mjs",
3096
3089
  typings: "dist/index.d.ts",
@@ -3116,33 +3109,32 @@ var package_default = {
3116
3109
  types: "pnpm tsc",
3117
3110
  build: "tinacms-scripts build",
3118
3111
  docs: "pnpm typedoc",
3119
- serve: "pnpm nodemon dist/server.js",
3120
3112
  test: "vitest run",
3121
3113
  "test-watch": "vitest"
3122
3114
  },
3123
3115
  dependencies: {
3124
- "@iarna/toml": "^2.2.5",
3116
+ "@iarna/toml": "catalog:",
3125
3117
  "@tinacms/mdx": "workspace:*",
3126
3118
  "@tinacms/schema-tools": "workspace:*",
3127
- "abstract-level": "^1.0.4",
3119
+ "abstract-level": "catalog:",
3128
3120
  "date-fns": "^2.30.0",
3129
- "fast-glob": "^3.3.3",
3130
- "fs-extra": "^11.3.0",
3131
- "glob-parent": "^6.0.2",
3121
+ "fast-glob": "catalog:",
3122
+ "fs-extra": "catalog:",
3123
+ "glob-parent": "catalog:",
3132
3124
  graphql: "15.8.0",
3133
- "gray-matter": "^4.0.3",
3134
- "isomorphic-git": "^1.29.0",
3135
- "js-sha1": "^0.6.0",
3125
+ "gray-matter": "catalog:",
3126
+ "isomorphic-git": "catalog:",
3127
+ "js-sha1": "catalog:",
3136
3128
  "js-yaml": "^3.14.1",
3137
- "jsonpath-plus": "10.1.0",
3138
- "lodash.clonedeep": "^4.5.0",
3139
- "lodash.set": "^4.3.2",
3140
- "lodash.uniqby": "^4.7.0",
3141
- "many-level": "^2.0.0",
3142
- micromatch: "4.0.8",
3143
- "normalize-path": "^3.0.0",
3144
- "readable-stream": "^4.7.0",
3145
- 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:",
3146
3138
  yup: "^0.32.11"
3147
3139
  },
3148
3140
  publishConfig: {
@@ -3157,25 +3149,24 @@ var package_default = {
3157
3149
  "@tinacms/scripts": "workspace:*",
3158
3150
  "@types/cors": "^2.8.17",
3159
3151
  "@types/estree": "^0.0.50",
3160
- "@types/express": "^4.17.21",
3152
+ "@types/express": "catalog:",
3161
3153
  "@types/fs-extra": "^9.0.13",
3162
3154
  "@types/js-yaml": "^3.12.10",
3163
- "@types/lodash.camelcase": "^4.3.9",
3164
- "@types/lodash.upperfirst": "^4.3.9",
3165
- "@types/lru-cache": "^5.1.1",
3166
- "@types/mdast": "^3.0.15",
3167
- "@types/micromatch": "^4.0.9",
3155
+ "@types/lodash.camelcase": "catalog:",
3156
+ "@types/lodash.upperfirst": "catalog:",
3157
+ "@types/lru-cache": "catalog:",
3158
+ "@types/mdast": "catalog:",
3159
+ "@types/micromatch": "catalog:",
3168
3160
  "@types/node": "^22.13.1",
3169
- "@types/normalize-path": "^3.0.2",
3170
- "@types/ws": "^7.4.7",
3161
+ "@types/normalize-path": "catalog:",
3162
+ "@types/ws": "catalog:",
3171
3163
  "@types/yup": "^0.29.14",
3172
3164
  "jest-file-snapshot": "^0.5.0",
3173
- "memory-level": "^1.0.0",
3174
- nodemon: "3.1.4",
3165
+ "memory-level": "catalog:",
3175
3166
  typescript: "^5.7.3",
3176
3167
  vite: "^4.5.9",
3177
3168
  vitest: "^0.32.4",
3178
- zod: "^3.24.2"
3169
+ zod: "catalog:"
3179
3170
  }
3180
3171
  };
3181
3172
 
@@ -3257,7 +3248,6 @@ var _buildQueries = async (builder, tinaSchema) => {
3257
3248
  const operationsDefinitions = [];
3258
3249
  const collections = tinaSchema.getCollections();
3259
3250
  await sequential(collections, async (collection) => {
3260
- var _a, _b, _c;
3261
3251
  const queryName = NAMER.queryName(collection.namespace);
3262
3252
  const queryListName = NAMER.generateQueryListName(collection.namespace);
3263
3253
  const queryFilterTypeName = NAMER.dataFilterTypeName(collection.namespace);
@@ -3272,7 +3262,7 @@ var _buildQueries = async (builder, tinaSchema) => {
3272
3262
  filterType: queryFilterTypeName,
3273
3263
  // look for flag to see if the data layer is enabled
3274
3264
  dataLayer: Boolean(
3275
- (_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")
3276
3266
  )
3277
3267
  })
3278
3268
  );
@@ -3332,7 +3322,9 @@ var _buildSchema = async (builder, tinaSchema) => {
3332
3322
  await builder.buildCreateCollectionFolderMutation()
3333
3323
  );
3334
3324
  await sequential(collections, async (collection) => {
3335
- queryTypeDefinitionFields.push(await builder.collectionDocument(collection));
3325
+ queryTypeDefinitionFields.push(
3326
+ await builder.collectionDocument(collection)
3327
+ );
3336
3328
  if (collection.isAuthCollection) {
3337
3329
  queryTypeDefinitionFields.push(
3338
3330
  await builder.authenticationCollectionDocument(collection)
@@ -3382,251 +3374,11 @@ var import_graphql5 = require("graphql");
3382
3374
  // src/resolver/index.ts
3383
3375
  var import_path3 = __toESM(require("path"));
3384
3376
  var import_isValid = __toESM(require("date-fns/isValid/index.js"));
3377
+ var import_jsonpath_plus2 = require("jsonpath-plus");
3385
3378
 
3386
3379
  // src/mdx/index.ts
3387
3380
  var import_mdx = require("@tinacms/mdx");
3388
3381
 
3389
- // src/resolver/index.ts
3390
- var import_jsonpath_plus2 = require("jsonpath-plus");
3391
-
3392
- // src/resolver/error.ts
3393
- var TinaGraphQLError = class extends Error {
3394
- constructor(message, extensions) {
3395
- super(message);
3396
- if (!this.name) {
3397
- Object.defineProperty(this, "name", { value: "TinaGraphQLError" });
3398
- }
3399
- this.extensions = { ...extensions };
3400
- }
3401
- };
3402
- var TinaFetchError = class extends Error {
3403
- constructor(message, args) {
3404
- super(message);
3405
- this.name = "TinaFetchError";
3406
- this.collection = args.collection;
3407
- this.stack = args.stack;
3408
- this.file = args.file;
3409
- this.originalError = args.originalError;
3410
- }
3411
- };
3412
- var TinaQueryError = class extends TinaFetchError {
3413
- constructor(args) {
3414
- super(
3415
- `Error querying file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
3416
- args
3417
- );
3418
- }
3419
- };
3420
- var TinaParseDocumentError = class extends TinaFetchError {
3421
- constructor(args) {
3422
- super(
3423
- `Error parsing file ${args.file} from collection ${args.collection}. ${auditMessage(args.includeAuditMessage)}`,
3424
- args
3425
- );
3426
- }
3427
- toString() {
3428
- return super.toString() + "\n OriginalError: \n" + this.originalError.toString();
3429
- }
3430
- };
3431
- var auditMessage = (includeAuditMessage = true) => includeAuditMessage ? `Please run "tinacms audit" or add the --verbose option for more info` : "";
3432
- var handleFetchErrorError = (e, verbose) => {
3433
- if (e instanceof Error) {
3434
- if (e instanceof TinaFetchError) {
3435
- if (verbose) {
3436
- console.log(e.toString());
3437
- console.log(e);
3438
- console.log(e.stack);
3439
- }
3440
- }
3441
- } else {
3442
- console.error(e);
3443
- }
3444
- throw e;
3445
- };
3446
-
3447
- // src/resolver/filter-utils.ts
3448
- var resolveReferences = async (filter, fields, resolver) => {
3449
- for (const fieldKey of Object.keys(filter)) {
3450
- const fieldDefinition = fields.find(
3451
- (f) => f.name === fieldKey
3452
- );
3453
- if (fieldDefinition) {
3454
- if (fieldDefinition.type === "reference") {
3455
- const { edges, values } = await resolver(filter, fieldDefinition);
3456
- if (edges.length === 1) {
3457
- filter[fieldKey] = {
3458
- eq: values[0]
3459
- };
3460
- } else if (edges.length > 1) {
3461
- filter[fieldKey] = {
3462
- in: values
3463
- };
3464
- } else {
3465
- filter[fieldKey] = {
3466
- eq: "___null___"
3467
- };
3468
- }
3469
- } else if (fieldDefinition.type === "object") {
3470
- if (fieldDefinition.templates) {
3471
- for (const templateName of Object.keys(filter[fieldKey])) {
3472
- const template = fieldDefinition.templates.find(
3473
- (template2) => !(typeof template2 === "string") && template2.name === templateName
3474
- );
3475
- if (template) {
3476
- await resolveReferences(
3477
- filter[fieldKey][templateName],
3478
- template.fields,
3479
- resolver
3480
- );
3481
- } else {
3482
- throw new Error(`Template ${templateName} not found`);
3483
- }
3484
- }
3485
- } else {
3486
- await resolveReferences(
3487
- filter[fieldKey],
3488
- fieldDefinition.fields,
3489
- resolver
3490
- );
3491
- }
3492
- }
3493
- } else {
3494
- throw new Error(`Unable to find field ${fieldKey}`);
3495
- }
3496
- }
3497
- };
3498
- var collectConditionsForChildFields = (filterNode, fields, pathExpression, collectCondition) => {
3499
- for (const childFieldName of Object.keys(filterNode)) {
3500
- const childField = fields.find((field) => field.name === childFieldName);
3501
- if (!childField) {
3502
- throw new Error(`Unable to find type for field ${childFieldName}`);
3503
- }
3504
- collectConditionsForField(
3505
- childFieldName,
3506
- childField,
3507
- filterNode[childFieldName],
3508
- pathExpression,
3509
- collectCondition
3510
- );
3511
- }
3512
- };
3513
- var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
3514
- if (field.list && field.templates) {
3515
- for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
3516
- const template = field.templates.find(
3517
- (template2) => !(typeof template2 === "string") && template2.name === filterKey
3518
- );
3519
- const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
3520
- const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
3521
- collectConditionsForChildFields(
3522
- childFilterNode,
3523
- template.fields,
3524
- filterPath,
3525
- collectCondition
3526
- );
3527
- }
3528
- } else {
3529
- const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
3530
- const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
3531
- collectConditionsForChildFields(
3532
- filterNode,
3533
- field.fields,
3534
- filterPath,
3535
- collectCondition
3536
- );
3537
- }
3538
- };
3539
- var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
3540
- if (field.type === "object") {
3541
- collectConditionsForObjectField(
3542
- fieldName,
3543
- field,
3544
- filterNode,
3545
- pathExpression,
3546
- collectCondition
3547
- );
3548
- } else {
3549
- collectCondition({
3550
- filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
3551
- filterExpression: {
3552
- _type: field.type,
3553
- _list: !!field.list,
3554
- ...filterNode
3555
- }
3556
- });
3557
- }
3558
- };
3559
-
3560
- // src/resolver/media-utils.ts
3561
- var resolveMediaCloudToRelative = (value, config = { useRelativeMedia: true }, schema) => {
3562
- if (config && value) {
3563
- if (config.useRelativeMedia === true) {
3564
- return value;
3565
- }
3566
- if (hasTinaMediaConfig(schema) === true) {
3567
- const assetsURL = `https://${config.assetsHost}/${config.clientId}`;
3568
- if (typeof value === "string" && value.includes(assetsURL)) {
3569
- const cleanMediaRoot = cleanUpSlashes(
3570
- schema.config.media.tina.mediaRoot
3571
- );
3572
- const strippedURL = value.replace(assetsURL, "");
3573
- return `${cleanMediaRoot}${strippedURL}`;
3574
- }
3575
- if (Array.isArray(value)) {
3576
- return value.map((v) => {
3577
- if (!v || typeof v !== "string") return v;
3578
- const cleanMediaRoot = cleanUpSlashes(
3579
- schema.config.media.tina.mediaRoot
3580
- );
3581
- const strippedURL = v.replace(assetsURL, "");
3582
- return `${cleanMediaRoot}${strippedURL}`;
3583
- });
3584
- }
3585
- return value;
3586
- }
3587
- return value;
3588
- } else {
3589
- return value;
3590
- }
3591
- };
3592
- var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, schema) => {
3593
- if (config && value) {
3594
- if (config.useRelativeMedia === true) {
3595
- return value;
3596
- }
3597
- if (hasTinaMediaConfig(schema) === true) {
3598
- const cleanMediaRoot = cleanUpSlashes(schema.config.media.tina.mediaRoot);
3599
- if (typeof value === "string") {
3600
- const strippedValue = value.replace(cleanMediaRoot, "");
3601
- return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3602
- }
3603
- if (Array.isArray(value)) {
3604
- return value.map((v) => {
3605
- if (!v || typeof v !== "string") return v;
3606
- const strippedValue = v.replace(cleanMediaRoot, "");
3607
- return `https://${config.assetsHost}/${config.clientId}${strippedValue}`;
3608
- });
3609
- }
3610
- }
3611
- return value;
3612
- } else {
3613
- return value;
3614
- }
3615
- };
3616
- var cleanUpSlashes = (path7) => {
3617
- if (path7) {
3618
- return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
3619
- }
3620
- return "";
3621
- };
3622
- var hasTinaMediaConfig = (schema) => {
3623
- var _a, _b, _c, _d, _e, _f, _g, _h;
3624
- if (!((_b = (_a = schema.config) == null ? void 0 : _a.media) == null ? void 0 : _b.tina)) return false;
3625
- 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")
3626
- return false;
3627
- return true;
3628
- };
3629
-
3630
3382
  // src/resolver/index.ts
3631
3383
  var import_graphql3 = require("graphql");
3632
3384
 
@@ -3648,7 +3400,9 @@ var LevelProxyHandler = {
3648
3400
  throw new Error(`The property, ${property.toString()}, doesn't exist`);
3649
3401
  }
3650
3402
  if (typeof target[property] !== "function") {
3651
- 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
+ );
3652
3406
  }
3653
3407
  if (property === "get") {
3654
3408
  return async (...args) => {
@@ -3686,11 +3440,11 @@ var import_path2 = __toESM(require("path"));
3686
3440
 
3687
3441
  // src/database/util.ts
3688
3442
  var import_toml = __toESM(require("@iarna/toml"));
3689
- var import_js_yaml = __toESM(require("js-yaml"));
3690
- var import_gray_matter = __toESM(require("gray-matter"));
3691
3443
  var import_schema_tools4 = require("@tinacms/schema-tools");
3692
- var import_micromatch = __toESM(require("micromatch"));
3444
+ var import_gray_matter = __toESM(require("gray-matter"));
3445
+ var import_js_yaml = __toESM(require("js-yaml"));
3693
3446
  var import_path = __toESM(require("path"));
3447
+ var import_micromatch = __toESM(require("micromatch"));
3694
3448
 
3695
3449
  // src/database/alias-utils.ts
3696
3450
  var replaceBlockAliases = (template, item) => {
@@ -3727,22 +3481,20 @@ var replaceNameOverrides = (template, obj) => {
3727
3481
  }
3728
3482
  };
3729
3483
  function isBlockField(field) {
3730
- var _a;
3731
- return field && field.type === "object" && ((_a = field.templates) == null ? void 0 : _a.length) > 0;
3484
+ return field && field.type === "object" && field.templates?.length > 0;
3732
3485
  }
3733
3486
  var _replaceNameOverrides = (fields, obj) => {
3734
3487
  const output = {};
3735
3488
  Object.keys(obj).forEach((key) => {
3736
3489
  const field = fields.find(
3737
- (fieldWithMatchingAlias) => ((fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.nameOverride) || (fieldWithMatchingAlias == null ? void 0 : fieldWithMatchingAlias.name)) === key
3490
+ (fieldWithMatchingAlias) => (fieldWithMatchingAlias?.nameOverride || fieldWithMatchingAlias?.name) === key
3738
3491
  );
3739
- 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];
3740
3493
  });
3741
3494
  return output;
3742
3495
  };
3743
3496
  var getTemplateForData = (field, data) => {
3744
- var _a;
3745
- if ((_a = field.templates) == null ? void 0 : _a.length) {
3497
+ if (field.templates?.length) {
3746
3498
  const templateKey = "_template";
3747
3499
  if (data[templateKey]) {
3748
3500
  const result = field.templates.find(
@@ -3800,8 +3552,8 @@ var _applyNameOverrides = (fields, obj) => {
3800
3552
  const output = {};
3801
3553
  Object.keys(obj).forEach((key) => {
3802
3554
  const field = fields.find((field2) => field2.name === key);
3803
- const outputKey = (field == null ? void 0 : field.nameOverride) || key;
3804
- 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];
3805
3557
  });
3806
3558
  return output;
3807
3559
  };
@@ -3814,7 +3566,6 @@ var matterEngines = {
3814
3566
  }
3815
3567
  };
3816
3568
  var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3817
- var _a, _b;
3818
3569
  const {
3819
3570
  _relativePath,
3820
3571
  _keepTemplateKey,
@@ -3838,9 +3589,9 @@ var stringifyFile = (content, format, keepTemplateKey, markdownParseConfig) => {
3838
3589
  ${$_body}`,
3839
3590
  strippedContent,
3840
3591
  {
3841
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3592
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3842
3593
  engines: matterEngines,
3843
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---"
3594
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---"
3844
3595
  }
3845
3596
  );
3846
3597
  return ok;
@@ -3856,15 +3607,14 @@ ${$_body}`,
3856
3607
  }
3857
3608
  };
3858
3609
  var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3859
- var _a, _b;
3860
3610
  try {
3861
3611
  switch (format) {
3862
3612
  case ".markdown":
3863
3613
  case ".mdx":
3864
3614
  case ".md":
3865
3615
  const contentJSON = (0, import_gray_matter.default)(content || "", {
3866
- language: (_a = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterFormat) != null ? _a : "yaml",
3867
- delimiters: (_b = markdownParseConfig == null ? void 0 : markdownParseConfig.frontmatterDelimiters) != null ? _b : "---",
3616
+ language: markdownParseConfig?.frontmatterFormat ?? "yaml",
3617
+ delimiters: markdownParseConfig?.frontmatterDelimiters ?? "---",
3868
3618
  engines: matterEngines
3869
3619
  });
3870
3620
  const markdownData = {
@@ -3963,7 +3713,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3963
3713
  ),
3964
3714
  template: void 0
3965
3715
  } : tinaSchema.getCollectionAndTemplateByFullPath(filepath, templateName);
3966
- const field = template == null ? void 0 : template.fields.find((field2) => {
3716
+ const field = template?.fields.find((field2) => {
3967
3717
  if (field2.type === "string" || field2.type === "rich-text") {
3968
3718
  if (field2.isBody) {
3969
3719
  return true;
@@ -3983,7 +3733,7 @@ var transformDocument = (filepath, contentObject, tinaSchema) => {
3983
3733
  ...data,
3984
3734
  _collection: collection.name,
3985
3735
  _keepTemplateKey: !!collection.templates,
3986
- _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,
3987
3737
  _relativePath: filepath.replace(collection.path, "").replace(/^\/|\/$/g, ""),
3988
3738
  _id: filepath
3989
3739
  };
@@ -3992,10 +3742,10 @@ function hasOwnProperty(obj, prop) {
3992
3742
  return obj.hasOwnProperty(prop);
3993
3743
  }
3994
3744
  var getTemplateForFile = (templateInfo, data) => {
3995
- if ((templateInfo == null ? void 0 : templateInfo.type) === "object") {
3745
+ if (templateInfo?.type === "object") {
3996
3746
  return templateInfo.template;
3997
3747
  }
3998
- if ((templateInfo == null ? void 0 : templateInfo.type) === "union") {
3748
+ if (templateInfo?.type === "union") {
3999
3749
  if (hasOwnProperty(data, "_template")) {
4000
3750
  const template = templateInfo.templates.find(
4001
3751
  (t) => lastItem(t.namespace) === data._template
@@ -4019,8 +3769,8 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
4019
3769
  import_path.default.extname(filepath),
4020
3770
  (yup3) => yup3.object({}),
4021
3771
  {
4022
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
4023
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
3772
+ frontmatterDelimiters: collection?.frontmatterDelimiters,
3773
+ frontmatterFormat: collection?.frontmatterFormat
4024
3774
  }
4025
3775
  );
4026
3776
  const template = getTemplateForFile(templateInfo, data);
@@ -4035,6 +3785,9 @@ var loadAndParseWithAliases = async (bridge, filepath, collection, templateInfo)
4035
3785
 
4036
3786
  // src/database/datalayer.ts
4037
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__";
4038
3791
  var DEFAULT_NUMERIC_LPAD = 4;
4039
3792
  var applyPadding = (input, pad) => {
4040
3793
  if (pad) {
@@ -4608,6 +4361,57 @@ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opT
4608
4361
  }
4609
4362
  return result;
4610
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
+ };
4611
4415
  var makeStringEscaper = (regex, replacement) => {
4612
4416
  return (input) => {
4613
4417
  if (Array.isArray(input)) {
@@ -4623,17 +4427,252 @@ var makeStringEscaper = (regex, replacement) => {
4623
4427
  }
4624
4428
  };
4625
4429
  };
4626
- var stringEscaper = makeStringEscaper(
4627
- new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"),
4628
- encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR)
4629
- );
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;
4669
+ };
4630
4670
 
4631
4671
  // src/resolver/index.ts
4632
4672
  var createResolver = (args) => {
4633
4673
  return new Resolver(args);
4634
4674
  };
4635
4675
  var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tinaSchema, config, isAudit) => {
4636
- var _a, _b;
4637
4676
  if (!rawData) {
4638
4677
  return void 0;
4639
4678
  }
@@ -4661,7 +4700,7 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4661
4700
  accumulator[field.name] = {
4662
4701
  value: void 0,
4663
4702
  // never resolve the password hash
4664
- passwordChangeRequired: (_a = value["passwordChangeRequired"]) != null ? _a : false
4703
+ passwordChangeRequired: value["passwordChangeRequired"] ?? false
4665
4704
  };
4666
4705
  break;
4667
4706
  case "image":
@@ -4677,11 +4716,11 @@ var resolveFieldData = async ({ namespace, ...field }, rawData, accumulator, tin
4677
4716
  field,
4678
4717
  (value2) => resolveMediaRelativeToCloud(value2, config, tinaSchema.schema)
4679
4718
  );
4680
- if (((_b = tree == null ? void 0 : tree.children[0]) == null ? void 0 : _b.type) === "invalid_markdown") {
4719
+ if (tree?.children[0]?.type === "invalid_markdown") {
4681
4720
  if (isAudit) {
4682
- const invalidNode = tree == null ? void 0 : tree.children[0];
4721
+ const invalidNode = tree?.children[0];
4683
4722
  throw new import_graphql3.GraphQLError(
4684
- `${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}` : ""}`
4685
4724
  );
4686
4725
  }
4687
4726
  }
@@ -4789,16 +4828,15 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4789
4828
  originalError: e,
4790
4829
  collection: collection.name,
4791
4830
  includeAuditMessage: !isAudit,
4792
- file: relativePath,
4793
- stack: e.stack
4831
+ file: relativePath
4794
4832
  });
4795
4833
  }
4796
4834
  const titleField = template.fields.find((x) => {
4797
- if (x.type === "string" && (x == null ? void 0 : x.isTitle)) {
4835
+ if (x.type === "string" && x?.isTitle) {
4798
4836
  return true;
4799
4837
  }
4800
4838
  });
4801
- const titleFieldName = titleField == null ? void 0 : titleField.name;
4839
+ const titleFieldName = titleField?.name;
4802
4840
  const title = data[titleFieldName || " "] || null;
4803
4841
  return {
4804
4842
  __typename: collection.fields ? NAMER.documentTypeName(collection.namespace) : NAMER.documentTypeName(template.namespace),
@@ -4829,24 +4867,33 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4829
4867
  throw e;
4830
4868
  }
4831
4869
  };
4832
- var updateObjectWithJsonPath = (obj, path7, newValue) => {
4870
+ var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4871
+ let updated = false;
4833
4872
  if (!path7.includes(".") && !path7.includes("[")) {
4834
- if (path7 in obj) {
4873
+ if (path7 in obj && obj[path7] === oldValue) {
4835
4874
  obj[path7] = newValue;
4875
+ updated = true;
4836
4876
  }
4837
- return obj;
4838
- }
4839
- const parentPath = path7.replace(/\.[^.]+$/, "");
4840
- const keyToUpdate = path7.match(/[^.]+$/)[0];
4841
- 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
+ });
4842
4886
  if (parents.length > 0) {
4843
4887
  parents.forEach((parent) => {
4844
4888
  if (parent && typeof parent === "object" && keyToUpdate in parent) {
4845
- parent[keyToUpdate] = newValue;
4889
+ if (parent[keyToUpdate] === oldValue) {
4890
+ parent[keyToUpdate] = newValue;
4891
+ updated = true;
4892
+ }
4846
4893
  }
4847
4894
  });
4848
4895
  }
4849
- return obj;
4896
+ return { object: obj, updated };
4850
4897
  };
4851
4898
  var Resolver = class {
4852
4899
  constructor(init) {
@@ -4863,7 +4910,9 @@ var Resolver = class {
4863
4910
  };
4864
4911
  this.getRaw = async (fullPath) => {
4865
4912
  if (typeof fullPath !== "string") {
4866
- 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
+ );
4867
4916
  }
4868
4917
  return this.database.get(fullPath);
4869
4918
  };
@@ -4892,10 +4941,12 @@ var Resolver = class {
4892
4941
  };
4893
4942
  this.getDocument = async (fullPath, opts = {}) => {
4894
4943
  if (typeof fullPath !== "string") {
4895
- 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
+ );
4896
4947
  }
4897
4948
  const rawData = await this.getRaw(fullPath);
4898
- 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;
4899
4950
  return transformDocumentIntoPayload(
4900
4951
  fullPath,
4901
4952
  rawData,
@@ -4907,7 +4958,9 @@ var Resolver = class {
4907
4958
  };
4908
4959
  this.deleteDocument = async (fullPath) => {
4909
4960
  if (typeof fullPath !== "string") {
4910
- 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
+ );
4911
4964
  }
4912
4965
  await this.database.delete(fullPath);
4913
4966
  };
@@ -4933,9 +4986,9 @@ var Resolver = class {
4933
4986
  return this.buildFieldMutations(
4934
4987
  item,
4935
4988
  objectTemplate,
4936
- idField && existingData && (existingData == null ? void 0 : existingData.find(
4989
+ idField && existingData && existingData?.find(
4937
4990
  (d) => d[idField.name] === item[idField.name]
4938
- ))
4991
+ )
4939
4992
  );
4940
4993
  }
4941
4994
  )
@@ -5061,7 +5114,7 @@ var Resolver = class {
5061
5114
  isCollectionSpecific
5062
5115
  }) => {
5063
5116
  const doc = await this.getDocument(realPath);
5064
- const oldDoc = this.resolveLegacyValues((doc == null ? void 0 : doc._rawData) || {}, collection);
5117
+ const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5065
5118
  if (isAddPendingDocument === true) {
5066
5119
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5067
5120
  const params2 = this.buildParams(args);
@@ -5071,7 +5124,7 @@ var Resolver = class {
5071
5124
  const values = await this.buildFieldMutations(
5072
5125
  params2,
5073
5126
  templateInfo.template,
5074
- doc == null ? void 0 : doc._rawData
5127
+ doc?._rawData
5075
5128
  );
5076
5129
  await this.database.put(
5077
5130
  realPath,
@@ -5095,7 +5148,7 @@ var Resolver = class {
5095
5148
  // @ts-ignore FIXME: failing on unknown, which we don't need to know because it's recursive
5096
5149
  templateParams,
5097
5150
  template,
5098
- doc == null ? void 0 : doc._rawData
5151
+ doc?._rawData
5099
5152
  ),
5100
5153
  _template: lastItem(template.namespace)
5101
5154
  };
@@ -5109,9 +5162,13 @@ var Resolver = class {
5109
5162
  //@ts-ignore
5110
5163
  isCollectionSpecific ? args.params : args.params[collection.name],
5111
5164
  collection,
5112
- doc == null ? void 0 : doc._rawData
5165
+ doc?._rawData
5166
+ );
5167
+ await this.database.put(
5168
+ realPath,
5169
+ { ...oldDoc, ...params },
5170
+ collection.name
5113
5171
  );
5114
- await this.database.put(realPath, { ...oldDoc, ...params }, collection.name);
5115
5172
  return this.getDocument(realPath);
5116
5173
  };
5117
5174
  /**
@@ -5121,7 +5178,6 @@ var Resolver = class {
5121
5178
  this.resolveLegacyValues = (oldDoc, collection) => {
5122
5179
  const legacyValues = {};
5123
5180
  Object.entries(oldDoc).forEach(([key, value]) => {
5124
- var _a;
5125
5181
  const reservedKeys = [
5126
5182
  "$_body",
5127
5183
  "_collection",
@@ -5134,7 +5190,7 @@ var Resolver = class {
5134
5190
  return;
5135
5191
  }
5136
5192
  if (oldDoc._template && collection.templates) {
5137
- const template = (_a = collection.templates) == null ? void 0 : _a.find(
5193
+ const template = collection.templates?.find(
5138
5194
  ({ name }) => name === oldDoc._template
5139
5195
  );
5140
5196
  if (template) {
@@ -5181,7 +5237,7 @@ var Resolver = class {
5181
5237
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5182
5238
  );
5183
5239
  const collection = await this.tinaSchema.getCollection(collectionLookup);
5184
- 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);
5185
5241
  if (isFolderCreation) {
5186
5242
  realPath = `${realPath}/.gitkeep.${collection.format || "md"}`;
5187
5243
  }
@@ -5225,17 +5281,35 @@ var Resolver = class {
5225
5281
  await this.deleteDocument(realPath);
5226
5282
  if (await this.hasReferences(realPath, collection)) {
5227
5283
  const collRefs = await this.findReferences(realPath, collection);
5228
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5229
- for (const [refPath, refs] of Object.entries(refFields)) {
5230
- let refDoc = await this.getRaw(refPath);
5231
- for (const ref of refs) {
5232
- 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(
5233
5292
  refDoc,
5234
- ref.path.join("."),
5293
+ path7,
5294
+ realPath,
5235
5295
  null
5236
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
+ );
5237
5312
  }
5238
- await this.database.put(refPath, refDoc, collection2);
5239
5313
  }
5240
5314
  }
5241
5315
  }
@@ -5247,12 +5321,12 @@ var Resolver = class {
5247
5321
  (yup3) => yup3.object({ params: yup3.object().required() })
5248
5322
  );
5249
5323
  assertShape(
5250
- args == null ? void 0 : args.params,
5324
+ args?.params,
5251
5325
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5252
5326
  );
5253
5327
  const doc = await this.getDocument(realPath);
5254
5328
  const newRealPath = import_path3.default.join(
5255
- collection == null ? void 0 : collection.path,
5329
+ collection?.path,
5256
5330
  args.params.relativePath
5257
5331
  );
5258
5332
  if (newRealPath === realPath) {
@@ -5261,23 +5335,43 @@ var Resolver = class {
5261
5335
  await this.database.put(newRealPath, doc._rawData, collection.name);
5262
5336
  await this.deleteDocument(realPath);
5263
5337
  const collRefs = await this.findReferences(realPath, collection);
5264
- for (const [collection2, refFields] of Object.entries(collRefs)) {
5265
- for (const [refPath, refs] of Object.entries(refFields)) {
5266
- let refDoc = await this.getRaw(refPath);
5267
- for (const ref of refs) {
5268
- refDoc = updateObjectWithJsonPath(
5269
- refDoc,
5270
- 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,
5271
5349
  newRealPath
5272
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
+ );
5273
5366
  }
5274
- await this.database.put(refPath, refDoc, collection2);
5275
5367
  }
5276
5368
  }
5277
5369
  return this.getDocument(newRealPath);
5278
5370
  }
5279
5371
  if (alreadyExists === false) {
5280
- 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
+ );
5281
5375
  }
5282
5376
  return this.updateResolveDocument({
5283
5377
  collection,
@@ -5403,35 +5497,30 @@ var Resolver = class {
5403
5497
  */
5404
5498
  this.hasReferences = async (id, c) => {
5405
5499
  let count = 0;
5406
- const deepRefs = this.tinaSchema.findReferences(c.name);
5407
- for (const [collection, refs] of Object.entries(deepRefs)) {
5408
- for (const ref of refs) {
5409
- await this.database.query(
5410
- {
5411
- collection,
5412
- filterChain: makeFilterChain({
5413
- conditions: [
5414
- {
5415
- filterPath: ref.path.join("."),
5416
- filterExpression: {
5417
- _type: "reference",
5418
- _list: false,
5419
- eq: id
5420
- }
5421
- }
5422
- ]
5423
- }),
5424
- sort: ref.field.name
5425
- },
5426
- (refId) => {
5427
- count++;
5428
- return refId;
5429
- }
5430
- );
5431
- if (count) {
5432
- return true;
5433
- }
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;
5434
5520
  }
5521
+ );
5522
+ if (count) {
5523
+ return true;
5435
5524
  }
5436
5525
  return false;
5437
5526
  };
@@ -5439,50 +5528,44 @@ var Resolver = class {
5439
5528
  * Finds references to a document
5440
5529
  * @param id the id of the document to find references to
5441
5530
  * @param c the collection to find references in
5442
- * @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
5443
5532
  */
5444
5533
  this.findReferences = async (id, c) => {
5445
5534
  const references = {};
5446
- const deepRefs = this.tinaSchema.findReferences(c.name);
5447
- for (const [collection, refs] of Object.entries(deepRefs)) {
5448
- for (const ref of refs) {
5449
- await this.database.query(
5450
- {
5451
- collection,
5452
- filterChain: makeFilterChain({
5453
- conditions: [
5454
- {
5455
- filterPath: ref.path.join("."),
5456
- filterExpression: {
5457
- _type: "reference",
5458
- _list: false,
5459
- eq: id
5460
- }
5461
- }
5462
- ]
5463
- }),
5464
- sort: ref.field.name
5465
- },
5466
- (refId) => {
5467
- if (!references[collection]) {
5468
- references[collection] = {};
5469
- }
5470
- if (!references[collection][refId]) {
5471
- 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
+ }
5472
5547
  }
5473
- references[collection][refId].push({
5474
- path: ref.path,
5475
- field: ref.field
5476
- });
5477
- return refId;
5478
- }
5479
- );
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;
5480
5564
  }
5481
- }
5565
+ );
5482
5566
  return references;
5483
5567
  };
5484
5568
  this.buildFieldMutations = async (fieldParams, template, existingData) => {
5485
- var _a;
5486
5569
  const accum = {};
5487
5570
  for (const passwordField of template.fields.filter(
5488
5571
  (f) => f.type === "password"
@@ -5525,7 +5608,7 @@ var Resolver = class {
5525
5608
  accum[fieldName] = await this.buildObjectMutations(
5526
5609
  fieldValue,
5527
5610
  field,
5528
- existingData == null ? void 0 : existingData[fieldName]
5611
+ existingData?.[fieldName]
5529
5612
  );
5530
5613
  break;
5531
5614
  case "password":
@@ -5544,12 +5627,12 @@ var Resolver = class {
5544
5627
  } else {
5545
5628
  accum[fieldName] = {
5546
5629
  ...fieldValue,
5547
- value: (_a = existingData == null ? void 0 : existingData[fieldName]) == null ? void 0 : _a["value"]
5630
+ value: existingData?.[fieldName]?.["value"]
5548
5631
  };
5549
5632
  }
5550
5633
  break;
5551
5634
  case "rich-text":
5552
- accum[fieldName] = (0, import_mdx.stringifyMDX)(
5635
+ accum[fieldName] = (0, import_mdx.serializeMDX)(
5553
5636
  fieldValue,
5554
5637
  field,
5555
5638
  (fieldValue2) => resolveMediaCloudToRelative(
@@ -5656,8 +5739,129 @@ var resolveDateInput = (value) => {
5656
5739
  return date;
5657
5740
  };
5658
5741
 
5659
- // src/resolve.ts
5742
+ // src/resolver/auth-fields.ts
5660
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
+ }
5661
5865
 
5662
5866
  // src/error.ts
5663
5867
  var import_graphql4 = require("graphql");
@@ -5679,9 +5883,8 @@ var resolve = async ({
5679
5883
  isAudit,
5680
5884
  ctxUser
5681
5885
  }) => {
5682
- var _a;
5683
5886
  try {
5684
- const verboseValue = verbose != null ? verbose : true;
5887
+ const verboseValue = verbose ?? true;
5685
5888
  const graphQLSchemaAst = await database.getGraphQLSchema();
5686
5889
  if (!graphQLSchemaAst) {
5687
5890
  throw new import_graphql5.GraphQLError("GraphQL schema not found");
@@ -5693,7 +5896,7 @@ var resolve = async ({
5693
5896
  // @ts-ignore
5694
5897
  schema: tinaConfig,
5695
5898
  // @ts-ignore
5696
- flags: (_a = tinaConfig == null ? void 0 : tinaConfig.meta) == null ? void 0 : _a.flags
5899
+ flags: tinaConfig?.meta?.flags
5697
5900
  });
5698
5901
  const resolver = createResolver({
5699
5902
  config,
@@ -5718,7 +5921,6 @@ var resolve = async ({
5718
5921
  throw new Error(`Unable to find lookup key for ${namedType}`);
5719
5922
  },
5720
5923
  fieldResolver: async (source = {}, _args = {}, _context, info) => {
5721
- var _a2, _b, _c, _d;
5722
5924
  try {
5723
5925
  const args = JSON.parse(JSON.stringify(_args));
5724
5926
  const returnType = (0, import_graphql5.getNamedType)(info.returnType).toString();
@@ -5735,8 +5937,7 @@ var resolve = async ({
5735
5937
  );
5736
5938
  const hasDocuments2 = collectionNode2.selectionSet.selections.find(
5737
5939
  (x) => {
5738
- var _a3;
5739
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5940
+ return x?.name?.value === "documents";
5740
5941
  }
5741
5942
  );
5742
5943
  return tinaSchema.getCollections().map((collection) => {
@@ -5752,8 +5953,7 @@ var resolve = async ({
5752
5953
  );
5753
5954
  const hasDocuments = collectionNode.selectionSet.selections.find(
5754
5955
  (x) => {
5755
- var _a3;
5756
- return ((_a3 = x == null ? void 0 : x.name) == null ? void 0 : _a3.value) === "documents";
5956
+ return x?.name?.value === "documents";
5757
5957
  }
5758
5958
  );
5759
5959
  return resolver.resolveCollection(
@@ -5771,119 +5971,33 @@ var resolve = async ({
5771
5971
  );
5772
5972
  }
5773
5973
  }
5774
- if (info.fieldName === "authenticate" || info.fieldName === "authorize") {
5775
- const sub = args.sub || (ctxUser == null ? void 0 : ctxUser.sub);
5776
- const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5777
- if (!collection) {
5778
- throw new Error("Auth collection not found");
5779
- }
5780
- const userFields = mapUserFields(collection, ["_rawData"]);
5781
- if (!userFields.length) {
5782
- throw new Error(
5783
- `No user field found in collection ${collection.name}`
5784
- );
5785
- }
5786
- if (userFields.length > 1) {
5787
- throw new Error(
5788
- `Multiple user fields found in collection ${collection.name}`
5789
- );
5790
- }
5791
- const userField = userFields[0];
5792
- const realPath = `${collection.path}/index.json`;
5793
- const userDoc = await resolver.getDocument(realPath);
5794
- const users = get(userDoc, userField.path);
5795
- if (!users) {
5796
- throw new Error("No users found");
5797
- }
5798
- const { idFieldName, passwordFieldName } = userField;
5799
- if (!idFieldName) {
5800
- throw new Error("No uid field found on user field");
5801
- }
5802
- const user = users.find((u) => u[idFieldName] === sub);
5803
- if (!user) {
5804
- return null;
5805
- }
5806
- if (info.fieldName === "authenticate") {
5807
- const saltedHash = get(user, [passwordFieldName || "", "value"]);
5808
- if (!saltedHash) {
5809
- throw new Error("No password field found on user field");
5810
- }
5811
- const matches = await checkPasswordHash({
5812
- saltedHash,
5813
- password: args.password
5814
- });
5815
- if (matches) {
5816
- return user;
5817
- }
5818
- return null;
5819
- }
5820
- 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
+ });
5821
5992
  }
5822
5993
  if (info.fieldName === "updatePassword") {
5823
- if (!(ctxUser == null ? void 0 : ctxUser.sub)) {
5824
- throw new Error("Not authorized");
5825
- }
5826
- if (!args.password) {
5827
- throw new Error("No password provided");
5828
- }
5829
- const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
5830
- if (!collection) {
5831
- throw new Error("Auth collection not found");
5832
- }
5833
- const userFields = mapUserFields(collection, ["_rawData"]);
5834
- if (!userFields.length) {
5835
- throw new Error(
5836
- `No user field found in collection ${collection.name}`
5837
- );
5838
- }
5839
- if (userFields.length > 1) {
5840
- throw new Error(
5841
- `Multiple user fields found in collection ${collection.name}`
5842
- );
5843
- }
5844
- const userField = userFields[0];
5845
- const realPath = `${collection.path}/index.json`;
5846
- const userDoc = await resolver.getDocument(realPath);
5847
- const users = get(userDoc, userField.path);
5848
- if (!users) {
5849
- throw new Error("No users found");
5850
- }
5851
- const { idFieldName, passwordFieldName } = userField;
5852
- const user = users.find((u) => u[idFieldName] === ctxUser.sub);
5853
- if (!user) {
5854
- throw new Error("Not authorized");
5855
- }
5856
- user[passwordFieldName] = {
5857
- value: args.password,
5858
- passwordChangeRequired: false
5859
- };
5860
- const params = {};
5861
- (0, import_lodash4.default)(
5862
- params,
5863
- userField.path.slice(1),
5864
- // remove _rawData from users path
5865
- users.map((u) => {
5866
- if (user[idFieldName] === u[idFieldName]) {
5867
- return user;
5868
- }
5869
- return {
5870
- // don't overwrite other users' passwords
5871
- ...u,
5872
- [passwordFieldName]: {
5873
- ...u[passwordFieldName],
5874
- value: ""
5875
- }
5876
- };
5877
- })
5878
- );
5879
- await resolver.updateResolveDocument({
5880
- collection,
5881
- args: { params },
5882
- realPath,
5883
- isCollectionSpecific: true,
5884
- isAddPendingDocument: false
5994
+ return handleUpdatePassword({
5995
+ tinaSchema,
5996
+ resolver,
5997
+ password: args.password,
5998
+ info,
5999
+ ctxUser
5885
6000
  });
5886
- return true;
5887
6001
  }
5888
6002
  if (!lookup) {
5889
6003
  return value;
@@ -5903,7 +6017,7 @@ var resolve = async ({
5903
6017
  if (typeof value === "string" && value !== "") {
5904
6018
  return resolver.getDocument(value);
5905
6019
  }
5906
- if ((args == null ? void 0 : args.collection) && info.fieldName === "addPendingDocument") {
6020
+ if (args?.collection && info.fieldName === "addPendingDocument") {
5907
6021
  return resolver.resolveDocument({
5908
6022
  args: { ...args, params: {} },
5909
6023
  collection: args.collection,
@@ -5927,7 +6041,7 @@ var resolve = async ({
5927
6041
  // Right now this is the only case for deletion
5928
6042
  isDeletion: info.fieldName === "deleteDocument",
5929
6043
  isFolderCreation: info.fieldName === "createFolder",
5930
- isUpdateName: Boolean((_a2 = args == null ? void 0 : args.params) == null ? void 0 : _a2.relativePath),
6044
+ isUpdateName: Boolean(args?.params?.relativePath),
5931
6045
  isAddPendingDocument: false,
5932
6046
  isCollectionSpecific: false
5933
6047
  });
@@ -5946,16 +6060,16 @@ var resolve = async ({
5946
6060
  })
5947
6061
  };
5948
6062
  }
5949
- 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) {
5950
6064
  let filter = args.filter;
5951
6065
  if (
5952
6066
  // 1. Make sure that the filter exists
5953
- 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
5954
6068
  // @ts-ignore
5955
- 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
5956
6070
  // @ts-ignore
5957
- Object.keys(args.filter).includes((_c = value == null ? void 0 : value.collection) == null ? void 0 : _c.name) && // @ts-ignore
5958
- 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"
5959
6073
  ) {
5960
6074
  filter = args.filter[value.collection.name];
5961
6075
  }
@@ -6092,15 +6206,15 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
6092
6206
  };
6093
6207
 
6094
6208
  // src/database/index.ts
6095
- var import_node_path = __toESM(require("path"));
6209
+ var import_node_path = __toESM(require("node:path"));
6096
6210
  var import_graphql6 = require("graphql");
6097
6211
  var import_micromatch2 = __toESM(require("micromatch"));
6098
6212
  var import_js_sha12 = __toESM(require("js-sha1"));
6099
6213
  var import_lodash5 = __toESM(require("lodash.set"));
6100
6214
  var createLocalDatabase = (config) => {
6101
- const level = new TinaLevelClient(config == null ? void 0 : config.port);
6215
+ const level = new TinaLevelClient(config?.port);
6102
6216
  level.openConnection();
6103
- const fsBridge = new FilesystemBridge((config == null ? void 0 : config.rootPath) || process.cwd());
6217
+ const fsBridge = new FilesystemBridge(config?.rootPath || process.cwd());
6104
6218
  return new Database({
6105
6219
  bridge: fsBridge,
6106
6220
  ...config || {},
@@ -6173,7 +6287,7 @@ var Database = class {
6173
6287
  );
6174
6288
  }
6175
6289
  const metadata = await metadataLevel.get(`metadata_${key}`);
6176
- return metadata == null ? void 0 : metadata.value;
6290
+ return metadata?.value;
6177
6291
  };
6178
6292
  this.setMetadata = async (key, value) => {
6179
6293
  await this.initLevel();
@@ -6195,7 +6309,7 @@ var Database = class {
6195
6309
  let level = this.contentLevel;
6196
6310
  if (this.appLevel) {
6197
6311
  collection = await this.collectionForPath(filepath);
6198
- if (collection == null ? void 0 : collection.isDetached) {
6312
+ if (collection?.isDetached) {
6199
6313
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
6200
6314
  }
6201
6315
  }
@@ -6226,9 +6340,10 @@ var Database = class {
6226
6340
  collection
6227
6341
  );
6228
6342
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6229
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
6343
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6344
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
6230
6345
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6231
- if (!(collection == null ? void 0 : collection.isDetached)) {
6346
+ if (!collection?.isDetached) {
6232
6347
  if (this.bridge) {
6233
6348
  await this.bridge.put(normalizedPath, stringifiedFile);
6234
6349
  }
@@ -6246,7 +6361,7 @@ var Database = class {
6246
6361
  }
6247
6362
  }
6248
6363
  let level = this.contentLevel;
6249
- if (collection == null ? void 0 : collection.isDetached) {
6364
+ if (collection?.isDetached) {
6250
6365
  level = this.appLevel.sublevel(collection.name, SUBLEVEL_OPTIONS);
6251
6366
  }
6252
6367
  const folderTreeBuilder = new FolderTreeBuilder();
@@ -6255,9 +6370,17 @@ var Database = class {
6255
6370
  let delOps = [];
6256
6371
  if (!isGitKeep(normalizedPath, collection)) {
6257
6372
  putOps = [
6373
+ ...makeRefOpsForDocument(
6374
+ normalizedPath,
6375
+ collection?.name,
6376
+ collectionReferences,
6377
+ dataFields,
6378
+ "put",
6379
+ level
6380
+ ),
6258
6381
  ...makeIndexOpsForDocument(
6259
6382
  normalizedPath,
6260
- collection == null ? void 0 : collection.name,
6383
+ collection?.name,
6261
6384
  collectionIndexDefinitions,
6262
6385
  dataFields,
6263
6386
  "put",
@@ -6266,7 +6389,7 @@ var Database = class {
6266
6389
  // folder indices
6267
6390
  ...makeIndexOpsForDocument(
6268
6391
  normalizedPath,
6269
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6392
+ `${collection?.name}_${folderKey}`,
6270
6393
  collectionIndexDefinitions,
6271
6394
  dataFields,
6272
6395
  "put",
@@ -6278,9 +6401,17 @@ var Database = class {
6278
6401
  SUBLEVEL_OPTIONS
6279
6402
  ).get(normalizedPath);
6280
6403
  delOps = existingItem ? [
6404
+ ...makeRefOpsForDocument(
6405
+ normalizedPath,
6406
+ collection?.name,
6407
+ collectionReferences,
6408
+ existingItem,
6409
+ "del",
6410
+ level
6411
+ ),
6281
6412
  ...makeIndexOpsForDocument(
6282
6413
  normalizedPath,
6283
- collection == null ? void 0 : collection.name,
6414
+ collection?.name,
6284
6415
  collectionIndexDefinitions,
6285
6416
  existingItem,
6286
6417
  "del",
@@ -6289,7 +6420,7 @@ var Database = class {
6289
6420
  // folder indices
6290
6421
  ...makeIndexOpsForDocument(
6291
6422
  normalizedPath,
6292
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6423
+ `${collection?.name}_${folderKey}`,
6293
6424
  collectionIndexDefinitions,
6294
6425
  existingItem,
6295
6426
  "del",
@@ -6313,7 +6444,6 @@ var Database = class {
6313
6444
  await level.batch(ops);
6314
6445
  };
6315
6446
  this.put = async (filepath, data, collectionName) => {
6316
- var _a, _b;
6317
6447
  await this.initLevel();
6318
6448
  try {
6319
6449
  if (SYSTEM_FILES.includes(filepath)) {
@@ -6324,15 +6454,16 @@ var Database = class {
6324
6454
  const indexDefinitions = await this.getIndexDefinitions(
6325
6455
  this.contentLevel
6326
6456
  );
6327
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
6457
+ collectionIndexDefinitions = indexDefinitions?.[collectionName];
6328
6458
  }
6459
+ const collectionReferences = (await this.getCollectionReferences())?.[collectionName];
6329
6460
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6330
6461
  const dataFields = await this.formatBodyOnPayload(filepath, data);
6331
6462
  const collection = await this.collectionForPath(filepath);
6332
6463
  if (!collection) {
6333
6464
  throw new import_graphql6.GraphQLError(`Unable to find collection for ${filepath}.`);
6334
6465
  }
6335
- 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) {
6336
6467
  const matches = this.tinaSchema.getMatches({ collection });
6337
6468
  const match = import_micromatch2.default.isMatch(filepath, matches);
6338
6469
  if (!match) {
@@ -6346,7 +6477,7 @@ var Database = class {
6346
6477
  const stringifiedFile = filepath.endsWith(
6347
6478
  `.gitkeep.${collection.format || "md"}`
6348
6479
  ) ? "" : await this.stringifyFile(filepath, dataFields, collection);
6349
- if (!(collection == null ? void 0 : collection.isDetached)) {
6480
+ if (!collection?.isDetached) {
6350
6481
  if (this.bridge) {
6351
6482
  await this.bridge.put(normalizedPath, stringifiedFile);
6352
6483
  }
@@ -6368,11 +6499,19 @@ var Database = class {
6368
6499
  filepath,
6369
6500
  collection.path || ""
6370
6501
  );
6371
- 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;
6372
6503
  let putOps = [];
6373
6504
  let delOps = [];
6374
6505
  if (!isGitKeep(normalizedPath, collection)) {
6375
6506
  putOps = [
6507
+ ...makeRefOpsForDocument(
6508
+ normalizedPath,
6509
+ collectionName,
6510
+ collectionReferences,
6511
+ dataFields,
6512
+ "put",
6513
+ level
6514
+ ),
6376
6515
  ...makeIndexOpsForDocument(
6377
6516
  normalizedPath,
6378
6517
  collectionName,
@@ -6384,7 +6523,7 @@ var Database = class {
6384
6523
  // folder indices
6385
6524
  ...makeIndexOpsForDocument(
6386
6525
  normalizedPath,
6387
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6526
+ `${collection?.name}_${folderKey}`,
6388
6527
  collectionIndexDefinitions,
6389
6528
  dataFields,
6390
6529
  "put",
@@ -6396,6 +6535,14 @@ var Database = class {
6396
6535
  SUBLEVEL_OPTIONS
6397
6536
  ).get(normalizedPath);
6398
6537
  delOps = existingItem ? [
6538
+ ...makeRefOpsForDocument(
6539
+ normalizedPath,
6540
+ collectionName,
6541
+ collectionReferences,
6542
+ existingItem,
6543
+ "del",
6544
+ level
6545
+ ),
6399
6546
  ...makeIndexOpsForDocument(
6400
6547
  normalizedPath,
6401
6548
  collectionName,
@@ -6407,7 +6554,7 @@ var Database = class {
6407
6554
  // folder indices
6408
6555
  ...makeIndexOpsForDocument(
6409
6556
  normalizedPath,
6410
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
6557
+ `${collection?.name}_${folderKey}`,
6411
6558
  collectionIndexDefinitions,
6412
6559
  existingItem,
6413
6560
  "del",
@@ -6438,8 +6585,7 @@ var Database = class {
6438
6585
  throw new TinaFetchError(`Error in PUT for ${filepath}`, {
6439
6586
  originalError: error,
6440
6587
  file: filepath,
6441
- collection: collectionName,
6442
- stack: error.stack
6588
+ collection: collectionName
6443
6589
  });
6444
6590
  }
6445
6591
  };
@@ -6484,8 +6630,8 @@ var Database = class {
6484
6630
  writeTemplateKey,
6485
6631
  //templateInfo.type === 'union',
6486
6632
  {
6487
- frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat,
6488
- frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters
6633
+ frontmatterFormat: collection?.frontmatterFormat,
6634
+ frontmatterDelimiters: collection?.frontmatterDelimiters
6489
6635
  }
6490
6636
  );
6491
6637
  };
@@ -6558,6 +6704,22 @@ var Database = class {
6558
6704
  this.tinaSchema = await createSchema({ schema });
6559
6705
  return this.tinaSchema;
6560
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
+ };
6561
6723
  this.getIndexDefinitions = async (level) => {
6562
6724
  if (!this.collectionIndexDefinitions) {
6563
6725
  await new Promise(async (resolve2, reject) => {
@@ -6567,11 +6729,53 @@ var Database = class {
6567
6729
  const collections = schema.getCollections();
6568
6730
  for (const collection of collections) {
6569
6731
  const indexDefinitions = {
6570
- [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
6732
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] },
6571
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
+ }
6572
6749
  };
6573
- if (collection.fields) {
6574
- 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) {
6575
6779
  if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
6576
6780
  continue;
6577
6781
  }
@@ -6596,8 +6800,8 @@ var Database = class {
6596
6800
  );
6597
6801
  return {
6598
6802
  name: indexField.name,
6599
- type: field == null ? void 0 : field.type,
6600
- list: !!(field == null ? void 0 : field.list)
6803
+ type: field?.type,
6804
+ list: !!field?.list
6601
6805
  };
6602
6806
  })
6603
6807
  };
@@ -6623,7 +6827,6 @@ var Database = class {
6623
6827
  return true;
6624
6828
  };
6625
6829
  this.query = async (queryOptions, hydrator) => {
6626
- var _a;
6627
6830
  await this.initLevel();
6628
6831
  const {
6629
6832
  first,
@@ -6651,14 +6854,14 @@ var Database = class {
6651
6854
  const allIndexDefinitions = await this.getIndexDefinitions(
6652
6855
  this.contentLevel
6653
6856
  );
6654
- const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[collection.name];
6857
+ const indexDefinitions = allIndexDefinitions?.[collection.name];
6655
6858
  if (!indexDefinitions) {
6656
6859
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
6657
6860
  }
6658
6861
  const filterChain = coerceFilterChainOperands(rawFilterChain);
6659
- const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
6862
+ const indexDefinition = sort && indexDefinitions?.[sort];
6660
6863
  const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
6661
- 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;
6662
6865
  const rootLevel = level.sublevel(
6663
6866
  CONTENT_ROOT_PREFIX,
6664
6867
  SUBLEVEL_OPTIONS
@@ -6668,17 +6871,17 @@ var Database = class {
6668
6871
  SUBLEVEL_OPTIONS
6669
6872
  ).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
6670
6873
  if (!query.gt && !query.gte) {
6671
- query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? filterSuffixes.left : "";
6874
+ query.gte = filterSuffixes?.left ? filterSuffixes.left : "";
6672
6875
  }
6673
6876
  if (!query.lt && !query.lte) {
6674
- query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6877
+ query.lte = filterSuffixes?.right ? `${filterSuffixes.right}\uFFFF` : "\uFFFF";
6675
6878
  }
6676
6879
  let edges = [];
6677
6880
  let startKey = "";
6678
6881
  let endKey = "";
6679
6882
  let hasPreviousPage = false;
6680
6883
  let hasNextPage = false;
6681
- 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("")}` : "";
6682
6885
  const valuesRegex = indexDefinition ? new RegExp(`^${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^(?<_filepath_>.+)`);
6683
6886
  const itemFilter = makeFilter({ filterChain });
6684
6887
  const iterator = sublevel.iterator(query);
@@ -6720,29 +6923,35 @@ var Database = class {
6720
6923
  }
6721
6924
  startKey = startKey || key || "";
6722
6925
  endKey = key || "";
6723
- edges = [...edges, { cursor: key, path: filepath }];
6926
+ edges = [...edges, { cursor: key, path: filepath, value: itemRecord }];
6724
6927
  }
6725
6928
  return {
6726
- edges: await sequential(edges, async (edge) => {
6727
- try {
6728
- const node = await hydrator(edge.path);
6729
- return {
6730
- node,
6731
- cursor: btoa(edge.cursor)
6732
- };
6733
- } catch (error) {
6734
- console.log(error);
6735
- if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
6736
- throw new TinaQueryError({
6737
- originalError: error,
6738
- file: edge.path,
6739
- collection: collection.name,
6740
- stack: error.stack
6741
- });
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;
6742
6952
  }
6743
- throw error;
6744
6953
  }
6745
- }),
6954
+ ),
6746
6955
  pageInfo: {
6747
6956
  hasPreviousPage,
6748
6957
  hasNextPage,
@@ -6866,13 +7075,14 @@ var Database = class {
6866
7075
  documentPaths,
6867
7076
  async (collection, documentPaths2) => {
6868
7077
  if (collection && !collection.isDetached) {
6869
- await _indexContent(
6870
- this,
6871
- this.contentLevel,
6872
- documentPaths2,
7078
+ await _indexContent({
7079
+ database: this,
7080
+ level: this.contentLevel,
7081
+ documentPaths: documentPaths2,
6873
7082
  enqueueOps,
6874
- collection
6875
- );
7083
+ collection,
7084
+ isPartialReindex: true
7085
+ });
6876
7086
  }
6877
7087
  }
6878
7088
  );
@@ -6888,10 +7098,11 @@ var Database = class {
6888
7098
  throw new Error(`No collection found for path: ${filepath}`);
6889
7099
  }
6890
7100
  const indexDefinitions = await this.getIndexDefinitions(this.contentLevel);
6891
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7101
+ const collectionReferences = (await this.getCollectionReferences())?.[collection.name];
7102
+ const collectionIndexDefinitions = indexDefinitions?.[collection.name];
6892
7103
  let level = this.contentLevel;
6893
- if (collection == null ? void 0 : collection.isDetached) {
6894
- 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);
6895
7106
  }
6896
7107
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
6897
7108
  const rootSublevel = level.sublevel(
@@ -6906,6 +7117,14 @@ var Database = class {
6906
7117
  collection.path || ""
6907
7118
  );
6908
7119
  await this.contentLevel.batch([
7120
+ ...makeRefOpsForDocument(
7121
+ normalizedPath,
7122
+ collection.name,
7123
+ collectionReferences,
7124
+ item,
7125
+ "del",
7126
+ level
7127
+ ),
6909
7128
  ...makeIndexOpsForDocument(
6910
7129
  normalizedPath,
6911
7130
  collection.name,
@@ -6930,7 +7149,7 @@ var Database = class {
6930
7149
  }
6931
7150
  ]);
6932
7151
  }
6933
- if (!(collection == null ? void 0 : collection.isDetached)) {
7152
+ if (!collection?.isDetached) {
6934
7153
  if (this.bridge) {
6935
7154
  await this.bridge.delete(normalizedPath);
6936
7155
  }
@@ -6970,20 +7189,26 @@ var Database = class {
6970
7189
  );
6971
7190
  const doc = await level2.keys({ limit: 1 }).next();
6972
7191
  if (!doc) {
6973
- await _indexContent(
6974
- this,
6975
- level2,
6976
- contentPaths,
7192
+ await _indexContent({
7193
+ database: this,
7194
+ level: level2,
7195
+ documentPaths: contentPaths,
6977
7196
  enqueueOps,
6978
7197
  collection,
6979
- userFields.map((field) => [
7198
+ passwordFields: userFields.map((field) => [
6980
7199
  ...field.path,
6981
7200
  field.passwordFieldName
6982
7201
  ])
6983
- );
7202
+ });
6984
7203
  }
6985
7204
  } else {
6986
- await _indexContent(this, level, contentPaths, enqueueOps, collection);
7205
+ await _indexContent({
7206
+ database: this,
7207
+ level,
7208
+ documentPaths: contentPaths,
7209
+ enqueueOps,
7210
+ collection
7211
+ });
6987
7212
  }
6988
7213
  }
6989
7214
  );
@@ -7019,7 +7244,7 @@ var Database = class {
7019
7244
  );
7020
7245
  }
7021
7246
  const metadata = await metadataLevel.get("metadata");
7022
- return metadata == null ? void 0 : metadata.version;
7247
+ return metadata?.version;
7023
7248
  }
7024
7249
  async initLevel() {
7025
7250
  if (this.contentLevel) {
@@ -7105,7 +7330,7 @@ var hashPasswordVisitor = async (node, path7) => {
7105
7330
  };
7106
7331
  var visitNodes = async (node, path7, callback) => {
7107
7332
  const [currentLevel, ...remainingLevels] = path7;
7108
- if (!(remainingLevels == null ? void 0 : remainingLevels.length)) {
7333
+ if (!remainingLevels?.length) {
7109
7334
  return callback(node, path7);
7110
7335
  }
7111
7336
  if (Array.isArray(node[currentLevel])) {
@@ -7121,18 +7346,27 @@ var hashPasswordValues = async (data, passwordFields) => Promise.all(
7121
7346
  async (passwordField) => visitNodes(data, passwordField, hashPasswordVisitor)
7122
7347
  )
7123
7348
  );
7124
- var isGitKeep = (filepath, collection) => filepath.endsWith(`.gitkeep.${(collection == null ? void 0 : collection.format) || "md"}`);
7125
- 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
+ }) => {
7126
7359
  let collectionIndexDefinitions;
7127
7360
  let collectionPath;
7128
7361
  if (collection) {
7129
7362
  const indexDefinitions = await database.getIndexDefinitions(level);
7130
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7363
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
7131
7364
  if (!collectionIndexDefinitions) {
7132
7365
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7133
7366
  }
7134
7367
  collectionPath = collection.path;
7135
7368
  }
7369
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7136
7370
  const tinaSchema = await database.getSchema();
7137
7371
  let templateInfo = null;
7138
7372
  if (collection) {
@@ -7150,7 +7384,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7150
7384
  if (!aliasedData) {
7151
7385
  return;
7152
7386
  }
7153
- if (passwordFields == null ? void 0 : passwordFields.length) {
7387
+ if (passwordFields?.length) {
7154
7388
  await hashPasswordValues(aliasedData, passwordFields);
7155
7389
  }
7156
7390
  const normalizedPath = (0, import_schema_tools4.normalizePath)(filepath);
@@ -7162,38 +7396,56 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7162
7396
  normalizedPath,
7163
7397
  collectionPath || ""
7164
7398
  );
7165
- const item = await rootSublevel.get(normalizedPath);
7166
- if (item) {
7167
- await database.contentLevel.batch([
7168
- ...makeIndexOpsForDocument(
7169
- normalizedPath,
7170
- collection.name,
7171
- collectionIndexDefinitions,
7172
- item,
7173
- "del",
7174
- level
7175
- ),
7176
- // folder indices
7177
- ...makeIndexOpsForDocument(
7178
- normalizedPath,
7179
- `${collection.name}_${folderKey}`,
7180
- collectionIndexDefinitions,
7181
- item,
7182
- "del",
7183
- level
7184
- ),
7185
- {
7186
- type: "del",
7187
- key: normalizedPath,
7188
- sublevel: rootSublevel
7189
- }
7190
- ]);
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
+ }
7191
7435
  }
7192
7436
  if (!isGitKeep(filepath, collection)) {
7193
7437
  await enqueueOps([
7438
+ ...makeRefOpsForDocument(
7439
+ normalizedPath,
7440
+ collection?.name,
7441
+ collectionReferences,
7442
+ aliasedData,
7443
+ "put",
7444
+ level
7445
+ ),
7194
7446
  ...makeIndexOpsForDocument(
7195
7447
  normalizedPath,
7196
- collection == null ? void 0 : collection.name,
7448
+ collection?.name,
7197
7449
  collectionIndexDefinitions,
7198
7450
  aliasedData,
7199
7451
  "put",
@@ -7202,7 +7454,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7202
7454
  // folder indexes
7203
7455
  ...makeIndexOpsForDocument(
7204
7456
  normalizedPath,
7205
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7457
+ `${collection?.name}_${folderKey}`,
7206
7458
  collectionIndexDefinitions,
7207
7459
  aliasedData,
7208
7460
  "put",
@@ -7223,8 +7475,7 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
7223
7475
  throw new TinaFetchError(`Unable to seed ${filepath}`, {
7224
7476
  originalError: error,
7225
7477
  file: filepath,
7226
- collection: collection == null ? void 0 : collection.name,
7227
- stack: error.stack
7478
+ collection: collection?.name
7228
7479
  });
7229
7480
  }
7230
7481
  });
@@ -7249,11 +7500,12 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7249
7500
  const indexDefinitions = await database.getIndexDefinitions(
7250
7501
  database.contentLevel
7251
7502
  );
7252
- collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
7503
+ collectionIndexDefinitions = indexDefinitions?.[collection.name];
7253
7504
  if (!collectionIndexDefinitions) {
7254
7505
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
7255
7506
  }
7256
7507
  }
7508
+ const collectionReferences = (await database.getCollectionReferences())?.[collection?.name];
7257
7509
  const tinaSchema = await database.getSchema();
7258
7510
  let templateInfo = null;
7259
7511
  if (collection) {
@@ -7270,13 +7522,21 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7270
7522
  if (item) {
7271
7523
  const folderKey = folderTreeBuilder.update(
7272
7524
  itemKey,
7273
- (collection == null ? void 0 : collection.path) || ""
7525
+ collection?.path || ""
7274
7526
  );
7275
7527
  const aliasedData = templateInfo ? replaceNameOverrides(
7276
7528
  getTemplateForFile(templateInfo, item),
7277
7529
  item
7278
7530
  ) : item;
7279
7531
  await enqueueOps([
7532
+ ...makeRefOpsForDocument(
7533
+ itemKey,
7534
+ collection?.name,
7535
+ collectionReferences,
7536
+ aliasedData,
7537
+ "del",
7538
+ database.contentLevel
7539
+ ),
7280
7540
  ...makeIndexOpsForDocument(
7281
7541
  itemKey,
7282
7542
  collection.name,
@@ -7288,7 +7548,7 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7288
7548
  // folder indexes
7289
7549
  ...makeIndexOpsForDocument(
7290
7550
  itemKey,
7291
- `${collection == null ? void 0 : collection.name}_${folderKey}`,
7551
+ `${collection?.name}_${folderKey}`,
7292
7552
  collectionIndexDefinitions,
7293
7553
  aliasedData,
7294
7554
  "del",
@@ -7373,12 +7633,12 @@ var getChangedFiles = async ({
7373
7633
  }
7374
7634
  }
7375
7635
  }
7376
- if (await (B == null ? void 0 : B.type()) === "tree") {
7636
+ if (await B?.type() === "tree") {
7377
7637
  return;
7378
7638
  }
7379
7639
  if (matches) {
7380
- const oidA = await (A == null ? void 0 : A.oid());
7381
- const oidB = await (B == null ? void 0 : B.oid());
7640
+ const oidA = await A?.oid();
7641
+ const oidB = await B?.oid();
7382
7642
  if (oidA !== oidB) {
7383
7643
  if (oidA === void 0) {
7384
7644
  results.added.push(relativePath);
@@ -7406,8 +7666,8 @@ var import_path5 = __toESM(require("path"));
7406
7666
  var import_normalize_path = __toESM(require("normalize-path"));
7407
7667
  var FilesystemBridge = class {
7408
7668
  constructor(rootPath, outputPath) {
7409
- this.rootPath = rootPath || "";
7410
- this.outputPath = outputPath || rootPath;
7669
+ this.rootPath = import_path5.default.resolve(rootPath);
7670
+ this.outputPath = outputPath ? import_path5.default.resolve(outputPath) : this.rootPath;
7411
7671
  }
7412
7672
  async glob(pattern, extension) {
7413
7673
  const basePath = import_path5.default.join(this.outputPath, ...pattern.split("/"));
@@ -7419,19 +7679,19 @@ var FilesystemBridge = class {
7419
7679
  }
7420
7680
  );
7421
7681
  const posixRootPath = (0, import_normalize_path.default)(this.outputPath);
7422
- return items.map((item) => {
7423
- return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
7424
- });
7682
+ return items.map(
7683
+ (item) => item.substring(posixRootPath.length).replace(/^\/|\/$/g, "")
7684
+ );
7425
7685
  }
7426
7686
  async delete(filepath) {
7427
7687
  await import_fs_extra2.default.remove(import_path5.default.join(this.outputPath, filepath));
7428
7688
  }
7429
7689
  async get(filepath) {
7430
- 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();
7431
7691
  }
7432
7692
  async put(filepath, data, basePathOverride) {
7433
7693
  const basePath = basePathOverride || this.outputPath;
7434
- 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);
7435
7695
  }
7436
7696
  };
7437
7697
  var AuditFileSystemBridge = class extends FilesystemBridge {