@tinacms/cli 0.0.0-9c44130-20241030170642 → 0.0.0-9e83b99-20250315180950

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
@@ -17,23 +17,28 @@ var __copyProps = (to, from, except, desc) => {
17
17
  return to;
18
18
  };
19
19
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
24
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
25
  mod
22
26
  ));
23
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
28
 
25
29
  // src/index.ts
26
- var src_exports = {};
27
- __export(src_exports, {
28
- default: () => src_default
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ default: () => index_default
29
33
  });
30
- module.exports = __toCommonJS(src_exports);
34
+ module.exports = __toCommonJS(index_exports);
31
35
  var import_clipanion8 = require("clipanion");
32
36
 
33
37
  // package.json
34
- var version = "1.6.11";
38
+ var version = "1.9.2";
35
39
 
36
40
  // src/next/commands/dev-command/index.ts
41
+ var import_async_lock = __toESM(require("async-lock"));
37
42
  var import_clipanion2 = require("clipanion");
38
43
  var import_fs_extra6 = __toESM(require("fs-extra"));
39
44
  var import_path5 = __toESM(require("path"));
@@ -57,7 +62,10 @@ function isUnicodeSupported() {
57
62
  if (process.platform !== "win32") {
58
63
  return process.env.TERM !== "linux";
59
64
  }
60
- return Boolean(process.env.CI) || Boolean(process.env.WT_SESSION) || Boolean(process.env.TERMINUS_SUBLIME) || process.env.ConEmuTask === "{cmd::Cmder}" || process.env.TERM_PROGRAM === "Terminus-Sublime" || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
65
+ return Boolean(process.env.CI) || Boolean(process.env.WT_SESSION) || // Windows Terminal
66
+ Boolean(process.env.TERMINUS_SUBLIME) || // Terminus (<0.2.27)
67
+ process.env.ConEmuTask === "{cmd::Cmder}" || // ConEmu and cmder
68
+ process.env.TERM_PROGRAM === "Terminus-Sublime" || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
61
69
  }
62
70
 
63
71
  // src/logger/index.ts
@@ -212,7 +220,7 @@ var ConfigManager = class {
212
220
  this.generatedCachePath = import_path.default.join(
213
221
  this.generatedFolderPath,
214
222
  ".cache",
215
- String(new Date().getTime())
223
+ String((/* @__PURE__ */ new Date()).getTime())
216
224
  );
217
225
  this.generatedGraphQLGQLPath = import_path.default.join(
218
226
  this.generatedFolderPath,
@@ -355,17 +363,22 @@ var ConfigManager = class {
355
363
  );
356
364
  }
357
365
  getTinaGraphQLVersion() {
358
- var _a, _b;
359
366
  if (this.tinaGraphQLVersionFromCLI) {
360
- return this.tinaGraphQLVersionFromCLI;
367
+ const version2 = this.tinaGraphQLVersionFromCLI.split(".");
368
+ return {
369
+ fullVersion: this.tinaGraphQLVersionFromCLI,
370
+ major: version2[0] || "x",
371
+ minor: version2[1] || "x",
372
+ patch: version2[2] || "x"
373
+ };
361
374
  }
362
375
  const generatedSchema = import_fs_extra.default.readJSONSync(this.generatedSchemaJSONPath);
363
- if (!generatedSchema || !(typeof (generatedSchema == null ? void 0 : generatedSchema.version) !== "undefined") || !(typeof ((_a = generatedSchema == null ? void 0 : generatedSchema.version) == null ? void 0 : _a.major) === "string") || !(typeof ((_b = generatedSchema == null ? void 0 : generatedSchema.version) == null ? void 0 : _b.minor) === "string")) {
376
+ if (!generatedSchema || !(typeof (generatedSchema == null ? void 0 : generatedSchema.version) !== "undefined")) {
364
377
  throw new Error(
365
378
  `Can not find Tina GraphQL version in ${this.generatedSchemaJSONPath}`
366
379
  );
367
380
  }
368
- return `${generatedSchema.version.major}.${generatedSchema.version.minor}`;
381
+ return generatedSchema.version;
369
382
  }
370
383
  printGeneratedClientFilePath() {
371
384
  if (this.isUsingTs()) {
@@ -394,6 +407,9 @@ var ConfigManager = class {
394
407
  }
395
408
  throw `No path provided to print`;
396
409
  }
410
+ /**
411
+ * Given a filepath without an extension, find the first match (eg. tsx, ts, jsx, js)
412
+ */
397
413
  async getPathWithExtension(filepath) {
398
414
  const extensions = ["tsx", "ts", "jsx", "js"];
399
415
  let result;
@@ -427,7 +443,10 @@ var ConfigManager = class {
427
443
  }
428
444
  async loadConfigFile(generatedFolderPath, configFilePath) {
429
445
  const tmpdir = import_path.default.join(import_os.default.tmpdir(), Date.now().toString());
430
- const prebuild = import_path.default.join(this.generatedFolderPath, "config.prebuild.jsx");
446
+ const preBuildConfigPath = import_path.default.join(
447
+ this.generatedFolderPath,
448
+ "config.prebuild.jsx"
449
+ );
431
450
  const outfile = import_path.default.join(tmpdir, "config.build.jsx");
432
451
  const outfile2 = import_path.default.join(tmpdir, "config.build.js");
433
452
  const tempTSConfigFile = import_path.default.join(tmpdir, "tsconfig.json");
@@ -441,7 +460,7 @@ var ConfigManager = class {
441
460
  logLevel: "silent",
442
461
  packages: "external",
443
462
  ignoreAnnotations: true,
444
- outfile: prebuild,
463
+ outfile: preBuildConfigPath,
445
464
  loader: loaders,
446
465
  metafile: true
447
466
  });
@@ -464,6 +483,7 @@ var ConfigManager = class {
464
483
  await esbuild.build({
465
484
  entryPoints: [outfile],
466
485
  bundle: true,
486
+ // Suppress warning about comparison with -0 from client module
467
487
  logLevel: "silent",
468
488
  platform: "node",
469
489
  outfile: outfile2,
@@ -481,7 +501,7 @@ var ConfigManager = class {
481
501
  import_fs_extra.default.removeSync(outfile2);
482
502
  return {
483
503
  config: result.default,
484
- prebuildPath: prebuild,
504
+ prebuildPath: preBuildConfigPath,
485
505
  watchList: flattenedList
486
506
  };
487
507
  }
@@ -570,19 +590,19 @@ var devHTML = (port) => `<!DOCTYPE html>
570
590
  window.$RefreshReg$ = () => {}
571
591
  window.$RefreshSig$ = () => (type) => type
572
592
  window.__vite_plugin_react_preamble_installed__ = true
573
- <\/script>
574
- <script type="module" src="http://localhost:${port}/@vite/client"><\/script>
593
+ </script>
594
+ <script type="module" src="http://localhost:${port}/@vite/client"></script>
575
595
  <script>
576
596
  function handleLoadError() {
577
597
  // Assets have failed to load
578
598
  document.getElementById('root').innerHTML = '${errorHTML}';
579
599
  }
580
- <\/script>
600
+ </script>
581
601
  <script
582
602
  type="module"
583
603
  src="http://localhost:${port}/src/main.tsx"
584
604
  onerror="handleLoadError()"
585
- ><\/script>
605
+ ></script>
586
606
  <body class="tina-tailwind">
587
607
  <div id="root"></div>
588
608
  </body>
@@ -628,6 +648,7 @@ var import_defaultTheme = __toESM(require("tailwindcss/defaultTheme.js"));
628
648
  var tinaTailwind = (spaPath, prebuildFilePath) => {
629
649
  return {
630
650
  name: "vite-plugin-tina",
651
+ // @ts-ignore
631
652
  config: (viteConfig) => {
632
653
  const plugins = [];
633
654
  const content = [
@@ -939,7 +960,6 @@ async function listFilesRecursively({
939
960
  }
940
961
  var createConfig = async ({
941
962
  configManager,
942
- database,
943
963
  apiURL,
944
964
  plugins = [],
945
965
  noWatch,
@@ -999,6 +1019,8 @@ var createConfig = async ({
999
1019
  if (configManager.config.build.basePath) {
1000
1020
  basePath = configManager.config.build.basePath;
1001
1021
  }
1022
+ const fullVersion = configManager.getTinaGraphQLVersion();
1023
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1002
1024
  const config2 = {
1003
1025
  root: configManager.spaRootPath,
1004
1026
  base: `/${basePath ? `${(0, import_normalize_path2.default)(basePath)}/` : ""}${(0, import_normalize_path2.default)(
@@ -1010,15 +1032,33 @@ var createConfig = async ({
1010
1032
  dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1011
1033
  },
1012
1034
  define: {
1035
+ /**
1036
+ * Since we prebuild the config.ts, it's possible for modules to be loaded which make
1037
+ * use of `process`. The main scenario where this is an issue is when co-locating schema
1038
+ * definitions with source files, and specifically source files which impor from NextJS.
1039
+ *
1040
+ * Some examples of what NextJS uses for `process.env` are:
1041
+ * - `process.env.__NEXT_TRAILING_SLASH`
1042
+ * - `process.env.__NEXT_CROSS_ORIGIN`
1043
+ * - `process.env.__NEXT_I18N_SUPPORT`
1044
+ *
1045
+ * Also, interestingly some of the advice for handling this doesn't work, references to replacing
1046
+ * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
1047
+ * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1048
+ */
1013
1049
  "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1050
+ // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1014
1051
  "process.platform": `"${process.platform}"`,
1015
1052
  __API_URL__: `"${apiURL}"`,
1016
1053
  __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1017
- __TINA_GRAPHQL_VERSION__: `"${configManager.getTinaGraphQLVersion()}"`
1054
+ __TINA_GRAPHQL_VERSION__: version2
1018
1055
  },
1019
1056
  logLevel: "error",
1057
+ // Vite import warnings are noisy
1020
1058
  optimizeDeps: {
1021
1059
  force: true,
1060
+ // Not 100% sure why this isn't being picked up automatically, this works from within the monorepo
1061
+ // but breaks externally
1022
1062
  include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1023
1063
  },
1024
1064
  server: {
@@ -1026,6 +1066,7 @@ var createConfig = async ({
1026
1066
  watch: noWatch ? {
1027
1067
  ignored: ["**/*"]
1028
1068
  } : {
1069
+ // Ignore everything except for the alias fields we specified above
1029
1070
  ignored: [
1030
1071
  `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1031
1072
  ]
@@ -1041,8 +1082,13 @@ var createConfig = async ({
1041
1082
  rollupOptions
1042
1083
  },
1043
1084
  plugins: [
1085
+ /**
1086
+ * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
1087
+ * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
1088
+ */
1044
1089
  (0, import_plugin_react.default)({
1045
1090
  babel: {
1091
+ // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1046
1092
  compact: true
1047
1093
  }
1048
1094
  }),
@@ -1119,8 +1165,7 @@ var createMediaRouter = (config2) => {
1119
1165
  };
1120
1166
  var parseMediaFolder = (str) => {
1121
1167
  let returnString = str;
1122
- if (returnString.startsWith("/"))
1123
- returnString = returnString.substr(1);
1168
+ if (returnString.startsWith("/")) returnString = returnString.substr(1);
1124
1169
  if (returnString.endsWith("/"))
1125
1170
  returnString = returnString.substr(0, returnString.length - 1);
1126
1171
  return returnString;
@@ -1137,7 +1182,7 @@ var MediaModel = class {
1137
1182
  this.rootPath,
1138
1183
  this.publicFolder,
1139
1184
  this.mediaRoot,
1140
- args.searchPath
1185
+ decodeURIComponent(args.searchPath)
1141
1186
  );
1142
1187
  const searchPath = parseMediaFolder(args.searchPath);
1143
1188
  if (!await import_fs_extra3.default.pathExists(folderPath)) {
@@ -1209,7 +1254,7 @@ var MediaModel = class {
1209
1254
  this.rootPath,
1210
1255
  this.publicFolder,
1211
1256
  this.mediaRoot,
1212
- args.searchPath
1257
+ decodeURIComponent(args.searchPath)
1213
1258
  );
1214
1259
  await import_fs_extra3.default.stat(file);
1215
1260
  await import_fs_extra3.default.remove(file);
@@ -1285,7 +1330,8 @@ var devServerEndPointsPlugin = ({
1285
1330
  configManager,
1286
1331
  apiURL,
1287
1332
  database,
1288
- searchIndex
1333
+ searchIndex,
1334
+ databaseLock
1289
1335
  }) => {
1290
1336
  const plug = {
1291
1337
  name: "graphql-endpoints",
@@ -1329,14 +1375,17 @@ var devServerEndPointsPlugin = ({
1329
1375
  }
1330
1376
  if (req.url === "/graphql") {
1331
1377
  const { query, variables } = req.body;
1332
- const result = await (0, import_graphql.resolve)({
1333
- config: {
1334
- useRelativeMedia: true
1335
- },
1336
- database,
1337
- query,
1338
- variables,
1339
- verbose: false
1378
+ let result;
1379
+ await databaseLock(async () => {
1380
+ result = await (0, import_graphql.resolve)({
1381
+ config: {
1382
+ useRelativeMedia: true
1383
+ },
1384
+ database,
1385
+ query,
1386
+ variables,
1387
+ verbose: false
1388
+ });
1340
1389
  });
1341
1390
  res.end(JSON.stringify(result));
1342
1391
  return;
@@ -1387,6 +1436,7 @@ function viteTransformExtension({
1387
1436
  return {
1388
1437
  code: res.code,
1389
1438
  map: null
1439
+ // TODO:
1390
1440
  };
1391
1441
  }
1392
1442
  }
@@ -1394,10 +1444,16 @@ function viteTransformExtension({
1394
1444
  }
1395
1445
 
1396
1446
  // src/next/commands/dev-command/server/index.ts
1397
- var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch) => {
1447
+ var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch, databaseLock) => {
1398
1448
  const plugins = [
1399
1449
  transformTsxPlugin({ configManager }),
1400
- devServerEndPointsPlugin({ apiURL, configManager, database, searchIndex }),
1450
+ devServerEndPointsPlugin({
1451
+ apiURL,
1452
+ configManager,
1453
+ database,
1454
+ searchIndex,
1455
+ databaseLock
1456
+ }),
1401
1457
  viteTransformExtension()
1402
1458
  ];
1403
1459
  return (0, import_vite3.createServer)(
@@ -1407,6 +1463,14 @@ var createDevServer = async (configManager, database, searchIndex, apiURL, noWat
1407
1463
  apiURL,
1408
1464
  plugins,
1409
1465
  noWatch,
1466
+ /**
1467
+ * Ensure Vite's import scan uses the spaMainPath as the input
1468
+ * so it properly finds everything. This is for dev only, and when
1469
+ * running the server outside of this monorepo vite fails to find
1470
+ * and optimize the imports, so you get errors about it not being
1471
+ * able to find an export from a module, and it's always a CJS
1472
+ * module that Vite would usually transform to an ES module.
1473
+ */
1410
1474
  rollupOptions: {
1411
1475
  input: configManager.spaMainPath,
1412
1476
  onwarn(warning, warn) {
@@ -1532,6 +1596,7 @@ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBas
1532
1596
  node,
1533
1597
  documentVariableName,
1534
1598
  operationType,
1599
+ // This is the only line that is different
1535
1600
  operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
1536
1601
  operationVariablesTypes
1537
1602
  });
@@ -1580,6 +1645,8 @@ var plugin = (schema, documents, config2) => {
1580
1645
  const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1581
1646
  const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1582
1647
  return {
1648
+ // We will take care of imports
1649
+ // prepend: visitor.getImports(),
1583
1650
  content: [
1584
1651
  visitor.fragments,
1585
1652
  ...visitorResult.definitions.filter((t) => typeof t === "string"),
@@ -1595,6 +1662,7 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
1595
1662
  docs = await loadGraphQLDocuments(queryPathGlob);
1596
1663
  fragDocs = await loadGraphQLDocuments(fragDocPath);
1597
1664
  const res = await (0, import_core.codegen)({
1665
+ // Filename is not used. This is because the typescript plugin returns a string instead of writing to a file.
1598
1666
  filename: process.cwd(),
1599
1667
  schema: (0, import_graphql5.parse)((0, import_graphql5.printSchema)(schema)),
1600
1668
  documents: [...docs, ...fragDocs],
@@ -1629,9 +1697,12 @@ var loadGraphQLDocuments = async (globPath) => {
1629
1697
  loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
1630
1698
  });
1631
1699
  } catch (e) {
1632
- if ((e.message || "").includes(
1633
- "Unable to find any GraphQL type definitions for the following pointers:"
1634
- )) {
1700
+ if (
1701
+ // https://www.graphql-tools.com/docs/documents-loading#no-files-found
1702
+ (e.message || "").includes(
1703
+ "Unable to find any GraphQL type definitions for the following pointers:"
1704
+ )
1705
+ ) {
1635
1706
  } else {
1636
1707
  throw e;
1637
1708
  }
@@ -1668,7 +1739,10 @@ var Codegen = class {
1668
1739
  this.noClientBuildCache = noClientBuildCache;
1669
1740
  }
1670
1741
  async writeConfigFile(fileName, data) {
1671
- const filePath = import_path4.default.join(this.configManager.generatedFolderPath, fileName);
1742
+ const filePath = import_path4.default.join(
1743
+ this.configManager.generatedFolderPath,
1744
+ fileName
1745
+ );
1672
1746
  await import_fs_extra4.default.ensureFile(filePath);
1673
1747
  await import_fs_extra4.default.outputFile(filePath, data);
1674
1748
  if (this.configManager.hasSeparateContentRoot()) {
@@ -1788,16 +1862,14 @@ var Codegen = class {
1788
1862
  const branch = (_a = this.configManager.config) == null ? void 0 : _a.branch;
1789
1863
  const clientId = (_b = this.configManager.config) == null ? void 0 : _b.clientId;
1790
1864
  const token = (_c = this.configManager.config) == null ? void 0 : _c.token;
1791
- const version2 = this.configManager.getTinaGraphQLVersion();
1865
+ const fullVersion = this.configManager.getTinaGraphQLVersion();
1866
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1792
1867
  const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
1793
1868
  if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
1794
1869
  const missing = [];
1795
- if (!branch)
1796
- missing.push("branch");
1797
- if (!clientId)
1798
- missing.push("clientId");
1799
- if (!token)
1800
- missing.push("token");
1870
+ if (!branch) missing.push("branch");
1871
+ if (!clientId) missing.push("clientId");
1872
+ if (!token) missing.push("token");
1801
1873
  throw new Error(
1802
1874
  `Client not configured properly. Missing ${missing.join(
1803
1875
  ", "
@@ -1951,7 +2023,11 @@ schema {
1951
2023
  }
1952
2024
  };
1953
2025
  var maybeWarnFragmentSize = async (filepath) => {
1954
- if ((await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
2026
+ if (
2027
+ // is the file bigger than 100kb?
2028
+ (await import_fs_extra4.default.stat(filepath)).size > // convert to 100 kb to bytes
2029
+ 100 * 1024
2030
+ ) {
1955
2031
  console.warn(
1956
2032
  "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
1957
2033
  );
@@ -1979,6 +2055,7 @@ var import_many_level = require("many-level");
1979
2055
  var import_memory_level = require("memory-level");
1980
2056
  var createDBServer = (port) => {
1981
2057
  const levelHost = new import_many_level.ManyLevelHost(
2058
+ // @ts-ignore
1982
2059
  new import_memory_level.MemoryLevel({
1983
2060
  valueEncoding: "json"
1984
2061
  })
@@ -2129,7 +2206,9 @@ var BaseCommand = class extends import_clipanion.Command {
2129
2206
  let subProc;
2130
2207
  if (this.subCommand) {
2131
2208
  subProc = await startSubprocess2({ command: this.subCommand });
2132
- logger.info(`Starting subprocess: ${import_chalk4.default.cyan(this.subCommand)}`);
2209
+ logger.info(
2210
+ `Running web application with command: ${import_chalk4.default.cyan(this.subCommand)}`
2211
+ );
2133
2212
  }
2134
2213
  function exitHandler(options, exitCode) {
2135
2214
  if (subProc) {
@@ -2209,7 +2288,7 @@ var BaseCommand = class extends import_clipanion.Command {
2209
2288
  pathFilter
2210
2289
  });
2211
2290
  const tinaPathUpdates = modified.filter(
2212
- (path13) => path13.startsWith(".tina/__generated__/_schema.json") || path13.startsWith("tina/tina-lock.json")
2291
+ (path14) => path14.startsWith(".tina/__generated__/_schema.json") || path14.startsWith("tina/tina-lock.json")
2213
2292
  );
2214
2293
  if (tinaPathUpdates.length > 0) {
2215
2294
  res = await database.indexContent({
@@ -2253,6 +2332,7 @@ var import_search = require("@tinacms/search");
2253
2332
  var DevCommand = class extends BaseCommand {
2254
2333
  constructor() {
2255
2334
  super(...arguments);
2335
+ // NOTE: camelCase commands for string options don't work if there's an `=` used https://github.com/arcanis/clipanion/issues/141
2256
2336
  this.watchFolders = import_clipanion2.Option.String("-w,--watchFolders", {
2257
2337
  description: "DEPRECATED - a list of folders (relative to where this is being run) that the cli will watch for changes"
2258
2338
  });
@@ -2262,6 +2342,10 @@ var DevCommand = class extends BaseCommand {
2262
2342
  this.outputSearchIndexPath = import_clipanion2.Option.String("--outputSearchIndexPath", {
2263
2343
  description: "Path to write the search index to"
2264
2344
  });
2345
+ this.noServer = import_clipanion2.Option.Boolean("--no-server", false, {
2346
+ description: "Do not start the dev server"
2347
+ });
2348
+ this.indexingLock = new import_async_lock.default();
2265
2349
  }
2266
2350
  async catch(error) {
2267
2351
  logger.error("Error occured during tinacms dev");
@@ -2282,10 +2366,13 @@ var DevCommand = class extends BaseCommand {
2282
2366
  rootPath: this.rootPath,
2283
2367
  legacyNoSDK: this.noSDK
2284
2368
  });
2285
- logger.info("Starting Tina Dev Server");
2369
+ logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2286
2370
  this.logDeprecationWarnings();
2287
2371
  createDBServer(Number(this.datalayerPort));
2288
2372
  let database = null;
2373
+ const dbLock = async (fn) => {
2374
+ return this.indexingLock.acquire("Key", fn);
2375
+ };
2289
2376
  const setup = async ({ firstTime }) => {
2290
2377
  try {
2291
2378
  await configManager.processConfig();
@@ -2336,9 +2423,6 @@ var DevCommand = class extends BaseCommand {
2336
2423
  await import_fs_extra6.default.outputFile(filePath, tinaLockContent);
2337
2424
  }
2338
2425
  }
2339
- if (!this.noWatch) {
2340
- this.watchQueries(configManager, async () => await codegen2.execute());
2341
- }
2342
2426
  await this.indexContentWithSpinner({
2343
2427
  database,
2344
2428
  graphQLSchema: graphQLSchema2,
@@ -2348,6 +2432,13 @@ var DevCommand = class extends BaseCommand {
2348
2432
  if (!firstTime) {
2349
2433
  logger.error("Re-index complete");
2350
2434
  }
2435
+ if (!this.noWatch) {
2436
+ this.watchQueries(
2437
+ configManager,
2438
+ dbLock,
2439
+ async () => await codegen2.execute()
2440
+ );
2441
+ }
2351
2442
  return { apiURL: apiURL2, database, graphQLSchema: graphQLSchema2, tinaSchema: tinaSchema2 };
2352
2443
  } catch (e) {
2353
2444
  logger.error(`
@@ -2382,14 +2473,6 @@ ${dangerText(e.message)}
2382
2473
  tokenSplitRegex: (_d = (_c = configManager.config.search) == null ? void 0 : _c.tina) == null ? void 0 : _d.tokenSplitRegex
2383
2474
  });
2384
2475
  await searchIndexClient.onStartIndexing();
2385
- const server = await createDevServer(
2386
- configManager,
2387
- database,
2388
- searchIndexClient.searchIndex,
2389
- apiURL,
2390
- this.noWatch
2391
- );
2392
- await server.listen(Number(this.port));
2393
2476
  const searchIndexer = new import_search.SearchIndexer({
2394
2477
  batchSize: ((_e = configManager.config.search) == null ? void 0 : _e.indexBatchSize) || 100,
2395
2478
  bridge: new import_graphql10.FilesystemBridge(
@@ -2411,16 +2494,34 @@ ${dangerText(e.message)}
2411
2494
  await searchIndexClient.export(this.outputSearchIndexPath);
2412
2495
  }
2413
2496
  }
2497
+ if (this.noServer) {
2498
+ logger.info("--no-server option specified - Dev server not started");
2499
+ process.exit(0);
2500
+ }
2414
2501
  if (!this.noWatch) {
2415
2502
  this.watchContentFiles(
2416
2503
  configManager,
2417
2504
  database,
2505
+ dbLock,
2418
2506
  configManager.config.search && searchIndexer
2419
2507
  );
2508
+ }
2509
+ const server = await createDevServer(
2510
+ configManager,
2511
+ database,
2512
+ searchIndexClient.searchIndex,
2513
+ apiURL,
2514
+ this.noWatch,
2515
+ dbLock
2516
+ );
2517
+ await server.listen(Number(this.port));
2518
+ if (!this.noWatch) {
2420
2519
  import_chokidar.default.watch(configManager.watchList).on("change", async () => {
2421
- logger.info(`Tina config change detected, rebuilding`);
2422
- await setup({ firstTime: false });
2423
- server.ws.send({ type: "full-reload", path: "*" });
2520
+ await dbLock(async () => {
2521
+ logger.info(`Tina config change detected, rebuilding`);
2522
+ await setup({ firstTime: false });
2523
+ server.ws.send({ type: "full-reload", path: "*" });
2524
+ });
2424
2525
  });
2425
2526
  }
2426
2527
  const subItems = [];
@@ -2433,7 +2534,7 @@ ${dangerText(e.message)}
2433
2534
  const summaryItems = [
2434
2535
  {
2435
2536
  emoji: "\u{1F999}",
2436
- heading: "Tina Config",
2537
+ heading: "TinaCMS URLs",
2437
2538
  subItems: [
2438
2539
  {
2439
2540
  key: "CMS",
@@ -2468,14 +2569,28 @@ ${dangerText(e.message)}
2468
2569
  });
2469
2570
  }
2470
2571
  summary({
2471
- heading: "Tina Dev Server is running...",
2572
+ heading: "\u2705 \u{1F999} TinaCMS Dev Server is active:",
2472
2573
  items: [
2473
2574
  ...summaryItems
2575
+ // {
2576
+ // emoji: '📚',
2577
+ // heading: 'Useful links',
2578
+ // subItems: [
2579
+ // {
2580
+ // key: 'Custom queries',
2581
+ // value: 'https://tina.io/querying',
2582
+ // },
2583
+ // {
2584
+ // key: 'Visual editing',
2585
+ // value: 'https://tina.io/visual-editing',
2586
+ // },
2587
+ // ],
2588
+ // },
2474
2589
  ]
2475
2590
  });
2476
2591
  await this.startSubCommand();
2477
2592
  }
2478
- watchContentFiles(configManager, database, searchIndexer) {
2593
+ watchContentFiles(configManager, database, databaseLock, searchIndexer) {
2479
2594
  const collectionContentFiles = [];
2480
2595
  configManager.config.schema.collections.forEach((collection) => {
2481
2596
  const collectionGlob = `${import_path5.default.join(
@@ -2491,39 +2606,42 @@ ${dangerText(e.message)}
2491
2606
  if (!ready) {
2492
2607
  return;
2493
2608
  }
2494
- const pathFromRoot = configManager.printContentRelativePath(addedFile);
2495
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2496
- if (searchIndexer) {
2497
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2498
- }
2609
+ await databaseLock(async () => {
2610
+ const pathFromRoot = configManager.printContentRelativePath(addedFile);
2611
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2612
+ if (searchIndexer) {
2613
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2614
+ }
2615
+ });
2499
2616
  }).on("change", async (changedFile) => {
2500
2617
  const pathFromRoot = configManager.printContentRelativePath(changedFile);
2501
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2502
- if (searchIndexer) {
2503
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2504
- }
2618
+ await databaseLock(async () => {
2619
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2620
+ if (searchIndexer) {
2621
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2622
+ }
2623
+ });
2505
2624
  }).on("unlink", async (removedFile) => {
2506
2625
  const pathFromRoot = configManager.printContentRelativePath(removedFile);
2507
- await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2508
- if (searchIndexer) {
2509
- await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2510
- }
2626
+ await databaseLock(async () => {
2627
+ await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2628
+ if (searchIndexer) {
2629
+ await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2630
+ }
2631
+ });
2511
2632
  });
2512
2633
  }
2513
- watchQueries(configManager, callback) {
2514
- let ready = false;
2515
- import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("ready", () => {
2516
- ready = true;
2517
- }).on("add", async (addedFile) => {
2518
- await callback();
2519
- }).on("change", async (changedFile) => {
2520
- await callback();
2521
- }).on("unlink", async (removedFile) => {
2522
- await callback();
2523
- });
2634
+ watchQueries(configManager, databaseLock, callback) {
2635
+ const executeCallback = async (_) => {
2636
+ await databaseLock(async () => {
2637
+ await callback();
2638
+ });
2639
+ };
2640
+ import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("add", executeCallback).on("change", executeCallback).on("unlink", executeCallback);
2524
2641
  }
2525
2642
  };
2526
2643
  DevCommand.paths = [["dev"], ["server:start"]];
2644
+ // Prevent indexes and reads occurring at once
2527
2645
  DevCommand.usage = import_clipanion2.Command.Usage({
2528
2646
  category: `Commands`,
2529
2647
  description: `Builds Tina and starts the dev server`,
@@ -2538,6 +2656,7 @@ var import_clipanion3 = require("clipanion");
2538
2656
  var import_progress2 = __toESM(require("progress"));
2539
2657
  var import_fs_extra7 = __toESM(require("fs-extra"));
2540
2658
  var import_crypto = __toESM(require("crypto"));
2659
+ var import_path6 = __toESM(require("path"));
2541
2660
  var import_graphql11 = require("@tinacms/graphql");
2542
2661
 
2543
2662
  // src/next/commands/build-command/server.ts
@@ -2581,7 +2700,7 @@ var buildProductionSpa = async (configManager, database, apiURL) => {
2581
2700
  // src/next/commands/build-command/index.ts
2582
2701
  var import_schema_tools2 = require("@tinacms/schema-tools");
2583
2702
  var import_graphql12 = require("graphql");
2584
- var import_core2 = require("@graphql-inspector/core");
2703
+ var import_core3 = require("@graphql-inspector/core");
2585
2704
 
2586
2705
  // src/next/commands/build-command/waitForDB.ts
2587
2706
  var import_progress = __toESM(require("progress"));
@@ -2683,6 +2802,20 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2683
2802
 
2684
2803
  // src/next/commands/build-command/index.ts
2685
2804
  var import_search2 = require("@tinacms/search");
2805
+
2806
+ // src/utils/index.ts
2807
+ var import_core2 = require("@graphql-inspector/core");
2808
+ var getFaqLink = (type) => {
2809
+ switch (type) {
2810
+ case import_core2.ChangeType.FieldRemoved: {
2811
+ return "https://tina.io/docs/introduction/faq#how-do-i-resolve-the-local-graphql-schema-doesnt-match-the-remote-graphql-schema-errors";
2812
+ }
2813
+ default:
2814
+ return null;
2815
+ }
2816
+ };
2817
+
2818
+ // src/next/commands/build-command/index.ts
2686
2819
  var BuildCommand = class extends BaseCommand {
2687
2820
  constructor() {
2688
2821
  super(...arguments);
@@ -2698,6 +2831,9 @@ var BuildCommand = class extends BaseCommand {
2698
2831
  this.tinaGraphQLVersion = import_clipanion3.Option.String("--tina-graphql-version", {
2699
2832
  description: "Specify the version of @tinacms/graphql to use (defaults to latest)"
2700
2833
  });
2834
+ /**
2835
+ * This option allows the user to skip the tina cloud checks if they want to. This could be useful for mismatched GraphQL versions or if they want to build only using the local client and never connect to Tina Cloud
2836
+ */
2701
2837
  this.skipCloudChecks = import_clipanion3.Option.Boolean("--skip-cloud-checks", false, {
2702
2838
  description: "Skips checking the provided cloud config."
2703
2839
  });
@@ -2803,14 +2939,15 @@ ${dangerText(e.message)}
2803
2939
  database,
2804
2940
  null,
2805
2941
  apiURL,
2806
- true
2942
+ true,
2943
+ (lockedFn) => lockedFn()
2807
2944
  );
2808
2945
  await server.listen(Number(this.port));
2809
2946
  console.log("server listening on port", this.port);
2810
2947
  }
2811
2948
  const skipCloudChecks = this.skipCloudChecks || configManager.hasSelfHostedConfig();
2812
2949
  if (!skipCloudChecks) {
2813
- const { hasUpstream } = await this.checkClientInfo(
2950
+ const { hasUpstream, timestamp } = await this.checkClientInfo(
2814
2951
  configManager,
2815
2952
  codegen2.productionUrl,
2816
2953
  this.previewBaseBranch
@@ -2838,14 +2975,16 @@ ${dangerText(e.message)}
2838
2975
  await this.checkGraphqlSchema(
2839
2976
  configManager,
2840
2977
  database,
2841
- codegen2.productionUrl
2978
+ codegen2.productionUrl,
2979
+ timestamp
2842
2980
  );
2843
2981
  await this.checkTinaSchema(
2844
2982
  configManager,
2845
2983
  database,
2846
2984
  codegen2.productionUrl,
2847
2985
  this.previewName,
2848
- this.verbose
2986
+ this.verbose,
2987
+ timestamp
2849
2988
  );
2850
2989
  }
2851
2990
  await buildProductionSpa(configManager, database, codegen2.productionUrl);
@@ -2863,7 +3002,9 @@ ${dangerText(e.message)}
2863
3002
  `ERROR: Branch not configured in tina search configuration.`
2864
3003
  )}`
2865
3004
  );
2866
- throw new Error("Branch not configured in tina search configuration.");
3005
+ throw new Error(
3006
+ "Branch not configured in tina search configuration."
3007
+ );
2867
3008
  }
2868
3009
  if (!((_d = configManager.config) == null ? void 0 : _d.clientId)) {
2869
3010
  logger.error(`${dangerText(`ERROR: clientId not configured.`)}`);
@@ -2964,11 +3105,13 @@ ${dangerText(e.message)}
2964
3105
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
2965
3106
  let branchKnown = false;
2966
3107
  let hasUpstream = false;
3108
+ let timestamp;
2967
3109
  try {
2968
3110
  const res = await request({
2969
3111
  token,
2970
3112
  url
2971
3113
  });
3114
+ timestamp = res.timestamp || 0;
2972
3115
  bar2.tick({
2973
3116
  prog: "\u2705"
2974
3117
  });
@@ -3004,13 +3147,17 @@ ${dangerText(e.message)}
3004
3147
  });
3005
3148
  throw e;
3006
3149
  }
3007
- const branchBar = new import_progress2.default("Checking branch is on Tina Cloud. :prog", 1);
3150
+ const branchBar = new import_progress2.default(
3151
+ "Checking branch is on Tina Cloud. :prog",
3152
+ 1
3153
+ );
3008
3154
  if (branchKnown) {
3009
3155
  branchBar.tick({
3010
3156
  prog: "\u2705"
3011
3157
  });
3012
3158
  return {
3013
- hasUpstream
3159
+ hasUpstream,
3160
+ timestamp
3014
3161
  };
3015
3162
  }
3016
3163
  for (let i = 0; i <= 5; i++) {
@@ -3100,14 +3247,14 @@ ${dangerText(e.message)}
3100
3247
  throw e;
3101
3248
  }
3102
3249
  }
3103
- async checkGraphqlSchema(configManager, database, apiURL) {
3250
+ async checkGraphqlSchema(configManager, database, apiURL, timestamp) {
3104
3251
  const bar2 = new import_progress2.default(
3105
3252
  "Checking local GraphQL Schema matches server. :prog",
3106
3253
  1
3107
3254
  );
3108
3255
  const { config: config2 } = configManager;
3109
3256
  const token = config2.token;
3110
- const remoteSchema = await fetchRemoteGraphqlSchema({
3257
+ const { remoteSchema, remoteProjectVersion } = await fetchRemoteGraphqlSchema({
3111
3258
  url: apiURL,
3112
3259
  token
3113
3260
  });
@@ -3127,7 +3274,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3127
3274
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
3128
3275
  const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
3129
3276
  try {
3130
- const diffResult = await (0, import_core2.diff)(localGraphqlSchema, remoteGqlSchema);
3277
+ const diffResult = await (0, import_core3.diff)(localGraphqlSchema, remoteGqlSchema);
3131
3278
  if (diffResult.length === 0) {
3132
3279
  bar2.tick({
3133
3280
  prog: "\u2705"
@@ -3136,12 +3283,30 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3136
3283
  bar2.tick({
3137
3284
  prog: "\u274C"
3138
3285
  });
3139
- let errorMessage = `The local GraphQL schema doesn't match the remote GraphQL schema. Please push up your changes to GitHub to update your remote GraphQL schema.`;
3140
- if (config2 == null ? void 0 : config2.branch) {
3141
- errorMessage += `
3286
+ const type = diffResult[0].type;
3287
+ const reason = diffResult[0].message;
3288
+ const errorLevel = diffResult[0].criticality.level;
3289
+ const faqLink = getFaqLink(type);
3290
+ const tinaGraphQLVersion = configManager.getTinaGraphQLVersion();
3291
+ let errorMessage = `The local GraphQL schema doesn't match the remote GraphQL schema. Please push up your changes to GitHub to update your remote GraphQL schema. ${faqLink && `
3292
+ Check out '${faqLink}' for possible solutions.`}`;
3293
+ errorMessage += `
3142
3294
 
3143
- Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3295
+ Additional info:
3296
+
3297
+ `;
3298
+ if (config2 == null ? void 0 : config2.branch) {
3299
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3300
+ `;
3144
3301
  }
3302
+ errorMessage += ` Local GraphQL version: ${tinaGraphQLVersion.fullVersion} / Remote GraphQL version: ${remoteProjectVersion}
3303
+ `;
3304
+ errorMessage += ` Last indexed at: ${new Date(
3305
+ timestamp
3306
+ ).toUTCString()}
3307
+ `;
3308
+ errorMessage += ` Reason: [${errorLevel} - ${type}] ${reason}
3309
+ `;
3145
3310
  throw new Error(errorMessage);
3146
3311
  }
3147
3312
  } catch (e) {
@@ -3156,7 +3321,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3156
3321
  }
3157
3322
  }
3158
3323
  }
3159
- async checkTinaSchema(configManager, database, apiURL, previewName, verbose) {
3324
+ async checkTinaSchema(configManager, database, apiURL, previewName, verbose, timestamp) {
3160
3325
  const bar2 = new import_progress2.default(
3161
3326
  "Checking local Tina Schema matches server. :prog",
3162
3327
  1
@@ -3166,7 +3331,9 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3166
3331
  const { clientId, branch, isLocalClient, host } = (0, import_schema_tools2.parseURL)(apiURL);
3167
3332
  if (isLocalClient || !host || !clientId || !branch) {
3168
3333
  if (verbose) {
3169
- logger.info(logText("Not using Tina Cloud, skipping Tina Schema check"));
3334
+ logger.info(
3335
+ logText("Not using Tina Cloud, skipping Tina Schema check")
3336
+ );
3170
3337
  }
3171
3338
  return;
3172
3339
  }
@@ -3174,7 +3341,6 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3174
3341
  url: `https://${host}/db/${clientId}/${previewName || branch}/schemaSha`,
3175
3342
  token
3176
3343
  });
3177
- console.log({ remoteTinaSchemaSha });
3178
3344
  if (!remoteTinaSchemaSha) {
3179
3345
  bar2.tick({
3180
3346
  prog: "\u274C"
@@ -3190,31 +3356,36 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3190
3356
  if (!database.bridge) {
3191
3357
  throw new Error(`No bridge configured`);
3192
3358
  }
3193
- try {
3194
- const localTinaSchema = JSON.parse(
3195
- await database.bridge.get(configManager.generatedSchemaJSONPath)
3196
- );
3197
- localTinaSchema.version = void 0;
3198
- const localTinaSchemaSha = import_crypto.default.createHash("sha256").update(JSON.stringify(localTinaSchema)).digest("hex");
3199
- console.log({ localTinaSchemaSha });
3200
- if (localTinaSchemaSha !== remoteTinaSchemaSha) {
3201
- bar2.tick({
3202
- prog: "\u2705"
3203
- });
3204
- } else {
3205
- bar2.tick({
3206
- prog: "\u274C"
3207
- });
3208
- let errorMessage = `The local Tina schema doesn't match the remote Tina schema. Please push up your changes to GitHub to update your remote tina schema.`;
3209
- if (config2 == null ? void 0 : config2.branch) {
3210
- errorMessage += `
3359
+ const localTinaSchema = JSON.parse(
3360
+ await database.bridge.get(
3361
+ import_path6.default.join(database.tinaDirectory, "__generated__", "_schema.json")
3362
+ )
3363
+ );
3364
+ localTinaSchema.version = void 0;
3365
+ const localTinaSchemaSha = import_crypto.default.createHash("sha256").update(JSON.stringify(localTinaSchema)).digest("hex");
3366
+ if (localTinaSchemaSha === remoteTinaSchemaSha) {
3367
+ bar2.tick({
3368
+ prog: "\u2705"
3369
+ });
3370
+ } else {
3371
+ bar2.tick({
3372
+ prog: "\u274C"
3373
+ });
3374
+ let errorMessage = `The local Tina schema doesn't match the remote Tina schema. Please push up your changes to GitHub to update your remote tina schema.`;
3375
+ errorMessage += `
3211
3376
 
3212
- Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3213
- }
3214
- throw new Error(errorMessage);
3377
+ Additional info:
3378
+
3379
+ `;
3380
+ if (config2 == null ? void 0 : config2.branch) {
3381
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3382
+ `;
3215
3383
  }
3216
- } catch (e) {
3217
- throw e;
3384
+ errorMessage += ` Last indexed at: ${new Date(
3385
+ timestamp
3386
+ ).toUTCString()}
3387
+ `;
3388
+ throw new Error(errorMessage);
3218
3389
  }
3219
3390
  }
3220
3391
  };
@@ -3283,13 +3454,16 @@ var fetchRemoteGraphqlSchema = async ({
3283
3454
  body
3284
3455
  });
3285
3456
  const data = await res.json();
3286
- return data == null ? void 0 : data.data;
3457
+ return {
3458
+ remoteSchema: data == null ? void 0 : data.data,
3459
+ remoteRuntimeVersion: res.headers.get("tinacms-grapqhl-version"),
3460
+ remoteProjectVersion: res.headers.get("tinacms-graphql-project-version")
3461
+ };
3287
3462
  };
3288
3463
  var fetchSchemaSha = async ({
3289
3464
  url,
3290
3465
  token
3291
3466
  }) => {
3292
- console.log(url);
3293
3467
  const headers = new Headers();
3294
3468
  if (token) {
3295
3469
  headers.append("X-API-KEY", token);
@@ -3299,8 +3473,7 @@ var fetchSchemaSha = async ({
3299
3473
  headers,
3300
3474
  cache: "no-cache"
3301
3475
  });
3302
- const data = await res.json();
3303
- return data == null ? void 0 : data.data;
3476
+ return res.json();
3304
3477
  };
3305
3478
 
3306
3479
  // src/next/commands/audit-command/index.ts
@@ -3409,6 +3582,7 @@ var auditDocuments = async (args) => {
3409
3582
  logger.error(import_chalk5.default.red(err.message));
3410
3583
  if (err.originalError.originalError) {
3411
3584
  logger.error(
3585
+ // @ts-ignore FIXME: this doesn't seem right
3412
3586
  import_chalk5.default.red(` ${err.originalError.originalError.message}`)
3413
3587
  );
3414
3588
  }
@@ -3555,25 +3729,25 @@ var import_clipanion6 = require("clipanion");
3555
3729
 
3556
3730
  // src/cmds/init/detectEnvironment.ts
3557
3731
  var import_fs_extra8 = __toESM(require("fs-extra"));
3558
- var import_path6 = __toESM(require("path"));
3732
+ var import_path7 = __toESM(require("path"));
3559
3733
  var checkGitignoreForItem = async ({
3560
3734
  baseDir,
3561
3735
  line
3562
3736
  }) => {
3563
- const gitignoreContent = import_fs_extra8.default.readFileSync(import_path6.default.join(baseDir, ".gitignore")).toString();
3737
+ const gitignoreContent = import_fs_extra8.default.readFileSync(import_path7.default.join(baseDir, ".gitignore")).toString();
3564
3738
  return gitignoreContent.split("\n").some((item) => item === line);
3565
3739
  };
3566
3740
  var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
3567
3741
  const result = {
3568
- fullPathTS: import_path6.default.join(
3742
+ fullPathTS: import_path7.default.join(
3569
3743
  parentPath,
3570
3744
  `${name2}.${(opts == null ? void 0 : opts.typescriptSuffix) || (opts == null ? void 0 : opts.extensionOverride) || "ts"}`
3571
3745
  ),
3572
- fullPathJS: import_path6.default.join(
3746
+ fullPathJS: import_path7.default.join(
3573
3747
  parentPath,
3574
3748
  `${name2}.${(opts == null ? void 0 : opts.extensionOverride) || "js"}`
3575
3749
  ),
3576
- fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path6.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3750
+ fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path7.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3577
3751
  generatedFileType,
3578
3752
  name: name2,
3579
3753
  parentPath,
@@ -3603,18 +3777,20 @@ var detectEnvironment = async ({
3603
3777
  }) => {
3604
3778
  var _a;
3605
3779
  const hasForestryConfig = await import_fs_extra8.default.pathExists(
3606
- import_path6.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3780
+ import_path7.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3607
3781
  );
3608
- const sampleContentPath = import_path6.default.join(
3782
+ const sampleContentPath = import_path7.default.join(
3609
3783
  baseDir,
3610
3784
  "content",
3611
3785
  "posts",
3612
3786
  "hello-world.md"
3613
3787
  );
3614
- const usingSrc = import_fs_extra8.default.pathExistsSync(import_path6.default.join(baseDir, "src")) && (import_fs_extra8.default.pathExistsSync(import_path6.default.join(baseDir, "src", "app")) || import_fs_extra8.default.pathExistsSync(import_path6.default.join(baseDir, "src", "pages")));
3615
- const tinaFolder = import_path6.default.join(baseDir, "tina");
3788
+ const usingSrc = import_fs_extra8.default.pathExistsSync(import_path7.default.join(baseDir, "src")) && (import_fs_extra8.default.pathExistsSync(import_path7.default.join(baseDir, "src", "app")) || import_fs_extra8.default.pathExistsSync(import_path7.default.join(baseDir, "src", "pages")));
3789
+ const tinaFolder = import_path7.default.join(baseDir, "tina");
3616
3790
  const tinaConfigExists = Boolean(
3617
- await import_fs_extra8.default.pathExists(tinaFolder) && (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3791
+ // Does the tina folder exist?
3792
+ await import_fs_extra8.default.pathExists(tinaFolder) && // Does the tina folder contain a config file?
3793
+ (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3618
3794
  );
3619
3795
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
3620
3796
  Boolean
@@ -3626,12 +3802,12 @@ var detectEnvironment = async ({
3626
3802
  "next-api-handler": await makeGeneratedFile(
3627
3803
  "[...routes]",
3628
3804
  "next-api-handler",
3629
- import_path6.default.join(...pagesDir, "api", "tina")
3805
+ import_path7.default.join(...pagesDir, "api", "tina")
3630
3806
  ),
3631
3807
  "reactive-example": await makeGeneratedFile(
3632
3808
  "[filename]",
3633
3809
  "reactive-example",
3634
- import_path6.default.join(...pagesDir, "demo", "blog"),
3810
+ import_path7.default.join(...pagesDir, "demo", "blog"),
3635
3811
  {
3636
3812
  typescriptSuffix: "tsx"
3637
3813
  }
@@ -3639,13 +3815,13 @@ var detectEnvironment = async ({
3639
3815
  "users-json": await makeGeneratedFile(
3640
3816
  "index",
3641
3817
  "users-json",
3642
- import_path6.default.join(baseDir, "content", "users"),
3818
+ import_path7.default.join(baseDir, "content", "users"),
3643
3819
  { extensionOverride: "json" }
3644
3820
  ),
3645
3821
  "sample-content": await makeGeneratedFile(
3646
3822
  "hello-world",
3647
3823
  "sample-content",
3648
- import_path6.default.join(baseDir, "content", "posts"),
3824
+ import_path7.default.join(baseDir, "content", "posts"),
3649
3825
  { extensionOverride: "md" }
3650
3826
  )
3651
3827
  };
@@ -3671,13 +3847,13 @@ var detectEnvironment = async ({
3671
3847
  );
3672
3848
  }
3673
3849
  }
3674
- const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path6.default.join(".gitignore"));
3850
+ const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path7.default.join(".gitignore"));
3675
3851
  const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
3676
3852
  const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
3677
3853
  const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
3678
3854
  let frontMatterFormat;
3679
3855
  if (hasForestryConfig) {
3680
- const hugoConfigPath = import_path6.default.join(rootPath, "config.toml");
3856
+ const hugoConfigPath = import_path7.default.join(rootPath, "config.toml");
3681
3857
  if (await import_fs_extra8.default.pathExists(hugoConfigPath)) {
3682
3858
  const hugoConfig = await import_fs_extra8.default.readFile(hugoConfigPath, "utf8");
3683
3859
  const metaDataFormat = (_a = hugoConfig.match(/metaDataFormat = "(.*)"/)) == null ? void 0 : _a[1];
@@ -3849,6 +4025,7 @@ var supportedDatabaseAdapters = {
3849
4025
  {
3850
4026
  from: "mongodb",
3851
4027
  imported: [],
4028
+ // not explicitly imported
3852
4029
  packageName: "mongodb"
3853
4030
  }
3854
4031
  ]
@@ -3921,6 +4098,10 @@ var chooseDatabaseAdapter = async ({
3921
4098
  title: "MongoDB",
3922
4099
  value: "mongodb"
3923
4100
  }
4101
+ // {
4102
+ // title: "I'll create my own database adapter",
4103
+ // value: 'other',
4104
+ // },
3924
4105
  ]
3925
4106
  }
3926
4107
  ]);
@@ -4198,6 +4379,7 @@ async function configure(env, opts) {
4198
4379
  packageManager,
4199
4380
  forestryMigrate: false,
4200
4381
  isLocalEnvVarName: "TINA_PUBLIC_IS_LOCAL",
4382
+ // TODO: give this a better default
4201
4383
  typescript: false
4202
4384
  };
4203
4385
  if (config2.framework.name === "next") {
@@ -4285,31 +4467,41 @@ var CLICommand = class {
4285
4467
  };
4286
4468
 
4287
4469
  // src/cmds/init/apply.ts
4288
- var import_path10 = __toESM(require("path"));
4470
+ var import_path11 = __toESM(require("path"));
4289
4471
 
4290
4472
  // src/cmds/forestry-migrate/index.ts
4291
4473
  var import_fs_extra10 = __toESM(require("fs-extra"));
4292
- var import_path8 = __toESM(require("path"));
4474
+ var import_path9 = __toESM(require("path"));
4293
4475
  var import_js_yaml2 = __toESM(require("js-yaml"));
4294
4476
  var import_minimatch = __toESM(require("minimatch"));
4295
4477
  var import_graphql16 = require("@tinacms/graphql");
4296
4478
 
4297
4479
  // src/cmds/forestry-migrate/util/index.ts
4298
4480
  var import_fs_extra9 = __toESM(require("fs-extra"));
4299
- var import_path7 = __toESM(require("path"));
4481
+ var import_path8 = __toESM(require("path"));
4300
4482
  var import_js_yaml = __toESM(require("js-yaml"));
4301
4483
  var import_zod = __toESM(require("zod"));
4302
4484
 
4303
4485
  // src/cmds/forestry-migrate/util/errorSingleton.ts
4304
- var ErrorSingleton = class {
4486
+ var ErrorSingleton = class _ErrorSingleton {
4487
+ /**
4488
+ * The Singleton's constructor should always be private to prevent direct
4489
+ * construction calls with the `new` operator.
4490
+ */
4305
4491
  constructor() {
4306
4492
  }
4493
+ /**
4494
+ * The static method that controls the access to the singleton instance.
4495
+ *
4496
+ * This implementation let you subclass the Singleton class while keeping
4497
+ * just one instance of each subclass around.
4498
+ */
4307
4499
  static getInstance() {
4308
- if (!ErrorSingleton.instance) {
4309
- ErrorSingleton.instance = new ErrorSingleton();
4310
- ErrorSingleton.instance.collectionNameErrors = [];
4500
+ if (!_ErrorSingleton.instance) {
4501
+ _ErrorSingleton.instance = new _ErrorSingleton();
4502
+ _ErrorSingleton.instance.collectionNameErrors = [];
4311
4503
  }
4312
- return ErrorSingleton.instance;
4504
+ return _ErrorSingleton.instance;
4313
4505
  }
4314
4506
  addErrorName(error) {
4315
4507
  this.collectionNameErrors.push(error);
@@ -4352,8 +4544,7 @@ var makeFieldsWithInternalCode = ({
4352
4544
  if (hasBody) {
4353
4545
  return [bodyField, `__TINA_INTERNAL__:::...${field}():::`];
4354
4546
  } else {
4355
- if (spread)
4356
- return `__TINA_INTERNAL__:::...${field}():::`;
4547
+ if (spread) return `__TINA_INTERNAL__:::...${field}():::`;
4357
4548
  return `__TINA_INTERNAL__:::${field}():::`;
4358
4549
  }
4359
4550
  };
@@ -4437,6 +4628,7 @@ var forestryConfigSchema = import_zod.default.object({
4437
4628
  )
4438
4629
  });
4439
4630
  var forestryFieldWithoutField = import_zod.default.object({
4631
+ // TODO: maybe better type this?
4440
4632
  type: import_zod.default.union([
4441
4633
  import_zod.default.literal("text"),
4442
4634
  import_zod.default.literal("datetime"),
@@ -4460,6 +4652,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4460
4652
  default: import_zod.default.any().optional(),
4461
4653
  template: import_zod.default.string().optional(),
4462
4654
  config: import_zod.default.object({
4655
+ // min and max are used for lists
4463
4656
  min: import_zod.default.number().optional().nullable(),
4464
4657
  max: import_zod.default.number().optional().nullable(),
4465
4658
  required: import_zod.default.boolean().optional().nullable(),
@@ -4473,6 +4666,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4473
4666
  import_zod.default.literal("pages"),
4474
4667
  import_zod.default.literal("documents"),
4475
4668
  import_zod.default.literal("simple"),
4669
+ // TODO: I want to ignore this key if its invalid
4476
4670
  import_zod.default.string()
4477
4671
  ]).optional().nullable(),
4478
4672
  section: import_zod.default.string().optional().nullable()
@@ -4508,6 +4702,7 @@ var transformForestryFieldsToTinaFields = ({
4508
4702
  }
4509
4703
  let field;
4510
4704
  switch (forestryField2.type) {
4705
+ // Single filed types
4511
4706
  case "text":
4512
4707
  field = {
4513
4708
  type: "string",
@@ -4587,6 +4782,7 @@ var transformForestryFieldsToTinaFields = ({
4587
4782
  );
4588
4783
  }
4589
4784
  break;
4785
+ // List Types
4590
4786
  case "list":
4591
4787
  field = {
4592
4788
  type: "string",
@@ -4609,6 +4805,7 @@ var transformForestryFieldsToTinaFields = ({
4609
4805
  }
4610
4806
  };
4611
4807
  break;
4808
+ // Object (Group) types
4612
4809
  case "field_group":
4613
4810
  field = {
4614
4811
  type: "object",
@@ -4649,6 +4846,7 @@ var transformForestryFieldsToTinaFields = ({
4649
4846
  });
4650
4847
  const fieldsString = stringifyLabelWithField(template2.label);
4651
4848
  const t = {
4849
+ // @ts-ignore
4652
4850
  fields: makeFieldsWithInternalCode({
4653
4851
  hasBody: false,
4654
4852
  field: fieldsString
@@ -4657,7 +4855,6 @@ var transformForestryFieldsToTinaFields = ({
4657
4855
  name: stringifyTemplateName(tem, tem)
4658
4856
  };
4659
4857
  if (t.name != tem) {
4660
- ;
4661
4858
  t.nameOverride = tem;
4662
4859
  }
4663
4860
  templates2.push(t);
@@ -4686,6 +4883,7 @@ var transformForestryFieldsToTinaFields = ({
4686
4883
  spread: true
4687
4884
  });
4688
4885
  tinaFields.push(
4886
+ // @ts-ignore
4689
4887
  field2
4690
4888
  );
4691
4889
  break;
@@ -4707,7 +4905,7 @@ var transformForestryFieldsToTinaFields = ({
4707
4905
  return tinaFields;
4708
4906
  };
4709
4907
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
4710
- const templatePath = import_path7.default.join(
4908
+ const templatePath = import_path8.default.join(
4711
4909
  pathToForestryConfig,
4712
4910
  ".forestry",
4713
4911
  "front_matter",
@@ -4745,6 +4943,7 @@ var parseSections = ({ val }) => {
4745
4943
 
4746
4944
  // src/cmds/forestry-migrate/index.ts
4747
4945
  var BODY_FIELD = {
4946
+ // This is the body field
4748
4947
  type: "rich-text",
4749
4948
  name: "body",
4750
4949
  label: "Body of Document",
@@ -4782,8 +4981,8 @@ var generateAllTemplates = async ({
4782
4981
  pathToForestryConfig
4783
4982
  }) => {
4784
4983
  const allTemplates = (await import_fs_extra10.default.readdir(
4785
- import_path8.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4786
- )).map((tem) => import_path8.default.basename(tem, ".yml"));
4984
+ import_path9.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4985
+ )).map((tem) => import_path9.default.basename(tem, ".yml"));
4787
4986
  const templateMap = /* @__PURE__ */ new Map();
4788
4987
  const proms = allTemplates.map(async (tem) => {
4789
4988
  try {
@@ -4803,8 +5002,7 @@ var generateAllTemplates = async ({
4803
5002
  };
4804
5003
  var generateCollectionFromForestrySection = (args) => {
4805
5004
  const { section, templateMap } = args;
4806
- if (section.read_only)
4807
- return;
5005
+ if (section.read_only) return;
4808
5006
  let format3 = "md";
4809
5007
  if (section.new_doc_ext) {
4810
5008
  const ext = checkExt(section.new_doc_ext);
@@ -4871,12 +5069,14 @@ var generateCollectionFromForestrySection = (args) => {
4871
5069
  if (((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1) {
4872
5070
  c = {
4873
5071
  ...baseCollection,
5072
+ // @ts-expect-error
4874
5073
  templates: forestryTemplates.map((tem) => {
4875
5074
  const currentTemplate = templateMap.get(tem);
4876
5075
  const fieldsString = stringifyLabelWithField(
4877
5076
  currentTemplate.templateObj.label
4878
5077
  );
4879
5078
  return {
5079
+ // fields: [BODY_FIELD],
4880
5080
  fields: makeFieldsWithInternalCode({
4881
5081
  hasBody,
4882
5082
  field: fieldsString,
@@ -4894,6 +5094,8 @@ var generateCollectionFromForestrySection = (args) => {
4894
5094
  const fieldsString = stringifyLabelWithField(template.templateObj.label);
4895
5095
  c = {
4896
5096
  ...baseCollection,
5097
+ // fields: [BODY_FIELD],
5098
+ // @ts-expect-error
4897
5099
  fields: makeFieldsWithInternalCode({
4898
5100
  field: fieldsString,
4899
5101
  hasBody,
@@ -4925,9 +5127,9 @@ var generateCollectionFromForestrySection = (args) => {
4925
5127
  return c;
4926
5128
  } else if (section.type === "document") {
4927
5129
  const filePath = section.path;
4928
- const extname = import_path8.default.extname(filePath);
4929
- const fileName = import_path8.default.basename(filePath, extname);
4930
- const dir = import_path8.default.dirname(filePath);
5130
+ const extname = import_path9.default.extname(filePath);
5131
+ const fileName = import_path9.default.basename(filePath, extname);
5132
+ const dir = import_path9.default.dirname(filePath);
4931
5133
  const ext = checkExt(extname);
4932
5134
  if (ext) {
4933
5135
  const fields = [];
@@ -4990,7 +5192,7 @@ var generateCollections = async ({
4990
5192
  usingTypescript
4991
5193
  });
4992
5194
  const forestryConfig = await import_fs_extra10.default.readFile(
4993
- import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
5195
+ import_path9.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4994
5196
  );
4995
5197
  rewriteTemplateKeysInDocs({
4996
5198
  templateMap,
@@ -5021,11 +5223,11 @@ var rewriteTemplateKeysInDocs = (args) => {
5021
5223
  const { templateObj } = templateMap.get(templateKey);
5022
5224
  (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
5023
5225
  try {
5024
- const filePath = import_path8.default.join(page);
5226
+ const filePath = import_path9.default.join(page);
5025
5227
  if (import_fs_extra10.default.lstatSync(filePath).isDirectory()) {
5026
5228
  return;
5027
5229
  }
5028
- const extname = import_path8.default.extname(filePath);
5230
+ const extname = import_path9.default.extname(filePath);
5029
5231
  const fileContent = import_fs_extra10.default.readFileSync(filePath).toString();
5030
5232
  const content = (0, import_graphql16.parseFile)(
5031
5233
  fileContent,
@@ -5057,7 +5259,7 @@ var import_fs_extra13 = __toESM(require("fs-extra"));
5057
5259
  // src/next/commands/codemod-command/index.ts
5058
5260
  var import_clipanion5 = require("clipanion");
5059
5261
  var import_fs_extra11 = __toESM(require("fs-extra"));
5060
- var import_path9 = __toESM(require("path"));
5262
+ var import_path10 = __toESM(require("path"));
5061
5263
  var CodemodCommand = class extends import_clipanion5.Command {
5062
5264
  constructor() {
5063
5265
  super(...arguments);
@@ -5101,7 +5303,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5101
5303
  logger.error(e.message);
5102
5304
  process.exit(1);
5103
5305
  }
5104
- const tinaDestination = import_path9.default.join(configManager.rootPath, "tina");
5306
+ const tinaDestination = import_path10.default.join(configManager.rootPath, "tina");
5105
5307
  if (await import_fs_extra11.default.existsSync(tinaDestination)) {
5106
5308
  logger.info(
5107
5309
  `Folder already exists at ${tinaDestination}. Either delete this folder to complete the codemod, or ensure you have properly copied your config from the ".tina" folder.`
@@ -5116,7 +5318,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5116
5318
  };
5117
5319
  var writeGitignore = async (rootPath) => {
5118
5320
  await import_fs_extra11.default.outputFileSync(
5119
- import_path9.default.join(rootPath, "tina", ".gitignore"),
5321
+ import_path10.default.join(rootPath, "tina", ".gitignore"),
5120
5322
  "__generated__"
5121
5323
  );
5122
5324
  };
@@ -5641,6 +5843,7 @@ var makeImportsVisitor = (sourceFile, importMap) => (ctx) => (node) => {
5641
5843
  ) : [];
5642
5844
  const newImports = [
5643
5845
  .../* @__PURE__ */ new Set([
5846
+ // we use Set to remove duplicates
5644
5847
  ...existingImports,
5645
5848
  ...imports
5646
5849
  ])
@@ -5795,10 +5998,14 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5795
5998
  );
5796
5999
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5797
6000
  const importMap = {
5798
- ...configImports.reduce((acc, { from, imported }) => {
5799
- acc[from] = imported;
5800
- return acc;
5801
- }, {})
6001
+ // iterate over configImports and add them to the import map
6002
+ ...configImports.reduce(
6003
+ (acc, { from, imported }) => {
6004
+ acc[from] = imported;
6005
+ return acc;
6006
+ },
6007
+ {}
6008
+ )
5802
6009
  };
5803
6010
  const transformedSourceFileResult = import_typescript3.default.transform(
5804
6011
  sourceFile,
@@ -5954,8 +6161,8 @@ async function apply({
5954
6161
  await addConfigFile({
5955
6162
  configArgs: {
5956
6163
  config: config2,
5957
- publicFolder: import_path10.default.join(
5958
- import_path10.default.relative(process.cwd(), pathToForestryConfig),
6164
+ publicFolder: import_path11.default.join(
6165
+ import_path11.default.relative(process.cwd(), pathToForestryConfig),
5959
6166
  config2.publicFolder
5960
6167
  ),
5961
6168
  collections,
@@ -5969,7 +6176,13 @@ async function apply({
5969
6176
  config: config2
5970
6177
  });
5971
6178
  }
5972
- if (env.tinaConfigExists && params.isBackendInit && config2.hosting === "self-host" && (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud") {
6179
+ if (
6180
+ // if the config was just generated we do not need to update the config file because it will be generated correctly
6181
+ env.tinaConfigExists && // Are we running tinacms init backend
6182
+ params.isBackendInit && // Do the user choose the 'self-host' option
6183
+ config2.hosting === "self-host" && // the user did not choose the 'tina-cloud' auth provider
6184
+ (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud"
6185
+ ) {
5973
6186
  await addSelfHostedTinaAuthToConfig(config2, env.generatedFiles["config"]);
5974
6187
  }
5975
6188
  logNextSteps({
@@ -6022,18 +6235,18 @@ var createPackageJSON = async () => {
6022
6235
  };
6023
6236
  var createGitignore = async ({ baseDir }) => {
6024
6237
  logger.info(logText("No .gitignore found, creating one"));
6025
- import_fs_extra13.default.outputFileSync(import_path10.default.join(baseDir, ".gitignore"), "node_modules");
6238
+ import_fs_extra13.default.outputFileSync(import_path11.default.join(baseDir, ".gitignore"), "node_modules");
6026
6239
  };
6027
6240
  var updateGitIgnore = async ({
6028
6241
  baseDir,
6029
6242
  items
6030
6243
  }) => {
6031
6244
  logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
6032
- const gitignoreContent = import_fs_extra13.default.readFileSync(import_path10.default.join(baseDir, ".gitignore")).toString();
6245
+ const gitignoreContent = import_fs_extra13.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
6033
6246
  const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
6034
6247
  "\n"
6035
6248
  );
6036
- await import_fs_extra13.default.writeFile(import_path10.default.join(baseDir, ".gitignore"), newGitignoreContent);
6249
+ await import_fs_extra13.default.writeFile(import_path11.default.join(baseDir, ".gitignore"), newGitignoreContent);
6037
6250
  };
6038
6251
  var addDependencies = async (config2, env, params) => {
6039
6252
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
@@ -6103,22 +6316,22 @@ var writeGeneratedFile = async ({
6103
6316
  content,
6104
6317
  typescript
6105
6318
  }) => {
6106
- const { exists, path: path13, parentPath } = generatedFile.resolve(typescript);
6319
+ const { exists, path: path14, parentPath } = generatedFile.resolve(typescript);
6107
6320
  if (exists) {
6108
6321
  if (overwrite) {
6109
- logger.info(`Overwriting file at ${path13}... \u2705`);
6110
- import_fs_extra13.default.outputFileSync(path13, content);
6322
+ logger.info(`Overwriting file at ${path14}... \u2705`);
6323
+ import_fs_extra13.default.outputFileSync(path14, content);
6111
6324
  } else {
6112
- logger.info(`Not overwriting file at ${path13}.`);
6325
+ logger.info(`Not overwriting file at ${path14}.`);
6113
6326
  logger.info(
6114
- logText(`Please add the following to ${path13}:
6327
+ logText(`Please add the following to ${path14}:
6115
6328
  ${indentText(content)}}`)
6116
6329
  );
6117
6330
  }
6118
6331
  } else {
6119
- logger.info(`Adding file at ${path13}... \u2705`);
6332
+ logger.info(`Adding file at ${path14}... \u2705`);
6120
6333
  await import_fs_extra13.default.ensureDir(parentPath);
6121
- import_fs_extra13.default.outputFileSync(path13, content);
6334
+ import_fs_extra13.default.outputFileSync(path14, content);
6122
6335
  }
6123
6336
  };
6124
6337
  var addConfigFile = async ({
@@ -6201,7 +6414,7 @@ var addContentFile = async ({
6201
6414
  return () => ({
6202
6415
  exists: env.sampleContentExists,
6203
6416
  path: env.sampleContentPath,
6204
- parentPath: import_path10.default.dirname(env.sampleContentPath)
6417
+ parentPath: import_path11.default.dirname(env.sampleContentPath)
6205
6418
  });
6206
6419
  }
6207
6420
  },
@@ -6224,7 +6437,7 @@ ${titleText(" TinaCMS ")} backend initialized!`));
6224
6437
  return `${x.key}=${x.value || "***"}`;
6225
6438
  }).join("\n") + `
6226
6439
  TINA_PUBLIC_IS_LOCAL=true`;
6227
- const envFile = import_path10.default.join(process.cwd(), ".env");
6440
+ const envFile = import_path11.default.join(process.cwd(), ".env");
6228
6441
  if (!import_fs_extra13.default.existsSync(envFile)) {
6229
6442
  logger.info(`Adding .env file to your project... \u2705`);
6230
6443
  import_fs_extra13.default.writeFileSync(envFile, envFileText);
@@ -6247,6 +6460,13 @@ ${titleText(" TinaCMS ")} has been initialized!`));
6247
6460
  logger.info(
6248
6461
  "To get started run: " + cmdText(frameworkDevCmds[framework.name]({ packageManager }))
6249
6462
  );
6463
+ if (framework.name === "hugo") {
6464
+ logger.info(
6465
+ focusText("Hugo is required. "),
6466
+ "Don't have Hugo installed? Follow this guide to set it up: ",
6467
+ linkText("https://gohugo.io/installation/")
6468
+ );
6469
+ }
6250
6470
  logger.info(
6251
6471
  "To get your site production ready, run: " + cmdText(`tinacms init backend`)
6252
6472
  );
@@ -6262,6 +6482,7 @@ var other = ({ packageManager }) => {
6262
6482
  const packageManagers = {
6263
6483
  pnpm: `pnpm`,
6264
6484
  npm: `npx`,
6485
+ // npx is the way to run executables that aren't in your "scripts"
6265
6486
  yarn: `yarn`
6266
6487
  };
6267
6488
  return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
@@ -6274,6 +6495,7 @@ var frameworkDevCmds = {
6274
6495
  const packageManagers = {
6275
6496
  pnpm: `pnpm`,
6276
6497
  npm: `npm run`,
6498
+ // npx is the way to run executables that aren't in your "scripts"
6277
6499
  yarn: `yarn`
6278
6500
  };
6279
6501
  return `${packageManagers[packageManager]} dev`;
@@ -6288,7 +6510,7 @@ var addReactiveFile = {
6288
6510
  dataLayer
6289
6511
  }) => {
6290
6512
  var _a, _b;
6291
- const packageJsonPath = import_path10.default.join(baseDir, "package.json");
6513
+ const packageJsonPath = import_path11.default.join(baseDir, "package.json");
6292
6514
  await writeGeneratedFile({
6293
6515
  generatedFile,
6294
6516
  typescript: config2.typescript,
@@ -6530,6 +6752,4 @@ cli.register(SearchIndexCommand);
6530
6752
  cli.register(import_clipanion8.Builtins.DefinitionsCommand);
6531
6753
  cli.register(import_clipanion8.Builtins.HelpCommand);
6532
6754
  cli.register(import_clipanion8.Builtins.VersionCommand);
6533
- var src_default = cli;
6534
- // Annotate the CommonJS export names for ESM import in node:
6535
- 0 && (module.exports = {});
6755
+ var index_default = cli;