@tinacms/graphql 2.0.3 → 2.0.4

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
@@ -45,8 +45,8 @@ var btoa = (string2) => {
45
45
  var lastItem = (arr) => {
46
46
  return arr[arr.length - 1];
47
47
  };
48
- var get = (obj, path7, defaultValue = void 0) => {
49
- const travel = (regexp) => String.prototype.split.call(path7, regexp).filter(Boolean).reduce(
48
+ var get = (obj, path8, defaultValue = void 0) => {
49
+ const travel = (regexp) => String.prototype.split.call(path8, regexp).filter(Boolean).reduce(
50
50
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
51
51
  obj
52
52
  );
@@ -3026,7 +3026,7 @@ var validateField = async (field) => {
3026
3026
  var package_default = {
3027
3027
  name: "@tinacms/graphql",
3028
3028
  type: "module",
3029
- version: "2.0.3",
3029
+ version: "2.0.4",
3030
3030
  main: "dist/index.js",
3031
3031
  module: "./dist/index.js",
3032
3032
  files: [
@@ -3308,7 +3308,12 @@ var _buildSchema = async (builder, tinaSchema) => {
3308
3308
  };
3309
3309
 
3310
3310
  // src/resolve.ts
3311
- import { graphql, buildASTSchema, getNamedType, GraphQLError as GraphQLError4 } from "graphql";
3311
+ import {
3312
+ graphql,
3313
+ buildASTSchema,
3314
+ getNamedType,
3315
+ GraphQLError as GraphQLError4
3316
+ } from "graphql";
3312
3317
 
3313
3318
  // src/resolver/index.ts
3314
3319
  import path3 from "path";
@@ -3647,17 +3652,17 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3647
3652
  const documentPaths = await bridge.glob(normalPath, format);
3648
3653
  const matches = tinaSchema.getMatches({ collection });
3649
3654
  const filteredPaths = matches.length > 0 ? micromatch(documentPaths, matches) : documentPaths;
3650
- filteredPaths.forEach((path7) => {
3651
- if (filesSeen.has(path7)) {
3652
- filesSeen.get(path7).push(collection.name);
3653
- duplicateFiles.add(path7);
3655
+ filteredPaths.forEach((path8) => {
3656
+ if (filesSeen.has(path8)) {
3657
+ filesSeen.get(path8).push(collection.name);
3658
+ duplicateFiles.add(path8);
3654
3659
  } else {
3655
- filesSeen.set(path7, [collection.name]);
3660
+ filesSeen.set(path8, [collection.name]);
3656
3661
  }
3657
3662
  });
3658
- duplicateFiles.forEach((path7) => {
3663
+ duplicateFiles.forEach((path8) => {
3659
3664
  warnings.push(
3660
- `"${path7}" Found in multiple collections: ${filesSeen.get(path7).map((collection2) => `"${collection2}"`).join(
3665
+ `"${path8}" Found in multiple collections: ${filesSeen.get(path8).map((collection2) => `"${collection2}"`).join(
3661
3666
  ", "
3662
3667
  )}. This can cause unexpected behavior. We recommend updating the \`match\` property of those collections so that each file is in only one collection.
3663
3668
  This will be an error in the future. See https://tina.io/docs/errors/file-in-mutpliple-collections/
@@ -4220,9 +4225,9 @@ var makeFilterSuffixes = (filterChain, index) => {
4220
4225
  }
4221
4226
  };
4222
4227
  var FOLDER_ROOT = "~";
4223
- var stripCollectionFromPath = (collectionPath, path7) => {
4228
+ var stripCollectionFromPath = (collectionPath, path8) => {
4224
4229
  const collectionPathParts = collectionPath.split("/");
4225
- const pathParts = path7.split("/");
4230
+ const pathParts = path8.split("/");
4226
4231
  const strippedPathParts = pathParts.slice(collectionPathParts.length);
4227
4232
  return strippedPathParts.join("/");
4228
4233
  };
@@ -4278,13 +4283,13 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4278
4283
  SUBLEVEL_OPTIONS
4279
4284
  );
4280
4285
  let folderSortingIdx = 0;
4281
- for (const path7 of Array.from(folder).sort()) {
4286
+ for (const path8 of Array.from(folder).sort()) {
4282
4287
  for (const [sort] of Object.entries(indexDefinitions)) {
4283
4288
  const indexSublevel = folderCollectionSublevel.sublevel(
4284
4289
  sort,
4285
4290
  SUBLEVEL_OPTIONS
4286
4291
  );
4287
- const subFolderKey = sha.hex(path7);
4292
+ const subFolderKey = sha.hex(path8);
4288
4293
  if (sort === DEFAULT_COLLECTION_SORT_KEY) {
4289
4294
  result.push({
4290
4295
  type: opType,
@@ -4366,8 +4371,8 @@ var makeRefOpsForDocument = (filepath, collection, references, data, opType, lev
4366
4371
  SUBLEVEL_OPTIONS
4367
4372
  );
4368
4373
  const references2 = {};
4369
- for (const path7 of referencePaths) {
4370
- const ref = JSONPath({ path: path7, json: data });
4374
+ for (const path8 of referencePaths) {
4375
+ const ref = JSONPath({ path: path8, json: data });
4371
4376
  if (!ref) {
4372
4377
  continue;
4373
4378
  }
@@ -4377,24 +4382,24 @@ var makeRefOpsForDocument = (filepath, collection, references, data, opType, lev
4377
4382
  continue;
4378
4383
  }
4379
4384
  if (references2[r]) {
4380
- references2[r].push(path7);
4385
+ references2[r].push(path8);
4381
4386
  } else {
4382
- references2[r] = [path7];
4387
+ references2[r] = [path8];
4383
4388
  }
4384
4389
  }
4385
4390
  } else {
4386
4391
  if (references2[ref]) {
4387
- references2[ref].push(path7);
4392
+ references2[ref].push(path8);
4388
4393
  } else {
4389
- references2[ref] = [path7];
4394
+ references2[ref] = [path8];
4390
4395
  }
4391
4396
  }
4392
4397
  }
4393
4398
  for (const ref of Object.keys(references2)) {
4394
- for (const path7 of references2[ref]) {
4399
+ for (const path8 of references2[ref]) {
4395
4400
  result.push({
4396
4401
  type: opType,
4397
- key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path7}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4402
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path8}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4398
4403
  sublevel: refSublevel,
4399
4404
  value: opType === "put" ? {} : void 0
4400
4405
  });
@@ -4661,9 +4666,9 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
4661
4666
  return value;
4662
4667
  }
4663
4668
  };
4664
- var cleanUpSlashes = (path7) => {
4665
- if (path7) {
4666
- return `/${path7.replace(/^\/+|\/+$/gm, "")}`;
4669
+ var cleanUpSlashes = (path8) => {
4670
+ if (path8) {
4671
+ return `/${path8.replace(/^\/+|\/+$/gm, "")}`;
4667
4672
  }
4668
4673
  return "";
4669
4674
  };
@@ -4873,17 +4878,17 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4873
4878
  throw e;
4874
4879
  }
4875
4880
  };
4876
- var updateObjectWithJsonPath = (obj, path7, oldValue, newValue) => {
4881
+ var updateObjectWithJsonPath = (obj, path8, oldValue, newValue) => {
4877
4882
  let updated = false;
4878
- if (!path7.includes(".") && !path7.includes("[")) {
4879
- if (path7 in obj && obj[path7] === oldValue) {
4880
- obj[path7] = newValue;
4883
+ if (!path8.includes(".") && !path8.includes("[")) {
4884
+ if (path8 in obj && obj[path8] === oldValue) {
4885
+ obj[path8] = newValue;
4881
4886
  updated = true;
4882
4887
  }
4883
4888
  return { object: obj, updated };
4884
4889
  }
4885
- const parentPath = path7.replace(/\.[^.\[\]]+$/, "");
4886
- const keyToUpdate = path7.match(/[^.\[\]]+$/)[0];
4890
+ const parentPath = path8.replace(/\.[^.\[\]]+$/, "");
4891
+ const keyToUpdate = path8.match(/[^.\[\]]+$/)[0];
4887
4892
  const parents = JSONPath2({
4888
4893
  path: parentPath,
4889
4894
  json: obj,
@@ -4913,7 +4918,7 @@ var Resolver = class {
4913
4918
  database;
4914
4919
  tinaSchema;
4915
4920
  isAudit;
4916
- resolveCollection = async (args, collectionName, hasDocuments) => {
4921
+ resolveCollection = async (_args, collectionName, hasDocuments) => {
4917
4922
  const collection = this.tinaSchema.getCollection(collectionName);
4918
4923
  const extraFields = {};
4919
4924
  return {
@@ -5080,38 +5085,296 @@ var Resolver = class {
5080
5085
  }
5081
5086
  }
5082
5087
  };
5083
- createResolveDocument = async ({
5084
- collection,
5085
- realPath,
5086
- args,
5087
- isAddPendingDocument
5088
+ resolveAddPendingDocument = async ({
5089
+ collectionName,
5090
+ relativePath,
5091
+ templateName
5088
5092
  }) => {
5089
- if (isAddPendingDocument === true) {
5090
- const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5091
- switch (templateInfo.type) {
5092
- case "object":
5093
- await this.database.addPendingDocument(realPath, {});
5094
- break;
5095
- case "union":
5096
- const templateString = args.template;
5097
- const template = templateInfo.templates.find(
5098
- (template2) => lastItem(template2.namespace) === templateString
5093
+ const collection = this.getCollectionWithName(collectionName);
5094
+ const realPath = path3.join(collection.path, relativePath);
5095
+ const alreadyExists = await this.database.documentExists(realPath);
5096
+ if (alreadyExists) {
5097
+ throw new Error(`Unable to add document, ${realPath} already exists`);
5098
+ }
5099
+ const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5100
+ switch (templateInfo.type) {
5101
+ case "object":
5102
+ await this.database.addPendingDocument(realPath, {});
5103
+ break;
5104
+ case "union":
5105
+ if (!templateName) {
5106
+ throw new Error(
5107
+ `Must specify a template when creating content for a collection with multiple templates. Possible templates are: ${templateInfo.templates.map((t) => lastItem(t.namespace)).join(" ")}`
5099
5108
  );
5100
- if (!args.template) {
5101
- throw new Error(
5102
- `Must specify a template when creating content for a collection with multiple templates. Possible templates are: ${templateInfo.templates.map((t) => lastItem(t.namespace)).join(" ")}`
5109
+ }
5110
+ const template = templateInfo.templates.find(
5111
+ (template2) => lastItem(template2.namespace) === templateName
5112
+ );
5113
+ if (!template) {
5114
+ throw new Error(
5115
+ `Expected to find template named ${templateName} in collection "${collection.name}" but none was found. Possible templates are: ${templateInfo.templates.map((t) => lastItem(t.namespace)).join(" ")}`
5116
+ );
5117
+ }
5118
+ await this.database.addPendingDocument(realPath, {
5119
+ _template: lastItem(template.namespace)
5120
+ });
5121
+ }
5122
+ return this.getDocument(realPath);
5123
+ };
5124
+ /**
5125
+ * Returns top-level fields which are not defined in the collection, so their
5126
+ * values are not eliminated from Tina when new values are saved
5127
+ */
5128
+ resolveLegacyValues = (oldDoc, collection) => {
5129
+ const legacyValues = {};
5130
+ Object.entries(oldDoc).forEach(([key, value]) => {
5131
+ const reservedKeys = [
5132
+ "$_body",
5133
+ "_collection",
5134
+ "_keepTemplateKey",
5135
+ "_template",
5136
+ "_relativePath",
5137
+ "_id"
5138
+ ];
5139
+ if (reservedKeys.includes(key)) {
5140
+ return;
5141
+ }
5142
+ if (oldDoc._template && collection.templates) {
5143
+ const template = collection.templates?.find(
5144
+ ({ name }) => name === oldDoc._template
5145
+ );
5146
+ if (template) {
5147
+ if (!template.fields.find(({ name }) => name === key)) {
5148
+ legacyValues[key] = value;
5149
+ }
5150
+ }
5151
+ }
5152
+ if (oldDoc._collection && collection.fields) {
5153
+ if (!collection.fields.find(({ name }) => name === key)) {
5154
+ legacyValues[key] = value;
5155
+ }
5156
+ }
5157
+ });
5158
+ return legacyValues;
5159
+ };
5160
+ getCollectionWithName = (collectionName) => {
5161
+ const collectionNames = this.tinaSchema.getCollections().map((item) => item.name);
5162
+ if (!collectionNames.includes(collectionName)) {
5163
+ throw new Error(
5164
+ `"collection" must be one of: [${collectionNames.join(
5165
+ ", "
5166
+ )}] but got ${collectionName}`
5167
+ );
5168
+ }
5169
+ return this.tinaSchema.getCollection(collectionName);
5170
+ };
5171
+ /*
5172
+ * Used for getDocument, get<Collection>Document.
5173
+ */
5174
+ resolveRetrievedDocument = async ({
5175
+ collectionName,
5176
+ relativePath
5177
+ }) => {
5178
+ const collection = this.getCollectionWithName(collectionName);
5179
+ const realPath = path3.join(collection.path, relativePath);
5180
+ return this.getDocument(realPath, {
5181
+ collection,
5182
+ checkReferences: true
5183
+ });
5184
+ };
5185
+ /*
5186
+ * Used for createFolder, create<Collection>Folder
5187
+ */
5188
+ resolveCreateFolder = async ({
5189
+ collectionName,
5190
+ relativePath
5191
+ }) => {
5192
+ const collection = this.getCollectionWithName(collectionName);
5193
+ const realPath = path3.join(
5194
+ collection.path,
5195
+ relativePath,
5196
+ `.gitkeep.${collection.format || "md"}`
5197
+ );
5198
+ const alreadyExists = await this.database.documentExists(realPath);
5199
+ if (alreadyExists) {
5200
+ throw new Error(`Unable to add folder, ${realPath} already exists`);
5201
+ }
5202
+ await this.database.put(
5203
+ realPath,
5204
+ { _is_tina_folder_placeholder: true },
5205
+ collection.name
5206
+ );
5207
+ return this.getDocument(realPath);
5208
+ };
5209
+ resolveCreateDocument = async ({
5210
+ collectionName,
5211
+ relativePath,
5212
+ body
5213
+ }) => {
5214
+ const collection = this.getCollectionWithName(collectionName);
5215
+ const realPath = path3.join(collection.path, relativePath);
5216
+ const alreadyExists = await this.database.documentExists(realPath);
5217
+ if (alreadyExists) {
5218
+ throw new Error(`Unable to add document, ${realPath} already exists`);
5219
+ }
5220
+ const params = await this.buildObjectMutations(body, collection);
5221
+ await this.database.put(realPath, params, collection.name);
5222
+ return this.getDocument(realPath);
5223
+ };
5224
+ resolveUpdateDocument = async ({
5225
+ collectionName,
5226
+ relativePath,
5227
+ newRelativePath,
5228
+ newBody
5229
+ }) => {
5230
+ const collection = this.getCollectionWithName(collectionName);
5231
+ const realPath = path3.join(collection.path, relativePath);
5232
+ const alreadyExists = await this.database.documentExists(realPath);
5233
+ if (!alreadyExists) {
5234
+ throw new Error(`Unable to update document, ${realPath} does not exist`);
5235
+ }
5236
+ const doc = await this.getDocument(realPath);
5237
+ if (newRelativePath) {
5238
+ const newRealPath = path3.join(collection?.path, newRelativePath);
5239
+ if (newRealPath === realPath) {
5240
+ return doc;
5241
+ }
5242
+ await this.database.put(newRealPath, doc._rawData, collection.name);
5243
+ await this.deleteDocument(realPath);
5244
+ const collRefs = await this.findReferences(realPath, collection);
5245
+ for (const [_collection, docsWithRefs] of Object.entries(collRefs)) {
5246
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5247
+ docsWithRefs
5248
+ )) {
5249
+ let docWithRef = await this.getRaw(pathToDocWithRef);
5250
+ let hasUpdate = false;
5251
+ for (const path8 of referencePaths) {
5252
+ const { object: object2, updated } = updateObjectWithJsonPath(
5253
+ docWithRef,
5254
+ path8,
5255
+ realPath,
5256
+ newRealPath
5103
5257
  );
5258
+ docWithRef = object2;
5259
+ hasUpdate = updated || hasUpdate;
5104
5260
  }
5105
- if (!template) {
5106
- throw new Error(
5107
- `Expected to find template named ${templateString} in collection "${collection.name}" but none was found. Possible templates are: ${templateInfo.templates.map((t) => lastItem(t.namespace)).join(" ")}`
5261
+ if (hasUpdate) {
5262
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5263
+ if (!collectionWithRef) {
5264
+ throw new Error(
5265
+ `Unable to find collection for ${pathToDocWithRef}`
5266
+ );
5267
+ }
5268
+ await this.database.put(
5269
+ pathToDocWithRef,
5270
+ docWithRef,
5271
+ collectionWithRef.name
5108
5272
  );
5109
5273
  }
5110
- await this.database.addPendingDocument(realPath, {
5111
- _template: lastItem(template.namespace)
5112
- });
5274
+ }
5275
+ }
5276
+ return this.getDocument(newRealPath);
5277
+ }
5278
+ if (!newBody) {
5279
+ throw new Error("Body not provided for updated document.");
5280
+ }
5281
+ const params = await this.buildObjectMutations(
5282
+ newBody,
5283
+ collection,
5284
+ doc?._rawData
5285
+ );
5286
+ const legacyValues = this.resolveLegacyValues(
5287
+ doc?._rawData || {},
5288
+ collection
5289
+ );
5290
+ await this.database.put(
5291
+ realPath,
5292
+ { ...legacyValues, ...params },
5293
+ collection.name
5294
+ );
5295
+ return this.getDocument(realPath);
5296
+ };
5297
+ resolveDeleteDocument = async ({
5298
+ collectionName,
5299
+ relativePath
5300
+ }) => {
5301
+ const collection = this.getCollectionWithName(collectionName);
5302
+ const realPath = path3.join(collection.path, relativePath);
5303
+ const alreadyExists = await this.database.documentExists(realPath);
5304
+ if (!alreadyExists) {
5305
+ throw new Error(`Unable to delete document, ${realPath} does not exist`);
5306
+ }
5307
+ const doc = await this.getDocument(realPath);
5308
+ await this.deleteDocument(realPath);
5309
+ if (await this.hasReferences(realPath, collection)) {
5310
+ const collRefs = await this.findReferences(realPath, collection);
5311
+ for (const [_collection, docsWithRefs] of Object.entries(collRefs)) {
5312
+ for (const [pathToDocWithRef, referencePaths] of Object.entries(
5313
+ docsWithRefs
5314
+ )) {
5315
+ let refDoc = await this.getRaw(pathToDocWithRef);
5316
+ let hasUpdate = false;
5317
+ for (const path8 of referencePaths) {
5318
+ const { object: object2, updated } = updateObjectWithJsonPath(
5319
+ refDoc,
5320
+ path8,
5321
+ realPath,
5322
+ null
5323
+ );
5324
+ refDoc = object2;
5325
+ hasUpdate = updated || hasUpdate;
5326
+ }
5327
+ if (hasUpdate) {
5328
+ const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5329
+ if (!collectionWithRef) {
5330
+ throw new Error(
5331
+ `Unable to find collection for ${pathToDocWithRef}`
5332
+ );
5333
+ }
5334
+ await this.database.put(
5335
+ pathToDocWithRef,
5336
+ refDoc,
5337
+ collectionWithRef.name
5338
+ );
5339
+ }
5340
+ }
5113
5341
  }
5114
- return this.getDocument(realPath);
5342
+ }
5343
+ return doc;
5344
+ };
5345
+ resolveAndValidateCollection = ({
5346
+ collectionName,
5347
+ args,
5348
+ isCollectionSpecific
5349
+ }) => {
5350
+ let collectionLookup = collectionName || void 0;
5351
+ if (!collectionLookup && isCollectionSpecific === false) {
5352
+ assertShape(
5353
+ args,
5354
+ (yup3) => yup3.object({
5355
+ params: yup3.object().required()
5356
+ })
5357
+ );
5358
+ collectionLookup = Object.keys(args.params)[0];
5359
+ }
5360
+ const collection = this.getCollectionWithName(collectionLookup);
5361
+ return { collection };
5362
+ };
5363
+ /**
5364
+ * @deprecated - To be removed in next major version.
5365
+ */
5366
+ createResolveDocument = async ({
5367
+ collection,
5368
+ realPath,
5369
+ args,
5370
+ isAddPendingDocument
5371
+ }) => {
5372
+ if (isAddPendingDocument === true) {
5373
+ return this.resolveAddPendingDocument({
5374
+ collectionName: collection.name,
5375
+ relativePath: path3.relative(collection.path, realPath),
5376
+ templateName: args.template
5377
+ });
5115
5378
  }
5116
5379
  const params = await this.buildObjectMutations(
5117
5380
  // @ts-ignore
@@ -5121,6 +5384,9 @@ var Resolver = class {
5121
5384
  await this.database.put(realPath, params, collection.name);
5122
5385
  return this.getDocument(realPath);
5123
5386
  };
5387
+ /**
5388
+ * @deprecated - To be removed in next major version.
5389
+ */
5124
5390
  updateResolveDocument = async ({
5125
5391
  collection,
5126
5392
  realPath,
@@ -5131,6 +5397,9 @@ var Resolver = class {
5131
5397
  const doc = await this.getDocument(realPath);
5132
5398
  const oldDoc = this.resolveLegacyValues(doc?._rawData || {}, collection);
5133
5399
  if (isAddPendingDocument === true) {
5400
+ console.warn(
5401
+ "*** DEPRECATION: isAddPendingDocument functionality will be removed Resolver.updateResolveDocument in a future version. ***"
5402
+ );
5134
5403
  const templateInfo = this.tinaSchema.getTemplatesForCollectable(collection);
5135
5404
  const params2 = this.buildParams(args);
5136
5405
  switch (templateInfo.type) {
@@ -5187,41 +5456,8 @@ var Resolver = class {
5187
5456
  return this.getDocument(realPath);
5188
5457
  };
5189
5458
  /**
5190
- * Returns top-level fields which are not defined in the collection, so their
5191
- * values are not eliminated from Tina when new values are saved
5459
+ * @deprecated
5192
5460
  */
5193
- resolveLegacyValues = (oldDoc, collection) => {
5194
- const legacyValues = {};
5195
- Object.entries(oldDoc).forEach(([key, value]) => {
5196
- const reservedKeys = [
5197
- "$_body",
5198
- "_collection",
5199
- "_keepTemplateKey",
5200
- "_template",
5201
- "_relativePath",
5202
- "_id"
5203
- ];
5204
- if (reservedKeys.includes(key)) {
5205
- return;
5206
- }
5207
- if (oldDoc._template && collection.templates) {
5208
- const template = collection.templates?.find(
5209
- ({ name }) => name === oldDoc._template
5210
- );
5211
- if (template) {
5212
- if (!template.fields.find(({ name }) => name === key)) {
5213
- legacyValues[key] = value;
5214
- }
5215
- }
5216
- }
5217
- if (oldDoc._collection && collection.fields) {
5218
- if (!collection.fields.find(({ name }) => name === key)) {
5219
- legacyValues[key] = value;
5220
- }
5221
- }
5222
- });
5223
- return legacyValues;
5224
- };
5225
5461
  resolveDocument = async ({
5226
5462
  args,
5227
5463
  collection: collectionName,
@@ -5233,169 +5469,76 @@ var Resolver = class {
5233
5469
  isCollectionSpecific,
5234
5470
  isUpdateName
5235
5471
  }) => {
5236
- let collectionLookup = collectionName || void 0;
5237
- if (!collectionLookup && isCollectionSpecific === false) {
5238
- collectionLookup = Object.keys(args.params)[0];
5239
- }
5240
- const collectionNames = this.tinaSchema.getCollections().map((item) => item.name);
5241
- assertShape(
5242
- collectionLookup,
5243
- (yup3) => {
5244
- return yup3.mixed().oneOf(collectionNames);
5245
- },
5246
- `"collection" must be one of: [${collectionNames.join(
5247
- ", "
5248
- )}] but got ${collectionLookup}`
5249
- );
5472
+ const { collection } = this.resolveAndValidateCollection({
5473
+ collectionName,
5474
+ args,
5475
+ isCollectionSpecific
5476
+ });
5250
5477
  assertShape(
5251
5478
  args,
5252
5479
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
5253
5480
  );
5254
- const collection = await this.tinaSchema.getCollection(collectionLookup);
5255
- let realPath = path3.join(collection?.path, args.relativePath);
5256
- if (isFolderCreation) {
5257
- realPath = `${realPath}/.gitkeep.${collection.format || "md"}`;
5258
- }
5259
- const alreadyExists = await this.database.documentExists(realPath);
5260
5481
  if (isMutation) {
5261
5482
  if (isCreation) {
5262
- if (alreadyExists === true) {
5263
- throw new Error(`Unable to add document, ${realPath} already exists`);
5483
+ if (isAddPendingDocument) {
5484
+ assertShape(
5485
+ args,
5486
+ (yup3) => yup3.object({ template: yup3.string() })
5487
+ );
5488
+ return this.resolveAddPendingDocument({
5489
+ collectionName: collection.name,
5490
+ relativePath: args.relativePath,
5491
+ templateName: args.template || ""
5492
+ });
5493
+ } else {
5494
+ assertShape(
5495
+ args,
5496
+ (yup3) => yup3.object({ params: yup3.object().required() })
5497
+ );
5498
+ return this.resolveCreateDocument({
5499
+ collectionName: collection.name,
5500
+ relativePath: args.relativePath,
5501
+ body: args.params[collection.name]
5502
+ });
5264
5503
  }
5265
- return this.createResolveDocument({
5504
+ } else if (isFolderCreation) {
5505
+ return this.resolveCreateFolder({
5506
+ collectionName: collection.name,
5507
+ relativePath: args.relativePath
5508
+ });
5509
+ } else if (isDeletion) {
5510
+ return this.resolveDeleteDocument({
5511
+ collectionName: collection.name,
5512
+ relativePath: args.relativePath
5513
+ });
5514
+ } else if (isUpdateName) {
5515
+ assertShape(
5516
+ args,
5517
+ (yup3) => yup3.object({
5518
+ params: yup3.object({ relativePath: yup3.string().required() }).required()
5519
+ })
5520
+ );
5521
+ const realPath = path3.join(collection.path, args.relativePath);
5522
+ return this.updateResolveDocument({
5266
5523
  collection,
5267
5524
  realPath,
5268
5525
  args,
5269
- isAddPendingDocument
5526
+ isAddPendingDocument,
5527
+ isCollectionSpecific
5270
5528
  });
5271
- } else if (isFolderCreation) {
5272
- if (alreadyExists === true) {
5273
- throw new Error(`Unable to add folder, ${realPath} already exists`);
5274
- }
5275
- await this.database.put(
5276
- realPath,
5277
- { _is_tina_folder_placeholder: true },
5278
- collection.name
5279
- );
5280
- return this.getDocument(realPath);
5281
- }
5282
- if (!alreadyExists) {
5283
- if (isDeletion) {
5284
- throw new Error(
5285
- `Unable to delete document, ${realPath} does not exist`
5286
- );
5287
- }
5288
- if (isUpdateName) {
5289
- throw new Error(
5290
- `Unable to update document, ${realPath} does not exist`
5291
- );
5292
- }
5293
- }
5294
- if (isDeletion) {
5295
- const doc = await this.getDocument(realPath);
5296
- await this.deleteDocument(realPath);
5297
- if (await this.hasReferences(realPath, collection)) {
5298
- const collRefs = await this.findReferences(realPath, collection);
5299
- for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5300
- for (const [pathToDocWithRef, referencePaths] of Object.entries(
5301
- docsWithRefs
5302
- )) {
5303
- let refDoc = await this.getRaw(pathToDocWithRef);
5304
- let hasUpdate = false;
5305
- for (const path7 of referencePaths) {
5306
- const { object: object2, updated } = updateObjectWithJsonPath(
5307
- refDoc,
5308
- path7,
5309
- realPath,
5310
- null
5311
- );
5312
- refDoc = object2;
5313
- hasUpdate = updated || hasUpdate;
5314
- }
5315
- if (hasUpdate) {
5316
- const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5317
- if (!collectionWithRef) {
5318
- throw new Error(
5319
- `Unable to find collection for ${pathToDocWithRef}`
5320
- );
5321
- }
5322
- await this.database.put(
5323
- pathToDocWithRef,
5324
- refDoc,
5325
- collectionWithRef.name
5326
- );
5327
- }
5328
- }
5329
- }
5330
- }
5331
- return doc;
5332
- }
5333
- if (isUpdateName) {
5529
+ } else {
5334
5530
  assertShape(
5335
5531
  args,
5336
5532
  (yup3) => yup3.object({ params: yup3.object().required() })
5337
5533
  );
5338
- assertShape(
5339
- args?.params,
5340
- (yup3) => yup3.object({ relativePath: yup3.string().required() })
5341
- );
5342
- const doc = await this.getDocument(realPath);
5343
- const newRealPath = path3.join(
5344
- collection?.path,
5345
- args.params.relativePath
5346
- );
5347
- if (newRealPath === realPath) {
5348
- return doc;
5349
- }
5350
- await this.database.put(newRealPath, doc._rawData, collection.name);
5351
- await this.deleteDocument(realPath);
5352
- const collRefs = await this.findReferences(realPath, collection);
5353
- for (const [collection2, docsWithRefs] of Object.entries(collRefs)) {
5354
- for (const [pathToDocWithRef, referencePaths] of Object.entries(
5355
- docsWithRefs
5356
- )) {
5357
- let docWithRef = await this.getRaw(pathToDocWithRef);
5358
- let hasUpdate = false;
5359
- for (const path7 of referencePaths) {
5360
- const { object: object2, updated } = updateObjectWithJsonPath(
5361
- docWithRef,
5362
- path7,
5363
- realPath,
5364
- newRealPath
5365
- );
5366
- docWithRef = object2;
5367
- hasUpdate = updated || hasUpdate;
5368
- }
5369
- if (hasUpdate) {
5370
- const collectionWithRef = this.tinaSchema.getCollectionByFullPath(pathToDocWithRef);
5371
- if (!collectionWithRef) {
5372
- throw new Error(
5373
- `Unable to find collection for ${pathToDocWithRef}`
5374
- );
5375
- }
5376
- await this.database.put(
5377
- pathToDocWithRef,
5378
- docWithRef,
5379
- collectionWithRef.name
5380
- );
5381
- }
5382
- }
5383
- }
5384
- return this.getDocument(newRealPath);
5385
- }
5386
- if (alreadyExists === false) {
5387
- throw new Error(
5388
- `Unable to update document, ${realPath} does not exist`
5389
- );
5534
+ return this.resolveUpdateDocument({
5535
+ collectionName: collection.name,
5536
+ relativePath: args.relativePath,
5537
+ newBody: isCollectionSpecific ? args.params : args.params[collection.name]
5538
+ });
5390
5539
  }
5391
- return this.updateResolveDocument({
5392
- collection,
5393
- realPath,
5394
- args,
5395
- isAddPendingDocument,
5396
- isCollectionSpecific
5397
- });
5398
5540
  } else {
5541
+ const realPath = path3.join(collection.path, args.relativePath);
5399
5542
  return this.getDocument(realPath, {
5400
5543
  collection,
5401
5544
  checkReferences: true
@@ -5435,7 +5578,7 @@ var Resolver = class {
5435
5578
  first: -1
5436
5579
  },
5437
5580
  collection: referencedCollection,
5438
- hydrator: (path7) => path7
5581
+ hydrator: (path8) => path8
5439
5582
  // just return the path
5440
5583
  }
5441
5584
  );
@@ -5750,6 +5893,7 @@ var resolveDateInput = (value) => {
5750
5893
  };
5751
5894
 
5752
5895
  // src/resolver/auth-fields.ts
5896
+ import path4 from "path";
5753
5897
  import { set } from "es-toolkit/compat";
5754
5898
  async function getUserDocumentContext(tinaSchema, resolver) {
5755
5899
  const collection = tinaSchema.getCollections().find((c) => c.isAuthCollection);
@@ -5766,13 +5910,14 @@ async function getUserDocumentContext(tinaSchema, resolver) {
5766
5910
  );
5767
5911
  }
5768
5912
  const userField = userFields[0];
5769
- const realPath = `${collection.path}/index.json`;
5913
+ const relativePath = "index.json";
5914
+ const realPath = path4.join(collection.path, relativePath);
5770
5915
  const userDoc = await resolver.getDocument(realPath);
5771
5916
  const users = get(userDoc, userField.path);
5772
5917
  if (!users) {
5773
5918
  throw new Error("No users found");
5774
5919
  }
5775
- return { collection, userField, users, userDoc, realPath };
5920
+ return { collection, userField, users, userDoc, relativePath };
5776
5921
  }
5777
5922
  function findUserInCollection(users, userField, userSub) {
5778
5923
  const { idFieldName } = userField;
@@ -5834,7 +5979,7 @@ async function handleUpdatePassword({
5834
5979
  if (!password) {
5835
5980
  throw new Error("No password provided");
5836
5981
  }
5837
- const { collection, userField, users, realPath } = await getUserDocumentContext(tinaSchema, resolver);
5982
+ const { collection, userField, users, relativePath } = await getUserDocumentContext(tinaSchema, resolver);
5838
5983
  const { idFieldName, passwordFieldName } = userField;
5839
5984
  const user = users.find((u) => u[idFieldName] === ctxUser.sub);
5840
5985
  if (!user) {
@@ -5844,9 +5989,9 @@ async function handleUpdatePassword({
5844
5989
  value: password,
5845
5990
  passwordChangeRequired: false
5846
5991
  };
5847
- const params = {};
5992
+ const newBody = {};
5848
5993
  set(
5849
- params,
5994
+ newBody,
5850
5995
  userField.path.slice(1),
5851
5996
  // remove _rawData from users path
5852
5997
  users.map((u) => {
@@ -5863,12 +6008,10 @@ async function handleUpdatePassword({
5863
6008
  };
5864
6009
  })
5865
6010
  );
5866
- await resolver.updateResolveDocument({
5867
- collection,
5868
- args: { params },
5869
- realPath,
5870
- isCollectionSpecific: true,
5871
- isAddPendingDocument: false
6011
+ await resolver.resolveUpdateDocument({
6012
+ collectionName: collection.name,
6013
+ relativePath,
6014
+ newBody
5872
6015
  });
5873
6016
  return true;
5874
6017
  }
@@ -5876,8 +6019,8 @@ async function handleUpdatePassword({
5876
6019
  // src/error.ts
5877
6020
  import { GraphQLError as GraphQLError3 } from "graphql";
5878
6021
  var NotFoundError = class extends GraphQLError3 {
5879
- constructor(message, nodes, source, positions, path7, originalError, extensions) {
5880
- super(message, nodes, source, positions, path7, originalError, extensions);
6022
+ constructor(message, nodes, source, positions, path8, originalError, extensions) {
6023
+ super(message, nodes, source, positions, path8, originalError, extensions);
5881
6024
  this.name = "NotFoundError";
5882
6025
  }
5883
6026
  };
@@ -5902,10 +6045,8 @@ var resolve = async ({
5902
6045
  const graphQLSchema = buildASTSchema(graphQLSchemaAst);
5903
6046
  const tinaConfig = await database.getTinaSchema();
5904
6047
  const tinaSchema = await createSchema({
5905
- // TODO: please update all the types to import from @tinacms/schema-tools
5906
- // @ts-ignore
5907
6048
  schema: tinaConfig,
5908
- // @ts-ignore
6049
+ // @ts-expect-error
5909
6050
  flags: tinaConfig?.meta?.flags
5910
6051
  });
5911
6052
  const resolver = createResolver({
@@ -5930,91 +6071,61 @@ var resolve = async ({
5930
6071
  }
5931
6072
  throw new Error(`Unable to find lookup key for ${namedType}`);
5932
6073
  },
5933
- fieldResolver: async (source = {}, _args = {}, _context, info) => {
6074
+ fieldResolver: async (source = {}, args = {}, _context, info) => {
5934
6075
  try {
5935
- const args = JSON.parse(JSON.stringify(_args));
5936
6076
  const returnType = getNamedType(info.returnType).toString();
5937
- const lookup = await database.getLookup(returnType);
5938
- const isMutation = info.parentType.toString() === "Mutation";
5939
- const value = source[info.fieldName];
5940
6077
  if (returnType === "Collection") {
5941
- if (value) {
5942
- return value;
6078
+ const possibleCollectionValue = source[info.fieldName];
6079
+ if (possibleCollectionValue) {
6080
+ return possibleCollectionValue;
5943
6081
  }
5944
6082
  if (info.fieldName === "collections") {
5945
- const collectionNode2 = info.fieldNodes.find(
5946
- (x) => x.name.value === "collections"
5947
- );
5948
- const hasDocuments2 = collectionNode2.selectionSet.selections.find(
5949
- (x) => {
5950
- return x?.name?.value === "documents";
5951
- }
5952
- );
5953
- return tinaSchema.getCollections().map((collection) => {
5954
- return resolver.resolveCollection(
5955
- args,
5956
- collection.name,
5957
- Boolean(hasDocuments2)
5958
- );
5959
- });
6083
+ return handleCollectionsField(info, tinaSchema, resolver, args);
5960
6084
  }
5961
- const collectionNode = info.fieldNodes.find(
5962
- (x) => x.name.value === "collection"
5963
- );
5964
- const hasDocuments = collectionNode.selectionSet.selections.find(
5965
- (x) => {
5966
- return x?.name?.value === "documents";
5967
- }
5968
- );
5969
- return resolver.resolveCollection(
5970
- args,
5971
- args.collection,
5972
- Boolean(hasDocuments)
5973
- );
6085
+ return handleCollectionField(info, args, resolver);
5974
6086
  }
5975
6087
  if (info.fieldName === "getOptimizedQuery") {
5976
- try {
5977
- return args.queryString;
5978
- } catch (e) {
5979
- throw new Error(
5980
- `Invalid query provided, Error message: ${e.message}`
5981
- );
5982
- }
6088
+ return args.queryString || "";
5983
6089
  }
5984
6090
  if (info.fieldName === "authenticate") {
6091
+ const authArgs = args;
5985
6092
  return handleAuthenticate({
5986
6093
  tinaSchema,
5987
6094
  resolver,
5988
- sub: args.sub,
5989
- password: args.password,
6095
+ sub: authArgs.sub,
6096
+ password: authArgs.password,
5990
6097
  info,
5991
6098
  ctxUser
5992
6099
  });
5993
6100
  }
5994
6101
  if (info.fieldName === "authorize") {
6102
+ const authArgs = args;
5995
6103
  return handleAuthorize({
5996
6104
  tinaSchema,
5997
6105
  resolver,
5998
- sub: args.sub,
6106
+ sub: authArgs.sub,
5999
6107
  info,
6000
6108
  ctxUser
6001
6109
  });
6002
6110
  }
6003
6111
  if (info.fieldName === "updatePassword") {
6112
+ const authArgs = args;
6004
6113
  return handleUpdatePassword({
6005
6114
  tinaSchema,
6006
6115
  resolver,
6007
- password: args.password,
6116
+ password: authArgs.password,
6008
6117
  info,
6009
6118
  ctxUser
6010
6119
  });
6011
6120
  }
6121
+ const lookup = await database.getLookup(returnType);
6012
6122
  if (!lookup) {
6013
- return value;
6123
+ return source[info.fieldName];
6014
6124
  }
6015
6125
  const isCreation = lookup[info.fieldName] === "create";
6126
+ const isMutation = info.parentType.toString() === "Mutation";
6016
6127
  switch (lookup.resolveType) {
6017
- /**
6128
+ /*
6018
6129
  * `node(id: $id)`
6019
6130
  */
6020
6131
  case "nodeDocument":
@@ -6024,78 +6135,114 @@ var resolve = async ({
6024
6135
  );
6025
6136
  return resolver.getDocument(args.id);
6026
6137
  case "multiCollectionDocument":
6027
- if (typeof value === "string" && value !== "") {
6028
- return resolver.getDocument(value);
6029
- }
6030
- if (args?.collection && info.fieldName === "addPendingDocument") {
6031
- return resolver.resolveDocument({
6032
- args: { ...args, params: {} },
6033
- collection: args.collection,
6034
- isMutation,
6035
- isCreation: true,
6036
- isAddPendingDocument: true
6037
- });
6138
+ const possibleValue = source[info.fieldName];
6139
+ if (typeof possibleValue === "string" && possibleValue !== "") {
6140
+ return resolver.getDocument(possibleValue);
6038
6141
  }
6039
6142
  if ([
6040
6143
  NAMER.documentQueryName(),
6144
+ "addPendingDocument",
6041
6145
  "createDocument",
6042
6146
  "updateDocument",
6043
6147
  "deleteDocument",
6044
6148
  "createFolder"
6045
6149
  ].includes(info.fieldName)) {
6046
- const result = await resolver.resolveDocument({
6150
+ assertShape(
6047
6151
  args,
6048
- collection: args.collection,
6049
- isMutation,
6050
- isCreation,
6051
- // Right now this is the only case for deletion
6052
- isDeletion: info.fieldName === "deleteDocument",
6053
- isFolderCreation: info.fieldName === "createFolder",
6054
- isUpdateName: Boolean(args?.params?.relativePath),
6055
- isAddPendingDocument: false,
6056
- isCollectionSpecific: false
6057
- });
6058
- return result;
6152
+ (yup3) => yup3.object({
6153
+ collection: yup3.string().required(),
6154
+ relativePath: yup3.string().required()
6155
+ })
6156
+ );
6157
+ if (isMutation) {
6158
+ switch (info.fieldName) {
6159
+ case "addPendingDocument":
6160
+ return resolver.resolveAddPendingDocument({
6161
+ collectionName: args.collection,
6162
+ relativePath: args.relativePath,
6163
+ templateName: args.template
6164
+ });
6165
+ case "createFolder":
6166
+ return resolver.resolveCreateFolder({
6167
+ collectionName: args.collection,
6168
+ relativePath: args.relativePath
6169
+ });
6170
+ case "createDocument": {
6171
+ assertShape(
6172
+ args,
6173
+ (yup3) => yup3.object({
6174
+ params: yup3.object().shape({
6175
+ [args.collection]: yup3.object().required()
6176
+ }).required()
6177
+ })
6178
+ );
6179
+ return resolver.resolveCreateDocument({
6180
+ collectionName: args.collection,
6181
+ relativePath: args.relativePath,
6182
+ body: args.params[args.collection]
6183
+ });
6184
+ }
6185
+ case "updateDocument": {
6186
+ assertShape(
6187
+ args,
6188
+ (yup3) => yup3.object({
6189
+ params: yup3.object().shape({
6190
+ relativePath: yup3.string().optional()
6191
+ }).required()
6192
+ })
6193
+ );
6194
+ const newRelativePath = args.params.relativePath;
6195
+ const newBody = args.params[args.collection];
6196
+ return resolver.resolveUpdateDocument({
6197
+ collectionName: args.collection,
6198
+ relativePath: args.relativePath,
6199
+ newRelativePath,
6200
+ newBody
6201
+ });
6202
+ }
6203
+ case "deleteDocument":
6204
+ return resolver.resolveDeleteDocument({
6205
+ collectionName: args.collection,
6206
+ relativePath: args.relativePath
6207
+ });
6208
+ }
6209
+ } else if (info.fieldName === NAMER.documentQueryName()) {
6210
+ return resolver.resolveRetrievedDocument({
6211
+ collectionName: args.collection,
6212
+ relativePath: args.relativePath
6213
+ });
6214
+ }
6059
6215
  }
6060
- return value;
6061
- /**
6216
+ return possibleValue;
6217
+ /*
6062
6218
  * eg `getMovieDocument.data.actors`
6063
6219
  */
6064
6220
  case "multiCollectionDocumentList":
6065
- if (Array.isArray(value)) {
6221
+ const listValue = source[info.fieldName];
6222
+ if (Array.isArray(listValue)) {
6066
6223
  return {
6067
- totalCount: value.length,
6068
- edges: value.map((document) => {
6224
+ totalCount: listValue.length,
6225
+ edges: listValue.map((document) => {
6069
6226
  return { node: document };
6070
6227
  })
6071
6228
  };
6072
6229
  }
6073
- if (info.fieldName === "documents" && value?.collection && value?.hasDocuments) {
6074
- let filter = args.filter;
6075
- if (
6076
- // 1. Make sure that the filter exists
6077
- typeof args?.filter !== "undefined" && args?.filter !== null && // 2. Make sure that the collection name exists
6078
- // @ts-ignore
6079
- typeof value?.collection?.name === "string" && // 3. Make sure that the collection name is in the filter and is not undefined
6080
- // @ts-ignore
6081
- Object.keys(args.filter).includes(value?.collection?.name) && // @ts-ignore
6082
- typeof args.filter[value?.collection?.name] !== "undefined"
6083
- ) {
6084
- filter = args.filter[value.collection.name];
6085
- }
6230
+ if (info.fieldName === "documents" && listValue?.collection && listValue?.hasDocuments) {
6231
+ const documentsArgs = args;
6232
+ const collectionName = listValue.collection?.name;
6233
+ const filter = (collectionName && documentsArgs.filter?.[collectionName]) ?? documentsArgs.filter;
6086
6234
  return resolver.resolveCollectionConnection({
6087
6235
  args: {
6088
- ...args,
6236
+ ...documentsArgs,
6089
6237
  filter
6090
6238
  },
6091
- // @ts-ignore
6092
- collection: value.collection
6239
+ collection: listValue.collection
6093
6240
  });
6094
6241
  }
6095
6242
  throw new Error(
6096
6243
  `Expected an array for result of ${info.fieldName} at ${info.path}`
6097
6244
  );
6098
- /**
6245
+ /*
6099
6246
  * Collections-specific getter
6100
6247
  * eg. `getPostDocument`/`createPostDocument`/`updatePostDocument`
6101
6248
  *
@@ -6103,29 +6250,54 @@ var resolve = async ({
6103
6250
  * the field will be `node`
6104
6251
  */
6105
6252
  case "collectionDocument": {
6106
- if (value) {
6107
- return value;
6253
+ const possibleDocValue = source[info.fieldName];
6254
+ if (possibleDocValue) {
6255
+ return possibleDocValue;
6108
6256
  }
6109
- const result = value || await resolver.resolveDocument({
6257
+ assertShape(
6110
6258
  args,
6111
- collection: lookup.collection,
6112
- isMutation,
6113
- isCreation,
6114
- isAddPendingDocument: false,
6115
- isCollectionSpecific: true
6116
- });
6117
- return result;
6259
+ (yup3) => yup3.object({
6260
+ relativePath: yup3.string().required()
6261
+ })
6262
+ );
6263
+ if (isMutation) {
6264
+ assertShape(
6265
+ args,
6266
+ (yup3) => yup3.object({
6267
+ params: yup3.object().required()
6268
+ })
6269
+ );
6270
+ if (isCreation) {
6271
+ return resolver.resolveCreateDocument({
6272
+ collectionName: lookup.collection,
6273
+ relativePath: args.relativePath,
6274
+ body: args.params
6275
+ });
6276
+ } else {
6277
+ return resolver.resolveUpdateDocument({
6278
+ collectionName: lookup.collection,
6279
+ relativePath: args.relativePath,
6280
+ newBody: args.params
6281
+ });
6282
+ }
6283
+ } else {
6284
+ return resolver.resolveRetrievedDocument({
6285
+ collectionName: lookup.collection,
6286
+ relativePath: args.relativePath
6287
+ });
6288
+ }
6118
6289
  }
6119
- /**
6290
+ /*
6120
6291
  * Collections-specific list getter
6121
6292
  * eg. `getPageList`
6122
6293
  */
6123
6294
  case "collectionDocumentList":
6295
+ const collectionArgs = args;
6124
6296
  return resolver.resolveCollectionConnection({
6125
- args,
6297
+ args: collectionArgs,
6126
6298
  collection: tinaSchema.getCollection(lookup.collection)
6127
6299
  });
6128
- /**
6300
+ /*
6129
6301
  * A polymorphic data set, it can be from a document's data
6130
6302
  * of any nested object which can be one of many shapes
6131
6303
  *
@@ -6143,22 +6315,52 @@ var resolve = async ({
6143
6315
  * ```
6144
6316
  */
6145
6317
  case "unionData":
6146
- if (!value) {
6147
- if (args.relativePath) {
6148
- const result = await resolver.resolveDocument({
6318
+ const unionValue = source[info.fieldName];
6319
+ if (!unionValue) {
6320
+ const unionArgs = args;
6321
+ if (unionArgs.relativePath) {
6322
+ assertShape(
6149
6323
  args,
6150
- collection: lookup.collection,
6151
- isMutation,
6152
- isCreation,
6153
- isAddPendingDocument: false,
6154
- isCollectionSpecific: true
6155
- });
6156
- return result;
6324
+ (yup3) => yup3.object({
6325
+ relativePath: yup3.string().required()
6326
+ })
6327
+ );
6328
+ if (isMutation) {
6329
+ assertShape(
6330
+ args,
6331
+ (yup3) => yup3.object({
6332
+ params: yup3.object().required()
6333
+ })
6334
+ );
6335
+ if (isCreation) {
6336
+ return resolver.resolveCreateDocument({
6337
+ collectionName: lookup.collection,
6338
+ relativePath: args.relativePath,
6339
+ body: args.params
6340
+ });
6341
+ } else {
6342
+ return resolver.resolveUpdateDocument({
6343
+ collectionName: lookup.collection,
6344
+ relativePath: args.relativePath,
6345
+ newBody: args.params
6346
+ });
6347
+ }
6348
+ } else {
6349
+ return resolver.resolveRetrievedDocument({
6350
+ collectionName: lookup.collection,
6351
+ relativePath: args.relativePath
6352
+ });
6353
+ }
6157
6354
  }
6158
6355
  }
6159
- return value;
6356
+ return unionValue;
6160
6357
  default:
6161
- console.error(lookup);
6358
+ console.error(
6359
+ `Could not recognize resolve type '${lookup.resolveType}'.`
6360
+ );
6361
+ console.error(
6362
+ "The field resolver needs to be updated to handle this new type."
6363
+ );
6162
6364
  throw new Error("Unexpected resolve type");
6163
6365
  }
6164
6366
  } catch (e) {
@@ -6194,6 +6396,40 @@ var resolve = async ({
6194
6396
  throw e;
6195
6397
  }
6196
6398
  };
6399
+ var handleCollectionsField = (info, tinaSchema, resolver, args) => {
6400
+ const collectionNode = info.fieldNodes.find(
6401
+ (x) => x.name.value === "collections"
6402
+ );
6403
+ const hasDocuments = collectionNode.selectionSet.selections.find(
6404
+ (x) => x.kind == "Field" && x?.name?.value === "documents"
6405
+ );
6406
+ return tinaSchema.getCollections().map((collection) => {
6407
+ return resolver.resolveCollection(
6408
+ args,
6409
+ collection.name,
6410
+ Boolean(hasDocuments)
6411
+ );
6412
+ });
6413
+ };
6414
+ var handleCollectionField = (info, args, resolver) => {
6415
+ const collectionNode = info.fieldNodes.find(
6416
+ (x) => x.name.value === "collection"
6417
+ );
6418
+ const hasDocuments = collectionNode.selectionSet.selections.find(
6419
+ (x) => x.kind == "Field" && x?.name?.value === "documents"
6420
+ );
6421
+ assertShape(
6422
+ args,
6423
+ (yup3) => yup3.object({
6424
+ collection: yup3.string().required()
6425
+ })
6426
+ );
6427
+ return resolver.resolveCollection(
6428
+ args,
6429
+ args.collection,
6430
+ Boolean(hasDocuments)
6431
+ );
6432
+ };
6197
6433
 
6198
6434
  // src/level/tinaLevel.ts
6199
6435
  import { ManyLevelGuest } from "many-level";
@@ -6217,7 +6453,7 @@ var TinaLevelClient = class extends ManyLevelGuest {
6217
6453
  };
6218
6454
 
6219
6455
  // src/database/index.ts
6220
- import path4 from "node:path";
6456
+ import path5 from "node:path";
6221
6457
  import { GraphQLError as GraphQLError5 } from "graphql";
6222
6458
  import micromatch2 from "micromatch";
6223
6459
  import sha2 from "js-sha1";
@@ -6308,7 +6544,7 @@ var Database = class {
6308
6544
  } catch (e) {
6309
6545
  }
6310
6546
  };
6311
- getGeneratedFolder = () => path4.join(this.tinaDirectory, "__generated__");
6547
+ getGeneratedFolder = () => path5.join(this.tinaDirectory, "__generated__");
6312
6548
  async updateDatabaseVersion(version) {
6313
6549
  let metadataLevel = this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
6314
6550
  if (this.contentNamespace) {
@@ -6724,7 +6960,7 @@ var Database = class {
6724
6960
  );
6725
6961
  const writeTemplateKey = templateDetails.info.type === "union";
6726
6962
  const aliasedData = applyNameOverrides(templateDetails.template, payload);
6727
- const extension = path4.extname(filepath);
6963
+ const extension = path5.extname(filepath);
6728
6964
  return stringifyFile(
6729
6965
  aliasedData,
6730
6966
  extension,
@@ -6756,7 +6992,7 @@ var Database = class {
6756
6992
  getLookup = async (returnType) => {
6757
6993
  await this.initLevel();
6758
6994
  const lookupPath = normalizePath(
6759
- path4.join(this.getGeneratedFolder(), `_lookup.json`)
6995
+ path5.join(this.getGeneratedFolder(), `_lookup.json`)
6760
6996
  );
6761
6997
  if (!this._lookup) {
6762
6998
  this._lookup = await this.contentLevel.sublevel(
@@ -6769,7 +7005,7 @@ var Database = class {
6769
7005
  getGraphQLSchema = async () => {
6770
7006
  await this.initLevel();
6771
7007
  const graphqlPath = normalizePath(
6772
- path4.join(this.getGeneratedFolder(), `_graphql.json`)
7008
+ path5.join(this.getGeneratedFolder(), `_graphql.json`)
6773
7009
  );
6774
7010
  return await this.contentLevel.sublevel(
6775
7011
  CONTENT_ROOT_PREFIX,
@@ -6782,7 +7018,7 @@ var Database = class {
6782
7018
  throw new Error(`No bridge configured`);
6783
7019
  }
6784
7020
  const graphqlPath = normalizePath(
6785
- path4.join(this.getGeneratedFolder(), `_graphql.json`)
7021
+ path5.join(this.getGeneratedFolder(), `_graphql.json`)
6786
7022
  );
6787
7023
  const _graphql = await this.bridge.get(graphqlPath);
6788
7024
  return JSON.parse(_graphql);
@@ -6790,7 +7026,7 @@ var Database = class {
6790
7026
  getTinaSchema = async (level) => {
6791
7027
  await this.initLevel();
6792
7028
  const schemaPath = normalizePath(
6793
- path4.join(this.getGeneratedFolder(), `_schema.json`)
7029
+ path5.join(this.getGeneratedFolder(), `_schema.json`)
6794
7030
  );
6795
7031
  return await (level || this.contentLevel).sublevel(
6796
7032
  CONTENT_ROOT_PREFIX,
@@ -6806,7 +7042,7 @@ var Database = class {
6806
7042
  if (!schema) {
6807
7043
  throw new Error(
6808
7044
  `Unable to get schema from level db: ${normalizePath(
6809
- path4.join(this.getGeneratedFolder(), `_schema.json`)
7045
+ path5.join(this.getGeneratedFolder(), `_schema.json`)
6810
7046
  )}`
6811
7047
  );
6812
7048
  }
@@ -7039,21 +7275,21 @@ var Database = class {
7039
7275
  edges,
7040
7276
  async ({
7041
7277
  cursor,
7042
- path: path7,
7278
+ path: path8,
7043
7279
  value
7044
7280
  }) => {
7045
7281
  try {
7046
- const node = await hydrator(path7, value);
7282
+ const node = await hydrator(path8, value);
7047
7283
  return {
7048
7284
  node,
7049
7285
  cursor: btoa(cursor)
7050
7286
  };
7051
7287
  } catch (error) {
7052
7288
  console.log(error);
7053
- if (error instanceof Error && (!path7.includes(".tina/__generated__/_graphql.json") || !path7.includes("tina/__generated__/_graphql.json"))) {
7289
+ if (error instanceof Error && (!path8.includes(".tina/__generated__/_graphql.json") || !path8.includes("tina/__generated__/_graphql.json"))) {
7054
7290
  throw new TinaQueryError({
7055
7291
  originalError: error,
7056
- file: path7,
7292
+ file: path8,
7057
7293
  collection: collection.name
7058
7294
  });
7059
7295
  }
@@ -7100,7 +7336,7 @@ var Database = class {
7100
7336
  lookup = lookupFromLockFile || JSON.parse(
7101
7337
  await this.bridge.get(
7102
7338
  normalizePath(
7103
- path4.join(this.getGeneratedFolder(), "_lookup.json")
7339
+ path5.join(this.getGeneratedFolder(), "_lookup.json")
7104
7340
  )
7105
7341
  )
7106
7342
  );
@@ -7124,15 +7360,15 @@ var Database = class {
7124
7360
  }
7125
7361
  const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
7126
7362
  await contentRootLevel.put(
7127
- normalizePath(path4.join(this.getGeneratedFolder(), "_graphql.json")),
7363
+ normalizePath(path5.join(this.getGeneratedFolder(), "_graphql.json")),
7128
7364
  graphQLSchema
7129
7365
  );
7130
7366
  await contentRootLevel.put(
7131
- normalizePath(path4.join(this.getGeneratedFolder(), "_schema.json")),
7367
+ normalizePath(path5.join(this.getGeneratedFolder(), "_schema.json")),
7132
7368
  tinaSchema.schema
7133
7369
  );
7134
7370
  await contentRootLevel.put(
7135
- normalizePath(path4.join(this.getGeneratedFolder(), "_lookup.json")),
7371
+ normalizePath(path5.join(this.getGeneratedFolder(), "_lookup.json")),
7136
7372
  lookup
7137
7373
  );
7138
7374
  const result = await this._indexAllContent(
@@ -7341,8 +7577,8 @@ var Database = class {
7341
7577
  return { warnings };
7342
7578
  };
7343
7579
  };
7344
- var hashPasswordVisitor = async (node, path7) => {
7345
- const passwordValuePath = [...path7, "value"];
7580
+ var hashPasswordVisitor = async (node, path8) => {
7581
+ const passwordValuePath = [...path8, "value"];
7346
7582
  const plaintextPassword = get(node, passwordValuePath);
7347
7583
  if (plaintextPassword) {
7348
7584
  set2(
@@ -7352,10 +7588,10 @@ var hashPasswordVisitor = async (node, path7) => {
7352
7588
  );
7353
7589
  }
7354
7590
  };
7355
- var visitNodes = async (node, path7, callback) => {
7356
- const [currentLevel, ...remainingLevels] = path7;
7591
+ var visitNodes = async (node, path8, callback) => {
7592
+ const [currentLevel, ...remainingLevels] = path8;
7357
7593
  if (!remainingLevels?.length) {
7358
- return callback(node, path7);
7594
+ return callback(node, path8);
7359
7595
  }
7360
7596
  if (Array.isArray(node[currentLevel])) {
7361
7597
  for (const item of node[currentLevel]) {
@@ -7598,13 +7834,13 @@ var _deleteIndexContent = async (database, documentPaths, enqueueOps, collection
7598
7834
  // src/git/index.ts
7599
7835
  import git from "isomorphic-git";
7600
7836
  import fs from "fs-extra";
7601
- import path5 from "path";
7837
+ import path6 from "path";
7602
7838
  import micromatch3 from "micromatch";
7603
7839
  var findGitRoot = async (dir) => {
7604
- if (await fs.pathExists(path5.join(dir, ".git"))) {
7840
+ if (await fs.pathExists(path6.join(dir, ".git"))) {
7605
7841
  return dir;
7606
7842
  }
7607
- const parentDir = path5.dirname(dir);
7843
+ const parentDir = path6.dirname(dir);
7608
7844
  if (parentDir === dir) {
7609
7845
  throw new Error("Could not find .git directory");
7610
7846
  }
@@ -7686,19 +7922,19 @@ var shaExists = async ({
7686
7922
  // src/database/bridge/filesystem.ts
7687
7923
  import fs2 from "fs-extra";
7688
7924
  import fg from "fast-glob";
7689
- import path6 from "path";
7925
+ import path7 from "path";
7690
7926
  import normalize from "normalize-path";
7691
7927
  var FilesystemBridge = class {
7692
7928
  rootPath;
7693
7929
  outputPath;
7694
7930
  constructor(rootPath, outputPath) {
7695
- this.rootPath = path6.resolve(rootPath);
7696
- this.outputPath = outputPath ? path6.resolve(outputPath) : this.rootPath;
7931
+ this.rootPath = path7.resolve(rootPath);
7932
+ this.outputPath = outputPath ? path7.resolve(outputPath) : this.rootPath;
7697
7933
  }
7698
7934
  async glob(pattern, extension) {
7699
- const basePath = path6.join(this.outputPath, ...pattern.split("/"));
7935
+ const basePath = path7.join(this.outputPath, ...pattern.split("/"));
7700
7936
  const items = await fg(
7701
- path6.join(basePath, "**", `/*.${extension}`).replace(/\\/g, "/"),
7937
+ path7.join(basePath, "**", `/*.${extension}`).replace(/\\/g, "/"),
7702
7938
  {
7703
7939
  dot: true,
7704
7940
  ignore: ["**/node_modules/**"]
@@ -7710,14 +7946,14 @@ var FilesystemBridge = class {
7710
7946
  );
7711
7947
  }
7712
7948
  async delete(filepath) {
7713
- await fs2.remove(path6.join(this.outputPath, filepath));
7949
+ await fs2.remove(path7.join(this.outputPath, filepath));
7714
7950
  }
7715
7951
  async get(filepath) {
7716
- return (await fs2.readFile(path6.join(this.outputPath, filepath))).toString();
7952
+ return (await fs2.readFile(path7.join(this.outputPath, filepath))).toString();
7717
7953
  }
7718
7954
  async put(filepath, data, basePathOverride) {
7719
7955
  const basePath = basePathOverride || this.outputPath;
7720
- await fs2.outputFile(path6.join(basePath, filepath), data);
7956
+ await fs2.outputFile(path7.join(basePath, filepath), data);
7721
7957
  }
7722
7958
  };
7723
7959
  var AuditFileSystemBridge = class extends FilesystemBridge {
@@ -7821,7 +8057,7 @@ var IsomorphicBridge = class {
7821
8057
  async listEntries({
7822
8058
  pattern,
7823
8059
  entry,
7824
- path: path7,
8060
+ path: path8,
7825
8061
  results
7826
8062
  }) {
7827
8063
  const treeResult = await git2.readTree({
@@ -7831,7 +8067,7 @@ var IsomorphicBridge = class {
7831
8067
  });
7832
8068
  const children = [];
7833
8069
  for (const childEntry of treeResult.tree) {
7834
- const childPath = path7 ? `${path7}/${childEntry.path}` : childEntry.path;
8070
+ const childPath = path8 ? `${path8}/${childEntry.path}` : childEntry.path;
7835
8071
  if (childEntry.type === "tree") {
7836
8072
  children.push(childEntry);
7837
8073
  } else {
@@ -7841,7 +8077,7 @@ var IsomorphicBridge = class {
7841
8077
  }
7842
8078
  }
7843
8079
  for (const childEntry of children) {
7844
- const childPath = path7 ? `${path7}/${childEntry.path}` : childEntry.path;
8080
+ const childPath = path8 ? `${path8}/${childEntry.path}` : childEntry.path;
7845
8081
  await this.listEntries({
7846
8082
  pattern,
7847
8083
  entry: childEntry,
@@ -7859,17 +8095,17 @@ var IsomorphicBridge = class {
7859
8095
  * @param ref - ref to resolve path entries for
7860
8096
  * @private
7861
8097
  */
7862
- async resolvePathEntries(path7, ref) {
7863
- let pathParts = path7.split("/");
8098
+ async resolvePathEntries(path8, ref) {
8099
+ let pathParts = path8.split("/");
7864
8100
  const result = await git2.walk({
7865
8101
  ...this.isomorphicConfig,
7866
8102
  map: async (filepath, [head]) => {
7867
8103
  if (head._fullpath === ".") {
7868
8104
  return head;
7869
8105
  }
7870
- if (path7.startsWith(filepath)) {
7871
- if (dirname(path7) === dirname(filepath)) {
7872
- if (path7 === filepath) {
8106
+ if (path8.startsWith(filepath)) {
8107
+ if (dirname(path8) === dirname(filepath)) {
8108
+ if (path8 === filepath) {
7873
8109
  return head;
7874
8110
  }
7875
8111
  } else {
@@ -7900,7 +8136,7 @@ var IsomorphicBridge = class {
7900
8136
  * @param pathParts - parent path parts
7901
8137
  * @private
7902
8138
  */
7903
- async updateTreeHierarchy(existingOid, updatedOid, path7, type, pathEntries, pathParts) {
8139
+ async updateTreeHierarchy(existingOid, updatedOid, path8, type, pathEntries, pathParts) {
7904
8140
  const lastIdx = pathEntries.length - 1;
7905
8141
  const parentEntry = pathEntries[lastIdx];
7906
8142
  const parentPath = pathParts[lastIdx];
@@ -7915,7 +8151,7 @@ var IsomorphicBridge = class {
7915
8151
  cache: this.cache
7916
8152
  });
7917
8153
  tree = existingOid ? treeResult.tree.map((entry) => {
7918
- if (entry.path === path7) {
8154
+ if (entry.path === path8) {
7919
8155
  entry.oid = updatedOid;
7920
8156
  }
7921
8157
  return entry;
@@ -7924,7 +8160,7 @@ var IsomorphicBridge = class {
7924
8160
  {
7925
8161
  oid: updatedOid,
7926
8162
  type,
7927
- path: path7,
8163
+ path: path8,
7928
8164
  mode
7929
8165
  }
7930
8166
  ];
@@ -7933,7 +8169,7 @@ var IsomorphicBridge = class {
7933
8169
  {
7934
8170
  oid: updatedOid,
7935
8171
  type,
7936
- path: path7,
8172
+ path: path8,
7937
8173
  mode
7938
8174
  }
7939
8175
  ];
@@ -8042,7 +8278,7 @@ var IsomorphicBridge = class {
8042
8278
  path: parentPath,
8043
8279
  results
8044
8280
  });
8045
- return results.map((path7) => this.unqualifyPath(path7)).filter((path7) => path7.endsWith(extension));
8281
+ return results.map((path8) => this.unqualifyPath(path8)).filter((path8) => path8.endsWith(extension));
8046
8282
  }
8047
8283
  async delete(filepath) {
8048
8284
  const ref = await this.getRef();