@tinacms/cli 0.0.0-9c44130-20241030170642 → 0.0.0-9db4961-20250328182422

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.4";
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,
@@ -995,10 +1015,14 @@ var createConfig = async ({
995
1015
  } else {
996
1016
  alias["CLIENT_IMPORT"] = configManager.isUsingTs() ? configManager.generatedTypesTSFilePath : configManager.generatedTypesJSFilePath;
997
1017
  }
1018
+ alias["react"] = import_node_path2.default.dirname(require.resolve("react"));
1019
+ alias["react-dom"] = import_node_path2.default.dirname(require.resolve("react-dom"));
998
1020
  let basePath;
999
1021
  if (configManager.config.build.basePath) {
1000
1022
  basePath = configManager.config.build.basePath;
1001
1023
  }
1024
+ const fullVersion = configManager.getTinaGraphQLVersion();
1025
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1002
1026
  const config2 = {
1003
1027
  root: configManager.spaRootPath,
1004
1028
  base: `/${basePath ? `${(0, import_normalize_path2.default)(basePath)}/` : ""}${(0, import_normalize_path2.default)(
@@ -1010,15 +1034,33 @@ var createConfig = async ({
1010
1034
  dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1011
1035
  },
1012
1036
  define: {
1037
+ /**
1038
+ * Since we prebuild the config.ts, it's possible for modules to be loaded which make
1039
+ * use of `process`. The main scenario where this is an issue is when co-locating schema
1040
+ * definitions with source files, and specifically source files which impor from NextJS.
1041
+ *
1042
+ * Some examples of what NextJS uses for `process.env` are:
1043
+ * - `process.env.__NEXT_TRAILING_SLASH`
1044
+ * - `process.env.__NEXT_CROSS_ORIGIN`
1045
+ * - `process.env.__NEXT_I18N_SUPPORT`
1046
+ *
1047
+ * Also, interestingly some of the advice for handling this doesn't work, references to replacing
1048
+ * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
1049
+ * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1050
+ */
1013
1051
  "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1052
+ // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1014
1053
  "process.platform": `"${process.platform}"`,
1015
1054
  __API_URL__: `"${apiURL}"`,
1016
1055
  __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1017
- __TINA_GRAPHQL_VERSION__: `"${configManager.getTinaGraphQLVersion()}"`
1056
+ __TINA_GRAPHQL_VERSION__: version2
1018
1057
  },
1019
1058
  logLevel: "error",
1059
+ // Vite import warnings are noisy
1020
1060
  optimizeDeps: {
1021
1061
  force: true,
1062
+ // Not 100% sure why this isn't being picked up automatically, this works from within the monorepo
1063
+ // but breaks externally
1022
1064
  include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1023
1065
  },
1024
1066
  server: {
@@ -1026,6 +1068,7 @@ var createConfig = async ({
1026
1068
  watch: noWatch ? {
1027
1069
  ignored: ["**/*"]
1028
1070
  } : {
1071
+ // Ignore everything except for the alias fields we specified above
1029
1072
  ignored: [
1030
1073
  `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1031
1074
  ]
@@ -1041,8 +1084,13 @@ var createConfig = async ({
1041
1084
  rollupOptions
1042
1085
  },
1043
1086
  plugins: [
1087
+ /**
1088
+ * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
1089
+ * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
1090
+ */
1044
1091
  (0, import_plugin_react.default)({
1045
1092
  babel: {
1093
+ // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1046
1094
  compact: true
1047
1095
  }
1048
1096
  }),
@@ -1119,8 +1167,7 @@ var createMediaRouter = (config2) => {
1119
1167
  };
1120
1168
  var parseMediaFolder = (str) => {
1121
1169
  let returnString = str;
1122
- if (returnString.startsWith("/"))
1123
- returnString = returnString.substr(1);
1170
+ if (returnString.startsWith("/")) returnString = returnString.substr(1);
1124
1171
  if (returnString.endsWith("/"))
1125
1172
  returnString = returnString.substr(0, returnString.length - 1);
1126
1173
  return returnString;
@@ -1137,7 +1184,7 @@ var MediaModel = class {
1137
1184
  this.rootPath,
1138
1185
  this.publicFolder,
1139
1186
  this.mediaRoot,
1140
- args.searchPath
1187
+ decodeURIComponent(args.searchPath)
1141
1188
  );
1142
1189
  const searchPath = parseMediaFolder(args.searchPath);
1143
1190
  if (!await import_fs_extra3.default.pathExists(folderPath)) {
@@ -1209,7 +1256,7 @@ var MediaModel = class {
1209
1256
  this.rootPath,
1210
1257
  this.publicFolder,
1211
1258
  this.mediaRoot,
1212
- args.searchPath
1259
+ decodeURIComponent(args.searchPath)
1213
1260
  );
1214
1261
  await import_fs_extra3.default.stat(file);
1215
1262
  await import_fs_extra3.default.remove(file);
@@ -1285,7 +1332,8 @@ var devServerEndPointsPlugin = ({
1285
1332
  configManager,
1286
1333
  apiURL,
1287
1334
  database,
1288
- searchIndex
1335
+ searchIndex,
1336
+ databaseLock
1289
1337
  }) => {
1290
1338
  const plug = {
1291
1339
  name: "graphql-endpoints",
@@ -1329,14 +1377,17 @@ var devServerEndPointsPlugin = ({
1329
1377
  }
1330
1378
  if (req.url === "/graphql") {
1331
1379
  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
1380
+ let result;
1381
+ await databaseLock(async () => {
1382
+ result = await (0, import_graphql.resolve)({
1383
+ config: {
1384
+ useRelativeMedia: true
1385
+ },
1386
+ database,
1387
+ query,
1388
+ variables,
1389
+ verbose: false
1390
+ });
1340
1391
  });
1341
1392
  res.end(JSON.stringify(result));
1342
1393
  return;
@@ -1387,6 +1438,7 @@ function viteTransformExtension({
1387
1438
  return {
1388
1439
  code: res.code,
1389
1440
  map: null
1441
+ // TODO:
1390
1442
  };
1391
1443
  }
1392
1444
  }
@@ -1394,10 +1446,16 @@ function viteTransformExtension({
1394
1446
  }
1395
1447
 
1396
1448
  // src/next/commands/dev-command/server/index.ts
1397
- var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch) => {
1449
+ var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch, databaseLock) => {
1398
1450
  const plugins = [
1399
1451
  transformTsxPlugin({ configManager }),
1400
- devServerEndPointsPlugin({ apiURL, configManager, database, searchIndex }),
1452
+ devServerEndPointsPlugin({
1453
+ apiURL,
1454
+ configManager,
1455
+ database,
1456
+ searchIndex,
1457
+ databaseLock
1458
+ }),
1401
1459
  viteTransformExtension()
1402
1460
  ];
1403
1461
  return (0, import_vite3.createServer)(
@@ -1407,6 +1465,14 @@ var createDevServer = async (configManager, database, searchIndex, apiURL, noWat
1407
1465
  apiURL,
1408
1466
  plugins,
1409
1467
  noWatch,
1468
+ /**
1469
+ * Ensure Vite's import scan uses the spaMainPath as the input
1470
+ * so it properly finds everything. This is for dev only, and when
1471
+ * running the server outside of this monorepo vite fails to find
1472
+ * and optimize the imports, so you get errors about it not being
1473
+ * able to find an export from a module, and it's always a CJS
1474
+ * module that Vite would usually transform to an ES module.
1475
+ */
1410
1476
  rollupOptions: {
1411
1477
  input: configManager.spaMainPath,
1412
1478
  onwarn(warning, warn) {
@@ -1532,6 +1598,7 @@ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBas
1532
1598
  node,
1533
1599
  documentVariableName,
1534
1600
  operationType,
1601
+ // This is the only line that is different
1535
1602
  operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
1536
1603
  operationVariablesTypes
1537
1604
  });
@@ -1580,6 +1647,8 @@ var plugin = (schema, documents, config2) => {
1580
1647
  const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1581
1648
  const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1582
1649
  return {
1650
+ // We will take care of imports
1651
+ // prepend: visitor.getImports(),
1583
1652
  content: [
1584
1653
  visitor.fragments,
1585
1654
  ...visitorResult.definitions.filter((t) => typeof t === "string"),
@@ -1595,6 +1664,7 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
1595
1664
  docs = await loadGraphQLDocuments(queryPathGlob);
1596
1665
  fragDocs = await loadGraphQLDocuments(fragDocPath);
1597
1666
  const res = await (0, import_core.codegen)({
1667
+ // Filename is not used. This is because the typescript plugin returns a string instead of writing to a file.
1598
1668
  filename: process.cwd(),
1599
1669
  schema: (0, import_graphql5.parse)((0, import_graphql5.printSchema)(schema)),
1600
1670
  documents: [...docs, ...fragDocs],
@@ -1629,9 +1699,12 @@ var loadGraphQLDocuments = async (globPath) => {
1629
1699
  loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
1630
1700
  });
1631
1701
  } catch (e) {
1632
- if ((e.message || "").includes(
1633
- "Unable to find any GraphQL type definitions for the following pointers:"
1634
- )) {
1702
+ if (
1703
+ // https://www.graphql-tools.com/docs/documents-loading#no-files-found
1704
+ (e.message || "").includes(
1705
+ "Unable to find any GraphQL type definitions for the following pointers:"
1706
+ )
1707
+ ) {
1635
1708
  } else {
1636
1709
  throw e;
1637
1710
  }
@@ -1668,7 +1741,10 @@ var Codegen = class {
1668
1741
  this.noClientBuildCache = noClientBuildCache;
1669
1742
  }
1670
1743
  async writeConfigFile(fileName, data) {
1671
- const filePath = import_path4.default.join(this.configManager.generatedFolderPath, fileName);
1744
+ const filePath = import_path4.default.join(
1745
+ this.configManager.generatedFolderPath,
1746
+ fileName
1747
+ );
1672
1748
  await import_fs_extra4.default.ensureFile(filePath);
1673
1749
  await import_fs_extra4.default.outputFile(filePath, data);
1674
1750
  if (this.configManager.hasSeparateContentRoot()) {
@@ -1788,16 +1864,14 @@ var Codegen = class {
1788
1864
  const branch = (_a = this.configManager.config) == null ? void 0 : _a.branch;
1789
1865
  const clientId = (_b = this.configManager.config) == null ? void 0 : _b.clientId;
1790
1866
  const token = (_c = this.configManager.config) == null ? void 0 : _c.token;
1791
- const version2 = this.configManager.getTinaGraphQLVersion();
1867
+ const fullVersion = this.configManager.getTinaGraphQLVersion();
1868
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1792
1869
  const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
1793
1870
  if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
1794
1871
  const missing = [];
1795
- if (!branch)
1796
- missing.push("branch");
1797
- if (!clientId)
1798
- missing.push("clientId");
1799
- if (!token)
1800
- missing.push("token");
1872
+ if (!branch) missing.push("branch");
1873
+ if (!clientId) missing.push("clientId");
1874
+ if (!token) missing.push("token");
1801
1875
  throw new Error(
1802
1876
  `Client not configured properly. Missing ${missing.join(
1803
1877
  ", "
@@ -1951,7 +2025,11 @@ schema {
1951
2025
  }
1952
2026
  };
1953
2027
  var maybeWarnFragmentSize = async (filepath) => {
1954
- if ((await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
2028
+ if (
2029
+ // is the file bigger than 100kb?
2030
+ (await import_fs_extra4.default.stat(filepath)).size > // convert to 100 kb to bytes
2031
+ 100 * 1024
2032
+ ) {
1955
2033
  console.warn(
1956
2034
  "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
1957
2035
  );
@@ -1979,6 +2057,7 @@ var import_many_level = require("many-level");
1979
2057
  var import_memory_level = require("memory-level");
1980
2058
  var createDBServer = (port) => {
1981
2059
  const levelHost = new import_many_level.ManyLevelHost(
2060
+ // @ts-ignore
1982
2061
  new import_memory_level.MemoryLevel({
1983
2062
  valueEncoding: "json"
1984
2063
  })
@@ -2129,7 +2208,9 @@ var BaseCommand = class extends import_clipanion.Command {
2129
2208
  let subProc;
2130
2209
  if (this.subCommand) {
2131
2210
  subProc = await startSubprocess2({ command: this.subCommand });
2132
- logger.info(`Starting subprocess: ${import_chalk4.default.cyan(this.subCommand)}`);
2211
+ logger.info(
2212
+ `Running web application with command: ${import_chalk4.default.cyan(this.subCommand)}`
2213
+ );
2133
2214
  }
2134
2215
  function exitHandler(options, exitCode) {
2135
2216
  if (subProc) {
@@ -2209,7 +2290,7 @@ var BaseCommand = class extends import_clipanion.Command {
2209
2290
  pathFilter
2210
2291
  });
2211
2292
  const tinaPathUpdates = modified.filter(
2212
- (path13) => path13.startsWith(".tina/__generated__/_schema.json") || path13.startsWith("tina/tina-lock.json")
2293
+ (path14) => path14.startsWith(".tina/__generated__/_schema.json") || path14.startsWith("tina/tina-lock.json")
2213
2294
  );
2214
2295
  if (tinaPathUpdates.length > 0) {
2215
2296
  res = await database.indexContent({
@@ -2253,6 +2334,7 @@ var import_search = require("@tinacms/search");
2253
2334
  var DevCommand = class extends BaseCommand {
2254
2335
  constructor() {
2255
2336
  super(...arguments);
2337
+ // NOTE: camelCase commands for string options don't work if there's an `=` used https://github.com/arcanis/clipanion/issues/141
2256
2338
  this.watchFolders = import_clipanion2.Option.String("-w,--watchFolders", {
2257
2339
  description: "DEPRECATED - a list of folders (relative to where this is being run) that the cli will watch for changes"
2258
2340
  });
@@ -2262,6 +2344,10 @@ var DevCommand = class extends BaseCommand {
2262
2344
  this.outputSearchIndexPath = import_clipanion2.Option.String("--outputSearchIndexPath", {
2263
2345
  description: "Path to write the search index to"
2264
2346
  });
2347
+ this.noServer = import_clipanion2.Option.Boolean("--no-server", false, {
2348
+ description: "Do not start the dev server"
2349
+ });
2350
+ this.indexingLock = new import_async_lock.default();
2265
2351
  }
2266
2352
  async catch(error) {
2267
2353
  logger.error("Error occured during tinacms dev");
@@ -2282,10 +2368,13 @@ var DevCommand = class extends BaseCommand {
2282
2368
  rootPath: this.rootPath,
2283
2369
  legacyNoSDK: this.noSDK
2284
2370
  });
2285
- logger.info("Starting Tina Dev Server");
2371
+ logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2286
2372
  this.logDeprecationWarnings();
2287
2373
  createDBServer(Number(this.datalayerPort));
2288
2374
  let database = null;
2375
+ const dbLock = async (fn) => {
2376
+ return this.indexingLock.acquire("Key", fn);
2377
+ };
2289
2378
  const setup = async ({ firstTime }) => {
2290
2379
  try {
2291
2380
  await configManager.processConfig();
@@ -2336,9 +2425,6 @@ var DevCommand = class extends BaseCommand {
2336
2425
  await import_fs_extra6.default.outputFile(filePath, tinaLockContent);
2337
2426
  }
2338
2427
  }
2339
- if (!this.noWatch) {
2340
- this.watchQueries(configManager, async () => await codegen2.execute());
2341
- }
2342
2428
  await this.indexContentWithSpinner({
2343
2429
  database,
2344
2430
  graphQLSchema: graphQLSchema2,
@@ -2348,6 +2434,13 @@ var DevCommand = class extends BaseCommand {
2348
2434
  if (!firstTime) {
2349
2435
  logger.error("Re-index complete");
2350
2436
  }
2437
+ if (!this.noWatch) {
2438
+ this.watchQueries(
2439
+ configManager,
2440
+ dbLock,
2441
+ async () => await codegen2.execute()
2442
+ );
2443
+ }
2351
2444
  return { apiURL: apiURL2, database, graphQLSchema: graphQLSchema2, tinaSchema: tinaSchema2 };
2352
2445
  } catch (e) {
2353
2446
  logger.error(`
@@ -2382,14 +2475,6 @@ ${dangerText(e.message)}
2382
2475
  tokenSplitRegex: (_d = (_c = configManager.config.search) == null ? void 0 : _c.tina) == null ? void 0 : _d.tokenSplitRegex
2383
2476
  });
2384
2477
  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
2478
  const searchIndexer = new import_search.SearchIndexer({
2394
2479
  batchSize: ((_e = configManager.config.search) == null ? void 0 : _e.indexBatchSize) || 100,
2395
2480
  bridge: new import_graphql10.FilesystemBridge(
@@ -2411,16 +2496,34 @@ ${dangerText(e.message)}
2411
2496
  await searchIndexClient.export(this.outputSearchIndexPath);
2412
2497
  }
2413
2498
  }
2499
+ if (this.noServer) {
2500
+ logger.info("--no-server option specified - Dev server not started");
2501
+ process.exit(0);
2502
+ }
2414
2503
  if (!this.noWatch) {
2415
2504
  this.watchContentFiles(
2416
2505
  configManager,
2417
2506
  database,
2507
+ dbLock,
2418
2508
  configManager.config.search && searchIndexer
2419
2509
  );
2510
+ }
2511
+ const server = await createDevServer(
2512
+ configManager,
2513
+ database,
2514
+ searchIndexClient.searchIndex,
2515
+ apiURL,
2516
+ this.noWatch,
2517
+ dbLock
2518
+ );
2519
+ await server.listen(Number(this.port));
2520
+ if (!this.noWatch) {
2420
2521
  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: "*" });
2522
+ await dbLock(async () => {
2523
+ logger.info(`Tina config change detected, rebuilding`);
2524
+ await setup({ firstTime: false });
2525
+ server.ws.send({ type: "full-reload", path: "*" });
2526
+ });
2424
2527
  });
2425
2528
  }
2426
2529
  const subItems = [];
@@ -2433,7 +2536,7 @@ ${dangerText(e.message)}
2433
2536
  const summaryItems = [
2434
2537
  {
2435
2538
  emoji: "\u{1F999}",
2436
- heading: "Tina Config",
2539
+ heading: "TinaCMS URLs",
2437
2540
  subItems: [
2438
2541
  {
2439
2542
  key: "CMS",
@@ -2468,14 +2571,28 @@ ${dangerText(e.message)}
2468
2571
  });
2469
2572
  }
2470
2573
  summary({
2471
- heading: "Tina Dev Server is running...",
2574
+ heading: "\u2705 \u{1F999} TinaCMS Dev Server is active:",
2472
2575
  items: [
2473
2576
  ...summaryItems
2577
+ // {
2578
+ // emoji: '📚',
2579
+ // heading: 'Useful links',
2580
+ // subItems: [
2581
+ // {
2582
+ // key: 'Custom queries',
2583
+ // value: 'https://tina.io/querying',
2584
+ // },
2585
+ // {
2586
+ // key: 'Visual editing',
2587
+ // value: 'https://tina.io/visual-editing',
2588
+ // },
2589
+ // ],
2590
+ // },
2474
2591
  ]
2475
2592
  });
2476
2593
  await this.startSubCommand();
2477
2594
  }
2478
- watchContentFiles(configManager, database, searchIndexer) {
2595
+ watchContentFiles(configManager, database, databaseLock, searchIndexer) {
2479
2596
  const collectionContentFiles = [];
2480
2597
  configManager.config.schema.collections.forEach((collection) => {
2481
2598
  const collectionGlob = `${import_path5.default.join(
@@ -2491,39 +2608,42 @@ ${dangerText(e.message)}
2491
2608
  if (!ready) {
2492
2609
  return;
2493
2610
  }
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
- }
2611
+ await databaseLock(async () => {
2612
+ const pathFromRoot = configManager.printContentRelativePath(addedFile);
2613
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2614
+ if (searchIndexer) {
2615
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2616
+ }
2617
+ });
2499
2618
  }).on("change", async (changedFile) => {
2500
2619
  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
- }
2620
+ await databaseLock(async () => {
2621
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2622
+ if (searchIndexer) {
2623
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2624
+ }
2625
+ });
2505
2626
  }).on("unlink", async (removedFile) => {
2506
2627
  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
- }
2628
+ await databaseLock(async () => {
2629
+ await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2630
+ if (searchIndexer) {
2631
+ await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2632
+ }
2633
+ });
2511
2634
  });
2512
2635
  }
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
- });
2636
+ watchQueries(configManager, databaseLock, callback) {
2637
+ const executeCallback = async (_) => {
2638
+ await databaseLock(async () => {
2639
+ await callback();
2640
+ });
2641
+ };
2642
+ import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("add", executeCallback).on("change", executeCallback).on("unlink", executeCallback);
2524
2643
  }
2525
2644
  };
2526
2645
  DevCommand.paths = [["dev"], ["server:start"]];
2646
+ // Prevent indexes and reads occurring at once
2527
2647
  DevCommand.usage = import_clipanion2.Command.Usage({
2528
2648
  category: `Commands`,
2529
2649
  description: `Builds Tina and starts the dev server`,
@@ -2538,6 +2658,7 @@ var import_clipanion3 = require("clipanion");
2538
2658
  var import_progress2 = __toESM(require("progress"));
2539
2659
  var import_fs_extra7 = __toESM(require("fs-extra"));
2540
2660
  var import_crypto = __toESM(require("crypto"));
2661
+ var import_path6 = __toESM(require("path"));
2541
2662
  var import_graphql11 = require("@tinacms/graphql");
2542
2663
 
2543
2664
  // src/next/commands/build-command/server.ts
@@ -2581,7 +2702,7 @@ var buildProductionSpa = async (configManager, database, apiURL) => {
2581
2702
  // src/next/commands/build-command/index.ts
2582
2703
  var import_schema_tools2 = require("@tinacms/schema-tools");
2583
2704
  var import_graphql12 = require("graphql");
2584
- var import_core2 = require("@graphql-inspector/core");
2705
+ var import_core3 = require("@graphql-inspector/core");
2585
2706
 
2586
2707
  // src/next/commands/build-command/waitForDB.ts
2587
2708
  var import_progress = __toESM(require("progress"));
@@ -2683,6 +2804,20 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2683
2804
 
2684
2805
  // src/next/commands/build-command/index.ts
2685
2806
  var import_search2 = require("@tinacms/search");
2807
+
2808
+ // src/utils/index.ts
2809
+ var import_core2 = require("@graphql-inspector/core");
2810
+ var getFaqLink = (type) => {
2811
+ switch (type) {
2812
+ case import_core2.ChangeType.FieldRemoved: {
2813
+ return "https://tina.io/docs/introduction/faq#how-do-i-resolve-the-local-graphql-schema-doesnt-match-the-remote-graphql-schema-errors";
2814
+ }
2815
+ default:
2816
+ return null;
2817
+ }
2818
+ };
2819
+
2820
+ // src/next/commands/build-command/index.ts
2686
2821
  var BuildCommand = class extends BaseCommand {
2687
2822
  constructor() {
2688
2823
  super(...arguments);
@@ -2698,6 +2833,9 @@ var BuildCommand = class extends BaseCommand {
2698
2833
  this.tinaGraphQLVersion = import_clipanion3.Option.String("--tina-graphql-version", {
2699
2834
  description: "Specify the version of @tinacms/graphql to use (defaults to latest)"
2700
2835
  });
2836
+ /**
2837
+ * 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
2838
+ */
2701
2839
  this.skipCloudChecks = import_clipanion3.Option.Boolean("--skip-cloud-checks", false, {
2702
2840
  description: "Skips checking the provided cloud config."
2703
2841
  });
@@ -2803,14 +2941,15 @@ ${dangerText(e.message)}
2803
2941
  database,
2804
2942
  null,
2805
2943
  apiURL,
2806
- true
2944
+ true,
2945
+ (lockedFn) => lockedFn()
2807
2946
  );
2808
2947
  await server.listen(Number(this.port));
2809
2948
  console.log("server listening on port", this.port);
2810
2949
  }
2811
2950
  const skipCloudChecks = this.skipCloudChecks || configManager.hasSelfHostedConfig();
2812
2951
  if (!skipCloudChecks) {
2813
- const { hasUpstream } = await this.checkClientInfo(
2952
+ const { hasUpstream, timestamp } = await this.checkClientInfo(
2814
2953
  configManager,
2815
2954
  codegen2.productionUrl,
2816
2955
  this.previewBaseBranch
@@ -2838,14 +2977,16 @@ ${dangerText(e.message)}
2838
2977
  await this.checkGraphqlSchema(
2839
2978
  configManager,
2840
2979
  database,
2841
- codegen2.productionUrl
2980
+ codegen2.productionUrl,
2981
+ timestamp
2842
2982
  );
2843
2983
  await this.checkTinaSchema(
2844
2984
  configManager,
2845
2985
  database,
2846
2986
  codegen2.productionUrl,
2847
2987
  this.previewName,
2848
- this.verbose
2988
+ this.verbose,
2989
+ timestamp
2849
2990
  );
2850
2991
  }
2851
2992
  await buildProductionSpa(configManager, database, codegen2.productionUrl);
@@ -2863,7 +3004,9 @@ ${dangerText(e.message)}
2863
3004
  `ERROR: Branch not configured in tina search configuration.`
2864
3005
  )}`
2865
3006
  );
2866
- throw new Error("Branch not configured in tina search configuration.");
3007
+ throw new Error(
3008
+ "Branch not configured in tina search configuration."
3009
+ );
2867
3010
  }
2868
3011
  if (!((_d = configManager.config) == null ? void 0 : _d.clientId)) {
2869
3012
  logger.error(`${dangerText(`ERROR: clientId not configured.`)}`);
@@ -2964,11 +3107,13 @@ ${dangerText(e.message)}
2964
3107
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
2965
3108
  let branchKnown = false;
2966
3109
  let hasUpstream = false;
3110
+ let timestamp;
2967
3111
  try {
2968
3112
  const res = await request({
2969
3113
  token,
2970
3114
  url
2971
3115
  });
3116
+ timestamp = res.timestamp || 0;
2972
3117
  bar2.tick({
2973
3118
  prog: "\u2705"
2974
3119
  });
@@ -3004,13 +3149,17 @@ ${dangerText(e.message)}
3004
3149
  });
3005
3150
  throw e;
3006
3151
  }
3007
- const branchBar = new import_progress2.default("Checking branch is on Tina Cloud. :prog", 1);
3152
+ const branchBar = new import_progress2.default(
3153
+ "Checking branch is on Tina Cloud. :prog",
3154
+ 1
3155
+ );
3008
3156
  if (branchKnown) {
3009
3157
  branchBar.tick({
3010
3158
  prog: "\u2705"
3011
3159
  });
3012
3160
  return {
3013
- hasUpstream
3161
+ hasUpstream,
3162
+ timestamp
3014
3163
  };
3015
3164
  }
3016
3165
  for (let i = 0; i <= 5; i++) {
@@ -3100,14 +3249,14 @@ ${dangerText(e.message)}
3100
3249
  throw e;
3101
3250
  }
3102
3251
  }
3103
- async checkGraphqlSchema(configManager, database, apiURL) {
3252
+ async checkGraphqlSchema(configManager, database, apiURL, timestamp) {
3104
3253
  const bar2 = new import_progress2.default(
3105
3254
  "Checking local GraphQL Schema matches server. :prog",
3106
3255
  1
3107
3256
  );
3108
3257
  const { config: config2 } = configManager;
3109
3258
  const token = config2.token;
3110
- const remoteSchema = await fetchRemoteGraphqlSchema({
3259
+ const { remoteSchema, remoteProjectVersion } = await fetchRemoteGraphqlSchema({
3111
3260
  url: apiURL,
3112
3261
  token
3113
3262
  });
@@ -3127,7 +3276,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3127
3276
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
3128
3277
  const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
3129
3278
  try {
3130
- const diffResult = await (0, import_core2.diff)(localGraphqlSchema, remoteGqlSchema);
3279
+ const diffResult = await (0, import_core3.diff)(remoteGqlSchema, localGraphqlSchema);
3131
3280
  if (diffResult.length === 0) {
3132
3281
  bar2.tick({
3133
3282
  prog: "\u2705"
@@ -3136,12 +3285,30 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3136
3285
  bar2.tick({
3137
3286
  prog: "\u274C"
3138
3287
  });
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 += `
3288
+ const type = diffResult[0].type;
3289
+ const reason = diffResult[0].message;
3290
+ const errorLevel = diffResult[0].criticality.level;
3291
+ const faqLink = getFaqLink(type);
3292
+ const tinaGraphQLVersion = configManager.getTinaGraphQLVersion();
3293
+ 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 && `
3294
+ Check out '${faqLink}' for possible solutions.`}`;
3295
+ errorMessage += `
3142
3296
 
3143
- Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3297
+ Additional info:
3298
+
3299
+ `;
3300
+ if (config2 == null ? void 0 : config2.branch) {
3301
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3302
+ `;
3144
3303
  }
3304
+ errorMessage += ` Local GraphQL version: ${tinaGraphQLVersion.fullVersion} / Remote GraphQL version: ${remoteProjectVersion}
3305
+ `;
3306
+ errorMessage += ` Last indexed at: ${new Date(
3307
+ timestamp
3308
+ ).toUTCString()}
3309
+ `;
3310
+ errorMessage += ` Reason: [${errorLevel} - ${type}] ${reason}
3311
+ `;
3145
3312
  throw new Error(errorMessage);
3146
3313
  }
3147
3314
  } catch (e) {
@@ -3156,7 +3323,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3156
3323
  }
3157
3324
  }
3158
3325
  }
3159
- async checkTinaSchema(configManager, database, apiURL, previewName, verbose) {
3326
+ async checkTinaSchema(configManager, database, apiURL, previewName, verbose, timestamp) {
3160
3327
  const bar2 = new import_progress2.default(
3161
3328
  "Checking local Tina Schema matches server. :prog",
3162
3329
  1
@@ -3166,7 +3333,9 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3166
3333
  const { clientId, branch, isLocalClient, host } = (0, import_schema_tools2.parseURL)(apiURL);
3167
3334
  if (isLocalClient || !host || !clientId || !branch) {
3168
3335
  if (verbose) {
3169
- logger.info(logText("Not using Tina Cloud, skipping Tina Schema check"));
3336
+ logger.info(
3337
+ logText("Not using Tina Cloud, skipping Tina Schema check")
3338
+ );
3170
3339
  }
3171
3340
  return;
3172
3341
  }
@@ -3174,7 +3343,6 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3174
3343
  url: `https://${host}/db/${clientId}/${previewName || branch}/schemaSha`,
3175
3344
  token
3176
3345
  });
3177
- console.log({ remoteTinaSchemaSha });
3178
3346
  if (!remoteTinaSchemaSha) {
3179
3347
  bar2.tick({
3180
3348
  prog: "\u274C"
@@ -3190,31 +3358,36 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3190
3358
  if (!database.bridge) {
3191
3359
  throw new Error(`No bridge configured`);
3192
3360
  }
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 += `
3361
+ const localTinaSchema = JSON.parse(
3362
+ await database.bridge.get(
3363
+ import_path6.default.join(database.tinaDirectory, "__generated__", "_schema.json")
3364
+ )
3365
+ );
3366
+ localTinaSchema.version = void 0;
3367
+ const localTinaSchemaSha = import_crypto.default.createHash("sha256").update(JSON.stringify(localTinaSchema)).digest("hex");
3368
+ if (localTinaSchemaSha === remoteTinaSchemaSha) {
3369
+ bar2.tick({
3370
+ prog: "\u2705"
3371
+ });
3372
+ } else {
3373
+ bar2.tick({
3374
+ prog: "\u274C"
3375
+ });
3376
+ 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.`;
3377
+ errorMessage += `
3211
3378
 
3212
- Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3213
- }
3214
- throw new Error(errorMessage);
3379
+ Additional info:
3380
+
3381
+ `;
3382
+ if (config2 == null ? void 0 : config2.branch) {
3383
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3384
+ `;
3215
3385
  }
3216
- } catch (e) {
3217
- throw e;
3386
+ errorMessage += ` Last indexed at: ${new Date(
3387
+ timestamp
3388
+ ).toUTCString()}
3389
+ `;
3390
+ throw new Error(errorMessage);
3218
3391
  }
3219
3392
  }
3220
3393
  };
@@ -3283,13 +3456,16 @@ var fetchRemoteGraphqlSchema = async ({
3283
3456
  body
3284
3457
  });
3285
3458
  const data = await res.json();
3286
- return data == null ? void 0 : data.data;
3459
+ return {
3460
+ remoteSchema: data == null ? void 0 : data.data,
3461
+ remoteRuntimeVersion: res.headers.get("tinacms-grapqhl-version"),
3462
+ remoteProjectVersion: res.headers.get("tinacms-graphql-project-version")
3463
+ };
3287
3464
  };
3288
3465
  var fetchSchemaSha = async ({
3289
3466
  url,
3290
3467
  token
3291
3468
  }) => {
3292
- console.log(url);
3293
3469
  const headers = new Headers();
3294
3470
  if (token) {
3295
3471
  headers.append("X-API-KEY", token);
@@ -3299,8 +3475,7 @@ var fetchSchemaSha = async ({
3299
3475
  headers,
3300
3476
  cache: "no-cache"
3301
3477
  });
3302
- const data = await res.json();
3303
- return data == null ? void 0 : data.data;
3478
+ return res.json();
3304
3479
  };
3305
3480
 
3306
3481
  // src/next/commands/audit-command/index.ts
@@ -3409,6 +3584,7 @@ var auditDocuments = async (args) => {
3409
3584
  logger.error(import_chalk5.default.red(err.message));
3410
3585
  if (err.originalError.originalError) {
3411
3586
  logger.error(
3587
+ // @ts-ignore FIXME: this doesn't seem right
3412
3588
  import_chalk5.default.red(` ${err.originalError.originalError.message}`)
3413
3589
  );
3414
3590
  }
@@ -3555,25 +3731,25 @@ var import_clipanion6 = require("clipanion");
3555
3731
 
3556
3732
  // src/cmds/init/detectEnvironment.ts
3557
3733
  var import_fs_extra8 = __toESM(require("fs-extra"));
3558
- var import_path6 = __toESM(require("path"));
3734
+ var import_path7 = __toESM(require("path"));
3559
3735
  var checkGitignoreForItem = async ({
3560
3736
  baseDir,
3561
3737
  line
3562
3738
  }) => {
3563
- const gitignoreContent = import_fs_extra8.default.readFileSync(import_path6.default.join(baseDir, ".gitignore")).toString();
3739
+ const gitignoreContent = import_fs_extra8.default.readFileSync(import_path7.default.join(baseDir, ".gitignore")).toString();
3564
3740
  return gitignoreContent.split("\n").some((item) => item === line);
3565
3741
  };
3566
3742
  var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
3567
3743
  const result = {
3568
- fullPathTS: import_path6.default.join(
3744
+ fullPathTS: import_path7.default.join(
3569
3745
  parentPath,
3570
3746
  `${name2}.${(opts == null ? void 0 : opts.typescriptSuffix) || (opts == null ? void 0 : opts.extensionOverride) || "ts"}`
3571
3747
  ),
3572
- fullPathJS: import_path6.default.join(
3748
+ fullPathJS: import_path7.default.join(
3573
3749
  parentPath,
3574
3750
  `${name2}.${(opts == null ? void 0 : opts.extensionOverride) || "js"}`
3575
3751
  ),
3576
- fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path6.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3752
+ fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path7.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3577
3753
  generatedFileType,
3578
3754
  name: name2,
3579
3755
  parentPath,
@@ -3603,18 +3779,20 @@ var detectEnvironment = async ({
3603
3779
  }) => {
3604
3780
  var _a;
3605
3781
  const hasForestryConfig = await import_fs_extra8.default.pathExists(
3606
- import_path6.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3782
+ import_path7.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3607
3783
  );
3608
- const sampleContentPath = import_path6.default.join(
3784
+ const sampleContentPath = import_path7.default.join(
3609
3785
  baseDir,
3610
3786
  "content",
3611
3787
  "posts",
3612
3788
  "hello-world.md"
3613
3789
  );
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");
3790
+ 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")));
3791
+ const tinaFolder = import_path7.default.join(baseDir, "tina");
3616
3792
  const tinaConfigExists = Boolean(
3617
- await import_fs_extra8.default.pathExists(tinaFolder) && (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3793
+ // Does the tina folder exist?
3794
+ await import_fs_extra8.default.pathExists(tinaFolder) && // Does the tina folder contain a config file?
3795
+ (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3618
3796
  );
3619
3797
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
3620
3798
  Boolean
@@ -3626,12 +3804,12 @@ var detectEnvironment = async ({
3626
3804
  "next-api-handler": await makeGeneratedFile(
3627
3805
  "[...routes]",
3628
3806
  "next-api-handler",
3629
- import_path6.default.join(...pagesDir, "api", "tina")
3807
+ import_path7.default.join(...pagesDir, "api", "tina")
3630
3808
  ),
3631
3809
  "reactive-example": await makeGeneratedFile(
3632
3810
  "[filename]",
3633
3811
  "reactive-example",
3634
- import_path6.default.join(...pagesDir, "demo", "blog"),
3812
+ import_path7.default.join(...pagesDir, "demo", "blog"),
3635
3813
  {
3636
3814
  typescriptSuffix: "tsx"
3637
3815
  }
@@ -3639,13 +3817,13 @@ var detectEnvironment = async ({
3639
3817
  "users-json": await makeGeneratedFile(
3640
3818
  "index",
3641
3819
  "users-json",
3642
- import_path6.default.join(baseDir, "content", "users"),
3820
+ import_path7.default.join(baseDir, "content", "users"),
3643
3821
  { extensionOverride: "json" }
3644
3822
  ),
3645
3823
  "sample-content": await makeGeneratedFile(
3646
3824
  "hello-world",
3647
3825
  "sample-content",
3648
- import_path6.default.join(baseDir, "content", "posts"),
3826
+ import_path7.default.join(baseDir, "content", "posts"),
3649
3827
  { extensionOverride: "md" }
3650
3828
  )
3651
3829
  };
@@ -3671,13 +3849,13 @@ var detectEnvironment = async ({
3671
3849
  );
3672
3850
  }
3673
3851
  }
3674
- const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path6.default.join(".gitignore"));
3852
+ const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path7.default.join(".gitignore"));
3675
3853
  const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
3676
3854
  const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
3677
3855
  const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
3678
3856
  let frontMatterFormat;
3679
3857
  if (hasForestryConfig) {
3680
- const hugoConfigPath = import_path6.default.join(rootPath, "config.toml");
3858
+ const hugoConfigPath = import_path7.default.join(rootPath, "config.toml");
3681
3859
  if (await import_fs_extra8.default.pathExists(hugoConfigPath)) {
3682
3860
  const hugoConfig = await import_fs_extra8.default.readFile(hugoConfigPath, "utf8");
3683
3861
  const metaDataFormat = (_a = hugoConfig.match(/metaDataFormat = "(.*)"/)) == null ? void 0 : _a[1];
@@ -3849,6 +4027,7 @@ var supportedDatabaseAdapters = {
3849
4027
  {
3850
4028
  from: "mongodb",
3851
4029
  imported: [],
4030
+ // not explicitly imported
3852
4031
  packageName: "mongodb"
3853
4032
  }
3854
4033
  ]
@@ -3921,6 +4100,10 @@ var chooseDatabaseAdapter = async ({
3921
4100
  title: "MongoDB",
3922
4101
  value: "mongodb"
3923
4102
  }
4103
+ // {
4104
+ // title: "I'll create my own database adapter",
4105
+ // value: 'other',
4106
+ // },
3924
4107
  ]
3925
4108
  }
3926
4109
  ]);
@@ -4198,6 +4381,7 @@ async function configure(env, opts) {
4198
4381
  packageManager,
4199
4382
  forestryMigrate: false,
4200
4383
  isLocalEnvVarName: "TINA_PUBLIC_IS_LOCAL",
4384
+ // TODO: give this a better default
4201
4385
  typescript: false
4202
4386
  };
4203
4387
  if (config2.framework.name === "next") {
@@ -4285,31 +4469,41 @@ var CLICommand = class {
4285
4469
  };
4286
4470
 
4287
4471
  // src/cmds/init/apply.ts
4288
- var import_path10 = __toESM(require("path"));
4472
+ var import_path11 = __toESM(require("path"));
4289
4473
 
4290
4474
  // src/cmds/forestry-migrate/index.ts
4291
4475
  var import_fs_extra10 = __toESM(require("fs-extra"));
4292
- var import_path8 = __toESM(require("path"));
4476
+ var import_path9 = __toESM(require("path"));
4293
4477
  var import_js_yaml2 = __toESM(require("js-yaml"));
4294
4478
  var import_minimatch = __toESM(require("minimatch"));
4295
4479
  var import_graphql16 = require("@tinacms/graphql");
4296
4480
 
4297
4481
  // src/cmds/forestry-migrate/util/index.ts
4298
4482
  var import_fs_extra9 = __toESM(require("fs-extra"));
4299
- var import_path7 = __toESM(require("path"));
4483
+ var import_path8 = __toESM(require("path"));
4300
4484
  var import_js_yaml = __toESM(require("js-yaml"));
4301
4485
  var import_zod = __toESM(require("zod"));
4302
4486
 
4303
4487
  // src/cmds/forestry-migrate/util/errorSingleton.ts
4304
- var ErrorSingleton = class {
4488
+ var ErrorSingleton = class _ErrorSingleton {
4489
+ /**
4490
+ * The Singleton's constructor should always be private to prevent direct
4491
+ * construction calls with the `new` operator.
4492
+ */
4305
4493
  constructor() {
4306
4494
  }
4495
+ /**
4496
+ * The static method that controls the access to the singleton instance.
4497
+ *
4498
+ * This implementation let you subclass the Singleton class while keeping
4499
+ * just one instance of each subclass around.
4500
+ */
4307
4501
  static getInstance() {
4308
- if (!ErrorSingleton.instance) {
4309
- ErrorSingleton.instance = new ErrorSingleton();
4310
- ErrorSingleton.instance.collectionNameErrors = [];
4502
+ if (!_ErrorSingleton.instance) {
4503
+ _ErrorSingleton.instance = new _ErrorSingleton();
4504
+ _ErrorSingleton.instance.collectionNameErrors = [];
4311
4505
  }
4312
- return ErrorSingleton.instance;
4506
+ return _ErrorSingleton.instance;
4313
4507
  }
4314
4508
  addErrorName(error) {
4315
4509
  this.collectionNameErrors.push(error);
@@ -4352,8 +4546,7 @@ var makeFieldsWithInternalCode = ({
4352
4546
  if (hasBody) {
4353
4547
  return [bodyField, `__TINA_INTERNAL__:::...${field}():::`];
4354
4548
  } else {
4355
- if (spread)
4356
- return `__TINA_INTERNAL__:::...${field}():::`;
4549
+ if (spread) return `__TINA_INTERNAL__:::...${field}():::`;
4357
4550
  return `__TINA_INTERNAL__:::${field}():::`;
4358
4551
  }
4359
4552
  };
@@ -4437,6 +4630,7 @@ var forestryConfigSchema = import_zod.default.object({
4437
4630
  )
4438
4631
  });
4439
4632
  var forestryFieldWithoutField = import_zod.default.object({
4633
+ // TODO: maybe better type this?
4440
4634
  type: import_zod.default.union([
4441
4635
  import_zod.default.literal("text"),
4442
4636
  import_zod.default.literal("datetime"),
@@ -4460,6 +4654,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4460
4654
  default: import_zod.default.any().optional(),
4461
4655
  template: import_zod.default.string().optional(),
4462
4656
  config: import_zod.default.object({
4657
+ // min and max are used for lists
4463
4658
  min: import_zod.default.number().optional().nullable(),
4464
4659
  max: import_zod.default.number().optional().nullable(),
4465
4660
  required: import_zod.default.boolean().optional().nullable(),
@@ -4473,6 +4668,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4473
4668
  import_zod.default.literal("pages"),
4474
4669
  import_zod.default.literal("documents"),
4475
4670
  import_zod.default.literal("simple"),
4671
+ // TODO: I want to ignore this key if its invalid
4476
4672
  import_zod.default.string()
4477
4673
  ]).optional().nullable(),
4478
4674
  section: import_zod.default.string().optional().nullable()
@@ -4508,6 +4704,7 @@ var transformForestryFieldsToTinaFields = ({
4508
4704
  }
4509
4705
  let field;
4510
4706
  switch (forestryField2.type) {
4707
+ // Single filed types
4511
4708
  case "text":
4512
4709
  field = {
4513
4710
  type: "string",
@@ -4587,6 +4784,7 @@ var transformForestryFieldsToTinaFields = ({
4587
4784
  );
4588
4785
  }
4589
4786
  break;
4787
+ // List Types
4590
4788
  case "list":
4591
4789
  field = {
4592
4790
  type: "string",
@@ -4609,6 +4807,7 @@ var transformForestryFieldsToTinaFields = ({
4609
4807
  }
4610
4808
  };
4611
4809
  break;
4810
+ // Object (Group) types
4612
4811
  case "field_group":
4613
4812
  field = {
4614
4813
  type: "object",
@@ -4649,6 +4848,7 @@ var transformForestryFieldsToTinaFields = ({
4649
4848
  });
4650
4849
  const fieldsString = stringifyLabelWithField(template2.label);
4651
4850
  const t = {
4851
+ // @ts-ignore
4652
4852
  fields: makeFieldsWithInternalCode({
4653
4853
  hasBody: false,
4654
4854
  field: fieldsString
@@ -4657,7 +4857,6 @@ var transformForestryFieldsToTinaFields = ({
4657
4857
  name: stringifyTemplateName(tem, tem)
4658
4858
  };
4659
4859
  if (t.name != tem) {
4660
- ;
4661
4860
  t.nameOverride = tem;
4662
4861
  }
4663
4862
  templates2.push(t);
@@ -4686,6 +4885,7 @@ var transformForestryFieldsToTinaFields = ({
4686
4885
  spread: true
4687
4886
  });
4688
4887
  tinaFields.push(
4888
+ // @ts-ignore
4689
4889
  field2
4690
4890
  );
4691
4891
  break;
@@ -4707,7 +4907,7 @@ var transformForestryFieldsToTinaFields = ({
4707
4907
  return tinaFields;
4708
4908
  };
4709
4909
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
4710
- const templatePath = import_path7.default.join(
4910
+ const templatePath = import_path8.default.join(
4711
4911
  pathToForestryConfig,
4712
4912
  ".forestry",
4713
4913
  "front_matter",
@@ -4745,6 +4945,7 @@ var parseSections = ({ val }) => {
4745
4945
 
4746
4946
  // src/cmds/forestry-migrate/index.ts
4747
4947
  var BODY_FIELD = {
4948
+ // This is the body field
4748
4949
  type: "rich-text",
4749
4950
  name: "body",
4750
4951
  label: "Body of Document",
@@ -4782,8 +4983,8 @@ var generateAllTemplates = async ({
4782
4983
  pathToForestryConfig
4783
4984
  }) => {
4784
4985
  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"));
4986
+ import_path9.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4987
+ )).map((tem) => import_path9.default.basename(tem, ".yml"));
4787
4988
  const templateMap = /* @__PURE__ */ new Map();
4788
4989
  const proms = allTemplates.map(async (tem) => {
4789
4990
  try {
@@ -4803,8 +5004,7 @@ var generateAllTemplates = async ({
4803
5004
  };
4804
5005
  var generateCollectionFromForestrySection = (args) => {
4805
5006
  const { section, templateMap } = args;
4806
- if (section.read_only)
4807
- return;
5007
+ if (section.read_only) return;
4808
5008
  let format3 = "md";
4809
5009
  if (section.new_doc_ext) {
4810
5010
  const ext = checkExt(section.new_doc_ext);
@@ -4871,12 +5071,14 @@ var generateCollectionFromForestrySection = (args) => {
4871
5071
  if (((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1) {
4872
5072
  c = {
4873
5073
  ...baseCollection,
5074
+ // @ts-expect-error
4874
5075
  templates: forestryTemplates.map((tem) => {
4875
5076
  const currentTemplate = templateMap.get(tem);
4876
5077
  const fieldsString = stringifyLabelWithField(
4877
5078
  currentTemplate.templateObj.label
4878
5079
  );
4879
5080
  return {
5081
+ // fields: [BODY_FIELD],
4880
5082
  fields: makeFieldsWithInternalCode({
4881
5083
  hasBody,
4882
5084
  field: fieldsString,
@@ -4894,6 +5096,8 @@ var generateCollectionFromForestrySection = (args) => {
4894
5096
  const fieldsString = stringifyLabelWithField(template.templateObj.label);
4895
5097
  c = {
4896
5098
  ...baseCollection,
5099
+ // fields: [BODY_FIELD],
5100
+ // @ts-expect-error
4897
5101
  fields: makeFieldsWithInternalCode({
4898
5102
  field: fieldsString,
4899
5103
  hasBody,
@@ -4925,9 +5129,9 @@ var generateCollectionFromForestrySection = (args) => {
4925
5129
  return c;
4926
5130
  } else if (section.type === "document") {
4927
5131
  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);
5132
+ const extname = import_path9.default.extname(filePath);
5133
+ const fileName = import_path9.default.basename(filePath, extname);
5134
+ const dir = import_path9.default.dirname(filePath);
4931
5135
  const ext = checkExt(extname);
4932
5136
  if (ext) {
4933
5137
  const fields = [];
@@ -4990,7 +5194,7 @@ var generateCollections = async ({
4990
5194
  usingTypescript
4991
5195
  });
4992
5196
  const forestryConfig = await import_fs_extra10.default.readFile(
4993
- import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
5197
+ import_path9.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4994
5198
  );
4995
5199
  rewriteTemplateKeysInDocs({
4996
5200
  templateMap,
@@ -5021,11 +5225,11 @@ var rewriteTemplateKeysInDocs = (args) => {
5021
5225
  const { templateObj } = templateMap.get(templateKey);
5022
5226
  (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
5023
5227
  try {
5024
- const filePath = import_path8.default.join(page);
5228
+ const filePath = import_path9.default.join(page);
5025
5229
  if (import_fs_extra10.default.lstatSync(filePath).isDirectory()) {
5026
5230
  return;
5027
5231
  }
5028
- const extname = import_path8.default.extname(filePath);
5232
+ const extname = import_path9.default.extname(filePath);
5029
5233
  const fileContent = import_fs_extra10.default.readFileSync(filePath).toString();
5030
5234
  const content = (0, import_graphql16.parseFile)(
5031
5235
  fileContent,
@@ -5057,7 +5261,7 @@ var import_fs_extra13 = __toESM(require("fs-extra"));
5057
5261
  // src/next/commands/codemod-command/index.ts
5058
5262
  var import_clipanion5 = require("clipanion");
5059
5263
  var import_fs_extra11 = __toESM(require("fs-extra"));
5060
- var import_path9 = __toESM(require("path"));
5264
+ var import_path10 = __toESM(require("path"));
5061
5265
  var CodemodCommand = class extends import_clipanion5.Command {
5062
5266
  constructor() {
5063
5267
  super(...arguments);
@@ -5101,7 +5305,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5101
5305
  logger.error(e.message);
5102
5306
  process.exit(1);
5103
5307
  }
5104
- const tinaDestination = import_path9.default.join(configManager.rootPath, "tina");
5308
+ const tinaDestination = import_path10.default.join(configManager.rootPath, "tina");
5105
5309
  if (await import_fs_extra11.default.existsSync(tinaDestination)) {
5106
5310
  logger.info(
5107
5311
  `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 +5320,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5116
5320
  };
5117
5321
  var writeGitignore = async (rootPath) => {
5118
5322
  await import_fs_extra11.default.outputFileSync(
5119
- import_path9.default.join(rootPath, "tina", ".gitignore"),
5323
+ import_path10.default.join(rootPath, "tina", ".gitignore"),
5120
5324
  "__generated__"
5121
5325
  );
5122
5326
  };
@@ -5641,6 +5845,7 @@ var makeImportsVisitor = (sourceFile, importMap) => (ctx) => (node) => {
5641
5845
  ) : [];
5642
5846
  const newImports = [
5643
5847
  .../* @__PURE__ */ new Set([
5848
+ // we use Set to remove duplicates
5644
5849
  ...existingImports,
5645
5850
  ...imports
5646
5851
  ])
@@ -5795,10 +6000,14 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5795
6000
  );
5796
6001
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5797
6002
  const importMap = {
5798
- ...configImports.reduce((acc, { from, imported }) => {
5799
- acc[from] = imported;
5800
- return acc;
5801
- }, {})
6003
+ // iterate over configImports and add them to the import map
6004
+ ...configImports.reduce(
6005
+ (acc, { from, imported }) => {
6006
+ acc[from] = imported;
6007
+ return acc;
6008
+ },
6009
+ {}
6010
+ )
5802
6011
  };
5803
6012
  const transformedSourceFileResult = import_typescript3.default.transform(
5804
6013
  sourceFile,
@@ -5954,8 +6163,8 @@ async function apply({
5954
6163
  await addConfigFile({
5955
6164
  configArgs: {
5956
6165
  config: config2,
5957
- publicFolder: import_path10.default.join(
5958
- import_path10.default.relative(process.cwd(), pathToForestryConfig),
6166
+ publicFolder: import_path11.default.join(
6167
+ import_path11.default.relative(process.cwd(), pathToForestryConfig),
5959
6168
  config2.publicFolder
5960
6169
  ),
5961
6170
  collections,
@@ -5969,7 +6178,13 @@ async function apply({
5969
6178
  config: config2
5970
6179
  });
5971
6180
  }
5972
- if (env.tinaConfigExists && params.isBackendInit && config2.hosting === "self-host" && (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud") {
6181
+ if (
6182
+ // if the config was just generated we do not need to update the config file because it will be generated correctly
6183
+ env.tinaConfigExists && // Are we running tinacms init backend
6184
+ params.isBackendInit && // Do the user choose the 'self-host' option
6185
+ config2.hosting === "self-host" && // the user did not choose the 'tina-cloud' auth provider
6186
+ (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud"
6187
+ ) {
5973
6188
  await addSelfHostedTinaAuthToConfig(config2, env.generatedFiles["config"]);
5974
6189
  }
5975
6190
  logNextSteps({
@@ -6022,18 +6237,18 @@ var createPackageJSON = async () => {
6022
6237
  };
6023
6238
  var createGitignore = async ({ baseDir }) => {
6024
6239
  logger.info(logText("No .gitignore found, creating one"));
6025
- import_fs_extra13.default.outputFileSync(import_path10.default.join(baseDir, ".gitignore"), "node_modules");
6240
+ import_fs_extra13.default.outputFileSync(import_path11.default.join(baseDir, ".gitignore"), "node_modules");
6026
6241
  };
6027
6242
  var updateGitIgnore = async ({
6028
6243
  baseDir,
6029
6244
  items
6030
6245
  }) => {
6031
6246
  logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
6032
- const gitignoreContent = import_fs_extra13.default.readFileSync(import_path10.default.join(baseDir, ".gitignore")).toString();
6247
+ const gitignoreContent = import_fs_extra13.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
6033
6248
  const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
6034
6249
  "\n"
6035
6250
  );
6036
- await import_fs_extra13.default.writeFile(import_path10.default.join(baseDir, ".gitignore"), newGitignoreContent);
6251
+ await import_fs_extra13.default.writeFile(import_path11.default.join(baseDir, ".gitignore"), newGitignoreContent);
6037
6252
  };
6038
6253
  var addDependencies = async (config2, env, params) => {
6039
6254
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
@@ -6103,22 +6318,22 @@ var writeGeneratedFile = async ({
6103
6318
  content,
6104
6319
  typescript
6105
6320
  }) => {
6106
- const { exists, path: path13, parentPath } = generatedFile.resolve(typescript);
6321
+ const { exists, path: path14, parentPath } = generatedFile.resolve(typescript);
6107
6322
  if (exists) {
6108
6323
  if (overwrite) {
6109
- logger.info(`Overwriting file at ${path13}... \u2705`);
6110
- import_fs_extra13.default.outputFileSync(path13, content);
6324
+ logger.info(`Overwriting file at ${path14}... \u2705`);
6325
+ import_fs_extra13.default.outputFileSync(path14, content);
6111
6326
  } else {
6112
- logger.info(`Not overwriting file at ${path13}.`);
6327
+ logger.info(`Not overwriting file at ${path14}.`);
6113
6328
  logger.info(
6114
- logText(`Please add the following to ${path13}:
6329
+ logText(`Please add the following to ${path14}:
6115
6330
  ${indentText(content)}}`)
6116
6331
  );
6117
6332
  }
6118
6333
  } else {
6119
- logger.info(`Adding file at ${path13}... \u2705`);
6334
+ logger.info(`Adding file at ${path14}... \u2705`);
6120
6335
  await import_fs_extra13.default.ensureDir(parentPath);
6121
- import_fs_extra13.default.outputFileSync(path13, content);
6336
+ import_fs_extra13.default.outputFileSync(path14, content);
6122
6337
  }
6123
6338
  };
6124
6339
  var addConfigFile = async ({
@@ -6201,7 +6416,7 @@ var addContentFile = async ({
6201
6416
  return () => ({
6202
6417
  exists: env.sampleContentExists,
6203
6418
  path: env.sampleContentPath,
6204
- parentPath: import_path10.default.dirname(env.sampleContentPath)
6419
+ parentPath: import_path11.default.dirname(env.sampleContentPath)
6205
6420
  });
6206
6421
  }
6207
6422
  },
@@ -6224,7 +6439,7 @@ ${titleText(" TinaCMS ")} backend initialized!`));
6224
6439
  return `${x.key}=${x.value || "***"}`;
6225
6440
  }).join("\n") + `
6226
6441
  TINA_PUBLIC_IS_LOCAL=true`;
6227
- const envFile = import_path10.default.join(process.cwd(), ".env");
6442
+ const envFile = import_path11.default.join(process.cwd(), ".env");
6228
6443
  if (!import_fs_extra13.default.existsSync(envFile)) {
6229
6444
  logger.info(`Adding .env file to your project... \u2705`);
6230
6445
  import_fs_extra13.default.writeFileSync(envFile, envFileText);
@@ -6247,6 +6462,13 @@ ${titleText(" TinaCMS ")} has been initialized!`));
6247
6462
  logger.info(
6248
6463
  "To get started run: " + cmdText(frameworkDevCmds[framework.name]({ packageManager }))
6249
6464
  );
6465
+ if (framework.name === "hugo") {
6466
+ logger.info(
6467
+ focusText("Hugo is required. "),
6468
+ "Don't have Hugo installed? Follow this guide to set it up: ",
6469
+ linkText("https://gohugo.io/installation/")
6470
+ );
6471
+ }
6250
6472
  logger.info(
6251
6473
  "To get your site production ready, run: " + cmdText(`tinacms init backend`)
6252
6474
  );
@@ -6262,6 +6484,7 @@ var other = ({ packageManager }) => {
6262
6484
  const packageManagers = {
6263
6485
  pnpm: `pnpm`,
6264
6486
  npm: `npx`,
6487
+ // npx is the way to run executables that aren't in your "scripts"
6265
6488
  yarn: `yarn`
6266
6489
  };
6267
6490
  return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
@@ -6274,6 +6497,7 @@ var frameworkDevCmds = {
6274
6497
  const packageManagers = {
6275
6498
  pnpm: `pnpm`,
6276
6499
  npm: `npm run`,
6500
+ // npx is the way to run executables that aren't in your "scripts"
6277
6501
  yarn: `yarn`
6278
6502
  };
6279
6503
  return `${packageManagers[packageManager]} dev`;
@@ -6288,7 +6512,7 @@ var addReactiveFile = {
6288
6512
  dataLayer
6289
6513
  }) => {
6290
6514
  var _a, _b;
6291
- const packageJsonPath = import_path10.default.join(baseDir, "package.json");
6515
+ const packageJsonPath = import_path11.default.join(baseDir, "package.json");
6292
6516
  await writeGeneratedFile({
6293
6517
  generatedFile,
6294
6518
  typescript: config2.typescript,
@@ -6530,6 +6754,4 @@ cli.register(SearchIndexCommand);
6530
6754
  cli.register(import_clipanion8.Builtins.DefinitionsCommand);
6531
6755
  cli.register(import_clipanion8.Builtins.HelpCommand);
6532
6756
  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 = {});
6757
+ var index_default = cli;