@tinacms/cli 0.0.0-bcdf830-20241023064032 → 0.0.0-bee8309-20241223064446

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,7 +35,7 @@ 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.7.0";
35
39
 
36
40
  // src/next/commands/dev-command/index.ts
37
41
  var import_clipanion2 = require("clipanion");
@@ -57,7 +61,10 @@ function isUnicodeSupported() {
57
61
  if (process.platform !== "win32") {
58
62
  return process.env.TERM !== "linux";
59
63
  }
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";
64
+ return Boolean(process.env.CI) || Boolean(process.env.WT_SESSION) || // Windows Terminal
65
+ Boolean(process.env.TERMINUS_SUBLIME) || // Terminus (<0.2.27)
66
+ process.env.ConEmuTask === "{cmd::Cmder}" || // ConEmu and cmder
67
+ 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
68
  }
62
69
 
63
70
  // src/logger/index.ts
@@ -212,7 +219,7 @@ var ConfigManager = class {
212
219
  this.generatedCachePath = import_path.default.join(
213
220
  this.generatedFolderPath,
214
221
  ".cache",
215
- String(new Date().getTime())
222
+ String((/* @__PURE__ */ new Date()).getTime())
216
223
  );
217
224
  this.generatedGraphQLGQLPath = import_path.default.join(
218
225
  this.generatedFolderPath,
@@ -355,17 +362,22 @@ var ConfigManager = class {
355
362
  );
356
363
  }
357
364
  getTinaGraphQLVersion() {
358
- var _a, _b;
359
365
  if (this.tinaGraphQLVersionFromCLI) {
360
- return this.tinaGraphQLVersionFromCLI;
366
+ const version2 = this.tinaGraphQLVersionFromCLI.split(".");
367
+ return {
368
+ fullVersion: this.tinaGraphQLVersionFromCLI,
369
+ major: version2[0] || "x",
370
+ minor: version2[1] || "x",
371
+ patch: version2[2] || "x"
372
+ };
361
373
  }
362
374
  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")) {
375
+ if (!generatedSchema || !(typeof (generatedSchema == null ? void 0 : generatedSchema.version) !== "undefined")) {
364
376
  throw new Error(
365
377
  `Can not find Tina GraphQL version in ${this.generatedSchemaJSONPath}`
366
378
  );
367
379
  }
368
- return `${generatedSchema.version.major}.${generatedSchema.version.minor}`;
380
+ return generatedSchema.version;
369
381
  }
370
382
  printGeneratedClientFilePath() {
371
383
  if (this.isUsingTs()) {
@@ -394,6 +406,9 @@ var ConfigManager = class {
394
406
  }
395
407
  throw `No path provided to print`;
396
408
  }
409
+ /**
410
+ * Given a filepath without an extension, find the first match (eg. tsx, ts, jsx, js)
411
+ */
397
412
  async getPathWithExtension(filepath) {
398
413
  const extensions = ["tsx", "ts", "jsx", "js"];
399
414
  let result;
@@ -427,7 +442,10 @@ var ConfigManager = class {
427
442
  }
428
443
  async loadConfigFile(generatedFolderPath, configFilePath) {
429
444
  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");
445
+ const preBuildConfigPath = import_path.default.join(
446
+ this.generatedFolderPath,
447
+ "config.prebuild.jsx"
448
+ );
431
449
  const outfile = import_path.default.join(tmpdir, "config.build.jsx");
432
450
  const outfile2 = import_path.default.join(tmpdir, "config.build.js");
433
451
  const tempTSConfigFile = import_path.default.join(tmpdir, "tsconfig.json");
@@ -441,7 +459,7 @@ var ConfigManager = class {
441
459
  logLevel: "silent",
442
460
  packages: "external",
443
461
  ignoreAnnotations: true,
444
- outfile: prebuild,
462
+ outfile: preBuildConfigPath,
445
463
  loader: loaders,
446
464
  metafile: true
447
465
  });
@@ -464,6 +482,7 @@ var ConfigManager = class {
464
482
  await esbuild.build({
465
483
  entryPoints: [outfile],
466
484
  bundle: true,
485
+ // Suppress warning about comparison with -0 from client module
467
486
  logLevel: "silent",
468
487
  platform: "node",
469
488
  outfile: outfile2,
@@ -481,7 +500,7 @@ var ConfigManager = class {
481
500
  import_fs_extra.default.removeSync(outfile2);
482
501
  return {
483
502
  config: result.default,
484
- prebuildPath: prebuild,
503
+ prebuildPath: preBuildConfigPath,
485
504
  watchList: flattenedList
486
505
  };
487
506
  }
@@ -570,19 +589,19 @@ var devHTML = (port) => `<!DOCTYPE html>
570
589
  window.$RefreshReg$ = () => {}
571
590
  window.$RefreshSig$ = () => (type) => type
572
591
  window.__vite_plugin_react_preamble_installed__ = true
573
- <\/script>
574
- <script type="module" src="http://localhost:${port}/@vite/client"><\/script>
592
+ </script>
593
+ <script type="module" src="http://localhost:${port}/@vite/client"></script>
575
594
  <script>
576
595
  function handleLoadError() {
577
596
  // Assets have failed to load
578
597
  document.getElementById('root').innerHTML = '${errorHTML}';
579
598
  }
580
- <\/script>
599
+ </script>
581
600
  <script
582
601
  type="module"
583
602
  src="http://localhost:${port}/src/main.tsx"
584
603
  onerror="handleLoadError()"
585
- ><\/script>
604
+ ></script>
586
605
  <body class="tina-tailwind">
587
606
  <div id="root"></div>
588
607
  </body>
@@ -628,6 +647,7 @@ var import_defaultTheme = __toESM(require("tailwindcss/defaultTheme.js"));
628
647
  var tinaTailwind = (spaPath, prebuildFilePath) => {
629
648
  return {
630
649
  name: "vite-plugin-tina",
650
+ // @ts-ignore
631
651
  config: (viteConfig) => {
632
652
  const plugins = [];
633
653
  const content = [
@@ -939,7 +959,6 @@ async function listFilesRecursively({
939
959
  }
940
960
  var createConfig = async ({
941
961
  configManager,
942
- database,
943
962
  apiURL,
944
963
  plugins = [],
945
964
  noWatch,
@@ -977,17 +996,14 @@ var createConfig = async ({
977
996
  } else {
978
997
  await import_fs_extra2.default.outputFile(staticMediaPath, `[]`);
979
998
  }
980
- const isBrowser = typeof window !== "undefined";
981
999
  const alias = {
982
1000
  TINA_IMPORT: configManager.prebuildFilePath,
983
1001
  SCHEMA_IMPORT: configManager.generatedGraphQLJSONPath,
984
1002
  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
- }
1003
+ crypto: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1004
+ fs: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1005
+ os: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1006
+ path: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts")
991
1007
  };
992
1008
  if (configManager.shouldSkipSDK()) {
993
1009
  alias["CLIENT_IMPORT"] = import_node_path2.default.join(
@@ -1002,6 +1018,8 @@ var createConfig = async ({
1002
1018
  if (configManager.config.build.basePath) {
1003
1019
  basePath = configManager.config.build.basePath;
1004
1020
  }
1021
+ const fullVersion = configManager.getTinaGraphQLVersion();
1022
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1005
1023
  const config2 = {
1006
1024
  root: configManager.spaRootPath,
1007
1025
  base: `/${basePath ? `${(0, import_normalize_path2.default)(basePath)}/` : ""}${(0, import_normalize_path2.default)(
@@ -1013,15 +1031,33 @@ var createConfig = async ({
1013
1031
  dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1014
1032
  },
1015
1033
  define: {
1034
+ /**
1035
+ * Since we prebuild the config.ts, it's possible for modules to be loaded which make
1036
+ * use of `process`. The main scenario where this is an issue is when co-locating schema
1037
+ * definitions with source files, and specifically source files which impor from NextJS.
1038
+ *
1039
+ * Some examples of what NextJS uses for `process.env` are:
1040
+ * - `process.env.__NEXT_TRAILING_SLASH`
1041
+ * - `process.env.__NEXT_CROSS_ORIGIN`
1042
+ * - `process.env.__NEXT_I18N_SUPPORT`
1043
+ *
1044
+ * Also, interestingly some of the advice for handling this doesn't work, references to replacing
1045
+ * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
1046
+ * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1047
+ */
1016
1048
  "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1049
+ // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1017
1050
  "process.platform": `"${process.platform}"`,
1018
1051
  __API_URL__: `"${apiURL}"`,
1019
1052
  __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1020
- __TINA_GRAPHQL_VERSION__: `"${configManager.getTinaGraphQLVersion()}"`
1053
+ __TINA_GRAPHQL_VERSION__: version2
1021
1054
  },
1022
1055
  logLevel: "error",
1056
+ // Vite import warnings are noisy
1023
1057
  optimizeDeps: {
1024
1058
  force: true,
1059
+ // Not 100% sure why this isn't being picked up automatically, this works from within the monorepo
1060
+ // but breaks externally
1025
1061
  include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1026
1062
  },
1027
1063
  server: {
@@ -1029,6 +1065,7 @@ var createConfig = async ({
1029
1065
  watch: noWatch ? {
1030
1066
  ignored: ["**/*"]
1031
1067
  } : {
1068
+ // Ignore everything except for the alias fields we specified above
1032
1069
  ignored: [
1033
1070
  `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1034
1071
  ]
@@ -1044,8 +1081,13 @@ var createConfig = async ({
1044
1081
  rollupOptions
1045
1082
  },
1046
1083
  plugins: [
1084
+ /**
1085
+ * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
1086
+ * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
1087
+ */
1047
1088
  (0, import_plugin_react.default)({
1048
1089
  babel: {
1090
+ // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1049
1091
  compact: true
1050
1092
  }
1051
1093
  }),
@@ -1122,8 +1164,7 @@ var createMediaRouter = (config2) => {
1122
1164
  };
1123
1165
  var parseMediaFolder = (str) => {
1124
1166
  let returnString = str;
1125
- if (returnString.startsWith("/"))
1126
- returnString = returnString.substr(1);
1167
+ if (returnString.startsWith("/")) returnString = returnString.substr(1);
1127
1168
  if (returnString.endsWith("/"))
1128
1169
  returnString = returnString.substr(0, returnString.length - 1);
1129
1170
  return returnString;
@@ -1390,6 +1431,7 @@ function viteTransformExtension({
1390
1431
  return {
1391
1432
  code: res.code,
1392
1433
  map: null
1434
+ // TODO:
1393
1435
  };
1394
1436
  }
1395
1437
  }
@@ -1410,6 +1452,14 @@ var createDevServer = async (configManager, database, searchIndex, apiURL, noWat
1410
1452
  apiURL,
1411
1453
  plugins,
1412
1454
  noWatch,
1455
+ /**
1456
+ * Ensure Vite's import scan uses the spaMainPath as the input
1457
+ * so it properly finds everything. This is for dev only, and when
1458
+ * running the server outside of this monorepo vite fails to find
1459
+ * and optimize the imports, so you get errors about it not being
1460
+ * able to find an export from a module, and it's always a CJS
1461
+ * module that Vite would usually transform to an ES module.
1462
+ */
1413
1463
  rollupOptions: {
1414
1464
  input: configManager.spaMainPath,
1415
1465
  onwarn(warning, warn) {
@@ -1535,6 +1585,7 @@ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBas
1535
1585
  node,
1536
1586
  documentVariableName,
1537
1587
  operationType,
1588
+ // This is the only line that is different
1538
1589
  operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
1539
1590
  operationVariablesTypes
1540
1591
  });
@@ -1583,6 +1634,8 @@ var plugin = (schema, documents, config2) => {
1583
1634
  const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1584
1635
  const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1585
1636
  return {
1637
+ // We will take care of imports
1638
+ // prepend: visitor.getImports(),
1586
1639
  content: [
1587
1640
  visitor.fragments,
1588
1641
  ...visitorResult.definitions.filter((t) => typeof t === "string"),
@@ -1598,6 +1651,7 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
1598
1651
  docs = await loadGraphQLDocuments(queryPathGlob);
1599
1652
  fragDocs = await loadGraphQLDocuments(fragDocPath);
1600
1653
  const res = await (0, import_core.codegen)({
1654
+ // Filename is not used. This is because the typescript plugin returns a string instead of writing to a file.
1601
1655
  filename: process.cwd(),
1602
1656
  schema: (0, import_graphql5.parse)((0, import_graphql5.printSchema)(schema)),
1603
1657
  documents: [...docs, ...fragDocs],
@@ -1632,9 +1686,12 @@ var loadGraphQLDocuments = async (globPath) => {
1632
1686
  loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
1633
1687
  });
1634
1688
  } catch (e) {
1635
- if ((e.message || "").includes(
1636
- "Unable to find any GraphQL type definitions for the following pointers:"
1637
- )) {
1689
+ if (
1690
+ // https://www.graphql-tools.com/docs/documents-loading#no-files-found
1691
+ (e.message || "").includes(
1692
+ "Unable to find any GraphQL type definitions for the following pointers:"
1693
+ )
1694
+ ) {
1638
1695
  } else {
1639
1696
  throw e;
1640
1697
  }
@@ -1791,16 +1848,14 @@ var Codegen = class {
1791
1848
  const branch = (_a = this.configManager.config) == null ? void 0 : _a.branch;
1792
1849
  const clientId = (_b = this.configManager.config) == null ? void 0 : _b.clientId;
1793
1850
  const token = (_c = this.configManager.config) == null ? void 0 : _c.token;
1794
- const version2 = this.configManager.getTinaGraphQLVersion();
1851
+ const fullVersion = this.configManager.getTinaGraphQLVersion();
1852
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1795
1853
  const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
1796
1854
  if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
1797
1855
  const missing = [];
1798
- if (!branch)
1799
- missing.push("branch");
1800
- if (!clientId)
1801
- missing.push("clientId");
1802
- if (!token)
1803
- missing.push("token");
1856
+ if (!branch) missing.push("branch");
1857
+ if (!clientId) missing.push("clientId");
1858
+ if (!token) missing.push("token");
1804
1859
  throw new Error(
1805
1860
  `Client not configured properly. Missing ${missing.join(
1806
1861
  ", "
@@ -1954,7 +2009,11 @@ schema {
1954
2009
  }
1955
2010
  };
1956
2011
  var maybeWarnFragmentSize = async (filepath) => {
1957
- if ((await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
2012
+ if (
2013
+ // is the file bigger than 100kb?
2014
+ (await import_fs_extra4.default.stat(filepath)).size > // convert to 100 kb to bytes
2015
+ 100 * 1024
2016
+ ) {
1958
2017
  console.warn(
1959
2018
  "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
1960
2019
  );
@@ -1982,6 +2041,7 @@ var import_many_level = require("many-level");
1982
2041
  var import_memory_level = require("memory-level");
1983
2042
  var createDBServer = (port) => {
1984
2043
  const levelHost = new import_many_level.ManyLevelHost(
2044
+ // @ts-ignore
1985
2045
  new import_memory_level.MemoryLevel({
1986
2046
  valueEncoding: "json"
1987
2047
  })
@@ -2212,7 +2272,7 @@ var BaseCommand = class extends import_clipanion.Command {
2212
2272
  pathFilter
2213
2273
  });
2214
2274
  const tinaPathUpdates = modified.filter(
2215
- (path13) => path13.startsWith(".tina/__generated__/_schema.json") || path13.startsWith("tina/tina-lock.json")
2275
+ (path14) => path14.startsWith(".tina/__generated__/_schema.json") || path14.startsWith("tina/tina-lock.json")
2216
2276
  );
2217
2277
  if (tinaPathUpdates.length > 0) {
2218
2278
  res = await database.indexContent({
@@ -2256,6 +2316,7 @@ var import_search = require("@tinacms/search");
2256
2316
  var DevCommand = class extends BaseCommand {
2257
2317
  constructor() {
2258
2318
  super(...arguments);
2319
+ // NOTE: camelCase commands for string options don't work if there's an `=` used https://github.com/arcanis/clipanion/issues/141
2259
2320
  this.watchFolders = import_clipanion2.Option.String("-w,--watchFolders", {
2260
2321
  description: "DEPRECATED - a list of folders (relative to where this is being run) that the cli will watch for changes"
2261
2322
  });
@@ -2474,6 +2535,20 @@ ${dangerText(e.message)}
2474
2535
  heading: "Tina Dev Server is running...",
2475
2536
  items: [
2476
2537
  ...summaryItems
2538
+ // {
2539
+ // emoji: '📚',
2540
+ // heading: 'Useful links',
2541
+ // subItems: [
2542
+ // {
2543
+ // key: 'Custom queries',
2544
+ // value: 'https://tina.io/querying',
2545
+ // },
2546
+ // {
2547
+ // key: 'Visual editing',
2548
+ // value: 'https://tina.io/visual-editing',
2549
+ // },
2550
+ // ],
2551
+ // },
2477
2552
  ]
2478
2553
  });
2479
2554
  await this.startSubCommand();
@@ -2540,6 +2615,8 @@ DevCommand.usage = import_clipanion2.Command.Usage({
2540
2615
  var import_clipanion3 = require("clipanion");
2541
2616
  var import_progress2 = __toESM(require("progress"));
2542
2617
  var import_fs_extra7 = __toESM(require("fs-extra"));
2618
+ var import_crypto = __toESM(require("crypto"));
2619
+ var import_path6 = __toESM(require("path"));
2543
2620
  var import_graphql11 = require("@tinacms/graphql");
2544
2621
 
2545
2622
  // src/next/commands/build-command/server.ts
@@ -2583,7 +2660,7 @@ var buildProductionSpa = async (configManager, database, apiURL) => {
2583
2660
  // src/next/commands/build-command/index.ts
2584
2661
  var import_schema_tools2 = require("@tinacms/schema-tools");
2585
2662
  var import_graphql12 = require("graphql");
2586
- var import_core2 = require("@graphql-inspector/core");
2663
+ var import_core3 = require("@graphql-inspector/core");
2587
2664
 
2588
2665
  // src/next/commands/build-command/waitForDB.ts
2589
2666
  var import_progress = __toESM(require("progress"));
@@ -2685,6 +2762,20 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2685
2762
 
2686
2763
  // src/next/commands/build-command/index.ts
2687
2764
  var import_search2 = require("@tinacms/search");
2765
+
2766
+ // src/utils/index.ts
2767
+ var import_core2 = require("@graphql-inspector/core");
2768
+ var getFaqLink = (type) => {
2769
+ switch (type) {
2770
+ case import_core2.ChangeType.FieldRemoved: {
2771
+ return "https://tina.io/docs/introduction/faq#how-do-i-resolve-the-local-graphql-schema-doesnt-match-the-remote-graphql-schema-errors";
2772
+ }
2773
+ default:
2774
+ return null;
2775
+ }
2776
+ };
2777
+
2778
+ // src/next/commands/build-command/index.ts
2688
2779
  var BuildCommand = class extends BaseCommand {
2689
2780
  constructor() {
2690
2781
  super(...arguments);
@@ -2700,6 +2791,9 @@ var BuildCommand = class extends BaseCommand {
2700
2791
  this.tinaGraphQLVersion = import_clipanion3.Option.String("--tina-graphql-version", {
2701
2792
  description: "Specify the version of @tinacms/graphql to use (defaults to latest)"
2702
2793
  });
2794
+ /**
2795
+ * 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
2796
+ */
2703
2797
  this.skipCloudChecks = import_clipanion3.Option.Boolean("--skip-cloud-checks", false, {
2704
2798
  description: "Skips checking the provided cloud config."
2705
2799
  });
@@ -2812,7 +2906,7 @@ ${dangerText(e.message)}
2812
2906
  }
2813
2907
  const skipCloudChecks = this.skipCloudChecks || configManager.hasSelfHostedConfig();
2814
2908
  if (!skipCloudChecks) {
2815
- const { hasUpstream } = await this.checkClientInfo(
2909
+ const { hasUpstream, timestamp } = await this.checkClientInfo(
2816
2910
  configManager,
2817
2911
  codegen2.productionUrl,
2818
2912
  this.previewBaseBranch
@@ -2840,7 +2934,16 @@ ${dangerText(e.message)}
2840
2934
  await this.checkGraphqlSchema(
2841
2935
  configManager,
2842
2936
  database,
2843
- codegen2.productionUrl
2937
+ codegen2.productionUrl,
2938
+ timestamp
2939
+ );
2940
+ await this.checkTinaSchema(
2941
+ configManager,
2942
+ database,
2943
+ codegen2.productionUrl,
2944
+ this.previewName,
2945
+ this.verbose,
2946
+ timestamp
2844
2947
  );
2845
2948
  }
2846
2949
  await buildProductionSpa(configManager, database, codegen2.productionUrl);
@@ -2959,11 +3062,13 @@ ${dangerText(e.message)}
2959
3062
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
2960
3063
  let branchKnown = false;
2961
3064
  let hasUpstream = false;
3065
+ let timestamp;
2962
3066
  try {
2963
3067
  const res = await request({
2964
3068
  token,
2965
3069
  url
2966
3070
  });
3071
+ timestamp = res.timestamp || 0;
2967
3072
  bar2.tick({
2968
3073
  prog: "\u2705"
2969
3074
  });
@@ -3005,7 +3110,8 @@ ${dangerText(e.message)}
3005
3110
  prog: "\u2705"
3006
3111
  });
3007
3112
  return {
3008
- hasUpstream
3113
+ hasUpstream,
3114
+ timestamp
3009
3115
  };
3010
3116
  }
3011
3117
  for (let i = 0; i <= 5; i++) {
@@ -3095,14 +3201,14 @@ ${dangerText(e.message)}
3095
3201
  throw e;
3096
3202
  }
3097
3203
  }
3098
- async checkGraphqlSchema(configManager, database, apiURL) {
3204
+ async checkGraphqlSchema(configManager, database, apiURL, timestamp) {
3099
3205
  const bar2 = new import_progress2.default(
3100
3206
  "Checking local GraphQL Schema matches server. :prog",
3101
3207
  1
3102
3208
  );
3103
3209
  const { config: config2 } = configManager;
3104
3210
  const token = config2.token;
3105
- const remoteSchema = await fetchRemoteGraphqlSchema({
3211
+ const { remoteSchema, remoteProjectVersion } = await fetchRemoteGraphqlSchema({
3106
3212
  url: apiURL,
3107
3213
  token
3108
3214
  });
@@ -3122,7 +3228,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3122
3228
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
3123
3229
  const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
3124
3230
  try {
3125
- const diffResult = await (0, import_core2.diff)(localGraphqlSchema, remoteGqlSchema);
3231
+ const diffResult = await (0, import_core3.diff)(localGraphqlSchema, remoteGqlSchema);
3126
3232
  if (diffResult.length === 0) {
3127
3233
  bar2.tick({
3128
3234
  prog: "\u2705"
@@ -3131,12 +3237,30 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3131
3237
  bar2.tick({
3132
3238
  prog: "\u274C"
3133
3239
  });
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 += `
3240
+ const type = diffResult[0].type;
3241
+ const reason = diffResult[0].message;
3242
+ const errorLevel = diffResult[0].criticality.level;
3243
+ const faqLink = getFaqLink(type);
3244
+ const tinaGraphQLVersion = configManager.getTinaGraphQLVersion();
3245
+ 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 && `
3246
+ Check out '${faqLink}' for possible solutions.`}`;
3247
+ errorMessage += `
3137
3248
 
3138
- Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3249
+ Additional info:
3250
+
3251
+ `;
3252
+ if (config2 == null ? void 0 : config2.branch) {
3253
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3254
+ `;
3139
3255
  }
3256
+ errorMessage += ` Local GraphQL version: ${tinaGraphQLVersion.fullVersion} / Remote GraphQL version: ${remoteProjectVersion}
3257
+ `;
3258
+ errorMessage += ` Last indexed at: ${new Date(
3259
+ timestamp
3260
+ ).toUTCString()}
3261
+ `;
3262
+ errorMessage += ` Reason: [${errorLevel} - ${type}] ${reason}
3263
+ `;
3140
3264
  throw new Error(errorMessage);
3141
3265
  }
3142
3266
  } catch (e) {
@@ -3151,6 +3275,71 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3151
3275
  }
3152
3276
  }
3153
3277
  }
3278
+ async checkTinaSchema(configManager, database, apiURL, previewName, verbose, timestamp) {
3279
+ const bar2 = new import_progress2.default(
3280
+ "Checking local Tina Schema matches server. :prog",
3281
+ 1
3282
+ );
3283
+ const { config: config2 } = configManager;
3284
+ const token = config2.token;
3285
+ const { clientId, branch, isLocalClient, host } = (0, import_schema_tools2.parseURL)(apiURL);
3286
+ if (isLocalClient || !host || !clientId || !branch) {
3287
+ if (verbose) {
3288
+ logger.info(logText("Not using Tina Cloud, skipping Tina Schema check"));
3289
+ }
3290
+ return;
3291
+ }
3292
+ const { tinaSchema: remoteTinaSchemaSha } = await fetchSchemaSha({
3293
+ url: `https://${host}/db/${clientId}/${previewName || branch}/schemaSha`,
3294
+ token
3295
+ });
3296
+ if (!remoteTinaSchemaSha) {
3297
+ bar2.tick({
3298
+ prog: "\u274C"
3299
+ });
3300
+ let errorMessage = `The remote Tina schema does not exist. Check indexing for this branch.`;
3301
+ if (config2 == null ? void 0 : config2.branch) {
3302
+ errorMessage += `
3303
+
3304
+ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3305
+ }
3306
+ throw new Error(errorMessage);
3307
+ }
3308
+ if (!database.bridge) {
3309
+ throw new Error(`No bridge configured`);
3310
+ }
3311
+ const localTinaSchema = JSON.parse(
3312
+ await database.bridge.get(
3313
+ import_path6.default.join(database.tinaDirectory, "__generated__", "_schema.json")
3314
+ )
3315
+ );
3316
+ localTinaSchema.version = void 0;
3317
+ const localTinaSchemaSha = import_crypto.default.createHash("sha256").update(JSON.stringify(localTinaSchema)).digest("hex");
3318
+ if (localTinaSchemaSha === remoteTinaSchemaSha) {
3319
+ bar2.tick({
3320
+ prog: "\u2705"
3321
+ });
3322
+ } else {
3323
+ bar2.tick({
3324
+ prog: "\u274C"
3325
+ });
3326
+ 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.`;
3327
+ errorMessage += `
3328
+
3329
+ Additional info:
3330
+
3331
+ `;
3332
+ if (config2 == null ? void 0 : config2.branch) {
3333
+ errorMessage += ` Branch: ${config2.branch}, Client ID: ${config2.clientId}
3334
+ `;
3335
+ }
3336
+ errorMessage += ` Last indexed at: ${new Date(
3337
+ timestamp
3338
+ ).toUTCString()}
3339
+ `;
3340
+ throw new Error(errorMessage);
3341
+ }
3342
+ }
3154
3343
  };
3155
3344
  BuildCommand.paths = [["build"]];
3156
3345
  BuildCommand.usage = import_clipanion3.Command.Usage({
@@ -3217,7 +3406,26 @@ var fetchRemoteGraphqlSchema = async ({
3217
3406
  body
3218
3407
  });
3219
3408
  const data = await res.json();
3220
- return data == null ? void 0 : data.data;
3409
+ return {
3410
+ remoteSchema: data == null ? void 0 : data.data,
3411
+ remoteRuntimeVersion: res.headers.get("tinacms-grapqhl-version"),
3412
+ remoteProjectVersion: res.headers.get("tinacms-graphql-project-version")
3413
+ };
3414
+ };
3415
+ var fetchSchemaSha = async ({
3416
+ url,
3417
+ token
3418
+ }) => {
3419
+ const headers = new Headers();
3420
+ if (token) {
3421
+ headers.append("X-API-KEY", token);
3422
+ }
3423
+ const res = await fetch(url, {
3424
+ method: "GET",
3425
+ headers,
3426
+ cache: "no-cache"
3427
+ });
3428
+ return res.json();
3221
3429
  };
3222
3430
 
3223
3431
  // src/next/commands/audit-command/index.ts
@@ -3326,6 +3534,7 @@ var auditDocuments = async (args) => {
3326
3534
  logger.error(import_chalk5.default.red(err.message));
3327
3535
  if (err.originalError.originalError) {
3328
3536
  logger.error(
3537
+ // @ts-ignore FIXME: this doesn't seem right
3329
3538
  import_chalk5.default.red(` ${err.originalError.originalError.message}`)
3330
3539
  );
3331
3540
  }
@@ -3472,25 +3681,25 @@ var import_clipanion6 = require("clipanion");
3472
3681
 
3473
3682
  // src/cmds/init/detectEnvironment.ts
3474
3683
  var import_fs_extra8 = __toESM(require("fs-extra"));
3475
- var import_path6 = __toESM(require("path"));
3684
+ var import_path7 = __toESM(require("path"));
3476
3685
  var checkGitignoreForItem = async ({
3477
3686
  baseDir,
3478
3687
  line
3479
3688
  }) => {
3480
- const gitignoreContent = import_fs_extra8.default.readFileSync(import_path6.default.join(baseDir, ".gitignore")).toString();
3689
+ const gitignoreContent = import_fs_extra8.default.readFileSync(import_path7.default.join(baseDir, ".gitignore")).toString();
3481
3690
  return gitignoreContent.split("\n").some((item) => item === line);
3482
3691
  };
3483
3692
  var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
3484
3693
  const result = {
3485
- fullPathTS: import_path6.default.join(
3694
+ fullPathTS: import_path7.default.join(
3486
3695
  parentPath,
3487
3696
  `${name2}.${(opts == null ? void 0 : opts.typescriptSuffix) || (opts == null ? void 0 : opts.extensionOverride) || "ts"}`
3488
3697
  ),
3489
- fullPathJS: import_path6.default.join(
3698
+ fullPathJS: import_path7.default.join(
3490
3699
  parentPath,
3491
3700
  `${name2}.${(opts == null ? void 0 : opts.extensionOverride) || "js"}`
3492
3701
  ),
3493
- fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path6.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3702
+ fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path7.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3494
3703
  generatedFileType,
3495
3704
  name: name2,
3496
3705
  parentPath,
@@ -3520,18 +3729,20 @@ var detectEnvironment = async ({
3520
3729
  }) => {
3521
3730
  var _a;
3522
3731
  const hasForestryConfig = await import_fs_extra8.default.pathExists(
3523
- import_path6.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3732
+ import_path7.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3524
3733
  );
3525
- const sampleContentPath = import_path6.default.join(
3734
+ const sampleContentPath = import_path7.default.join(
3526
3735
  baseDir,
3527
3736
  "content",
3528
3737
  "posts",
3529
3738
  "hello-world.md"
3530
3739
  );
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");
3740
+ 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")));
3741
+ const tinaFolder = import_path7.default.join(baseDir, "tina");
3533
3742
  const tinaConfigExists = Boolean(
3534
- await import_fs_extra8.default.pathExists(tinaFolder) && (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3743
+ // Does the tina folder exist?
3744
+ await import_fs_extra8.default.pathExists(tinaFolder) && // Does the tina folder contain a config file?
3745
+ (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3535
3746
  );
3536
3747
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
3537
3748
  Boolean
@@ -3543,12 +3754,12 @@ var detectEnvironment = async ({
3543
3754
  "next-api-handler": await makeGeneratedFile(
3544
3755
  "[...routes]",
3545
3756
  "next-api-handler",
3546
- import_path6.default.join(...pagesDir, "api", "tina")
3757
+ import_path7.default.join(...pagesDir, "api", "tina")
3547
3758
  ),
3548
3759
  "reactive-example": await makeGeneratedFile(
3549
3760
  "[filename]",
3550
3761
  "reactive-example",
3551
- import_path6.default.join(...pagesDir, "demo", "blog"),
3762
+ import_path7.default.join(...pagesDir, "demo", "blog"),
3552
3763
  {
3553
3764
  typescriptSuffix: "tsx"
3554
3765
  }
@@ -3556,13 +3767,13 @@ var detectEnvironment = async ({
3556
3767
  "users-json": await makeGeneratedFile(
3557
3768
  "index",
3558
3769
  "users-json",
3559
- import_path6.default.join(baseDir, "content", "users"),
3770
+ import_path7.default.join(baseDir, "content", "users"),
3560
3771
  { extensionOverride: "json" }
3561
3772
  ),
3562
3773
  "sample-content": await makeGeneratedFile(
3563
3774
  "hello-world",
3564
3775
  "sample-content",
3565
- import_path6.default.join(baseDir, "content", "posts"),
3776
+ import_path7.default.join(baseDir, "content", "posts"),
3566
3777
  { extensionOverride: "md" }
3567
3778
  )
3568
3779
  };
@@ -3588,13 +3799,13 @@ var detectEnvironment = async ({
3588
3799
  );
3589
3800
  }
3590
3801
  }
3591
- const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path6.default.join(".gitignore"));
3802
+ const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path7.default.join(".gitignore"));
3592
3803
  const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
3593
3804
  const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
3594
3805
  const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
3595
3806
  let frontMatterFormat;
3596
3807
  if (hasForestryConfig) {
3597
- const hugoConfigPath = import_path6.default.join(rootPath, "config.toml");
3808
+ const hugoConfigPath = import_path7.default.join(rootPath, "config.toml");
3598
3809
  if (await import_fs_extra8.default.pathExists(hugoConfigPath)) {
3599
3810
  const hugoConfig = await import_fs_extra8.default.readFile(hugoConfigPath, "utf8");
3600
3811
  const metaDataFormat = (_a = hugoConfig.match(/metaDataFormat = "(.*)"/)) == null ? void 0 : _a[1];
@@ -3766,6 +3977,7 @@ var supportedDatabaseAdapters = {
3766
3977
  {
3767
3978
  from: "mongodb",
3768
3979
  imported: [],
3980
+ // not explicitly imported
3769
3981
  packageName: "mongodb"
3770
3982
  }
3771
3983
  ]
@@ -3838,6 +4050,10 @@ var chooseDatabaseAdapter = async ({
3838
4050
  title: "MongoDB",
3839
4051
  value: "mongodb"
3840
4052
  }
4053
+ // {
4054
+ // title: "I'll create my own database adapter",
4055
+ // value: 'other',
4056
+ // },
3841
4057
  ]
3842
4058
  }
3843
4059
  ]);
@@ -4115,6 +4331,7 @@ async function configure(env, opts) {
4115
4331
  packageManager,
4116
4332
  forestryMigrate: false,
4117
4333
  isLocalEnvVarName: "TINA_PUBLIC_IS_LOCAL",
4334
+ // TODO: give this a better default
4118
4335
  typescript: false
4119
4336
  };
4120
4337
  if (config2.framework.name === "next") {
@@ -4202,31 +4419,41 @@ var CLICommand = class {
4202
4419
  };
4203
4420
 
4204
4421
  // src/cmds/init/apply.ts
4205
- var import_path10 = __toESM(require("path"));
4422
+ var import_path11 = __toESM(require("path"));
4206
4423
 
4207
4424
  // src/cmds/forestry-migrate/index.ts
4208
4425
  var import_fs_extra10 = __toESM(require("fs-extra"));
4209
- var import_path8 = __toESM(require("path"));
4426
+ var import_path9 = __toESM(require("path"));
4210
4427
  var import_js_yaml2 = __toESM(require("js-yaml"));
4211
4428
  var import_minimatch = __toESM(require("minimatch"));
4212
4429
  var import_graphql16 = require("@tinacms/graphql");
4213
4430
 
4214
4431
  // src/cmds/forestry-migrate/util/index.ts
4215
4432
  var import_fs_extra9 = __toESM(require("fs-extra"));
4216
- var import_path7 = __toESM(require("path"));
4433
+ var import_path8 = __toESM(require("path"));
4217
4434
  var import_js_yaml = __toESM(require("js-yaml"));
4218
4435
  var import_zod = __toESM(require("zod"));
4219
4436
 
4220
4437
  // src/cmds/forestry-migrate/util/errorSingleton.ts
4221
- var ErrorSingleton = class {
4438
+ var ErrorSingleton = class _ErrorSingleton {
4439
+ /**
4440
+ * The Singleton's constructor should always be private to prevent direct
4441
+ * construction calls with the `new` operator.
4442
+ */
4222
4443
  constructor() {
4223
4444
  }
4445
+ /**
4446
+ * The static method that controls the access to the singleton instance.
4447
+ *
4448
+ * This implementation let you subclass the Singleton class while keeping
4449
+ * just one instance of each subclass around.
4450
+ */
4224
4451
  static getInstance() {
4225
- if (!ErrorSingleton.instance) {
4226
- ErrorSingleton.instance = new ErrorSingleton();
4227
- ErrorSingleton.instance.collectionNameErrors = [];
4452
+ if (!_ErrorSingleton.instance) {
4453
+ _ErrorSingleton.instance = new _ErrorSingleton();
4454
+ _ErrorSingleton.instance.collectionNameErrors = [];
4228
4455
  }
4229
- return ErrorSingleton.instance;
4456
+ return _ErrorSingleton.instance;
4230
4457
  }
4231
4458
  addErrorName(error) {
4232
4459
  this.collectionNameErrors.push(error);
@@ -4269,8 +4496,7 @@ var makeFieldsWithInternalCode = ({
4269
4496
  if (hasBody) {
4270
4497
  return [bodyField, `__TINA_INTERNAL__:::...${field}():::`];
4271
4498
  } else {
4272
- if (spread)
4273
- return `__TINA_INTERNAL__:::...${field}():::`;
4499
+ if (spread) return `__TINA_INTERNAL__:::...${field}():::`;
4274
4500
  return `__TINA_INTERNAL__:::${field}():::`;
4275
4501
  }
4276
4502
  };
@@ -4354,6 +4580,7 @@ var forestryConfigSchema = import_zod.default.object({
4354
4580
  )
4355
4581
  });
4356
4582
  var forestryFieldWithoutField = import_zod.default.object({
4583
+ // TODO: maybe better type this?
4357
4584
  type: import_zod.default.union([
4358
4585
  import_zod.default.literal("text"),
4359
4586
  import_zod.default.literal("datetime"),
@@ -4377,6 +4604,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4377
4604
  default: import_zod.default.any().optional(),
4378
4605
  template: import_zod.default.string().optional(),
4379
4606
  config: import_zod.default.object({
4607
+ // min and max are used for lists
4380
4608
  min: import_zod.default.number().optional().nullable(),
4381
4609
  max: import_zod.default.number().optional().nullable(),
4382
4610
  required: import_zod.default.boolean().optional().nullable(),
@@ -4390,6 +4618,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4390
4618
  import_zod.default.literal("pages"),
4391
4619
  import_zod.default.literal("documents"),
4392
4620
  import_zod.default.literal("simple"),
4621
+ // TODO: I want to ignore this key if its invalid
4393
4622
  import_zod.default.string()
4394
4623
  ]).optional().nullable(),
4395
4624
  section: import_zod.default.string().optional().nullable()
@@ -4425,6 +4654,7 @@ var transformForestryFieldsToTinaFields = ({
4425
4654
  }
4426
4655
  let field;
4427
4656
  switch (forestryField2.type) {
4657
+ // Single filed types
4428
4658
  case "text":
4429
4659
  field = {
4430
4660
  type: "string",
@@ -4504,6 +4734,7 @@ var transformForestryFieldsToTinaFields = ({
4504
4734
  );
4505
4735
  }
4506
4736
  break;
4737
+ // List Types
4507
4738
  case "list":
4508
4739
  field = {
4509
4740
  type: "string",
@@ -4526,6 +4757,7 @@ var transformForestryFieldsToTinaFields = ({
4526
4757
  }
4527
4758
  };
4528
4759
  break;
4760
+ // Object (Group) types
4529
4761
  case "field_group":
4530
4762
  field = {
4531
4763
  type: "object",
@@ -4566,6 +4798,7 @@ var transformForestryFieldsToTinaFields = ({
4566
4798
  });
4567
4799
  const fieldsString = stringifyLabelWithField(template2.label);
4568
4800
  const t = {
4801
+ // @ts-ignore
4569
4802
  fields: makeFieldsWithInternalCode({
4570
4803
  hasBody: false,
4571
4804
  field: fieldsString
@@ -4603,6 +4836,7 @@ var transformForestryFieldsToTinaFields = ({
4603
4836
  spread: true
4604
4837
  });
4605
4838
  tinaFields.push(
4839
+ // @ts-ignore
4606
4840
  field2
4607
4841
  );
4608
4842
  break;
@@ -4624,7 +4858,7 @@ var transformForestryFieldsToTinaFields = ({
4624
4858
  return tinaFields;
4625
4859
  };
4626
4860
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
4627
- const templatePath = import_path7.default.join(
4861
+ const templatePath = import_path8.default.join(
4628
4862
  pathToForestryConfig,
4629
4863
  ".forestry",
4630
4864
  "front_matter",
@@ -4662,6 +4896,7 @@ var parseSections = ({ val }) => {
4662
4896
 
4663
4897
  // src/cmds/forestry-migrate/index.ts
4664
4898
  var BODY_FIELD = {
4899
+ // This is the body field
4665
4900
  type: "rich-text",
4666
4901
  name: "body",
4667
4902
  label: "Body of Document",
@@ -4699,8 +4934,8 @@ var generateAllTemplates = async ({
4699
4934
  pathToForestryConfig
4700
4935
  }) => {
4701
4936
  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"));
4937
+ import_path9.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4938
+ )).map((tem) => import_path9.default.basename(tem, ".yml"));
4704
4939
  const templateMap = /* @__PURE__ */ new Map();
4705
4940
  const proms = allTemplates.map(async (tem) => {
4706
4941
  try {
@@ -4720,8 +4955,7 @@ var generateAllTemplates = async ({
4720
4955
  };
4721
4956
  var generateCollectionFromForestrySection = (args) => {
4722
4957
  const { section, templateMap } = args;
4723
- if (section.read_only)
4724
- return;
4958
+ if (section.read_only) return;
4725
4959
  let format3 = "md";
4726
4960
  if (section.new_doc_ext) {
4727
4961
  const ext = checkExt(section.new_doc_ext);
@@ -4788,12 +5022,14 @@ var generateCollectionFromForestrySection = (args) => {
4788
5022
  if (((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1) {
4789
5023
  c = {
4790
5024
  ...baseCollection,
5025
+ // @ts-expect-error
4791
5026
  templates: forestryTemplates.map((tem) => {
4792
5027
  const currentTemplate = templateMap.get(tem);
4793
5028
  const fieldsString = stringifyLabelWithField(
4794
5029
  currentTemplate.templateObj.label
4795
5030
  );
4796
5031
  return {
5032
+ // fields: [BODY_FIELD],
4797
5033
  fields: makeFieldsWithInternalCode({
4798
5034
  hasBody,
4799
5035
  field: fieldsString,
@@ -4811,6 +5047,8 @@ var generateCollectionFromForestrySection = (args) => {
4811
5047
  const fieldsString = stringifyLabelWithField(template.templateObj.label);
4812
5048
  c = {
4813
5049
  ...baseCollection,
5050
+ // fields: [BODY_FIELD],
5051
+ // @ts-expect-error
4814
5052
  fields: makeFieldsWithInternalCode({
4815
5053
  field: fieldsString,
4816
5054
  hasBody,
@@ -4842,9 +5080,9 @@ var generateCollectionFromForestrySection = (args) => {
4842
5080
  return c;
4843
5081
  } else if (section.type === "document") {
4844
5082
  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);
5083
+ const extname = import_path9.default.extname(filePath);
5084
+ const fileName = import_path9.default.basename(filePath, extname);
5085
+ const dir = import_path9.default.dirname(filePath);
4848
5086
  const ext = checkExt(extname);
4849
5087
  if (ext) {
4850
5088
  const fields = [];
@@ -4907,7 +5145,7 @@ var generateCollections = async ({
4907
5145
  usingTypescript
4908
5146
  });
4909
5147
  const forestryConfig = await import_fs_extra10.default.readFile(
4910
- import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
5148
+ import_path9.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4911
5149
  );
4912
5150
  rewriteTemplateKeysInDocs({
4913
5151
  templateMap,
@@ -4938,11 +5176,11 @@ var rewriteTemplateKeysInDocs = (args) => {
4938
5176
  const { templateObj } = templateMap.get(templateKey);
4939
5177
  (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
4940
5178
  try {
4941
- const filePath = import_path8.default.join(page);
5179
+ const filePath = import_path9.default.join(page);
4942
5180
  if (import_fs_extra10.default.lstatSync(filePath).isDirectory()) {
4943
5181
  return;
4944
5182
  }
4945
- const extname = import_path8.default.extname(filePath);
5183
+ const extname = import_path9.default.extname(filePath);
4946
5184
  const fileContent = import_fs_extra10.default.readFileSync(filePath).toString();
4947
5185
  const content = (0, import_graphql16.parseFile)(
4948
5186
  fileContent,
@@ -4974,7 +5212,7 @@ var import_fs_extra13 = __toESM(require("fs-extra"));
4974
5212
  // src/next/commands/codemod-command/index.ts
4975
5213
  var import_clipanion5 = require("clipanion");
4976
5214
  var import_fs_extra11 = __toESM(require("fs-extra"));
4977
- var import_path9 = __toESM(require("path"));
5215
+ var import_path10 = __toESM(require("path"));
4978
5216
  var CodemodCommand = class extends import_clipanion5.Command {
4979
5217
  constructor() {
4980
5218
  super(...arguments);
@@ -5018,7 +5256,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5018
5256
  logger.error(e.message);
5019
5257
  process.exit(1);
5020
5258
  }
5021
- const tinaDestination = import_path9.default.join(configManager.rootPath, "tina");
5259
+ const tinaDestination = import_path10.default.join(configManager.rootPath, "tina");
5022
5260
  if (await import_fs_extra11.default.existsSync(tinaDestination)) {
5023
5261
  logger.info(
5024
5262
  `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 +5271,7 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5033
5271
  };
5034
5272
  var writeGitignore = async (rootPath) => {
5035
5273
  await import_fs_extra11.default.outputFileSync(
5036
- import_path9.default.join(rootPath, "tina", ".gitignore"),
5274
+ import_path10.default.join(rootPath, "tina", ".gitignore"),
5037
5275
  "__generated__"
5038
5276
  );
5039
5277
  };
@@ -5558,6 +5796,7 @@ var makeImportsVisitor = (sourceFile, importMap) => (ctx) => (node) => {
5558
5796
  ) : [];
5559
5797
  const newImports = [
5560
5798
  .../* @__PURE__ */ new Set([
5799
+ // we use Set to remove duplicates
5561
5800
  ...existingImports,
5562
5801
  ...imports
5563
5802
  ])
@@ -5712,6 +5951,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5712
5951
  );
5713
5952
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5714
5953
  const importMap = {
5954
+ // iterate over configImports and add them to the import map
5715
5955
  ...configImports.reduce((acc, { from, imported }) => {
5716
5956
  acc[from] = imported;
5717
5957
  return acc;
@@ -5871,8 +6111,8 @@ async function apply({
5871
6111
  await addConfigFile({
5872
6112
  configArgs: {
5873
6113
  config: config2,
5874
- publicFolder: import_path10.default.join(
5875
- import_path10.default.relative(process.cwd(), pathToForestryConfig),
6114
+ publicFolder: import_path11.default.join(
6115
+ import_path11.default.relative(process.cwd(), pathToForestryConfig),
5876
6116
  config2.publicFolder
5877
6117
  ),
5878
6118
  collections,
@@ -5886,7 +6126,13 @@ async function apply({
5886
6126
  config: config2
5887
6127
  });
5888
6128
  }
5889
- if (env.tinaConfigExists && params.isBackendInit && config2.hosting === "self-host" && (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud") {
6129
+ if (
6130
+ // if the config was just generated we do not need to update the config file because it will be generated correctly
6131
+ env.tinaConfigExists && // Are we running tinacms init backend
6132
+ params.isBackendInit && // Do the user choose the 'self-host' option
6133
+ config2.hosting === "self-host" && // the user did not choose the 'tina-cloud' auth provider
6134
+ (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud"
6135
+ ) {
5890
6136
  await addSelfHostedTinaAuthToConfig(config2, env.generatedFiles["config"]);
5891
6137
  }
5892
6138
  logNextSteps({
@@ -5939,18 +6185,18 @@ var createPackageJSON = async () => {
5939
6185
  };
5940
6186
  var createGitignore = async ({ baseDir }) => {
5941
6187
  logger.info(logText("No .gitignore found, creating one"));
5942
- import_fs_extra13.default.outputFileSync(import_path10.default.join(baseDir, ".gitignore"), "node_modules");
6188
+ import_fs_extra13.default.outputFileSync(import_path11.default.join(baseDir, ".gitignore"), "node_modules");
5943
6189
  };
5944
6190
  var updateGitIgnore = async ({
5945
6191
  baseDir,
5946
6192
  items
5947
6193
  }) => {
5948
6194
  logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
5949
- const gitignoreContent = import_fs_extra13.default.readFileSync(import_path10.default.join(baseDir, ".gitignore")).toString();
6195
+ const gitignoreContent = import_fs_extra13.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
5950
6196
  const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
5951
6197
  "\n"
5952
6198
  );
5953
- await import_fs_extra13.default.writeFile(import_path10.default.join(baseDir, ".gitignore"), newGitignoreContent);
6199
+ await import_fs_extra13.default.writeFile(import_path11.default.join(baseDir, ".gitignore"), newGitignoreContent);
5954
6200
  };
5955
6201
  var addDependencies = async (config2, env, params) => {
5956
6202
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
@@ -6020,22 +6266,22 @@ var writeGeneratedFile = async ({
6020
6266
  content,
6021
6267
  typescript
6022
6268
  }) => {
6023
- const { exists, path: path13, parentPath } = generatedFile.resolve(typescript);
6269
+ const { exists, path: path14, parentPath } = generatedFile.resolve(typescript);
6024
6270
  if (exists) {
6025
6271
  if (overwrite) {
6026
- logger.info(`Overwriting file at ${path13}... \u2705`);
6027
- import_fs_extra13.default.outputFileSync(path13, content);
6272
+ logger.info(`Overwriting file at ${path14}... \u2705`);
6273
+ import_fs_extra13.default.outputFileSync(path14, content);
6028
6274
  } else {
6029
- logger.info(`Not overwriting file at ${path13}.`);
6275
+ logger.info(`Not overwriting file at ${path14}.`);
6030
6276
  logger.info(
6031
- logText(`Please add the following to ${path13}:
6277
+ logText(`Please add the following to ${path14}:
6032
6278
  ${indentText(content)}}`)
6033
6279
  );
6034
6280
  }
6035
6281
  } else {
6036
- logger.info(`Adding file at ${path13}... \u2705`);
6282
+ logger.info(`Adding file at ${path14}... \u2705`);
6037
6283
  await import_fs_extra13.default.ensureDir(parentPath);
6038
- import_fs_extra13.default.outputFileSync(path13, content);
6284
+ import_fs_extra13.default.outputFileSync(path14, content);
6039
6285
  }
6040
6286
  };
6041
6287
  var addConfigFile = async ({
@@ -6118,7 +6364,7 @@ var addContentFile = async ({
6118
6364
  return () => ({
6119
6365
  exists: env.sampleContentExists,
6120
6366
  path: env.sampleContentPath,
6121
- parentPath: import_path10.default.dirname(env.sampleContentPath)
6367
+ parentPath: import_path11.default.dirname(env.sampleContentPath)
6122
6368
  });
6123
6369
  }
6124
6370
  },
@@ -6141,7 +6387,7 @@ ${titleText(" TinaCMS ")} backend initialized!`));
6141
6387
  return `${x.key}=${x.value || "***"}`;
6142
6388
  }).join("\n") + `
6143
6389
  TINA_PUBLIC_IS_LOCAL=true`;
6144
- const envFile = import_path10.default.join(process.cwd(), ".env");
6390
+ const envFile = import_path11.default.join(process.cwd(), ".env");
6145
6391
  if (!import_fs_extra13.default.existsSync(envFile)) {
6146
6392
  logger.info(`Adding .env file to your project... \u2705`);
6147
6393
  import_fs_extra13.default.writeFileSync(envFile, envFileText);
@@ -6179,6 +6425,7 @@ var other = ({ packageManager }) => {
6179
6425
  const packageManagers = {
6180
6426
  pnpm: `pnpm`,
6181
6427
  npm: `npx`,
6428
+ // npx is the way to run executables that aren't in your "scripts"
6182
6429
  yarn: `yarn`
6183
6430
  };
6184
6431
  return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
@@ -6191,6 +6438,7 @@ var frameworkDevCmds = {
6191
6438
  const packageManagers = {
6192
6439
  pnpm: `pnpm`,
6193
6440
  npm: `npm run`,
6441
+ // npx is the way to run executables that aren't in your "scripts"
6194
6442
  yarn: `yarn`
6195
6443
  };
6196
6444
  return `${packageManagers[packageManager]} dev`;
@@ -6205,7 +6453,7 @@ var addReactiveFile = {
6205
6453
  dataLayer
6206
6454
  }) => {
6207
6455
  var _a, _b;
6208
- const packageJsonPath = import_path10.default.join(baseDir, "package.json");
6456
+ const packageJsonPath = import_path11.default.join(baseDir, "package.json");
6209
6457
  await writeGeneratedFile({
6210
6458
  generatedFile,
6211
6459
  typescript: config2.typescript,
@@ -6448,5 +6696,3 @@ cli.register(import_clipanion8.Builtins.DefinitionsCommand);
6448
6696
  cli.register(import_clipanion8.Builtins.HelpCommand);
6449
6697
  cli.register(import_clipanion8.Builtins.VersionCommand);
6450
6698
  var src_default = cli;
6451
- // Annotate the CommonJS export names for ESM import in node:
6452
- 0 && (module.exports = {});
@@ -21,15 +21,25 @@ export declare class BuildCommand extends BaseCommand {
21
21
  execute(): Promise<number | void>;
22
22
  checkClientInfo(configManager: ConfigManager, apiURL: string, previewBaseBranch?: string): Promise<{
23
23
  hasUpstream: boolean;
24
+ timestamp: number;
24
25
  }>;
25
26
  syncProject(configManager: ConfigManager, apiURL: string, options?: {
26
27
  upstreamBranch?: string;
27
28
  previewBaseBranch?: string;
28
29
  previewName?: string;
29
30
  }): Promise<void>;
30
- checkGraphqlSchema(configManager: ConfigManager, database: Database, apiURL: string): Promise<void>;
31
+ checkGraphqlSchema(configManager: ConfigManager, database: Database, apiURL: string, timestamp: number): Promise<void>;
32
+ checkTinaSchema(configManager: ConfigManager, database: Database, apiURL: string, previewName: string, verbose: boolean, timestamp: number): Promise<void>;
31
33
  }
32
34
  export declare const fetchRemoteGraphqlSchema: ({ url, token, }: {
33
35
  url: string;
34
36
  token?: string;
37
+ }) => Promise<{
38
+ remoteSchema: any;
39
+ remoteRuntimeVersion: string;
40
+ remoteProjectVersion: string;
41
+ }>;
42
+ export declare const fetchSchemaSha: ({ url, token, }: {
43
+ url: string;
44
+ token?: string;
35
45
  }) => Promise<any>;
@@ -55,7 +55,12 @@ export declare class ConfigManager {
55
55
  shouldSkipSDK(): boolean;
56
56
  processConfig(): Promise<void>;
57
57
  getTinaFolderPath(rootPath: any): Promise<string>;
58
- getTinaGraphQLVersion(): string;
58
+ getTinaGraphQLVersion(): {
59
+ fullVersion: string;
60
+ major: string;
61
+ minor: string;
62
+ patch: string;
63
+ };
59
64
  printGeneratedClientFilePath(): string;
60
65
  printGeneratedTypesFilePath(): string;
61
66
  printoutputHTMLFilePath(): string;
@@ -22,7 +22,7 @@ interface StaticMediaItem {
22
22
  export interface StaticMedia {
23
23
  [offset: string]: StaticMediaItem[];
24
24
  }
25
- export declare const createConfig: ({ configManager, database, apiURL, plugins, noWatch, rollupOptions, }: {
25
+ export declare const createConfig: ({ configManager, apiURL, plugins, noWatch, rollupOptions, }: {
26
26
  configManager: ConfigManager;
27
27
  database: Database;
28
28
  apiURL: string;
@@ -1,5 +1,5 @@
1
1
  /**
2
2
 
3
3
  */
4
- import http from 'http';
4
+ import http from 'node:http';
5
5
  export declare const gqlServer: (database: any, verbose: boolean) => Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
@@ -1,4 +1,6 @@
1
1
  /**
2
2
 
3
3
  */
4
+ import { ChangeType } from '@graphql-inspector/core';
4
5
  export declare const parseMediaFolder: (str: string) => string;
6
+ export declare const getFaqLink: (type: ChangeType) => string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/cli",
3
- "version": "0.0.0-bcdf830-20241023064032",
3
+ "version": "0.0.0-bee8309-20241223064446",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
6
6
  "files": [
@@ -26,9 +26,8 @@
26
26
  "@types/cors": "2.8.5",
27
27
  "@types/crypto-js": "^4.2.2",
28
28
  "@types/express": "^4.17.21",
29
- "@types/express-graphql": "^0.9.0",
30
29
  "@types/figlet": "1.2.0",
31
- "@types/fs-extra": "^9.0.13",
30
+ "@types/fs-extra": "^11.0.4",
32
31
  "@types/jest": "26.0.4",
33
32
  "@types/js-yaml": "^4.0.9",
34
33
  "@types/listr": "0.14.2",
@@ -36,20 +35,20 @@
36
35
  "@types/multer": "^1.4.12",
37
36
  "@types/progress": "^2.0.7",
38
37
  "@types/prompts": "^2.4.9",
39
- "@types/yup": "^0.29.14",
38
+ "@types/yup": "^0.32.0",
40
39
  "jest": "^29.7.0",
41
- "@tinacms/scripts": "1.3.0"
40
+ "@tinacms/scripts": "1.3.1"
42
41
  },
43
42
  "dependencies": {
44
43
  "@graphql-codegen/core": "^2.6.8",
45
44
  "@graphql-codegen/plugin-helpers": "latest",
46
- "@graphql-codegen/typescript": "^4.0.9",
47
- "@graphql-codegen/typescript-operations": "^4.2.3",
45
+ "@graphql-codegen/typescript": "^4.1.1",
46
+ "@graphql-codegen/typescript-operations": "^4.3.1",
48
47
  "@graphql-codegen/visitor-plugin-common": "^4.1.2",
49
48
  "@graphql-inspector/core": "^4.2.2",
50
49
  "@graphql-tools/graphql-file-loader": "^7.5.17",
51
50
  "@graphql-tools/load": "^7.8.14",
52
- "@rollup/pluginutils": "^5.1.2",
51
+ "@rollup/pluginutils": "^5.1.3",
53
52
  "@svgr/core": "8.1.0",
54
53
  "@tailwindcss/aspect-ratio": "^0.4.2",
55
54
  "@tailwindcss/container-queries": "^0.1.1",
@@ -66,7 +65,7 @@
66
65
  "cors": "^2.8.5",
67
66
  "crypto-js": "^4.2.0",
68
67
  "dotenv": "^16.4.5",
69
- "esbuild": "^0.18.20",
68
+ "esbuild": "^0.24.0",
70
69
  "fs-extra": "^11.2.0",
71
70
  "graphql": "15.8.0",
72
71
  "js-yaml": "^4.1.0",
@@ -79,18 +78,18 @@
79
78
  "progress": "^2.0.3",
80
79
  "prompts": "^2.4.2",
81
80
  "readable-stream": "^4.5.2",
82
- "tailwindcss": "^3.4.13",
81
+ "tailwindcss": "^3.4.15",
83
82
  "typanion": "3.13.0",
84
- "typescript": "^5.6.2",
83
+ "typescript": "^5.6.3",
85
84
  "vite": "^4.5.5",
86
- "yup": "^0.32.11",
85
+ "yup": "^1.4.0",
87
86
  "zod": "^3.23.8",
88
- "@tinacms/app": "0.0.0-bcdf830-20241023064032",
89
- "@tinacms/graphql": "1.5.6",
90
- "@tinacms/schema-tools": "1.6.6",
91
- "@tinacms/metrics": "1.0.7",
92
- "@tinacms/search": "1.0.33",
93
- "tinacms": "0.0.0-bcdf830-20241023064032"
87
+ "@tinacms/app": "2.1.14",
88
+ "@tinacms/metrics": "1.0.8",
89
+ "@tinacms/graphql": "1.5.9",
90
+ "@tinacms/schema-tools": "1.6.9",
91
+ "@tinacms/search": "1.0.36",
92
+ "tinacms": "2.5.2"
94
93
  },
95
94
  "publishConfig": {
96
95
  "registry": "https://registry.npmjs.org"