@tinacms/cli 0.0.0-bcdf830-20241023064032 → 0.0.0-bd0c18e-20250217004931

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,6 +17,10 @@ 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
  ));
@@ -31,9 +35,10 @@ module.exports = __toCommonJS(src_exports);
31
35
  var import_clipanion8 = require("clipanion");
32
36
 
33
37
  // package.json
34
- var version = "1.6.10";
38
+ var version = "1.8.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,
@@ -977,17 +997,14 @@ var createConfig = async ({
977
997
  } else {
978
998
  await import_fs_extra2.default.outputFile(staticMediaPath, `[]`);
979
999
  }
980
- const isBrowser = typeof window !== "undefined";
981
1000
  const alias = {
982
1001
  TINA_IMPORT: configManager.prebuildFilePath,
983
1002
  SCHEMA_IMPORT: configManager.generatedGraphQLJSONPath,
984
1003
  STATIC_MEDIA_IMPORT: staticMediaPath,
985
- ...isBrowser && {
986
- crypto: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
987
- fs: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
988
- os: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
989
- path: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts")
990
- }
1004
+ crypto: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1005
+ fs: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1006
+ os: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1007
+ path: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts")
991
1008
  };
992
1009
  if (configManager.shouldSkipSDK()) {
993
1010
  alias["CLIENT_IMPORT"] = import_node_path2.default.join(
@@ -1002,6 +1019,8 @@ var createConfig = async ({
1002
1019
  if (configManager.config.build.basePath) {
1003
1020
  basePath = configManager.config.build.basePath;
1004
1021
  }
1022
+ const fullVersion = configManager.getTinaGraphQLVersion();
1023
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1005
1024
  const config2 = {
1006
1025
  root: configManager.spaRootPath,
1007
1026
  base: `/${basePath ? `${(0, import_normalize_path2.default)(basePath)}/` : ""}${(0, import_normalize_path2.default)(
@@ -1013,15 +1032,33 @@ var createConfig = async ({
1013
1032
  dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1014
1033
  },
1015
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
+ */
1016
1049
  "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1050
+ // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1017
1051
  "process.platform": `"${process.platform}"`,
1018
1052
  __API_URL__: `"${apiURL}"`,
1019
1053
  __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1020
- __TINA_GRAPHQL_VERSION__: `"${configManager.getTinaGraphQLVersion()}"`
1054
+ __TINA_GRAPHQL_VERSION__: version2
1021
1055
  },
1022
1056
  logLevel: "error",
1057
+ // Vite import warnings are noisy
1023
1058
  optimizeDeps: {
1024
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
1025
1062
  include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1026
1063
  },
1027
1064
  server: {
@@ -1029,6 +1066,7 @@ var createConfig = async ({
1029
1066
  watch: noWatch ? {
1030
1067
  ignored: ["**/*"]
1031
1068
  } : {
1069
+ // Ignore everything except for the alias fields we specified above
1032
1070
  ignored: [
1033
1071
  `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1034
1072
  ]
@@ -1044,8 +1082,13 @@ var createConfig = async ({
1044
1082
  rollupOptions
1045
1083
  },
1046
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
+ */
1047
1089
  (0, import_plugin_react.default)({
1048
1090
  babel: {
1091
+ // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1049
1092
  compact: true
1050
1093
  }
1051
1094
  }),
@@ -1122,8 +1165,7 @@ var createMediaRouter = (config2) => {
1122
1165
  };
1123
1166
  var parseMediaFolder = (str) => {
1124
1167
  let returnString = str;
1125
- if (returnString.startsWith("/"))
1126
- returnString = returnString.substr(1);
1168
+ if (returnString.startsWith("/")) returnString = returnString.substr(1);
1127
1169
  if (returnString.endsWith("/"))
1128
1170
  returnString = returnString.substr(0, returnString.length - 1);
1129
1171
  return returnString;
@@ -1288,7 +1330,8 @@ var devServerEndPointsPlugin = ({
1288
1330
  configManager,
1289
1331
  apiURL,
1290
1332
  database,
1291
- searchIndex
1333
+ searchIndex,
1334
+ databaseLock
1292
1335
  }) => {
1293
1336
  const plug = {
1294
1337
  name: "graphql-endpoints",
@@ -1332,14 +1375,17 @@ var devServerEndPointsPlugin = ({
1332
1375
  }
1333
1376
  if (req.url === "/graphql") {
1334
1377
  const { query, variables } = req.body;
1335
- const result = await (0, import_graphql.resolve)({
1336
- config: {
1337
- useRelativeMedia: true
1338
- },
1339
- database,
1340
- query,
1341
- variables,
1342
- 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
+ });
1343
1389
  });
1344
1390
  res.end(JSON.stringify(result));
1345
1391
  return;
@@ -1390,6 +1436,7 @@ function viteTransformExtension({
1390
1436
  return {
1391
1437
  code: res.code,
1392
1438
  map: null
1439
+ // TODO:
1393
1440
  };
1394
1441
  }
1395
1442
  }
@@ -1397,10 +1444,16 @@ function viteTransformExtension({
1397
1444
  }
1398
1445
 
1399
1446
  // src/next/commands/dev-command/server/index.ts
1400
- var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch) => {
1447
+ var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch, databaseLock) => {
1401
1448
  const plugins = [
1402
1449
  transformTsxPlugin({ configManager }),
1403
- devServerEndPointsPlugin({ apiURL, configManager, database, searchIndex }),
1450
+ devServerEndPointsPlugin({
1451
+ apiURL,
1452
+ configManager,
1453
+ database,
1454
+ searchIndex,
1455
+ databaseLock
1456
+ }),
1404
1457
  viteTransformExtension()
1405
1458
  ];
1406
1459
  return (0, import_vite3.createServer)(
@@ -1410,6 +1463,14 @@ var createDevServer = async (configManager, database, searchIndex, apiURL, noWat
1410
1463
  apiURL,
1411
1464
  plugins,
1412
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
+ */
1413
1474
  rollupOptions: {
1414
1475
  input: configManager.spaMainPath,
1415
1476
  onwarn(warning, warn) {
@@ -1535,6 +1596,7 @@ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBas
1535
1596
  node,
1536
1597
  documentVariableName,
1537
1598
  operationType,
1599
+ // This is the only line that is different
1538
1600
  operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
1539
1601
  operationVariablesTypes
1540
1602
  });
@@ -1583,6 +1645,8 @@ var plugin = (schema, documents, config2) => {
1583
1645
  const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1584
1646
  const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1585
1647
  return {
1648
+ // We will take care of imports
1649
+ // prepend: visitor.getImports(),
1586
1650
  content: [
1587
1651
  visitor.fragments,
1588
1652
  ...visitorResult.definitions.filter((t) => typeof t === "string"),
@@ -1598,6 +1662,7 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
1598
1662
  docs = await loadGraphQLDocuments(queryPathGlob);
1599
1663
  fragDocs = await loadGraphQLDocuments(fragDocPath);
1600
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.
1601
1666
  filename: process.cwd(),
1602
1667
  schema: (0, import_graphql5.parse)((0, import_graphql5.printSchema)(schema)),
1603
1668
  documents: [...docs, ...fragDocs],
@@ -1632,9 +1697,12 @@ var loadGraphQLDocuments = async (globPath) => {
1632
1697
  loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
1633
1698
  });
1634
1699
  } catch (e) {
1635
- if ((e.message || "").includes(
1636
- "Unable to find any GraphQL type definitions for the following pointers:"
1637
- )) {
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
+ ) {
1638
1706
  } else {
1639
1707
  throw e;
1640
1708
  }
@@ -1791,16 +1859,14 @@ var Codegen = class {
1791
1859
  const branch = (_a = this.configManager.config) == null ? void 0 : _a.branch;
1792
1860
  const clientId = (_b = this.configManager.config) == null ? void 0 : _b.clientId;
1793
1861
  const token = (_c = this.configManager.config) == null ? void 0 : _c.token;
1794
- const version2 = this.configManager.getTinaGraphQLVersion();
1862
+ const fullVersion = this.configManager.getTinaGraphQLVersion();
1863
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1795
1864
  const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
1796
1865
  if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
1797
1866
  const missing = [];
1798
- if (!branch)
1799
- missing.push("branch");
1800
- if (!clientId)
1801
- missing.push("clientId");
1802
- if (!token)
1803
- missing.push("token");
1867
+ if (!branch) missing.push("branch");
1868
+ if (!clientId) missing.push("clientId");
1869
+ if (!token) missing.push("token");
1804
1870
  throw new Error(
1805
1871
  `Client not configured properly. Missing ${missing.join(
1806
1872
  ", "
@@ -1954,7 +2020,11 @@ schema {
1954
2020
  }
1955
2021
  };
1956
2022
  var maybeWarnFragmentSize = async (filepath) => {
1957
- if ((await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
2023
+ if (
2024
+ // is the file bigger than 100kb?
2025
+ (await import_fs_extra4.default.stat(filepath)).size > // convert to 100 kb to bytes
2026
+ 100 * 1024
2027
+ ) {
1958
2028
  console.warn(
1959
2029
  "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
1960
2030
  );
@@ -1982,6 +2052,7 @@ var import_many_level = require("many-level");
1982
2052
  var import_memory_level = require("memory-level");
1983
2053
  var createDBServer = (port) => {
1984
2054
  const levelHost = new import_many_level.ManyLevelHost(
2055
+ // @ts-ignore
1985
2056
  new import_memory_level.MemoryLevel({
1986
2057
  valueEncoding: "json"
1987
2058
  })
@@ -2132,7 +2203,9 @@ var BaseCommand = class extends import_clipanion.Command {
2132
2203
  let subProc;
2133
2204
  if (this.subCommand) {
2134
2205
  subProc = await startSubprocess2({ command: this.subCommand });
2135
- logger.info(`Starting subprocess: ${import_chalk4.default.cyan(this.subCommand)}`);
2206
+ logger.info(
2207
+ `Running web application with command: ${import_chalk4.default.cyan(this.subCommand)}`
2208
+ );
2136
2209
  }
2137
2210
  function exitHandler(options, exitCode) {
2138
2211
  if (subProc) {
@@ -2212,7 +2285,7 @@ var BaseCommand = class extends import_clipanion.Command {
2212
2285
  pathFilter
2213
2286
  });
2214
2287
  const tinaPathUpdates = modified.filter(
2215
- (path13) => path13.startsWith(".tina/__generated__/_schema.json") || path13.startsWith("tina/tina-lock.json")
2288
+ (path14) => path14.startsWith(".tina/__generated__/_schema.json") || path14.startsWith("tina/tina-lock.json")
2216
2289
  );
2217
2290
  if (tinaPathUpdates.length > 0) {
2218
2291
  res = await database.indexContent({
@@ -2256,6 +2329,7 @@ var import_search = require("@tinacms/search");
2256
2329
  var DevCommand = class extends BaseCommand {
2257
2330
  constructor() {
2258
2331
  super(...arguments);
2332
+ // NOTE: camelCase commands for string options don't work if there's an `=` used https://github.com/arcanis/clipanion/issues/141
2259
2333
  this.watchFolders = import_clipanion2.Option.String("-w,--watchFolders", {
2260
2334
  description: "DEPRECATED - a list of folders (relative to where this is being run) that the cli will watch for changes"
2261
2335
  });
@@ -2265,6 +2339,7 @@ var DevCommand = class extends BaseCommand {
2265
2339
  this.outputSearchIndexPath = import_clipanion2.Option.String("--outputSearchIndexPath", {
2266
2340
  description: "Path to write the search index to"
2267
2341
  });
2342
+ this.indexingLock = new import_async_lock.default();
2268
2343
  }
2269
2344
  async catch(error) {
2270
2345
  logger.error("Error occured during tinacms dev");
@@ -2285,10 +2360,13 @@ var DevCommand = class extends BaseCommand {
2285
2360
  rootPath: this.rootPath,
2286
2361
  legacyNoSDK: this.noSDK
2287
2362
  });
2288
- logger.info("Starting Tina Dev Server");
2363
+ logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2289
2364
  this.logDeprecationWarnings();
2290
2365
  createDBServer(Number(this.datalayerPort));
2291
2366
  let database = null;
2367
+ const dbLock = async (fn) => {
2368
+ return this.indexingLock.acquire("Key", fn);
2369
+ };
2292
2370
  const setup = async ({ firstTime }) => {
2293
2371
  try {
2294
2372
  await configManager.processConfig();
@@ -2339,9 +2417,6 @@ var DevCommand = class extends BaseCommand {
2339
2417
  await import_fs_extra6.default.outputFile(filePath, tinaLockContent);
2340
2418
  }
2341
2419
  }
2342
- if (!this.noWatch) {
2343
- this.watchQueries(configManager, async () => await codegen2.execute());
2344
- }
2345
2420
  await this.indexContentWithSpinner({
2346
2421
  database,
2347
2422
  graphQLSchema: graphQLSchema2,
@@ -2351,6 +2426,13 @@ var DevCommand = class extends BaseCommand {
2351
2426
  if (!firstTime) {
2352
2427
  logger.error("Re-index complete");
2353
2428
  }
2429
+ if (!this.noWatch) {
2430
+ this.watchQueries(
2431
+ configManager,
2432
+ dbLock,
2433
+ async () => await codegen2.execute()
2434
+ );
2435
+ }
2354
2436
  return { apiURL: apiURL2, database, graphQLSchema: graphQLSchema2, tinaSchema: tinaSchema2 };
2355
2437
  } catch (e) {
2356
2438
  logger.error(`
@@ -2385,14 +2467,6 @@ ${dangerText(e.message)}
2385
2467
  tokenSplitRegex: (_d = (_c = configManager.config.search) == null ? void 0 : _c.tina) == null ? void 0 : _d.tokenSplitRegex
2386
2468
  });
2387
2469
  await searchIndexClient.onStartIndexing();
2388
- const server = await createDevServer(
2389
- configManager,
2390
- database,
2391
- searchIndexClient.searchIndex,
2392
- apiURL,
2393
- this.noWatch
2394
- );
2395
- await server.listen(Number(this.port));
2396
2470
  const searchIndexer = new import_search.SearchIndexer({
2397
2471
  batchSize: ((_e = configManager.config.search) == null ? void 0 : _e.indexBatchSize) || 100,
2398
2472
  bridge: new import_graphql10.FilesystemBridge(
@@ -2418,12 +2492,26 @@ ${dangerText(e.message)}
2418
2492
  this.watchContentFiles(
2419
2493
  configManager,
2420
2494
  database,
2495
+ dbLock,
2421
2496
  configManager.config.search && searchIndexer
2422
2497
  );
2498
+ }
2499
+ const server = await createDevServer(
2500
+ configManager,
2501
+ database,
2502
+ searchIndexClient.searchIndex,
2503
+ apiURL,
2504
+ this.noWatch,
2505
+ dbLock
2506
+ );
2507
+ await server.listen(Number(this.port));
2508
+ if (!this.noWatch) {
2423
2509
  import_chokidar.default.watch(configManager.watchList).on("change", async () => {
2424
- logger.info(`Tina config change detected, rebuilding`);
2425
- await setup({ firstTime: false });
2426
- server.ws.send({ type: "full-reload", path: "*" });
2510
+ await dbLock(async () => {
2511
+ logger.info(`Tina config change detected, rebuilding`);
2512
+ await setup({ firstTime: false });
2513
+ server.ws.send({ type: "full-reload", path: "*" });
2514
+ });
2427
2515
  });
2428
2516
  }
2429
2517
  const subItems = [];
@@ -2436,7 +2524,7 @@ ${dangerText(e.message)}
2436
2524
  const summaryItems = [
2437
2525
  {
2438
2526
  emoji: "\u{1F999}",
2439
- heading: "Tina Config",
2527
+ heading: "TinaCMS URLs",
2440
2528
  subItems: [
2441
2529
  {
2442
2530
  key: "CMS",
@@ -2471,14 +2559,28 @@ ${dangerText(e.message)}
2471
2559
  });
2472
2560
  }
2473
2561
  summary({
2474
- heading: "Tina Dev Server is running...",
2562
+ heading: "\u2705 \u{1F999} TinaCMS Dev Server is active:",
2475
2563
  items: [
2476
2564
  ...summaryItems
2565
+ // {
2566
+ // emoji: '📚',
2567
+ // heading: 'Useful links',
2568
+ // subItems: [
2569
+ // {
2570
+ // key: 'Custom queries',
2571
+ // value: 'https://tina.io/querying',
2572
+ // },
2573
+ // {
2574
+ // key: 'Visual editing',
2575
+ // value: 'https://tina.io/visual-editing',
2576
+ // },
2577
+ // ],
2578
+ // },
2477
2579
  ]
2478
2580
  });
2479
2581
  await this.startSubCommand();
2480
2582
  }
2481
- watchContentFiles(configManager, database, searchIndexer) {
2583
+ watchContentFiles(configManager, database, databaseLock, searchIndexer) {
2482
2584
  const collectionContentFiles = [];
2483
2585
  configManager.config.schema.collections.forEach((collection) => {
2484
2586
  const collectionGlob = `${import_path5.default.join(
@@ -2494,39 +2596,42 @@ ${dangerText(e.message)}
2494
2596
  if (!ready) {
2495
2597
  return;
2496
2598
  }
2497
- const pathFromRoot = configManager.printContentRelativePath(addedFile);
2498
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2499
- if (searchIndexer) {
2500
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2501
- }
2599
+ await databaseLock(async () => {
2600
+ const pathFromRoot = configManager.printContentRelativePath(addedFile);
2601
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2602
+ if (searchIndexer) {
2603
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2604
+ }
2605
+ });
2502
2606
  }).on("change", async (changedFile) => {
2503
2607
  const pathFromRoot = configManager.printContentRelativePath(changedFile);
2504
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2505
- if (searchIndexer) {
2506
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2507
- }
2608
+ await databaseLock(async () => {
2609
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2610
+ if (searchIndexer) {
2611
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2612
+ }
2613
+ });
2508
2614
  }).on("unlink", async (removedFile) => {
2509
2615
  const pathFromRoot = configManager.printContentRelativePath(removedFile);
2510
- await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2511
- if (searchIndexer) {
2512
- await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2513
- }
2616
+ await databaseLock(async () => {
2617
+ await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2618
+ if (searchIndexer) {
2619
+ await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2620
+ }
2621
+ });
2514
2622
  });
2515
2623
  }
2516
- watchQueries(configManager, callback) {
2517
- let ready = false;
2518
- import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("ready", () => {
2519
- ready = true;
2520
- }).on("add", async (addedFile) => {
2521
- await callback();
2522
- }).on("change", async (changedFile) => {
2523
- await callback();
2524
- }).on("unlink", async (removedFile) => {
2525
- await callback();
2526
- });
2624
+ watchQueries(configManager, databaseLock, callback) {
2625
+ const executeCallback = async (_) => {
2626
+ await databaseLock(async () => {
2627
+ await callback();
2628
+ });
2629
+ };
2630
+ import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("add", executeCallback).on("change", executeCallback).on("unlink", executeCallback);
2527
2631
  }
2528
2632
  };
2529
2633
  DevCommand.paths = [["dev"], ["server:start"]];
2634
+ // Prevent indexes and reads occurring at once
2530
2635
  DevCommand.usage = import_clipanion2.Command.Usage({
2531
2636
  category: `Commands`,
2532
2637
  description: `Builds Tina and starts the dev server`,
@@ -2540,6 +2645,8 @@ DevCommand.usage = import_clipanion2.Command.Usage({
2540
2645
  var import_clipanion3 = require("clipanion");
2541
2646
  var import_progress2 = __toESM(require("progress"));
2542
2647
  var import_fs_extra7 = __toESM(require("fs-extra"));
2648
+ var import_crypto = __toESM(require("crypto"));
2649
+ var import_path6 = __toESM(require("path"));
2543
2650
  var import_graphql11 = require("@tinacms/graphql");
2544
2651
 
2545
2652
  // src/next/commands/build-command/server.ts
@@ -2583,7 +2690,7 @@ var buildProductionSpa = async (configManager, database, apiURL) => {
2583
2690
  // src/next/commands/build-command/index.ts
2584
2691
  var import_schema_tools2 = require("@tinacms/schema-tools");
2585
2692
  var import_graphql12 = require("graphql");
2586
- var import_core2 = require("@graphql-inspector/core");
2693
+ var import_core3 = require("@graphql-inspector/core");
2587
2694
 
2588
2695
  // src/next/commands/build-command/waitForDB.ts
2589
2696
  var import_progress = __toESM(require("progress"));
@@ -2685,6 +2792,20 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2685
2792
 
2686
2793
  // src/next/commands/build-command/index.ts
2687
2794
  var import_search2 = require("@tinacms/search");
2795
+
2796
+ // src/utils/index.ts
2797
+ var import_core2 = require("@graphql-inspector/core");
2798
+ var getFaqLink = (type) => {
2799
+ switch (type) {
2800
+ case import_core2.ChangeType.FieldRemoved: {
2801
+ return "https://tina.io/docs/introduction/faq#how-do-i-resolve-the-local-graphql-schema-doesnt-match-the-remote-graphql-schema-errors";
2802
+ }
2803
+ default:
2804
+ return null;
2805
+ }
2806
+ };
2807
+
2808
+ // src/next/commands/build-command/index.ts
2688
2809
  var BuildCommand = class extends BaseCommand {
2689
2810
  constructor() {
2690
2811
  super(...arguments);
@@ -2700,6 +2821,9 @@ var BuildCommand = class extends BaseCommand {
2700
2821
  this.tinaGraphQLVersion = import_clipanion3.Option.String("--tina-graphql-version", {
2701
2822
  description: "Specify the version of @tinacms/graphql to use (defaults to latest)"
2702
2823
  });
2824
+ /**
2825
+ * 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
2826
+ */
2703
2827
  this.skipCloudChecks = import_clipanion3.Option.Boolean("--skip-cloud-checks", false, {
2704
2828
  description: "Skips checking the provided cloud config."
2705
2829
  });
@@ -2805,14 +2929,15 @@ ${dangerText(e.message)}
2805
2929
  database,
2806
2930
  null,
2807
2931
  apiURL,
2808
- true
2932
+ true,
2933
+ (lockedFn) => lockedFn()
2809
2934
  );
2810
2935
  await server.listen(Number(this.port));
2811
2936
  console.log("server listening on port", this.port);
2812
2937
  }
2813
2938
  const skipCloudChecks = this.skipCloudChecks || configManager.hasSelfHostedConfig();
2814
2939
  if (!skipCloudChecks) {
2815
- const { hasUpstream } = await this.checkClientInfo(
2940
+ const { hasUpstream, timestamp } = await this.checkClientInfo(
2816
2941
  configManager,
2817
2942
  codegen2.productionUrl,
2818
2943
  this.previewBaseBranch
@@ -2840,7 +2965,16 @@ ${dangerText(e.message)}
2840
2965
  await this.checkGraphqlSchema(
2841
2966
  configManager,
2842
2967
  database,
2843
- codegen2.productionUrl
2968
+ codegen2.productionUrl,
2969
+ timestamp
2970
+ );
2971
+ await this.checkTinaSchema(
2972
+ configManager,
2973
+ database,
2974
+ codegen2.productionUrl,
2975
+ this.previewName,
2976
+ this.verbose,
2977
+ timestamp
2844
2978
  );
2845
2979
  }
2846
2980
  await buildProductionSpa(configManager, database, codegen2.productionUrl);
@@ -2959,11 +3093,13 @@ ${dangerText(e.message)}
2959
3093
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
2960
3094
  let branchKnown = false;
2961
3095
  let hasUpstream = false;
3096
+ let timestamp;
2962
3097
  try {
2963
3098
  const res = await request({
2964
3099
  token,
2965
3100
  url
2966
3101
  });
3102
+ timestamp = res.timestamp || 0;
2967
3103
  bar2.tick({
2968
3104
  prog: "\u2705"
2969
3105
  });
@@ -3005,7 +3141,8 @@ ${dangerText(e.message)}
3005
3141
  prog: "\u2705"
3006
3142
  });
3007
3143
  return {
3008
- hasUpstream
3144
+ hasUpstream,
3145
+ timestamp
3009
3146
  };
3010
3147
  }
3011
3148
  for (let i = 0; i <= 5; i++) {
@@ -3095,14 +3232,14 @@ ${dangerText(e.message)}
3095
3232
  throw e;
3096
3233
  }
3097
3234
  }
3098
- async checkGraphqlSchema(configManager, database, apiURL) {
3235
+ async checkGraphqlSchema(configManager, database, apiURL, timestamp) {
3099
3236
  const bar2 = new import_progress2.default(
3100
3237
  "Checking local GraphQL Schema matches server. :prog",
3101
3238
  1
3102
3239
  );
3103
3240
  const { config: config2 } = configManager;
3104
3241
  const token = config2.token;
3105
- const remoteSchema = await fetchRemoteGraphqlSchema({
3242
+ const { remoteSchema, remoteProjectVersion } = await fetchRemoteGraphqlSchema({
3106
3243
  url: apiURL,
3107
3244
  token
3108
3245
  });
@@ -3122,7 +3259,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3122
3259
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
3123
3260
  const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
3124
3261
  try {
3125
- const diffResult = await (0, import_core2.diff)(localGraphqlSchema, remoteGqlSchema);
3262
+ const diffResult = await (0, import_core3.diff)(localGraphqlSchema, remoteGqlSchema);
3126
3263
  if (diffResult.length === 0) {
3127
3264
  bar2.tick({
3128
3265
  prog: "\u2705"
@@ -3131,12 +3268,30 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3131
3268
  bar2.tick({
3132
3269
  prog: "\u274C"
3133
3270
  });
3134
- 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.`;
3135
- if (config2 == null ? void 0 : config2.branch) {
3136
- errorMessage += `
3271
+ const type = diffResult[0].type;
3272
+ const reason = diffResult[0].message;
3273
+ const errorLevel = diffResult[0].criticality.level;
3274
+ const faqLink = getFaqLink(type);
3275
+ const tinaGraphQLVersion = configManager.getTinaGraphQLVersion();
3276
+ 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 && `
3277
+ Check out '${faqLink}' for possible solutions.`}`;
3278
+ errorMessage += `
3137
3279
 
3138
- Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3280
+ Additional info:
3281
+
3282
+ `;
3283
+ if (config2 == null ? void 0 : config2.branch) {
3284
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3285
+ `;
3139
3286
  }
3287
+ errorMessage += ` Local GraphQL version: ${tinaGraphQLVersion.fullVersion} / Remote GraphQL version: ${remoteProjectVersion}
3288
+ `;
3289
+ errorMessage += ` Last indexed at: ${new Date(
3290
+ timestamp
3291
+ ).toUTCString()}
3292
+ `;
3293
+ errorMessage += ` Reason: [${errorLevel} - ${type}] ${reason}
3294
+ `;
3140
3295
  throw new Error(errorMessage);
3141
3296
  }
3142
3297
  } catch (e) {
@@ -3151,6 +3306,71 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3151
3306
  }
3152
3307
  }
3153
3308
  }
3309
+ async checkTinaSchema(configManager, database, apiURL, previewName, verbose, timestamp) {
3310
+ const bar2 = new import_progress2.default(
3311
+ "Checking local Tina Schema matches server. :prog",
3312
+ 1
3313
+ );
3314
+ const { config: config2 } = configManager;
3315
+ const token = config2.token;
3316
+ const { clientId, branch, isLocalClient, host } = (0, import_schema_tools2.parseURL)(apiURL);
3317
+ if (isLocalClient || !host || !clientId || !branch) {
3318
+ if (verbose) {
3319
+ logger.info(logText("Not using Tina Cloud, skipping Tina Schema check"));
3320
+ }
3321
+ return;
3322
+ }
3323
+ const { tinaSchema: remoteTinaSchemaSha } = await fetchSchemaSha({
3324
+ url: `https://${host}/db/${clientId}/${previewName || branch}/schemaSha`,
3325
+ token
3326
+ });
3327
+ if (!remoteTinaSchemaSha) {
3328
+ bar2.tick({
3329
+ prog: "\u274C"
3330
+ });
3331
+ let errorMessage = `The remote Tina schema does not exist. Check indexing for this branch.`;
3332
+ if (config2 == null ? void 0 : config2.branch) {
3333
+ errorMessage += `
3334
+
3335
+ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3336
+ }
3337
+ throw new Error(errorMessage);
3338
+ }
3339
+ if (!database.bridge) {
3340
+ throw new Error(`No bridge configured`);
3341
+ }
3342
+ const localTinaSchema = JSON.parse(
3343
+ await database.bridge.get(
3344
+ import_path6.default.join(database.tinaDirectory, "__generated__", "_schema.json")
3345
+ )
3346
+ );
3347
+ localTinaSchema.version = void 0;
3348
+ const localTinaSchemaSha = import_crypto.default.createHash("sha256").update(JSON.stringify(localTinaSchema)).digest("hex");
3349
+ if (localTinaSchemaSha === remoteTinaSchemaSha) {
3350
+ bar2.tick({
3351
+ prog: "\u2705"
3352
+ });
3353
+ } else {
3354
+ bar2.tick({
3355
+ prog: "\u274C"
3356
+ });
3357
+ 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.`;
3358
+ errorMessage += `
3359
+
3360
+ Additional info:
3361
+
3362
+ `;
3363
+ if (config2 == null ? void 0 : config2.branch) {
3364
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3365
+ `;
3366
+ }
3367
+ errorMessage += ` Last indexed at: ${new Date(
3368
+ timestamp
3369
+ ).toUTCString()}
3370
+ `;
3371
+ throw new Error(errorMessage);
3372
+ }
3373
+ }
3154
3374
  };
3155
3375
  BuildCommand.paths = [["build"]];
3156
3376
  BuildCommand.usage = import_clipanion3.Command.Usage({
@@ -3217,7 +3437,26 @@ var fetchRemoteGraphqlSchema = async ({
3217
3437
  body
3218
3438
  });
3219
3439
  const data = await res.json();
3220
- return data == null ? void 0 : data.data;
3440
+ return {
3441
+ remoteSchema: data == null ? void 0 : data.data,
3442
+ remoteRuntimeVersion: res.headers.get("tinacms-grapqhl-version"),
3443
+ remoteProjectVersion: res.headers.get("tinacms-graphql-project-version")
3444
+ };
3445
+ };
3446
+ var fetchSchemaSha = async ({
3447
+ url,
3448
+ token
3449
+ }) => {
3450
+ const headers = new Headers();
3451
+ if (token) {
3452
+ headers.append("X-API-KEY", token);
3453
+ }
3454
+ const res = await fetch(url, {
3455
+ method: "GET",
3456
+ headers,
3457
+ cache: "no-cache"
3458
+ });
3459
+ return res.json();
3221
3460
  };
3222
3461
 
3223
3462
  // src/next/commands/audit-command/index.ts
@@ -3326,6 +3565,7 @@ var auditDocuments = async (args) => {
3326
3565
  logger.error(import_chalk5.default.red(err.message));
3327
3566
  if (err.originalError.originalError) {
3328
3567
  logger.error(
3568
+ // @ts-ignore FIXME: this doesn't seem right
3329
3569
  import_chalk5.default.red(` ${err.originalError.originalError.message}`)
3330
3570
  );
3331
3571
  }
@@ -3472,25 +3712,25 @@ var import_clipanion6 = require("clipanion");
3472
3712
 
3473
3713
  // src/cmds/init/detectEnvironment.ts
3474
3714
  var import_fs_extra8 = __toESM(require("fs-extra"));
3475
- var import_path6 = __toESM(require("path"));
3715
+ var import_path7 = __toESM(require("path"));
3476
3716
  var checkGitignoreForItem = async ({
3477
3717
  baseDir,
3478
3718
  line
3479
3719
  }) => {
3480
- const gitignoreContent = import_fs_extra8.default.readFileSync(import_path6.default.join(baseDir, ".gitignore")).toString();
3720
+ const gitignoreContent = import_fs_extra8.default.readFileSync(import_path7.default.join(baseDir, ".gitignore")).toString();
3481
3721
  return gitignoreContent.split("\n").some((item) => item === line);
3482
3722
  };
3483
3723
  var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
3484
3724
  const result = {
3485
- fullPathTS: import_path6.default.join(
3725
+ fullPathTS: import_path7.default.join(
3486
3726
  parentPath,
3487
3727
  `${name2}.${(opts == null ? void 0 : opts.typescriptSuffix) || (opts == null ? void 0 : opts.extensionOverride) || "ts"}`
3488
3728
  ),
3489
- fullPathJS: import_path6.default.join(
3729
+ fullPathJS: import_path7.default.join(
3490
3730
  parentPath,
3491
3731
  `${name2}.${(opts == null ? void 0 : opts.extensionOverride) || "js"}`
3492
3732
  ),
3493
- fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path6.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3733
+ fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path7.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3494
3734
  generatedFileType,
3495
3735
  name: name2,
3496
3736
  parentPath,
@@ -3520,18 +3760,20 @@ var detectEnvironment = async ({
3520
3760
  }) => {
3521
3761
  var _a;
3522
3762
  const hasForestryConfig = await import_fs_extra8.default.pathExists(
3523
- import_path6.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3763
+ import_path7.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3524
3764
  );
3525
- const sampleContentPath = import_path6.default.join(
3765
+ const sampleContentPath = import_path7.default.join(
3526
3766
  baseDir,
3527
3767
  "content",
3528
3768
  "posts",
3529
3769
  "hello-world.md"
3530
3770
  );
3531
- 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")));
3532
- const tinaFolder = import_path6.default.join(baseDir, "tina");
3771
+ 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")));
3772
+ const tinaFolder = import_path7.default.join(baseDir, "tina");
3533
3773
  const tinaConfigExists = Boolean(
3534
- await import_fs_extra8.default.pathExists(tinaFolder) && (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3774
+ // Does the tina folder exist?
3775
+ await import_fs_extra8.default.pathExists(tinaFolder) && // Does the tina folder contain a config file?
3776
+ (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3535
3777
  );
3536
3778
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
3537
3779
  Boolean
@@ -3543,12 +3785,12 @@ var detectEnvironment = async ({
3543
3785
  "next-api-handler": await makeGeneratedFile(
3544
3786
  "[...routes]",
3545
3787
  "next-api-handler",
3546
- import_path6.default.join(...pagesDir, "api", "tina")
3788
+ import_path7.default.join(...pagesDir, "api", "tina")
3547
3789
  ),
3548
3790
  "reactive-example": await makeGeneratedFile(
3549
3791
  "[filename]",
3550
3792
  "reactive-example",
3551
- import_path6.default.join(...pagesDir, "demo", "blog"),
3793
+ import_path7.default.join(...pagesDir, "demo", "blog"),
3552
3794
  {
3553
3795
  typescriptSuffix: "tsx"
3554
3796
  }
@@ -3556,13 +3798,13 @@ var detectEnvironment = async ({
3556
3798
  "users-json": await makeGeneratedFile(
3557
3799
  "index",
3558
3800
  "users-json",
3559
- import_path6.default.join(baseDir, "content", "users"),
3801
+ import_path7.default.join(baseDir, "content", "users"),
3560
3802
  { extensionOverride: "json" }
3561
3803
  ),
3562
3804
  "sample-content": await makeGeneratedFile(
3563
3805
  "hello-world",
3564
3806
  "sample-content",
3565
- import_path6.default.join(baseDir, "content", "posts"),
3807
+ import_path7.default.join(baseDir, "content", "posts"),
3566
3808
  { extensionOverride: "md" }
3567
3809
  )
3568
3810
  };
@@ -3588,13 +3830,13 @@ var detectEnvironment = async ({
3588
3830
  );
3589
3831
  }
3590
3832
  }
3591
- const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path6.default.join(".gitignore"));
3833
+ const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path7.default.join(".gitignore"));
3592
3834
  const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
3593
3835
  const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
3594
3836
  const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
3595
3837
  let frontMatterFormat;
3596
3838
  if (hasForestryConfig) {
3597
- const hugoConfigPath = import_path6.default.join(rootPath, "config.toml");
3839
+ const hugoConfigPath = import_path7.default.join(rootPath, "config.toml");
3598
3840
  if (await import_fs_extra8.default.pathExists(hugoConfigPath)) {
3599
3841
  const hugoConfig = await import_fs_extra8.default.readFile(hugoConfigPath, "utf8");
3600
3842
  const metaDataFormat = (_a = hugoConfig.match(/metaDataFormat = "(.*)"/)) == null ? void 0 : _a[1];
@@ -3766,6 +4008,7 @@ var supportedDatabaseAdapters = {
3766
4008
  {
3767
4009
  from: "mongodb",
3768
4010
  imported: [],
4011
+ // not explicitly imported
3769
4012
  packageName: "mongodb"
3770
4013
  }
3771
4014
  ]
@@ -3838,6 +4081,10 @@ var chooseDatabaseAdapter = async ({
3838
4081
  title: "MongoDB",
3839
4082
  value: "mongodb"
3840
4083
  }
4084
+ // {
4085
+ // title: "I'll create my own database adapter",
4086
+ // value: 'other',
4087
+ // },
3841
4088
  ]
3842
4089
  }
3843
4090
  ]);
@@ -4115,6 +4362,7 @@ async function configure(env, opts) {
4115
4362
  packageManager,
4116
4363
  forestryMigrate: false,
4117
4364
  isLocalEnvVarName: "TINA_PUBLIC_IS_LOCAL",
4365
+ // TODO: give this a better default
4118
4366
  typescript: false
4119
4367
  };
4120
4368
  if (config2.framework.name === "next") {
@@ -4202,31 +4450,41 @@ var CLICommand = class {
4202
4450
  };
4203
4451
 
4204
4452
  // src/cmds/init/apply.ts
4205
- var import_path10 = __toESM(require("path"));
4453
+ var import_path11 = __toESM(require("path"));
4206
4454
 
4207
4455
  // src/cmds/forestry-migrate/index.ts
4208
4456
  var import_fs_extra10 = __toESM(require("fs-extra"));
4209
- var import_path8 = __toESM(require("path"));
4457
+ var import_path9 = __toESM(require("path"));
4210
4458
  var import_js_yaml2 = __toESM(require("js-yaml"));
4211
4459
  var import_minimatch = __toESM(require("minimatch"));
4212
4460
  var import_graphql16 = require("@tinacms/graphql");
4213
4461
 
4214
4462
  // src/cmds/forestry-migrate/util/index.ts
4215
4463
  var import_fs_extra9 = __toESM(require("fs-extra"));
4216
- var import_path7 = __toESM(require("path"));
4464
+ var import_path8 = __toESM(require("path"));
4217
4465
  var import_js_yaml = __toESM(require("js-yaml"));
4218
4466
  var import_zod = __toESM(require("zod"));
4219
4467
 
4220
4468
  // src/cmds/forestry-migrate/util/errorSingleton.ts
4221
- var ErrorSingleton = class {
4469
+ var ErrorSingleton = class _ErrorSingleton {
4470
+ /**
4471
+ * The Singleton's constructor should always be private to prevent direct
4472
+ * construction calls with the `new` operator.
4473
+ */
4222
4474
  constructor() {
4223
4475
  }
4476
+ /**
4477
+ * The static method that controls the access to the singleton instance.
4478
+ *
4479
+ * This implementation let you subclass the Singleton class while keeping
4480
+ * just one instance of each subclass around.
4481
+ */
4224
4482
  static getInstance() {
4225
- if (!ErrorSingleton.instance) {
4226
- ErrorSingleton.instance = new ErrorSingleton();
4227
- ErrorSingleton.instance.collectionNameErrors = [];
4483
+ if (!_ErrorSingleton.instance) {
4484
+ _ErrorSingleton.instance = new _ErrorSingleton();
4485
+ _ErrorSingleton.instance.collectionNameErrors = [];
4228
4486
  }
4229
- return ErrorSingleton.instance;
4487
+ return _ErrorSingleton.instance;
4230
4488
  }
4231
4489
  addErrorName(error) {
4232
4490
  this.collectionNameErrors.push(error);
@@ -4269,8 +4527,7 @@ var makeFieldsWithInternalCode = ({
4269
4527
  if (hasBody) {
4270
4528
  return [bodyField, `__TINA_INTERNAL__:::...${field}():::`];
4271
4529
  } else {
4272
- if (spread)
4273
- return `__TINA_INTERNAL__:::...${field}():::`;
4530
+ if (spread) return `__TINA_INTERNAL__:::...${field}():::`;
4274
4531
  return `__TINA_INTERNAL__:::${field}():::`;
4275
4532
  }
4276
4533
  };
@@ -4354,6 +4611,7 @@ var forestryConfigSchema = import_zod.default.object({
4354
4611
  )
4355
4612
  });
4356
4613
  var forestryFieldWithoutField = import_zod.default.object({
4614
+ // TODO: maybe better type this?
4357
4615
  type: import_zod.default.union([
4358
4616
  import_zod.default.literal("text"),
4359
4617
  import_zod.default.literal("datetime"),
@@ -4377,6 +4635,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4377
4635
  default: import_zod.default.any().optional(),
4378
4636
  template: import_zod.default.string().optional(),
4379
4637
  config: import_zod.default.object({
4638
+ // min and max are used for lists
4380
4639
  min: import_zod.default.number().optional().nullable(),
4381
4640
  max: import_zod.default.number().optional().nullable(),
4382
4641
  required: import_zod.default.boolean().optional().nullable(),
@@ -4390,6 +4649,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4390
4649
  import_zod.default.literal("pages"),
4391
4650
  import_zod.default.literal("documents"),
4392
4651
  import_zod.default.literal("simple"),
4652
+ // TODO: I want to ignore this key if its invalid
4393
4653
  import_zod.default.string()
4394
4654
  ]).optional().nullable(),
4395
4655
  section: import_zod.default.string().optional().nullable()
@@ -4425,6 +4685,7 @@ var transformForestryFieldsToTinaFields = ({
4425
4685
  }
4426
4686
  let field;
4427
4687
  switch (forestryField2.type) {
4688
+ // Single filed types
4428
4689
  case "text":
4429
4690
  field = {
4430
4691
  type: "string",
@@ -4504,6 +4765,7 @@ var transformForestryFieldsToTinaFields = ({
4504
4765
  );
4505
4766
  }
4506
4767
  break;
4768
+ // List Types
4507
4769
  case "list":
4508
4770
  field = {
4509
4771
  type: "string",
@@ -4526,6 +4788,7 @@ var transformForestryFieldsToTinaFields = ({
4526
4788
  }
4527
4789
  };
4528
4790
  break;
4791
+ // Object (Group) types
4529
4792
  case "field_group":
4530
4793
  field = {
4531
4794
  type: "object",
@@ -4566,6 +4829,7 @@ var transformForestryFieldsToTinaFields = ({
4566
4829
  });
4567
4830
  const fieldsString = stringifyLabelWithField(template2.label);
4568
4831
  const t = {
4832
+ // @ts-ignore
4569
4833
  fields: makeFieldsWithInternalCode({
4570
4834
  hasBody: false,
4571
4835
  field: fieldsString
@@ -4603,6 +4867,7 @@ var transformForestryFieldsToTinaFields = ({
4603
4867
  spread: true
4604
4868
  });
4605
4869
  tinaFields.push(
4870
+ // @ts-ignore
4606
4871
  field2
4607
4872
  );
4608
4873
  break;
@@ -4624,7 +4889,7 @@ var transformForestryFieldsToTinaFields = ({
4624
4889
  return tinaFields;
4625
4890
  };
4626
4891
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
4627
- const templatePath = import_path7.default.join(
4892
+ const templatePath = import_path8.default.join(
4628
4893
  pathToForestryConfig,
4629
4894
  ".forestry",
4630
4895
  "front_matter",
@@ -4662,6 +4927,7 @@ var parseSections = ({ val }) => {
4662
4927
 
4663
4928
  // src/cmds/forestry-migrate/index.ts
4664
4929
  var BODY_FIELD = {
4930
+ // This is the body field
4665
4931
  type: "rich-text",
4666
4932
  name: "body",
4667
4933
  label: "Body of Document",
@@ -4699,8 +4965,8 @@ var generateAllTemplates = async ({
4699
4965
  pathToForestryConfig
4700
4966
  }) => {
4701
4967
  const allTemplates = (await import_fs_extra10.default.readdir(
4702
- import_path8.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4703
- )).map((tem) => import_path8.default.basename(tem, ".yml"));
4968
+ import_path9.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4969
+ )).map((tem) => import_path9.default.basename(tem, ".yml"));
4704
4970
  const templateMap = /* @__PURE__ */ new Map();
4705
4971
  const proms = allTemplates.map(async (tem) => {
4706
4972
  try {
@@ -4720,8 +4986,7 @@ var generateAllTemplates = async ({
4720
4986
  };
4721
4987
  var generateCollectionFromForestrySection = (args) => {
4722
4988
  const { section, templateMap } = args;
4723
- if (section.read_only)
4724
- return;
4989
+ if (section.read_only) return;
4725
4990
  let format3 = "md";
4726
4991
  if (section.new_doc_ext) {
4727
4992
  const ext = checkExt(section.new_doc_ext);
@@ -4788,12 +5053,14 @@ var generateCollectionFromForestrySection = (args) => {
4788
5053
  if (((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1) {
4789
5054
  c = {
4790
5055
  ...baseCollection,
5056
+ // @ts-expect-error
4791
5057
  templates: forestryTemplates.map((tem) => {
4792
5058
  const currentTemplate = templateMap.get(tem);
4793
5059
  const fieldsString = stringifyLabelWithField(
4794
5060
  currentTemplate.templateObj.label
4795
5061
  );
4796
5062
  return {
5063
+ // fields: [BODY_FIELD],
4797
5064
  fields: makeFieldsWithInternalCode({
4798
5065
  hasBody,
4799
5066
  field: fieldsString,
@@ -4811,6 +5078,8 @@ var generateCollectionFromForestrySection = (args) => {
4811
5078
  const fieldsString = stringifyLabelWithField(template.templateObj.label);
4812
5079
  c = {
4813
5080
  ...baseCollection,
5081
+ // fields: [BODY_FIELD],
5082
+ // @ts-expect-error
4814
5083
  fields: makeFieldsWithInternalCode({
4815
5084
  field: fieldsString,
4816
5085
  hasBody,
@@ -4842,9 +5111,9 @@ var generateCollectionFromForestrySection = (args) => {
4842
5111
  return c;
4843
5112
  } else if (section.type === "document") {
4844
5113
  const filePath = section.path;
4845
- const extname = import_path8.default.extname(filePath);
4846
- const fileName = import_path8.default.basename(filePath, extname);
4847
- const dir = import_path8.default.dirname(filePath);
5114
+ const extname = import_path9.default.extname(filePath);
5115
+ const fileName = import_path9.default.basename(filePath, extname);
5116
+ const dir = import_path9.default.dirname(filePath);
4848
5117
  const ext = checkExt(extname);
4849
5118
  if (ext) {
4850
5119
  const fields = [];
@@ -4907,7 +5176,7 @@ var generateCollections = async ({
4907
5176
  usingTypescript
4908
5177
  });
4909
5178
  const forestryConfig = await import_fs_extra10.default.readFile(
4910
- import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
5179
+ import_path9.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4911
5180
  );
4912
5181
  rewriteTemplateKeysInDocs({
4913
5182
  templateMap,
@@ -4938,11 +5207,11 @@ var rewriteTemplateKeysInDocs = (args) => {
4938
5207
  const { templateObj } = templateMap.get(templateKey);
4939
5208
  (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
4940
5209
  try {
4941
- const filePath = import_path8.default.join(page);
5210
+ const filePath = import_path9.default.join(page);
4942
5211
  if (import_fs_extra10.default.lstatSync(filePath).isDirectory()) {
4943
5212
  return;
4944
5213
  }
4945
- const extname = import_path8.default.extname(filePath);
5214
+ const extname = import_path9.default.extname(filePath);
4946
5215
  const fileContent = import_fs_extra10.default.readFileSync(filePath).toString();
4947
5216
  const content = (0, import_graphql16.parseFile)(
4948
5217
  fileContent,
@@ -4974,7 +5243,7 @@ var import_fs_extra13 = __toESM(require("fs-extra"));
4974
5243
  // src/next/commands/codemod-command/index.ts
4975
5244
  var import_clipanion5 = require("clipanion");
4976
5245
  var import_fs_extra11 = __toESM(require("fs-extra"));
4977
- var import_path9 = __toESM(require("path"));
5246
+ var import_path10 = __toESM(require("path"));
4978
5247
  var CodemodCommand = class extends import_clipanion5.Command {
4979
5248
  constructor() {
4980
5249
  super(...arguments);
@@ -5018,7 +5287,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5018
5287
  logger.error(e.message);
5019
5288
  process.exit(1);
5020
5289
  }
5021
- const tinaDestination = import_path9.default.join(configManager.rootPath, "tina");
5290
+ const tinaDestination = import_path10.default.join(configManager.rootPath, "tina");
5022
5291
  if (await import_fs_extra11.default.existsSync(tinaDestination)) {
5023
5292
  logger.info(
5024
5293
  `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.`
@@ -5033,7 +5302,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5033
5302
  };
5034
5303
  var writeGitignore = async (rootPath) => {
5035
5304
  await import_fs_extra11.default.outputFileSync(
5036
- import_path9.default.join(rootPath, "tina", ".gitignore"),
5305
+ import_path10.default.join(rootPath, "tina", ".gitignore"),
5037
5306
  "__generated__"
5038
5307
  );
5039
5308
  };
@@ -5558,6 +5827,7 @@ var makeImportsVisitor = (sourceFile, importMap) => (ctx) => (node) => {
5558
5827
  ) : [];
5559
5828
  const newImports = [
5560
5829
  .../* @__PURE__ */ new Set([
5830
+ // we use Set to remove duplicates
5561
5831
  ...existingImports,
5562
5832
  ...imports
5563
5833
  ])
@@ -5712,6 +5982,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5712
5982
  );
5713
5983
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5714
5984
  const importMap = {
5985
+ // iterate over configImports and add them to the import map
5715
5986
  ...configImports.reduce((acc, { from, imported }) => {
5716
5987
  acc[from] = imported;
5717
5988
  return acc;
@@ -5871,8 +6142,8 @@ async function apply({
5871
6142
  await addConfigFile({
5872
6143
  configArgs: {
5873
6144
  config: config2,
5874
- publicFolder: import_path10.default.join(
5875
- import_path10.default.relative(process.cwd(), pathToForestryConfig),
6145
+ publicFolder: import_path11.default.join(
6146
+ import_path11.default.relative(process.cwd(), pathToForestryConfig),
5876
6147
  config2.publicFolder
5877
6148
  ),
5878
6149
  collections,
@@ -5886,7 +6157,13 @@ async function apply({
5886
6157
  config: config2
5887
6158
  });
5888
6159
  }
5889
- if (env.tinaConfigExists && params.isBackendInit && config2.hosting === "self-host" && (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud") {
6160
+ if (
6161
+ // if the config was just generated we do not need to update the config file because it will be generated correctly
6162
+ env.tinaConfigExists && // Are we running tinacms init backend
6163
+ params.isBackendInit && // Do the user choose the 'self-host' option
6164
+ config2.hosting === "self-host" && // the user did not choose the 'tina-cloud' auth provider
6165
+ (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud"
6166
+ ) {
5890
6167
  await addSelfHostedTinaAuthToConfig(config2, env.generatedFiles["config"]);
5891
6168
  }
5892
6169
  logNextSteps({
@@ -5939,18 +6216,18 @@ var createPackageJSON = async () => {
5939
6216
  };
5940
6217
  var createGitignore = async ({ baseDir }) => {
5941
6218
  logger.info(logText("No .gitignore found, creating one"));
5942
- import_fs_extra13.default.outputFileSync(import_path10.default.join(baseDir, ".gitignore"), "node_modules");
6219
+ import_fs_extra13.default.outputFileSync(import_path11.default.join(baseDir, ".gitignore"), "node_modules");
5943
6220
  };
5944
6221
  var updateGitIgnore = async ({
5945
6222
  baseDir,
5946
6223
  items
5947
6224
  }) => {
5948
6225
  logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
5949
- const gitignoreContent = import_fs_extra13.default.readFileSync(import_path10.default.join(baseDir, ".gitignore")).toString();
6226
+ const gitignoreContent = import_fs_extra13.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
5950
6227
  const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
5951
6228
  "\n"
5952
6229
  );
5953
- await import_fs_extra13.default.writeFile(import_path10.default.join(baseDir, ".gitignore"), newGitignoreContent);
6230
+ await import_fs_extra13.default.writeFile(import_path11.default.join(baseDir, ".gitignore"), newGitignoreContent);
5954
6231
  };
5955
6232
  var addDependencies = async (config2, env, params) => {
5956
6233
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
@@ -6020,22 +6297,22 @@ var writeGeneratedFile = async ({
6020
6297
  content,
6021
6298
  typescript
6022
6299
  }) => {
6023
- const { exists, path: path13, parentPath } = generatedFile.resolve(typescript);
6300
+ const { exists, path: path14, parentPath } = generatedFile.resolve(typescript);
6024
6301
  if (exists) {
6025
6302
  if (overwrite) {
6026
- logger.info(`Overwriting file at ${path13}... \u2705`);
6027
- import_fs_extra13.default.outputFileSync(path13, content);
6303
+ logger.info(`Overwriting file at ${path14}... \u2705`);
6304
+ import_fs_extra13.default.outputFileSync(path14, content);
6028
6305
  } else {
6029
- logger.info(`Not overwriting file at ${path13}.`);
6306
+ logger.info(`Not overwriting file at ${path14}.`);
6030
6307
  logger.info(
6031
- logText(`Please add the following to ${path13}:
6308
+ logText(`Please add the following to ${path14}:
6032
6309
  ${indentText(content)}}`)
6033
6310
  );
6034
6311
  }
6035
6312
  } else {
6036
- logger.info(`Adding file at ${path13}... \u2705`);
6313
+ logger.info(`Adding file at ${path14}... \u2705`);
6037
6314
  await import_fs_extra13.default.ensureDir(parentPath);
6038
- import_fs_extra13.default.outputFileSync(path13, content);
6315
+ import_fs_extra13.default.outputFileSync(path14, content);
6039
6316
  }
6040
6317
  };
6041
6318
  var addConfigFile = async ({
@@ -6118,7 +6395,7 @@ var addContentFile = async ({
6118
6395
  return () => ({
6119
6396
  exists: env.sampleContentExists,
6120
6397
  path: env.sampleContentPath,
6121
- parentPath: import_path10.default.dirname(env.sampleContentPath)
6398
+ parentPath: import_path11.default.dirname(env.sampleContentPath)
6122
6399
  });
6123
6400
  }
6124
6401
  },
@@ -6141,7 +6418,7 @@ ${titleText(" TinaCMS ")} backend initialized!`));
6141
6418
  return `${x.key}=${x.value || "***"}`;
6142
6419
  }).join("\n") + `
6143
6420
  TINA_PUBLIC_IS_LOCAL=true`;
6144
- const envFile = import_path10.default.join(process.cwd(), ".env");
6421
+ const envFile = import_path11.default.join(process.cwd(), ".env");
6145
6422
  if (!import_fs_extra13.default.existsSync(envFile)) {
6146
6423
  logger.info(`Adding .env file to your project... \u2705`);
6147
6424
  import_fs_extra13.default.writeFileSync(envFile, envFileText);
@@ -6179,6 +6456,7 @@ var other = ({ packageManager }) => {
6179
6456
  const packageManagers = {
6180
6457
  pnpm: `pnpm`,
6181
6458
  npm: `npx`,
6459
+ // npx is the way to run executables that aren't in your "scripts"
6182
6460
  yarn: `yarn`
6183
6461
  };
6184
6462
  return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
@@ -6191,6 +6469,7 @@ var frameworkDevCmds = {
6191
6469
  const packageManagers = {
6192
6470
  pnpm: `pnpm`,
6193
6471
  npm: `npm run`,
6472
+ // npx is the way to run executables that aren't in your "scripts"
6194
6473
  yarn: `yarn`
6195
6474
  };
6196
6475
  return `${packageManagers[packageManager]} dev`;
@@ -6205,7 +6484,7 @@ var addReactiveFile = {
6205
6484
  dataLayer
6206
6485
  }) => {
6207
6486
  var _a, _b;
6208
- const packageJsonPath = import_path10.default.join(baseDir, "package.json");
6487
+ const packageJsonPath = import_path11.default.join(baseDir, "package.json");
6209
6488
  await writeGeneratedFile({
6210
6489
  generatedFile,
6211
6490
  typescript: config2.typescript,
@@ -6448,5 +6727,3 @@ cli.register(import_clipanion8.Builtins.DefinitionsCommand);
6448
6727
  cli.register(import_clipanion8.Builtins.HelpCommand);
6449
6728
  cli.register(import_clipanion8.Builtins.VersionCommand);
6450
6729
  var src_default = cli;
6451
- // Annotate the CommonJS export names for ESM import in node:
6452
- 0 && (module.exports = {});