@tinacms/graphql 1.3.5 → 1.4.0

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
@@ -46,13 +46,10 @@ __export(src_exports, {
46
46
  stringifyFile: () => stringifyFile
47
47
  });
48
48
  module.exports = __toCommonJS(src_exports);
49
- var import_fs_extra4 = __toESM(require("fs-extra"));
50
- var import_path6 = __toESM(require("path"));
51
49
  var import_graphql7 = require("graphql");
52
50
 
53
51
  // src/build.ts
54
52
  var import_lodash3 = __toESM(require("lodash"));
55
- var import_fs_extra = __toESM(require("fs-extra"));
56
53
  var import_graphql2 = require("graphql");
57
54
 
58
55
  // src/ast-builder/index.ts
@@ -2436,19 +2433,29 @@ var validationCollectionsPathAndMatch = (collections) => {
2436
2433
  }
2437
2434
  const noMatchCollections = collections.filter((x) => {
2438
2435
  return typeof (x == null ? void 0 : x.match) === "undefined";
2439
- }).map((x) => x.path);
2436
+ }).map((x) => `${x.path}${x.format || "md"}`);
2440
2437
  if (noMatchCollections.length !== new Set(noMatchCollections).size) {
2441
- throw new Error("path must be unique");
2438
+ throw new Error(
2439
+ "Two collections without match can not have the same `path`. Please make the `path` unique or add a matches property to the collection."
2440
+ );
2442
2441
  }
2443
2442
  const hasMatchAndPath = collections.filter((x) => {
2444
2443
  return typeof x.path !== "undefined" && typeof x.match !== "undefined";
2445
- }).map((x) => `${x.path}|${x.match}`);
2444
+ }).map(
2445
+ (x) => {
2446
+ var _a, _b;
2447
+ 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"}`;
2448
+ }
2449
+ );
2446
2450
  if (hasMatchAndPath.length !== new Set(hasMatchAndPath).size) {
2447
- throw new Error("Both `match` and `path` can not be the same");
2451
+ throw new Error(
2452
+ "Can not have two or more collections with the same path and match. Please update either the path or the match to be unique."
2453
+ );
2448
2454
  }
2449
2455
  const groupbyPath = collections.reduce((r, a) => {
2450
- r[a.path] = r[a.path] || [];
2451
- r[a.path].push(a);
2456
+ const key = `${a.path}|${a.format || "md"}`;
2457
+ r[key] = r[key] || [];
2458
+ r[key].push(a);
2452
2459
  return r;
2453
2460
  }, /* @__PURE__ */ Object.create(null));
2454
2461
  Object.keys(groupbyPath).forEach((key) => {
@@ -2456,12 +2463,20 @@ var validationCollectionsPathAndMatch = (collections) => {
2456
2463
  if (collectionsArr.length === 1) {
2457
2464
  return;
2458
2465
  }
2459
- const matches = collectionsArr.filter((x) => {
2460
- return typeof x.match !== "undefined";
2461
- });
2462
- if (matches.length !== collections.length) {
2463
- throw new Error("path must be unique when no `match` is provided");
2466
+ if (collectionsArr.some((x) => typeof x.match === "undefined")) {
2467
+ throw new Error(
2468
+ "Can not have two or more collections with the same path and format if one doesn't have a match property"
2469
+ );
2470
+ }
2471
+ const matches = collectionsArr.map(
2472
+ (x) => typeof (x == null ? void 0 : x.match) === "object" ? JSON.stringify(x.match) : ""
2473
+ );
2474
+ if (matches.length === new Set(matches).size) {
2475
+ return;
2464
2476
  }
2477
+ throw new Error(
2478
+ "Can not have two or more collections with the same path format and match. Please update either the path or the match to be unique."
2479
+ );
2465
2480
  });
2466
2481
  };
2467
2482
  var validateCollection = async (collection) => {
@@ -2527,7 +2542,7 @@ var validateField = async (field) => {
2527
2542
  // package.json
2528
2543
  var package_default = {
2529
2544
  name: "@tinacms/graphql",
2530
- version: "1.3.5",
2545
+ version: "1.4.0",
2531
2546
  main: "dist/index.js",
2532
2547
  module: "dist/index.es.js",
2533
2548
  typings: "dist/index.d.ts",
@@ -2590,6 +2605,7 @@ var package_default = {
2590
2605
  "mdast-util-mdx-expression": "^1.1.0",
2591
2606
  "mdast-util-to-markdown": "^1.2.1",
2592
2607
  "micromark-extension-mdxjs": "^1.0.0",
2608
+ micromatch: "4.0.5",
2593
2609
  "normalize-path": "^3.0.0",
2594
2610
  prettier: "^2.2.1",
2595
2611
  "readable-stream": "^4.3.0",
@@ -2630,6 +2646,7 @@ var package_default = {
2630
2646
  "@types/lodash.upperfirst": "^4.3.6",
2631
2647
  "@types/lru-cache": "^5.1.0",
2632
2648
  "@types/mdast": "^3.0.10",
2649
+ "@types/micromatch": "^4.0.2",
2633
2650
  "@types/node": "^14.17.34",
2634
2651
  "@types/normalize-path": "^3.0.0",
2635
2652
  "@types/ws": "^7.2.6",
@@ -2668,7 +2685,6 @@ var createSchema = async ({
2668
2685
  };
2669
2686
 
2670
2687
  // src/build.ts
2671
- var import_path = __toESM(require("path"));
2672
2688
  var buildDotTinaFiles = async ({
2673
2689
  database,
2674
2690
  config,
@@ -2678,7 +2694,11 @@ var buildDotTinaFiles = async ({
2678
2694
  if (flags.indexOf("experimentalData") === -1) {
2679
2695
  flags.push("experimentalData");
2680
2696
  }
2681
- const tinaSchema = await createSchema({ schema: config, flags });
2697
+ const { schema } = config;
2698
+ const tinaSchema = await createSchema({
2699
+ schema: { ...schema, config },
2700
+ flags
2701
+ });
2682
2702
  const builder = await createBuilder({
2683
2703
  database,
2684
2704
  tinaSchema
@@ -2692,11 +2712,21 @@ var buildDotTinaFiles = async ({
2692
2712
  await database.bridge.get(".tina/__generated__/_graphql.json")
2693
2713
  );
2694
2714
  }
2715
+ let fragDoc = "";
2716
+ let queryDoc = "";
2695
2717
  if (buildSDK) {
2696
- await _buildFragments(builder, tinaSchema, database.bridge.rootPath);
2697
- await _buildQueries(builder, tinaSchema, database.bridge.rootPath);
2718
+ fragDoc = await _buildFragments(
2719
+ builder,
2720
+ tinaSchema,
2721
+ database.bridge.rootPath
2722
+ );
2723
+ queryDoc = await _buildQueries(
2724
+ builder,
2725
+ tinaSchema,
2726
+ database.bridge.rootPath
2727
+ );
2698
2728
  }
2699
- return { graphQLSchema, tinaSchema };
2729
+ return { graphQLSchema, tinaSchema, fragDoc, queryDoc };
2700
2730
  };
2701
2731
  var _buildFragments = async (builder, tinaSchema, rootPath) => {
2702
2732
  const fragmentDefinitionsFields = [];
@@ -2714,23 +2744,7 @@ var _buildFragments = async (builder, tinaSchema, rootPath) => {
2714
2744
  (node) => node.name.value
2715
2745
  )
2716
2746
  };
2717
- const fragPath = import_path.default.join(rootPath, ".tina", "__generated__");
2718
- await import_fs_extra.default.outputFile(import_path.default.join(fragPath, "frags.gql"), (0, import_graphql2.print)(fragDoc));
2719
- if (await (await import_fs_extra.default.stat(import_path.default.join(fragPath, "frags.gql"))).size > 100 * 1024) {
2720
- console.warn(
2721
- "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
2722
- );
2723
- console.log(
2724
- `const schema = defineSchema({
2725
- config: {
2726
- client: {
2727
- referenceDepth: 1,
2728
- },
2729
- }
2730
- // ...
2731
- })`
2732
- );
2733
- }
2747
+ return (0, import_graphql2.print)(fragDoc);
2734
2748
  };
2735
2749
  var _buildQueries = async (builder, tinaSchema, rootPath) => {
2736
2750
  const operationsDefinitions = [];
@@ -2762,8 +2776,7 @@ var _buildQueries = async (builder, tinaSchema, rootPath) => {
2762
2776
  (node) => node.name.value
2763
2777
  )
2764
2778
  };
2765
- const fragPath = import_path.default.join(rootPath, ".tina", "__generated__");
2766
- await import_fs_extra.default.outputFile(import_path.default.join(fragPath, "queries.gql"), (0, import_graphql2.print)(queryDoc));
2779
+ return (0, import_graphql2.print)(queryDoc);
2767
2780
  };
2768
2781
  var _buildSchema = async (builder, tinaSchema) => {
2769
2782
  const definitions = [];
@@ -2844,7 +2857,7 @@ var _buildSchema = async (builder, tinaSchema) => {
2844
2857
  var import_graphql4 = require("graphql");
2845
2858
 
2846
2859
  // src/resolver/index.ts
2847
- var import_path2 = __toESM(require("path"));
2860
+ var import_path = __toESM(require("path"));
2848
2861
  var import_isValid = __toESM(require("date-fns/isValid"));
2849
2862
 
2850
2863
  // src/mdx/index.ts
@@ -3054,9 +3067,9 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
3054
3067
  return value;
3055
3068
  }
3056
3069
  };
3057
- var cleanUpSlashes = (path6) => {
3058
- if (path6) {
3059
- return `/${path6.replace(/^\/+|\/+$/gm, "")}`;
3070
+ var cleanUpSlashes = (path4) => {
3071
+ if (path4) {
3072
+ return `/${path4.replace(/^\/+|\/+$/gm, "")}`;
3060
3073
  }
3061
3074
  return "";
3062
3075
  };
@@ -3521,7 +3534,11 @@ var makeStringEscaper = (regex, replacement) => {
3521
3534
  (val) => val.replace(regex, replacement)
3522
3535
  );
3523
3536
  } else {
3524
- return input.replace(regex, replacement);
3537
+ if (typeof input === "string") {
3538
+ return input.replace(regex, replacement);
3539
+ } else {
3540
+ return input;
3541
+ }
3525
3542
  }
3526
3543
  };
3527
3544
  };
@@ -3561,7 +3578,7 @@ var Resolver = class {
3561
3578
  base: basename,
3562
3579
  ext: extension,
3563
3580
  name: filename
3564
- } = import_path2.default.parse(fullPath);
3581
+ } = import_path.default.parse(fullPath);
3565
3582
  const relativePath = fullPath.replace(/\\/g, "/").replace(collection.path, "").replace(/^\/|\/$/g, "");
3566
3583
  const breadcrumbs = relativePath.replace(extension, "").split("/");
3567
3584
  const data = {
@@ -3804,7 +3821,7 @@ var Resolver = class {
3804
3821
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
3805
3822
  );
3806
3823
  const collection = await this.tinaSchema.getCollection(collectionLookup);
3807
- const realPath = import_path2.default.join(collection == null ? void 0 : collection.path, args.relativePath);
3824
+ const realPath = import_path.default.join(collection == null ? void 0 : collection.path, args.relativePath);
3808
3825
  const alreadyExists = await this.database.documentExists(realPath);
3809
3826
  if (isMutation) {
3810
3827
  if (isCreation) {
@@ -3845,7 +3862,7 @@ var Resolver = class {
3845
3862
  (yup3) => yup3.object({ relativePath: yup3.string().required() })
3846
3863
  );
3847
3864
  const doc = await this.getDocument(realPath);
3848
- const newRealPath = import_path2.default.join(
3865
+ const newRealPath = import_path.default.join(
3849
3866
  collection == null ? void 0 : collection.path,
3850
3867
  args.params.relativePath
3851
3868
  );
@@ -3900,7 +3917,7 @@ var Resolver = class {
3900
3917
  first: -1
3901
3918
  },
3902
3919
  collection: referencedCollection,
3903
- hydrator: (path6) => path6
3920
+ hydrator: (path4) => path4
3904
3921
  }
3905
3922
  );
3906
3923
  const { edges } = resolvedCollectionConnection;
@@ -4434,13 +4451,15 @@ var resolve = async ({
4434
4451
  };
4435
4452
 
4436
4453
  // src/database/index.ts
4437
- var import_path3 = __toESM(require("path"));
4454
+ var import_path2 = __toESM(require("path"));
4438
4455
  var import_graphql5 = require("graphql");
4456
+ var import_micromatch = __toESM(require("micromatch"));
4439
4457
 
4440
4458
  // src/database/util.ts
4441
4459
  var import_toml = __toESM(require("@iarna/toml"));
4442
4460
  var import_js_yaml = __toESM(require("js-yaml"));
4443
4461
  var import_gray_matter = __toESM(require("gray-matter"));
4462
+ var import_schema_tools3 = require("@tinacms/schema-tools");
4444
4463
  var matterEngines = {
4445
4464
  toml: {
4446
4465
  parse: (val) => import_toml.default.parse(val),
@@ -4524,7 +4543,6 @@ var parseFile = (content, format, yupSchema, markdownParseConfig) => {
4524
4543
  throw new Error(`Must specify a valid format, got ${format}`);
4525
4544
  }
4526
4545
  };
4527
- var normalizePath = (filepath) => filepath.replace(/\\/g, "/");
4528
4546
 
4529
4547
  // src/database/alias-utils.ts
4530
4548
  var replaceNameOverrides = (template, obj) => {
@@ -4615,18 +4633,18 @@ var Database = class {
4615
4633
  const tinaSchema = await this.getSchema(this.level);
4616
4634
  return tinaSchema.getCollectionByFullPath(filepath);
4617
4635
  };
4618
- this.getGeneratedFolder = () => import_path3.default.join(this.tinaDirectory, "__generated__");
4636
+ this.getGeneratedFolder = () => import_path2.default.join(this.tinaDirectory, "__generated__");
4619
4637
  this.get = async (filepath) => {
4620
4638
  await this.initLevel();
4621
4639
  if (SYSTEM_FILES.includes(filepath)) {
4622
4640
  throw new Error(`Unexpected get for config file ${filepath}`);
4623
4641
  } else {
4624
4642
  const tinaSchema = await this.getSchema(this.level);
4625
- const extension = import_path3.default.extname(filepath);
4643
+ const extension = import_path2.default.extname(filepath);
4626
4644
  const contentObject = await this.level.sublevel(
4627
4645
  CONTENT_ROOT_PREFIX,
4628
4646
  SUBLEVEL_OPTIONS
4629
- ).get(normalizePath(filepath));
4647
+ ).get((0, import_schema_tools3.normalizePath)(filepath));
4630
4648
  if (!contentObject) {
4631
4649
  throw new import_graphql5.GraphQLError(`Unable to find record ${filepath}`);
4632
4650
  }
@@ -4672,7 +4690,7 @@ var Database = class {
4672
4690
  const indexDefinitions = await this.getIndexDefinitions(this.level);
4673
4691
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
4674
4692
  }
4675
- const normalizedPath = normalizePath(filepath);
4693
+ const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
4676
4694
  if (this.bridge) {
4677
4695
  await this.bridge.put(normalizedPath, stringifiedFile);
4678
4696
  }
@@ -4713,6 +4731,7 @@ var Database = class {
4713
4731
  await this.level.batch(ops);
4714
4732
  };
4715
4733
  this.put = async (filepath, data, collectionName) => {
4734
+ var _a, _b;
4716
4735
  await this.initLevel();
4717
4736
  try {
4718
4737
  if (SYSTEM_FILES.includes(filepath)) {
@@ -4723,9 +4742,20 @@ var Database = class {
4723
4742
  const indexDefinitions = await this.getIndexDefinitions(this.level);
4724
4743
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collectionName];
4725
4744
  }
4726
- const normalizedPath = normalizePath(filepath);
4745
+ const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
4727
4746
  const dataFields = await this.formatBodyOnPayload(filepath, data);
4728
4747
  const collection = await this.collectionForPath(filepath);
4748
+ if (((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include)) {
4749
+ const matches = this.tinaSchema.getMatches({ collection });
4750
+ const match = import_micromatch.default.isMatch(filepath, matches);
4751
+ if (!match) {
4752
+ throw new import_graphql5.GraphQLError(
4753
+ `File ${filepath} does not match collection ${collection.name} glob ${matches.join(
4754
+ ","
4755
+ )}. Please change the filename or update matches for ${collection.name} in your config file.`
4756
+ );
4757
+ }
4758
+ }
4729
4759
  const stringifiedFile = await this.stringifyFile(
4730
4760
  filepath,
4731
4761
  dataFields,
@@ -4812,7 +4842,7 @@ var Database = class {
4812
4842
  );
4813
4843
  const writeTemplateKey = templateDetails.info.type === "union";
4814
4844
  const aliasedData = applyNameOverrides(templateDetails.template, payload);
4815
- const extension = import_path3.default.extname(filepath);
4845
+ const extension = import_path2.default.extname(filepath);
4816
4846
  const stringifiedFile = stringifyFile(
4817
4847
  aliasedData,
4818
4848
  extension,
@@ -4837,8 +4867,8 @@ var Database = class {
4837
4867
  };
4838
4868
  this.getLookup = async (returnType) => {
4839
4869
  await this.initLevel();
4840
- const lookupPath = normalizePath(
4841
- import_path3.default.join(this.getGeneratedFolder(), `_lookup.json`)
4870
+ const lookupPath = (0, import_schema_tools3.normalizePath)(
4871
+ import_path2.default.join(this.getGeneratedFolder(), `_lookup.json`)
4842
4872
  );
4843
4873
  if (!this._lookup) {
4844
4874
  const _lookup = await this.level.sublevel(
@@ -4851,8 +4881,8 @@ var Database = class {
4851
4881
  };
4852
4882
  this.getGraphQLSchema = async () => {
4853
4883
  await this.initLevel();
4854
- const graphqlPath = normalizePath(
4855
- import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`)
4884
+ const graphqlPath = (0, import_schema_tools3.normalizePath)(
4885
+ import_path2.default.join(this.getGeneratedFolder(), `_graphql.json`)
4856
4886
  );
4857
4887
  return await this.level.sublevel(
4858
4888
  CONTENT_ROOT_PREFIX,
@@ -4863,16 +4893,16 @@ var Database = class {
4863
4893
  if (!this.bridge) {
4864
4894
  throw new Error(`No bridge configured`);
4865
4895
  }
4866
- const graphqlPath = normalizePath(
4867
- import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`)
4896
+ const graphqlPath = (0, import_schema_tools3.normalizePath)(
4897
+ import_path2.default.join(this.getGeneratedFolder(), `_graphql.json`)
4868
4898
  );
4869
4899
  const _graphql = await this.bridge.get(graphqlPath);
4870
4900
  return JSON.parse(_graphql);
4871
4901
  };
4872
4902
  this.getTinaSchema = async (level) => {
4873
4903
  await this.initLevel();
4874
- const schemaPath = normalizePath(
4875
- import_path3.default.join(this.getGeneratedFolder(), `_schema.json`)
4904
+ const schemaPath = (0, import_schema_tools3.normalizePath)(
4905
+ import_path2.default.join(this.getGeneratedFolder(), `_schema.json`)
4876
4906
  );
4877
4907
  return await (level || this.level).sublevel(
4878
4908
  CONTENT_ROOT_PREFIX,
@@ -5061,11 +5091,11 @@ var Database = class {
5061
5091
  }) => {
5062
5092
  if (this.bridge && this.bridge.supportsBuilding()) {
5063
5093
  await this.bridge.putConfig(
5064
- normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`)),
5094
+ (0, import_schema_tools3.normalizePath)(import_path2.default.join(this.getGeneratedFolder(), `_graphql.json`)),
5065
5095
  JSON.stringify(graphQLSchema)
5066
5096
  );
5067
5097
  await this.bridge.putConfig(
5068
- normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_schema.json`)),
5098
+ (0, import_schema_tools3.normalizePath)(import_path2.default.join(this.getGeneratedFolder(), `_schema.json`)),
5069
5099
  JSON.stringify(tinaSchema.schema)
5070
5100
  );
5071
5101
  }
@@ -5079,10 +5109,10 @@ var Database = class {
5079
5109
  throw new Error("No bridge configured");
5080
5110
  }
5081
5111
  await this.initLevel();
5082
- await this.indexStatusCallbackWrapper(async () => {
5112
+ const result = await this.indexStatusCallbackWrapper(async () => {
5083
5113
  const lookup = lookupFromLockFile || JSON.parse(
5084
5114
  await this.bridge.get(
5085
- normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_lookup.json"))
5115
+ (0, import_schema_tools3.normalizePath)(import_path2.default.join(this.getGeneratedFolder(), "_lookup.json"))
5086
5116
  )
5087
5117
  );
5088
5118
  let nextLevel;
@@ -5100,18 +5130,18 @@ var Database = class {
5100
5130
  SUBLEVEL_OPTIONS
5101
5131
  );
5102
5132
  await contentRootLevel.put(
5103
- normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_graphql.json")),
5133
+ (0, import_schema_tools3.normalizePath)(import_path2.default.join(this.getGeneratedFolder(), "_graphql.json")),
5104
5134
  graphQLSchema
5105
5135
  );
5106
5136
  await contentRootLevel.put(
5107
- normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_schema.json")),
5137
+ (0, import_schema_tools3.normalizePath)(import_path2.default.join(this.getGeneratedFolder(), "_schema.json")),
5108
5138
  tinaSchema.schema
5109
5139
  );
5110
5140
  await contentRootLevel.put(
5111
- normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_lookup.json")),
5141
+ (0, import_schema_tools3.normalizePath)(import_path2.default.join(this.getGeneratedFolder(), "_lookup.json")),
5112
5142
  lookup
5113
5143
  );
5114
- await this._indexAllContent(nextLevel);
5144
+ const result2 = await this._indexAllContent(nextLevel);
5115
5145
  if (this.config.version) {
5116
5146
  await this.updateDatabaseVersion(nextVersion);
5117
5147
  if (this.level) {
@@ -5119,7 +5149,9 @@ var Database = class {
5119
5149
  }
5120
5150
  this.level = nextLevel;
5121
5151
  }
5152
+ return result2;
5122
5153
  });
5154
+ return result;
5123
5155
  };
5124
5156
  this.deleteContentByPaths = async (documentPaths) => {
5125
5157
  await this.initLevel();
@@ -5184,7 +5216,7 @@ var Database = class {
5184
5216
  CONTENT_ROOT_PREFIX,
5185
5217
  SUBLEVEL_OPTIONS
5186
5218
  );
5187
- const itemKey = normalizePath(filepath);
5219
+ const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
5188
5220
  const rootSublevel = this.level.sublevel(
5189
5221
  CONTENT_ROOT_PREFIX,
5190
5222
  SUBLEVEL_OPTIONS
@@ -5208,11 +5240,12 @@ var Database = class {
5208
5240
  ]);
5209
5241
  }
5210
5242
  if (this.bridge) {
5211
- await this.bridge.delete(normalizePath(filepath));
5243
+ await this.bridge.delete((0, import_schema_tools3.normalizePath)(filepath));
5212
5244
  }
5213
- await this.onDelete(normalizePath(filepath));
5245
+ await this.onDelete((0, import_schema_tools3.normalizePath)(filepath));
5214
5246
  };
5215
5247
  this._indexAllContent = async (level) => {
5248
+ const warnings = [];
5216
5249
  const tinaSchema = await this.getSchema(level);
5217
5250
  const operations = [];
5218
5251
  const enqueueOps = async (ops) => {
@@ -5222,25 +5255,46 @@ var Database = class {
5222
5255
  await level.batch(batchOps);
5223
5256
  }
5224
5257
  };
5258
+ const filesSeen = /* @__PURE__ */ new Map();
5259
+ const duplicateFiles = /* @__PURE__ */ new Set();
5225
5260
  await sequential(tinaSchema.getCollections(), async (collection) => {
5226
- const documentPaths = await this.bridge.glob(
5227
- normalizePath(collection.path),
5228
- collection.format || "md"
5229
- );
5230
- await _indexContent(this, level, documentPaths, enqueueOps, collection);
5261
+ const normalPath = (0, import_schema_tools3.normalizePath)(collection.path);
5262
+ const format = collection.format || "md";
5263
+ const documentPaths = await this.bridge.glob(normalPath, format);
5264
+ const matches = this.tinaSchema.getMatches({ collection });
5265
+ const filteredPaths = matches.length > 0 ? (0, import_micromatch.default)(documentPaths, matches) : documentPaths;
5266
+ filteredPaths.forEach((path4) => {
5267
+ if (filesSeen.has(path4)) {
5268
+ filesSeen.get(path4).push(collection.name);
5269
+ duplicateFiles.add(path4);
5270
+ } else {
5271
+ filesSeen.set(path4, [collection.name]);
5272
+ }
5273
+ });
5274
+ duplicateFiles.forEach((path4) => {
5275
+ warnings.push(
5276
+ `"${path4}" Found in multiple collections: ${filesSeen.get(path4).map((collection2) => `"${collection2}"`).join(
5277
+ ", "
5278
+ )}. This can cause unexpected behavior. We recommend updating the \`match\` property of those collections so that each file is in only one collection.
5279
+ This will be an error in the future.
5280
+ `
5281
+ );
5282
+ });
5283
+ await _indexContent(this, level, filteredPaths, enqueueOps, collection);
5231
5284
  });
5232
5285
  while (operations.length) {
5233
5286
  await level.batch(operations.splice(0, 25));
5234
5287
  }
5288
+ return { warnings };
5235
5289
  };
5236
5290
  this.addToLookupMap = async (lookup) => {
5237
5291
  if (!this.bridge) {
5238
5292
  throw new Error("No bridge configured");
5239
5293
  }
5240
- const lookupPath = import_path3.default.join(this.getGeneratedFolder(), `_lookup.json`);
5294
+ const lookupPath = import_path2.default.join(this.getGeneratedFolder(), `_lookup.json`);
5241
5295
  let lookupMap;
5242
5296
  try {
5243
- lookupMap = JSON.parse(await this.bridge.get(normalizePath(lookupPath)));
5297
+ lookupMap = JSON.parse(await this.bridge.get((0, import_schema_tools3.normalizePath)(lookupPath)));
5244
5298
  } catch (e) {
5245
5299
  lookupMap = {};
5246
5300
  }
@@ -5249,7 +5303,7 @@ var Database = class {
5249
5303
  [lookup.type]: lookup
5250
5304
  };
5251
5305
  await this.bridge.putConfig(
5252
- normalizePath(lookupPath),
5306
+ (0, import_schema_tools3.normalizePath)(lookupPath),
5253
5307
  JSON.stringify(updatedLookup)
5254
5308
  );
5255
5309
  };
@@ -5338,8 +5392,9 @@ var Database = class {
5338
5392
  async indexStatusCallbackWrapper(fn) {
5339
5393
  await this.indexStatusCallback({ status: "inprogress" });
5340
5394
  try {
5341
- await fn();
5395
+ const result = await fn();
5342
5396
  await this.indexStatusCallback({ status: "complete" });
5397
+ return result;
5343
5398
  } catch (error) {
5344
5399
  await this.indexStatusCallback({ status: "failed", error });
5345
5400
  throw error;
@@ -5365,17 +5420,17 @@ var _indexContent = async (database, level, documentPaths, enqueueOps, collectio
5365
5420
  }
5366
5421
  await sequential(documentPaths, async (filepath) => {
5367
5422
  try {
5368
- const dataString = await database.bridge.get(normalizePath(filepath));
5423
+ const dataString = await database.bridge.get((0, import_schema_tools3.normalizePath)(filepath));
5369
5424
  const data = parseFile(
5370
5425
  dataString,
5371
- import_path3.default.extname(filepath),
5426
+ import_path2.default.extname(filepath),
5372
5427
  (yup3) => yup3.object({}),
5373
5428
  {
5374
5429
  frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
5375
5430
  frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
5376
5431
  }
5377
5432
  );
5378
- const normalizedPath = normalizePath(filepath);
5433
+ const normalizedPath = (0, import_schema_tools3.normalizePath)(filepath);
5379
5434
  const aliasedData = templateInfo ? replaceNameOverrides(
5380
5435
  getTemplateForFile(templateInfo, data),
5381
5436
  data
@@ -5423,7 +5478,7 @@ var _deleteIndexContent = async (database, documentPaths, enequeueOps, collectio
5423
5478
  SUBLEVEL_OPTIONS
5424
5479
  );
5425
5480
  await sequential(documentPaths, async (filepath) => {
5426
- const itemKey = normalizePath(filepath);
5481
+ const itemKey = (0, import_schema_tools3.normalizePath)(filepath);
5427
5482
  const item = await rootLevel.get(itemKey);
5428
5483
  if (item) {
5429
5484
  await enequeueOps([
@@ -5479,22 +5534,19 @@ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
5479
5534
  };
5480
5535
 
5481
5536
  // src/database/bridge/filesystem.ts
5482
- var import_fs_extra2 = __toESM(require("fs-extra"));
5537
+ var import_fs_extra = __toESM(require("fs-extra"));
5483
5538
  var import_fast_glob = __toESM(require("fast-glob"));
5484
- var import_path4 = __toESM(require("path"));
5539
+ var import_path3 = __toESM(require("path"));
5485
5540
  var import_normalize_path = __toESM(require("normalize-path"));
5486
5541
  var FilesystemBridge = class {
5487
- constructor(rootPath) {
5542
+ constructor(rootPath, outputPath) {
5488
5543
  this.rootPath = rootPath || "";
5489
- this.outputPath = rootPath || "";
5490
- }
5491
- addOutputPath(outputPath) {
5492
- this.outputPath = outputPath;
5544
+ this.outputPath = outputPath || rootPath;
5493
5545
  }
5494
5546
  async glob(pattern, extension) {
5495
- const basePath = import_path4.default.join(this.outputPath, ...pattern.split("/"));
5547
+ const basePath = import_path3.default.join(this.outputPath, ...pattern.split("/"));
5496
5548
  const items = await (0, import_fast_glob.default)(
5497
- import_path4.default.join(basePath, "**", `/*${extension}`).replace(/\\/g, "/"),
5549
+ import_path3.default.join(basePath, "**", `/*${extension}`).replace(/\\/g, "/"),
5498
5550
  {
5499
5551
  dot: true
5500
5552
  }
@@ -5508,10 +5560,10 @@ var FilesystemBridge = class {
5508
5560
  return true;
5509
5561
  }
5510
5562
  async delete(filepath) {
5511
- await import_fs_extra2.default.remove(import_path4.default.join(this.outputPath, filepath));
5563
+ await import_fs_extra.default.remove(import_path3.default.join(this.outputPath, filepath));
5512
5564
  }
5513
5565
  async get(filepath) {
5514
- return import_fs_extra2.default.readFileSync(import_path4.default.join(this.outputPath, filepath)).toString();
5566
+ return import_fs_extra.default.readFileSync(import_path3.default.join(this.outputPath, filepath)).toString();
5515
5567
  }
5516
5568
  async putConfig(filepath, data) {
5517
5569
  if (this.rootPath !== this.outputPath) {
@@ -5523,7 +5575,7 @@ var FilesystemBridge = class {
5523
5575
  }
5524
5576
  async put(filepath, data, basePathOverride) {
5525
5577
  const basePath = basePathOverride || this.outputPath;
5526
- await import_fs_extra2.default.outputFileSync(import_path4.default.join(basePath, filepath), data);
5578
+ await import_fs_extra.default.outputFileSync(import_path3.default.join(basePath, filepath), data);
5527
5579
  }
5528
5580
  };
5529
5581
  var AuditFileSystemBridge = class extends FilesystemBridge {
@@ -5541,11 +5593,11 @@ var AuditFileSystemBridge = class extends FilesystemBridge {
5541
5593
 
5542
5594
  // src/database/bridge/isomorphic.ts
5543
5595
  var import_isomorphic_git = __toESM(require("isomorphic-git"));
5544
- var import_fs_extra3 = __toESM(require("fs-extra"));
5596
+ var import_fs_extra2 = __toESM(require("fs-extra"));
5545
5597
  var import_glob_parent = __toESM(require("glob-parent"));
5546
5598
  var import_normalize_path2 = __toESM(require("normalize-path"));
5547
5599
  var import_graphql6 = require("graphql");
5548
- var import_path5 = require("path");
5600
+ var import_path4 = require("path");
5549
5601
  var flat = typeof Array.prototype.flat === "undefined" ? (entries) => entries.reduce((acc, x) => acc.concat(x), []) : (entries) => entries.flat();
5550
5602
  var toUint8Array = (buf) => {
5551
5603
  const ab = new ArrayBuffer(buf.length);
@@ -5560,7 +5612,7 @@ var IsomorphicBridge = class {
5560
5612
  gitRoot,
5561
5613
  author,
5562
5614
  committer,
5563
- fsModule = import_fs_extra3.default,
5615
+ fsModule = import_fs_extra2.default,
5564
5616
  commitMessage = "Update from GraphQL client",
5565
5617
  ref,
5566
5618
  onPut,
@@ -5604,7 +5656,7 @@ var IsomorphicBridge = class {
5604
5656
  async listEntries({
5605
5657
  pattern,
5606
5658
  entry,
5607
- path: path6,
5659
+ path: path4,
5608
5660
  results
5609
5661
  }) {
5610
5662
  const treeResult = await import_isomorphic_git.default.readTree({
@@ -5614,7 +5666,7 @@ var IsomorphicBridge = class {
5614
5666
  });
5615
5667
  const children = [];
5616
5668
  for (const childEntry of treeResult.tree) {
5617
- const childPath = path6 ? `${path6}/${childEntry.path}` : childEntry.path;
5669
+ const childPath = path4 ? `${path4}/${childEntry.path}` : childEntry.path;
5618
5670
  if (childEntry.type === "tree") {
5619
5671
  children.push(childEntry);
5620
5672
  } else {
@@ -5624,7 +5676,7 @@ var IsomorphicBridge = class {
5624
5676
  }
5625
5677
  }
5626
5678
  for (const childEntry of children) {
5627
- const childPath = path6 ? `${path6}/${childEntry.path}` : childEntry.path;
5679
+ const childPath = path4 ? `${path4}/${childEntry.path}` : childEntry.path;
5628
5680
  await this.listEntries({
5629
5681
  pattern,
5630
5682
  entry: childEntry,
@@ -5633,17 +5685,17 @@ var IsomorphicBridge = class {
5633
5685
  });
5634
5686
  }
5635
5687
  }
5636
- async resolvePathEntries(path6, ref) {
5637
- let pathParts = path6.split("/");
5688
+ async resolvePathEntries(path4, ref) {
5689
+ let pathParts = path4.split("/");
5638
5690
  const result = await import_isomorphic_git.default.walk({
5639
5691
  ...this.isomorphicConfig,
5640
5692
  map: async (filepath, [head]) => {
5641
5693
  if (head._fullpath === ".") {
5642
5694
  return head;
5643
5695
  }
5644
- if (path6.startsWith(filepath)) {
5645
- if ((0, import_path5.dirname)(path6) === (0, import_path5.dirname)(filepath)) {
5646
- if (path6 === filepath) {
5696
+ if (path4.startsWith(filepath)) {
5697
+ if ((0, import_path4.dirname)(path4) === (0, import_path4.dirname)(filepath)) {
5698
+ if (path4 === filepath) {
5647
5699
  return head;
5648
5700
  }
5649
5701
  } else {
@@ -5663,7 +5715,7 @@ var IsomorphicBridge = class {
5663
5715
  }
5664
5716
  return { pathParts, pathEntries };
5665
5717
  }
5666
- async updateTreeHierarchy(existingOid, updatedOid, path6, type, pathEntries, pathParts) {
5718
+ async updateTreeHierarchy(existingOid, updatedOid, path4, type, pathEntries, pathParts) {
5667
5719
  const lastIdx = pathEntries.length - 1;
5668
5720
  const parentEntry = pathEntries[lastIdx];
5669
5721
  const parentPath = pathParts[lastIdx];
@@ -5678,7 +5730,7 @@ var IsomorphicBridge = class {
5678
5730
  cache: this.cache
5679
5731
  });
5680
5732
  tree = existingOid ? treeResult.tree.map((entry) => {
5681
- if (entry.path === path6) {
5733
+ if (entry.path === path4) {
5682
5734
  entry.oid = updatedOid;
5683
5735
  }
5684
5736
  return entry;
@@ -5687,7 +5739,7 @@ var IsomorphicBridge = class {
5687
5739
  {
5688
5740
  oid: updatedOid,
5689
5741
  type,
5690
- path: path6,
5742
+ path: path4,
5691
5743
  mode
5692
5744
  }
5693
5745
  ];
@@ -5696,7 +5748,7 @@ var IsomorphicBridge = class {
5696
5748
  {
5697
5749
  oid: updatedOid,
5698
5750
  type,
5699
- path: path6,
5751
+ path: path4,
5700
5752
  mode
5701
5753
  }
5702
5754
  ];
@@ -5797,7 +5849,7 @@ var IsomorphicBridge = class {
5797
5849
  path: parentPath,
5798
5850
  results
5799
5851
  });
5800
- return results.map((path6) => this.unqualifyPath(path6)).filter((path6) => path6.endsWith(extension));
5852
+ return results.map((path4) => this.unqualifyPath(path4)).filter((path4) => path4.endsWith(extension));
5801
5853
  }
5802
5854
  supportsBuilding() {
5803
5855
  return true;
@@ -5933,16 +5985,12 @@ var IsomorphicBridge = class {
5933
5985
  };
5934
5986
 
5935
5987
  // src/index.ts
5936
- var buildSchema = async (rootPath, database, flags) => {
5937
- const tempConfig = import_path6.default.join(rootPath, ".tina", "__generated__", "config");
5938
- const config = await import_fs_extra4.default.readFileSync(import_path6.default.join(tempConfig, "schema.json")).toString();
5939
- await import_fs_extra4.default.remove(tempConfig);
5940
- const { graphQLSchema, tinaSchema } = await buildDotTinaFiles({
5988
+ var buildSchema = async (database, config, flags) => {
5989
+ return buildDotTinaFiles({
5941
5990
  database,
5942
- config: JSON.parse(config),
5991
+ config,
5943
5992
  flags
5944
5993
  });
5945
- return { graphQLSchema, tinaSchema };
5946
5994
  };
5947
5995
  var getASTSchema = async (database) => {
5948
5996
  const gqlAst = await database.getGraphQLSchemaFromBridge();