@tinacms/cli 0.0.0-d888ad0-20241223044700 → 0.0.0-db8aa8e-20250228034006

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.
@@ -150,7 +150,7 @@ export declare const parseSections: ({ val }: {
150
150
  }) => {
151
151
  sections?: {
152
152
  exclude?: string;
153
- type?: "heading" | "document" | "directory" | "jekyll-pages" | "jekyll-posts";
153
+ type?: "document" | "heading" | "directory" | "jekyll-pages" | "jekyll-posts";
154
154
  match?: string;
155
155
  path?: string;
156
156
  templates?: string[];
package/dist/index.js CHANGED
@@ -17,23 +17,28 @@ var __copyProps = (to, from, except, desc) => {
17
17
  return to;
18
18
  };
19
19
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
24
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
25
  mod
22
26
  ));
23
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
28
 
25
29
  // src/index.ts
26
- var src_exports = {};
27
- __export(src_exports, {
28
- default: () => src_default
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ default: () => index_default
29
33
  });
30
- module.exports = __toCommonJS(src_exports);
34
+ module.exports = __toCommonJS(index_exports);
31
35
  var import_clipanion8 = require("clipanion");
32
36
 
33
37
  // package.json
34
- var version = "1.7.0";
38
+ var version = "1.9.1";
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,
@@ -399,6 +407,9 @@ var ConfigManager = class {
399
407
  }
400
408
  throw `No path provided to print`;
401
409
  }
410
+ /**
411
+ * Given a filepath without an extension, find the first match (eg. tsx, ts, jsx, js)
412
+ */
402
413
  async getPathWithExtension(filepath) {
403
414
  const extensions = ["tsx", "ts", "jsx", "js"];
404
415
  let result;
@@ -472,6 +483,7 @@ var ConfigManager = class {
472
483
  await esbuild.build({
473
484
  entryPoints: [outfile],
474
485
  bundle: true,
486
+ // Suppress warning about comparison with -0 from client module
475
487
  logLevel: "silent",
476
488
  platform: "node",
477
489
  outfile: outfile2,
@@ -578,19 +590,19 @@ var devHTML = (port) => `<!DOCTYPE html>
578
590
  window.$RefreshReg$ = () => {}
579
591
  window.$RefreshSig$ = () => (type) => type
580
592
  window.__vite_plugin_react_preamble_installed__ = true
581
- <\/script>
582
- <script type="module" src="http://localhost:${port}/@vite/client"><\/script>
593
+ </script>
594
+ <script type="module" src="http://localhost:${port}/@vite/client"></script>
583
595
  <script>
584
596
  function handleLoadError() {
585
597
  // Assets have failed to load
586
598
  document.getElementById('root').innerHTML = '${errorHTML}';
587
599
  }
588
- <\/script>
600
+ </script>
589
601
  <script
590
602
  type="module"
591
603
  src="http://localhost:${port}/src/main.tsx"
592
604
  onerror="handleLoadError()"
593
- ><\/script>
605
+ ></script>
594
606
  <body class="tina-tailwind">
595
607
  <div id="root"></div>
596
608
  </body>
@@ -636,6 +648,7 @@ var import_defaultTheme = __toESM(require("tailwindcss/defaultTheme.js"));
636
648
  var tinaTailwind = (spaPath, prebuildFilePath) => {
637
649
  return {
638
650
  name: "vite-plugin-tina",
651
+ // @ts-ignore
639
652
  config: (viteConfig) => {
640
653
  const plugins = [];
641
654
  const content = [
@@ -984,10 +997,17 @@ var createConfig = async ({
984
997
  } else {
985
998
  await import_fs_extra2.default.outputFile(staticMediaPath, `[]`);
986
999
  }
1000
+ console.log("ConfigManager", configManager.spaRootPath);
987
1001
  const alias = {
988
1002
  TINA_IMPORT: configManager.prebuildFilePath,
989
1003
  SCHEMA_IMPORT: configManager.generatedGraphQLJSONPath,
990
1004
  STATIC_MEDIA_IMPORT: staticMediaPath,
1005
+ react: import_node_path2.default.join(configManager.spaRootPath, "node_modules", "react"),
1006
+ "react-dom": import_node_path2.default.join(
1007
+ configManager.spaRootPath,
1008
+ "node_modules",
1009
+ "react-dom"
1010
+ ),
991
1011
  crypto: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
992
1012
  fs: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
993
1013
  os: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
@@ -1016,18 +1036,36 @@ var createConfig = async ({
1016
1036
  appType: "spa",
1017
1037
  resolve: {
1018
1038
  alias,
1019
- dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1039
+ dedupe: ["graphql", "tinacms"]
1020
1040
  },
1021
1041
  define: {
1042
+ /**
1043
+ * Since we prebuild the config.ts, it's possible for modules to be loaded which make
1044
+ * use of `process`. The main scenario where this is an issue is when co-locating schema
1045
+ * definitions with source files, and specifically source files which impor from NextJS.
1046
+ *
1047
+ * Some examples of what NextJS uses for `process.env` are:
1048
+ * - `process.env.__NEXT_TRAILING_SLASH`
1049
+ * - `process.env.__NEXT_CROSS_ORIGIN`
1050
+ * - `process.env.__NEXT_I18N_SUPPORT`
1051
+ *
1052
+ * Also, interestingly some of the advice for handling this doesn't work, references to replacing
1053
+ * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
1054
+ * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1055
+ */
1022
1056
  "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1057
+ // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1023
1058
  "process.platform": `"${process.platform}"`,
1024
1059
  __API_URL__: `"${apiURL}"`,
1025
1060
  __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1026
1061
  __TINA_GRAPHQL_VERSION__: version2
1027
1062
  },
1028
1063
  logLevel: "error",
1064
+ // Vite import warnings are noisy
1029
1065
  optimizeDeps: {
1030
1066
  force: true,
1067
+ // Not 100% sure why this isn't being picked up automatically, this works from within the monorepo
1068
+ // but breaks externally
1031
1069
  include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1032
1070
  },
1033
1071
  server: {
@@ -1035,6 +1073,7 @@ var createConfig = async ({
1035
1073
  watch: noWatch ? {
1036
1074
  ignored: ["**/*"]
1037
1075
  } : {
1076
+ // Ignore everything except for the alias fields we specified above
1038
1077
  ignored: [
1039
1078
  `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1040
1079
  ]
@@ -1047,11 +1086,21 @@ var createConfig = async ({
1047
1086
  sourcemap: false,
1048
1087
  outDir: configManager.outputFolderPath,
1049
1088
  emptyOutDir: true,
1050
- rollupOptions
1089
+ rollupOptions: {
1090
+ external: (id) => {
1091
+ console.log("I am rollup id", id);
1092
+ return id.includes("react") || id.includes("react-dom") ? false : true;
1093
+ }
1094
+ }
1051
1095
  },
1052
1096
  plugins: [
1097
+ /**
1098
+ * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
1099
+ * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
1100
+ */
1053
1101
  (0, import_plugin_react.default)({
1054
1102
  babel: {
1103
+ // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1055
1104
  compact: true
1056
1105
  }
1057
1106
  }),
@@ -1128,8 +1177,7 @@ var createMediaRouter = (config2) => {
1128
1177
  };
1129
1178
  var parseMediaFolder = (str) => {
1130
1179
  let returnString = str;
1131
- if (returnString.startsWith("/"))
1132
- returnString = returnString.substr(1);
1180
+ if (returnString.startsWith("/")) returnString = returnString.substr(1);
1133
1181
  if (returnString.endsWith("/"))
1134
1182
  returnString = returnString.substr(0, returnString.length - 1);
1135
1183
  return returnString;
@@ -1294,7 +1342,8 @@ var devServerEndPointsPlugin = ({
1294
1342
  configManager,
1295
1343
  apiURL,
1296
1344
  database,
1297
- searchIndex
1345
+ searchIndex,
1346
+ databaseLock
1298
1347
  }) => {
1299
1348
  const plug = {
1300
1349
  name: "graphql-endpoints",
@@ -1338,14 +1387,17 @@ var devServerEndPointsPlugin = ({
1338
1387
  }
1339
1388
  if (req.url === "/graphql") {
1340
1389
  const { query, variables } = req.body;
1341
- const result = await (0, import_graphql.resolve)({
1342
- config: {
1343
- useRelativeMedia: true
1344
- },
1345
- database,
1346
- query,
1347
- variables,
1348
- verbose: false
1390
+ let result;
1391
+ await databaseLock(async () => {
1392
+ result = await (0, import_graphql.resolve)({
1393
+ config: {
1394
+ useRelativeMedia: true
1395
+ },
1396
+ database,
1397
+ query,
1398
+ variables,
1399
+ verbose: false
1400
+ });
1349
1401
  });
1350
1402
  res.end(JSON.stringify(result));
1351
1403
  return;
@@ -1396,6 +1448,7 @@ function viteTransformExtension({
1396
1448
  return {
1397
1449
  code: res.code,
1398
1450
  map: null
1451
+ // TODO:
1399
1452
  };
1400
1453
  }
1401
1454
  }
@@ -1403,10 +1456,16 @@ function viteTransformExtension({
1403
1456
  }
1404
1457
 
1405
1458
  // src/next/commands/dev-command/server/index.ts
1406
- var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch) => {
1459
+ var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch, databaseLock) => {
1407
1460
  const plugins = [
1408
1461
  transformTsxPlugin({ configManager }),
1409
- devServerEndPointsPlugin({ apiURL, configManager, database, searchIndex }),
1462
+ devServerEndPointsPlugin({
1463
+ apiURL,
1464
+ configManager,
1465
+ database,
1466
+ searchIndex,
1467
+ databaseLock
1468
+ }),
1410
1469
  viteTransformExtension()
1411
1470
  ];
1412
1471
  return (0, import_vite3.createServer)(
@@ -1416,6 +1475,14 @@ var createDevServer = async (configManager, database, searchIndex, apiURL, noWat
1416
1475
  apiURL,
1417
1476
  plugins,
1418
1477
  noWatch,
1478
+ /**
1479
+ * Ensure Vite's import scan uses the spaMainPath as the input
1480
+ * so it properly finds everything. This is for dev only, and when
1481
+ * running the server outside of this monorepo vite fails to find
1482
+ * and optimize the imports, so you get errors about it not being
1483
+ * able to find an export from a module, and it's always a CJS
1484
+ * module that Vite would usually transform to an ES module.
1485
+ */
1419
1486
  rollupOptions: {
1420
1487
  input: configManager.spaMainPath,
1421
1488
  onwarn(warning, warn) {
@@ -1541,6 +1608,7 @@ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBas
1541
1608
  node,
1542
1609
  documentVariableName,
1543
1610
  operationType,
1611
+ // This is the only line that is different
1544
1612
  operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
1545
1613
  operationVariablesTypes
1546
1614
  });
@@ -1589,6 +1657,8 @@ var plugin = (schema, documents, config2) => {
1589
1657
  const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1590
1658
  const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1591
1659
  return {
1660
+ // We will take care of imports
1661
+ // prepend: visitor.getImports(),
1592
1662
  content: [
1593
1663
  visitor.fragments,
1594
1664
  ...visitorResult.definitions.filter((t) => typeof t === "string"),
@@ -1604,6 +1674,7 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
1604
1674
  docs = await loadGraphQLDocuments(queryPathGlob);
1605
1675
  fragDocs = await loadGraphQLDocuments(fragDocPath);
1606
1676
  const res = await (0, import_core.codegen)({
1677
+ // Filename is not used. This is because the typescript plugin returns a string instead of writing to a file.
1607
1678
  filename: process.cwd(),
1608
1679
  schema: (0, import_graphql5.parse)((0, import_graphql5.printSchema)(schema)),
1609
1680
  documents: [...docs, ...fragDocs],
@@ -1638,9 +1709,12 @@ var loadGraphQLDocuments = async (globPath) => {
1638
1709
  loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
1639
1710
  });
1640
1711
  } catch (e) {
1641
- if ((e.message || "").includes(
1642
- "Unable to find any GraphQL type definitions for the following pointers:"
1643
- )) {
1712
+ if (
1713
+ // https://www.graphql-tools.com/docs/documents-loading#no-files-found
1714
+ (e.message || "").includes(
1715
+ "Unable to find any GraphQL type definitions for the following pointers:"
1716
+ )
1717
+ ) {
1644
1718
  } else {
1645
1719
  throw e;
1646
1720
  }
@@ -1802,12 +1876,9 @@ var Codegen = class {
1802
1876
  const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
1803
1877
  if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
1804
1878
  const missing = [];
1805
- if (!branch)
1806
- missing.push("branch");
1807
- if (!clientId)
1808
- missing.push("clientId");
1809
- if (!token)
1810
- missing.push("token");
1879
+ if (!branch) missing.push("branch");
1880
+ if (!clientId) missing.push("clientId");
1881
+ if (!token) missing.push("token");
1811
1882
  throw new Error(
1812
1883
  `Client not configured properly. Missing ${missing.join(
1813
1884
  ", "
@@ -1961,7 +2032,11 @@ schema {
1961
2032
  }
1962
2033
  };
1963
2034
  var maybeWarnFragmentSize = async (filepath) => {
1964
- if ((await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
2035
+ if (
2036
+ // is the file bigger than 100kb?
2037
+ (await import_fs_extra4.default.stat(filepath)).size > // convert to 100 kb to bytes
2038
+ 100 * 1024
2039
+ ) {
1965
2040
  console.warn(
1966
2041
  "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
1967
2042
  );
@@ -1989,6 +2064,7 @@ var import_many_level = require("many-level");
1989
2064
  var import_memory_level = require("memory-level");
1990
2065
  var createDBServer = (port) => {
1991
2066
  const levelHost = new import_many_level.ManyLevelHost(
2067
+ // @ts-ignore
1992
2068
  new import_memory_level.MemoryLevel({
1993
2069
  valueEncoding: "json"
1994
2070
  })
@@ -2139,7 +2215,9 @@ var BaseCommand = class extends import_clipanion.Command {
2139
2215
  let subProc;
2140
2216
  if (this.subCommand) {
2141
2217
  subProc = await startSubprocess2({ command: this.subCommand });
2142
- logger.info(`Starting subprocess: ${import_chalk4.default.cyan(this.subCommand)}`);
2218
+ logger.info(
2219
+ `Running web application with command: ${import_chalk4.default.cyan(this.subCommand)}`
2220
+ );
2143
2221
  }
2144
2222
  function exitHandler(options, exitCode) {
2145
2223
  if (subProc) {
@@ -2263,6 +2341,7 @@ var import_search = require("@tinacms/search");
2263
2341
  var DevCommand = class extends BaseCommand {
2264
2342
  constructor() {
2265
2343
  super(...arguments);
2344
+ // NOTE: camelCase commands for string options don't work if there's an `=` used https://github.com/arcanis/clipanion/issues/141
2266
2345
  this.watchFolders = import_clipanion2.Option.String("-w,--watchFolders", {
2267
2346
  description: "DEPRECATED - a list of folders (relative to where this is being run) that the cli will watch for changes"
2268
2347
  });
@@ -2272,6 +2351,10 @@ var DevCommand = class extends BaseCommand {
2272
2351
  this.outputSearchIndexPath = import_clipanion2.Option.String("--outputSearchIndexPath", {
2273
2352
  description: "Path to write the search index to"
2274
2353
  });
2354
+ this.noServer = import_clipanion2.Option.Boolean("--no-server", false, {
2355
+ description: "Do not start the dev server"
2356
+ });
2357
+ this.indexingLock = new import_async_lock.default();
2275
2358
  }
2276
2359
  async catch(error) {
2277
2360
  logger.error("Error occured during tinacms dev");
@@ -2292,10 +2375,13 @@ var DevCommand = class extends BaseCommand {
2292
2375
  rootPath: this.rootPath,
2293
2376
  legacyNoSDK: this.noSDK
2294
2377
  });
2295
- logger.info("Starting Tina Dev Server");
2378
+ logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2296
2379
  this.logDeprecationWarnings();
2297
2380
  createDBServer(Number(this.datalayerPort));
2298
2381
  let database = null;
2382
+ const dbLock = async (fn) => {
2383
+ return this.indexingLock.acquire("Key", fn);
2384
+ };
2299
2385
  const setup = async ({ firstTime }) => {
2300
2386
  try {
2301
2387
  await configManager.processConfig();
@@ -2346,9 +2432,6 @@ var DevCommand = class extends BaseCommand {
2346
2432
  await import_fs_extra6.default.outputFile(filePath, tinaLockContent);
2347
2433
  }
2348
2434
  }
2349
- if (!this.noWatch) {
2350
- this.watchQueries(configManager, async () => await codegen2.execute());
2351
- }
2352
2435
  await this.indexContentWithSpinner({
2353
2436
  database,
2354
2437
  graphQLSchema: graphQLSchema2,
@@ -2358,6 +2441,13 @@ var DevCommand = class extends BaseCommand {
2358
2441
  if (!firstTime) {
2359
2442
  logger.error("Re-index complete");
2360
2443
  }
2444
+ if (!this.noWatch) {
2445
+ this.watchQueries(
2446
+ configManager,
2447
+ dbLock,
2448
+ async () => await codegen2.execute()
2449
+ );
2450
+ }
2361
2451
  return { apiURL: apiURL2, database, graphQLSchema: graphQLSchema2, tinaSchema: tinaSchema2 };
2362
2452
  } catch (e) {
2363
2453
  logger.error(`
@@ -2392,14 +2482,6 @@ ${dangerText(e.message)}
2392
2482
  tokenSplitRegex: (_d = (_c = configManager.config.search) == null ? void 0 : _c.tina) == null ? void 0 : _d.tokenSplitRegex
2393
2483
  });
2394
2484
  await searchIndexClient.onStartIndexing();
2395
- const server = await createDevServer(
2396
- configManager,
2397
- database,
2398
- searchIndexClient.searchIndex,
2399
- apiURL,
2400
- this.noWatch
2401
- );
2402
- await server.listen(Number(this.port));
2403
2485
  const searchIndexer = new import_search.SearchIndexer({
2404
2486
  batchSize: ((_e = configManager.config.search) == null ? void 0 : _e.indexBatchSize) || 100,
2405
2487
  bridge: new import_graphql10.FilesystemBridge(
@@ -2421,16 +2503,34 @@ ${dangerText(e.message)}
2421
2503
  await searchIndexClient.export(this.outputSearchIndexPath);
2422
2504
  }
2423
2505
  }
2506
+ if (this.noServer) {
2507
+ logger.info("--no-server option specified - Dev server not started");
2508
+ process.exit(0);
2509
+ }
2424
2510
  if (!this.noWatch) {
2425
2511
  this.watchContentFiles(
2426
2512
  configManager,
2427
2513
  database,
2514
+ dbLock,
2428
2515
  configManager.config.search && searchIndexer
2429
2516
  );
2517
+ }
2518
+ const server = await createDevServer(
2519
+ configManager,
2520
+ database,
2521
+ searchIndexClient.searchIndex,
2522
+ apiURL,
2523
+ this.noWatch,
2524
+ dbLock
2525
+ );
2526
+ await server.listen(Number(this.port));
2527
+ if (!this.noWatch) {
2430
2528
  import_chokidar.default.watch(configManager.watchList).on("change", async () => {
2431
- logger.info(`Tina config change detected, rebuilding`);
2432
- await setup({ firstTime: false });
2433
- server.ws.send({ type: "full-reload", path: "*" });
2529
+ await dbLock(async () => {
2530
+ logger.info(`Tina config change detected, rebuilding`);
2531
+ await setup({ firstTime: false });
2532
+ server.ws.send({ type: "full-reload", path: "*" });
2533
+ });
2434
2534
  });
2435
2535
  }
2436
2536
  const subItems = [];
@@ -2443,7 +2543,7 @@ ${dangerText(e.message)}
2443
2543
  const summaryItems = [
2444
2544
  {
2445
2545
  emoji: "\u{1F999}",
2446
- heading: "Tina Config",
2546
+ heading: "TinaCMS URLs",
2447
2547
  subItems: [
2448
2548
  {
2449
2549
  key: "CMS",
@@ -2478,14 +2578,28 @@ ${dangerText(e.message)}
2478
2578
  });
2479
2579
  }
2480
2580
  summary({
2481
- heading: "Tina Dev Server is running...",
2581
+ heading: "\u2705 \u{1F999} TinaCMS Dev Server is active:",
2482
2582
  items: [
2483
2583
  ...summaryItems
2584
+ // {
2585
+ // emoji: '📚',
2586
+ // heading: 'Useful links',
2587
+ // subItems: [
2588
+ // {
2589
+ // key: 'Custom queries',
2590
+ // value: 'https://tina.io/querying',
2591
+ // },
2592
+ // {
2593
+ // key: 'Visual editing',
2594
+ // value: 'https://tina.io/visual-editing',
2595
+ // },
2596
+ // ],
2597
+ // },
2484
2598
  ]
2485
2599
  });
2486
2600
  await this.startSubCommand();
2487
2601
  }
2488
- watchContentFiles(configManager, database, searchIndexer) {
2602
+ watchContentFiles(configManager, database, databaseLock, searchIndexer) {
2489
2603
  const collectionContentFiles = [];
2490
2604
  configManager.config.schema.collections.forEach((collection) => {
2491
2605
  const collectionGlob = `${import_path5.default.join(
@@ -2501,39 +2615,42 @@ ${dangerText(e.message)}
2501
2615
  if (!ready) {
2502
2616
  return;
2503
2617
  }
2504
- const pathFromRoot = configManager.printContentRelativePath(addedFile);
2505
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2506
- if (searchIndexer) {
2507
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2508
- }
2618
+ await databaseLock(async () => {
2619
+ const pathFromRoot = configManager.printContentRelativePath(addedFile);
2620
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2621
+ if (searchIndexer) {
2622
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2623
+ }
2624
+ });
2509
2625
  }).on("change", async (changedFile) => {
2510
2626
  const pathFromRoot = configManager.printContentRelativePath(changedFile);
2511
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2512
- if (searchIndexer) {
2513
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2514
- }
2627
+ await databaseLock(async () => {
2628
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2629
+ if (searchIndexer) {
2630
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2631
+ }
2632
+ });
2515
2633
  }).on("unlink", async (removedFile) => {
2516
2634
  const pathFromRoot = configManager.printContentRelativePath(removedFile);
2517
- await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2518
- if (searchIndexer) {
2519
- await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2520
- }
2635
+ await databaseLock(async () => {
2636
+ await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2637
+ if (searchIndexer) {
2638
+ await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2639
+ }
2640
+ });
2521
2641
  });
2522
2642
  }
2523
- watchQueries(configManager, callback) {
2524
- let ready = false;
2525
- import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("ready", () => {
2526
- ready = true;
2527
- }).on("add", async (addedFile) => {
2528
- await callback();
2529
- }).on("change", async (changedFile) => {
2530
- await callback();
2531
- }).on("unlink", async (removedFile) => {
2532
- await callback();
2533
- });
2643
+ watchQueries(configManager, databaseLock, callback) {
2644
+ const executeCallback = async (_) => {
2645
+ await databaseLock(async () => {
2646
+ await callback();
2647
+ });
2648
+ };
2649
+ import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("add", executeCallback).on("change", executeCallback).on("unlink", executeCallback);
2534
2650
  }
2535
2651
  };
2536
2652
  DevCommand.paths = [["dev"], ["server:start"]];
2653
+ // Prevent indexes and reads occurring at once
2537
2654
  DevCommand.usage = import_clipanion2.Command.Usage({
2538
2655
  category: `Commands`,
2539
2656
  description: `Builds Tina and starts the dev server`,
@@ -2723,6 +2840,9 @@ var BuildCommand = class extends BaseCommand {
2723
2840
  this.tinaGraphQLVersion = import_clipanion3.Option.String("--tina-graphql-version", {
2724
2841
  description: "Specify the version of @tinacms/graphql to use (defaults to latest)"
2725
2842
  });
2843
+ /**
2844
+ * 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
2845
+ */
2726
2846
  this.skipCloudChecks = import_clipanion3.Option.Boolean("--skip-cloud-checks", false, {
2727
2847
  description: "Skips checking the provided cloud config."
2728
2848
  });
@@ -2828,7 +2948,8 @@ ${dangerText(e.message)}
2828
2948
  database,
2829
2949
  null,
2830
2950
  apiURL,
2831
- true
2951
+ true,
2952
+ (lockedFn) => lockedFn()
2832
2953
  );
2833
2954
  await server.listen(Number(this.port));
2834
2955
  console.log("server listening on port", this.port);
@@ -3463,6 +3584,7 @@ var auditDocuments = async (args) => {
3463
3584
  logger.error(import_chalk5.default.red(err.message));
3464
3585
  if (err.originalError.originalError) {
3465
3586
  logger.error(
3587
+ // @ts-ignore FIXME: this doesn't seem right
3466
3588
  import_chalk5.default.red(` ${err.originalError.originalError.message}`)
3467
3589
  );
3468
3590
  }
@@ -3668,7 +3790,9 @@ var detectEnvironment = async ({
3668
3790
  const usingSrc = import_fs_extra8.default.pathExistsSync(import_path7.default.join(baseDir, "src")) && (import_fs_extra8.default.pathExistsSync(import_path7.default.join(baseDir, "src", "app")) || import_fs_extra8.default.pathExistsSync(import_path7.default.join(baseDir, "src", "pages")));
3669
3791
  const tinaFolder = import_path7.default.join(baseDir, "tina");
3670
3792
  const tinaConfigExists = Boolean(
3671
- await import_fs_extra8.default.pathExists(tinaFolder) && (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3793
+ // Does the tina folder exist?
3794
+ await import_fs_extra8.default.pathExists(tinaFolder) && // Does the tina folder contain a config file?
3795
+ (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3672
3796
  );
3673
3797
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
3674
3798
  Boolean
@@ -3903,6 +4027,7 @@ var supportedDatabaseAdapters = {
3903
4027
  {
3904
4028
  from: "mongodb",
3905
4029
  imported: [],
4030
+ // not explicitly imported
3906
4031
  packageName: "mongodb"
3907
4032
  }
3908
4033
  ]
@@ -3975,6 +4100,10 @@ var chooseDatabaseAdapter = async ({
3975
4100
  title: "MongoDB",
3976
4101
  value: "mongodb"
3977
4102
  }
4103
+ // {
4104
+ // title: "I'll create my own database adapter",
4105
+ // value: 'other',
4106
+ // },
3978
4107
  ]
3979
4108
  }
3980
4109
  ]);
@@ -4252,6 +4381,7 @@ async function configure(env, opts) {
4252
4381
  packageManager,
4253
4382
  forestryMigrate: false,
4254
4383
  isLocalEnvVarName: "TINA_PUBLIC_IS_LOCAL",
4384
+ // TODO: give this a better default
4255
4385
  typescript: false
4256
4386
  };
4257
4387
  if (config2.framework.name === "next") {
@@ -4355,15 +4485,25 @@ var import_js_yaml = __toESM(require("js-yaml"));
4355
4485
  var import_zod = __toESM(require("zod"));
4356
4486
 
4357
4487
  // src/cmds/forestry-migrate/util/errorSingleton.ts
4358
- var ErrorSingleton = class {
4488
+ var ErrorSingleton = class _ErrorSingleton {
4489
+ /**
4490
+ * The Singleton's constructor should always be private to prevent direct
4491
+ * construction calls with the `new` operator.
4492
+ */
4359
4493
  constructor() {
4360
4494
  }
4495
+ /**
4496
+ * The static method that controls the access to the singleton instance.
4497
+ *
4498
+ * This implementation let you subclass the Singleton class while keeping
4499
+ * just one instance of each subclass around.
4500
+ */
4361
4501
  static getInstance() {
4362
- if (!ErrorSingleton.instance) {
4363
- ErrorSingleton.instance = new ErrorSingleton();
4364
- ErrorSingleton.instance.collectionNameErrors = [];
4502
+ if (!_ErrorSingleton.instance) {
4503
+ _ErrorSingleton.instance = new _ErrorSingleton();
4504
+ _ErrorSingleton.instance.collectionNameErrors = [];
4365
4505
  }
4366
- return ErrorSingleton.instance;
4506
+ return _ErrorSingleton.instance;
4367
4507
  }
4368
4508
  addErrorName(error) {
4369
4509
  this.collectionNameErrors.push(error);
@@ -4406,8 +4546,7 @@ var makeFieldsWithInternalCode = ({
4406
4546
  if (hasBody) {
4407
4547
  return [bodyField, `__TINA_INTERNAL__:::...${field}():::`];
4408
4548
  } else {
4409
- if (spread)
4410
- return `__TINA_INTERNAL__:::...${field}():::`;
4549
+ if (spread) return `__TINA_INTERNAL__:::...${field}():::`;
4411
4550
  return `__TINA_INTERNAL__:::${field}():::`;
4412
4551
  }
4413
4552
  };
@@ -4491,6 +4630,7 @@ var forestryConfigSchema = import_zod.default.object({
4491
4630
  )
4492
4631
  });
4493
4632
  var forestryFieldWithoutField = import_zod.default.object({
4633
+ // TODO: maybe better type this?
4494
4634
  type: import_zod.default.union([
4495
4635
  import_zod.default.literal("text"),
4496
4636
  import_zod.default.literal("datetime"),
@@ -4514,6 +4654,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4514
4654
  default: import_zod.default.any().optional(),
4515
4655
  template: import_zod.default.string().optional(),
4516
4656
  config: import_zod.default.object({
4657
+ // min and max are used for lists
4517
4658
  min: import_zod.default.number().optional().nullable(),
4518
4659
  max: import_zod.default.number().optional().nullable(),
4519
4660
  required: import_zod.default.boolean().optional().nullable(),
@@ -4527,6 +4668,7 @@ var forestryFieldWithoutField = import_zod.default.object({
4527
4668
  import_zod.default.literal("pages"),
4528
4669
  import_zod.default.literal("documents"),
4529
4670
  import_zod.default.literal("simple"),
4671
+ // TODO: I want to ignore this key if its invalid
4530
4672
  import_zod.default.string()
4531
4673
  ]).optional().nullable(),
4532
4674
  section: import_zod.default.string().optional().nullable()
@@ -4562,6 +4704,7 @@ var transformForestryFieldsToTinaFields = ({
4562
4704
  }
4563
4705
  let field;
4564
4706
  switch (forestryField2.type) {
4707
+ // Single filed types
4565
4708
  case "text":
4566
4709
  field = {
4567
4710
  type: "string",
@@ -4641,6 +4784,7 @@ var transformForestryFieldsToTinaFields = ({
4641
4784
  );
4642
4785
  }
4643
4786
  break;
4787
+ // List Types
4644
4788
  case "list":
4645
4789
  field = {
4646
4790
  type: "string",
@@ -4663,6 +4807,7 @@ var transformForestryFieldsToTinaFields = ({
4663
4807
  }
4664
4808
  };
4665
4809
  break;
4810
+ // Object (Group) types
4666
4811
  case "field_group":
4667
4812
  field = {
4668
4813
  type: "object",
@@ -4703,6 +4848,7 @@ var transformForestryFieldsToTinaFields = ({
4703
4848
  });
4704
4849
  const fieldsString = stringifyLabelWithField(template2.label);
4705
4850
  const t = {
4851
+ // @ts-ignore
4706
4852
  fields: makeFieldsWithInternalCode({
4707
4853
  hasBody: false,
4708
4854
  field: fieldsString
@@ -4740,6 +4886,7 @@ var transformForestryFieldsToTinaFields = ({
4740
4886
  spread: true
4741
4887
  });
4742
4888
  tinaFields.push(
4889
+ // @ts-ignore
4743
4890
  field2
4744
4891
  );
4745
4892
  break;
@@ -4799,6 +4946,7 @@ var parseSections = ({ val }) => {
4799
4946
 
4800
4947
  // src/cmds/forestry-migrate/index.ts
4801
4948
  var BODY_FIELD = {
4949
+ // This is the body field
4802
4950
  type: "rich-text",
4803
4951
  name: "body",
4804
4952
  label: "Body of Document",
@@ -4857,8 +5005,7 @@ var generateAllTemplates = async ({
4857
5005
  };
4858
5006
  var generateCollectionFromForestrySection = (args) => {
4859
5007
  const { section, templateMap } = args;
4860
- if (section.read_only)
4861
- return;
5008
+ if (section.read_only) return;
4862
5009
  let format3 = "md";
4863
5010
  if (section.new_doc_ext) {
4864
5011
  const ext = checkExt(section.new_doc_ext);
@@ -4925,12 +5072,14 @@ var generateCollectionFromForestrySection = (args) => {
4925
5072
  if (((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1) {
4926
5073
  c = {
4927
5074
  ...baseCollection,
5075
+ // @ts-expect-error
4928
5076
  templates: forestryTemplates.map((tem) => {
4929
5077
  const currentTemplate = templateMap.get(tem);
4930
5078
  const fieldsString = stringifyLabelWithField(
4931
5079
  currentTemplate.templateObj.label
4932
5080
  );
4933
5081
  return {
5082
+ // fields: [BODY_FIELD],
4934
5083
  fields: makeFieldsWithInternalCode({
4935
5084
  hasBody,
4936
5085
  field: fieldsString,
@@ -4948,6 +5097,8 @@ var generateCollectionFromForestrySection = (args) => {
4948
5097
  const fieldsString = stringifyLabelWithField(template.templateObj.label);
4949
5098
  c = {
4950
5099
  ...baseCollection,
5100
+ // fields: [BODY_FIELD],
5101
+ // @ts-expect-error
4951
5102
  fields: makeFieldsWithInternalCode({
4952
5103
  field: fieldsString,
4953
5104
  hasBody,
@@ -5695,6 +5846,7 @@ var makeImportsVisitor = (sourceFile, importMap) => (ctx) => (node) => {
5695
5846
  ) : [];
5696
5847
  const newImports = [
5697
5848
  .../* @__PURE__ */ new Set([
5849
+ // we use Set to remove duplicates
5698
5850
  ...existingImports,
5699
5851
  ...imports
5700
5852
  ])
@@ -5849,6 +6001,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5849
6001
  );
5850
6002
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5851
6003
  const importMap = {
6004
+ // iterate over configImports and add them to the import map
5852
6005
  ...configImports.reduce((acc, { from, imported }) => {
5853
6006
  acc[from] = imported;
5854
6007
  return acc;
@@ -6023,7 +6176,13 @@ async function apply({
6023
6176
  config: config2
6024
6177
  });
6025
6178
  }
6026
- if (env.tinaConfigExists && params.isBackendInit && config2.hosting === "self-host" && (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud") {
6179
+ if (
6180
+ // if the config was just generated we do not need to update the config file because it will be generated correctly
6181
+ env.tinaConfigExists && // Are we running tinacms init backend
6182
+ params.isBackendInit && // Do the user choose the 'self-host' option
6183
+ config2.hosting === "self-host" && // the user did not choose the 'tina-cloud' auth provider
6184
+ (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud"
6185
+ ) {
6027
6186
  await addSelfHostedTinaAuthToConfig(config2, env.generatedFiles["config"]);
6028
6187
  }
6029
6188
  logNextSteps({
@@ -6316,6 +6475,7 @@ var other = ({ packageManager }) => {
6316
6475
  const packageManagers = {
6317
6476
  pnpm: `pnpm`,
6318
6477
  npm: `npx`,
6478
+ // npx is the way to run executables that aren't in your "scripts"
6319
6479
  yarn: `yarn`
6320
6480
  };
6321
6481
  return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
@@ -6328,6 +6488,7 @@ var frameworkDevCmds = {
6328
6488
  const packageManagers = {
6329
6489
  pnpm: `pnpm`,
6330
6490
  npm: `npm run`,
6491
+ // npx is the way to run executables that aren't in your "scripts"
6331
6492
  yarn: `yarn`
6332
6493
  };
6333
6494
  return `${packageManagers[packageManager]} dev`;
@@ -6584,6 +6745,4 @@ cli.register(SearchIndexCommand);
6584
6745
  cli.register(import_clipanion8.Builtins.DefinitionsCommand);
6585
6746
  cli.register(import_clipanion8.Builtins.HelpCommand);
6586
6747
  cli.register(import_clipanion8.Builtins.VersionCommand);
6587
- var src_default = cli;
6588
- // Annotate the CommonJS export names for ESM import in node:
6589
- 0 && (module.exports = {});
6748
+ var index_default = cli;
@@ -1,3 +1,4 @@
1
+ import AsyncLock from 'async-lock';
1
2
  import { Database } from '@tinacms/graphql';
2
3
  import { ConfigManager } from '../../config-manager';
3
4
  import { BaseCommand } from '../baseCommands';
@@ -7,10 +8,12 @@ export declare class DevCommand extends BaseCommand {
7
8
  watchFolders: string;
8
9
  noWatch: boolean;
9
10
  outputSearchIndexPath: string;
11
+ noServer: boolean;
12
+ indexingLock: AsyncLock;
10
13
  static usage: import("clipanion").Usage;
11
14
  catch(error: any): Promise<void>;
12
15
  logDeprecationWarnings(): void;
13
16
  execute(): Promise<number | void>;
14
- watchContentFiles(configManager: ConfigManager, database: Database, searchIndexer?: SearchIndexer): void;
15
- watchQueries(configManager: ConfigManager, callback: () => Promise<string>): void;
17
+ watchContentFiles(configManager: ConfigManager, database: Database, databaseLock: (fn: () => Promise<void>) => Promise<void>, searchIndexer?: SearchIndexer): void;
18
+ watchQueries(configManager: ConfigManager, databaseLock: (fn: () => Promise<void>) => Promise<void>, callback: () => Promise<string>): void;
16
19
  }
@@ -1,3 +1,3 @@
1
1
  import type { Database } from '@tinacms/graphql';
2
2
  import { ConfigManager } from '../../../config-manager';
3
- export declare const createDevServer: (configManager: ConfigManager, database: Database, searchIndex: any, apiURL: string, noWatch: boolean) => Promise<import("vite").ViteDevServer>;
3
+ export declare const createDevServer: (configManager: ConfigManager, database: Database, searchIndex: any, apiURL: string, noWatch: boolean, databaseLock: (fn: () => Promise<void>) => Promise<void>) => Promise<import("vite").ViteDevServer>;
@@ -7,11 +7,12 @@ import type { ConfigManager } from '../config-manager';
7
7
  export declare const transformTsxPlugin: ({ configManager: _configManager, }: {
8
8
  configManager: ConfigManager;
9
9
  }) => Plugin;
10
- export declare const devServerEndPointsPlugin: ({ configManager, apiURL, database, searchIndex, }: {
10
+ export declare const devServerEndPointsPlugin: ({ configManager, apiURL, database, searchIndex, databaseLock, }: {
11
11
  apiURL: string;
12
12
  database: Database;
13
13
  configManager: ConfigManager;
14
14
  searchIndex: any;
15
+ databaseLock: (fn: () => Promise<void>) => Promise<void>;
15
16
  }) => Plugin;
16
17
  export interface ViteSvgrOptions {
17
18
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/cli",
3
- "version": "0.0.0-d888ad0-20241223044700",
3
+ "version": "0.0.0-db8aa8e-20250228034006",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
6
6
  "files": [
@@ -37,24 +37,25 @@
37
37
  "@types/prompts": "^2.4.9",
38
38
  "@types/yup": "^0.32.0",
39
39
  "jest": "^29.7.0",
40
- "@tinacms/scripts": "1.3.1"
40
+ "@tinacms/scripts": "0.0.0-db8aa8e-20250228034006"
41
41
  },
42
42
  "dependencies": {
43
43
  "@graphql-codegen/core": "^2.6.8",
44
44
  "@graphql-codegen/plugin-helpers": "latest",
45
- "@graphql-codegen/typescript": "^4.1.1",
46
- "@graphql-codegen/typescript-operations": "^4.3.1",
45
+ "@graphql-codegen/typescript": "^4.1.3",
46
+ "@graphql-codegen/typescript-operations": "^4.4.1",
47
47
  "@graphql-codegen/visitor-plugin-common": "^4.1.2",
48
48
  "@graphql-inspector/core": "^4.2.2",
49
49
  "@graphql-tools/graphql-file-loader": "^7.5.17",
50
50
  "@graphql-tools/load": "^7.8.14",
51
- "@rollup/pluginutils": "^5.1.3",
51
+ "@rollup/pluginutils": "^5.1.4",
52
52
  "@svgr/core": "8.1.0",
53
53
  "@tailwindcss/aspect-ratio": "^0.4.2",
54
54
  "@tailwindcss/container-queries": "^0.1.1",
55
- "@tailwindcss/typography": "^0.5.15",
55
+ "@tailwindcss/typography": "^0.5.16",
56
56
  "@vitejs/plugin-react": "3.1.0",
57
57
  "altair-express-middleware": "^7.3.6",
58
+ "async-lock": "^1.4.1",
58
59
  "auto-bind": "^4.0.0",
59
60
  "body-parser": "^1.20.3",
60
61
  "busboy": "^1.6.0",
@@ -64,9 +65,9 @@
64
65
  "clipanion": "^3.2.1",
65
66
  "cors": "^2.8.5",
66
67
  "crypto-js": "^4.2.0",
67
- "dotenv": "^16.4.5",
68
- "esbuild": "^0.24.0",
69
- "fs-extra": "^11.2.0",
68
+ "dotenv": "^16.4.7",
69
+ "esbuild": "^0.24.2",
70
+ "fs-extra": "^11.3.0",
70
71
  "graphql": "15.8.0",
71
72
  "js-yaml": "^4.1.0",
72
73
  "log4js": "^6.9.1",
@@ -77,19 +78,21 @@
77
78
  "prettier": "^2.8.8",
78
79
  "progress": "^2.0.3",
79
80
  "prompts": "^2.4.2",
80
- "readable-stream": "^4.5.2",
81
- "tailwindcss": "^3.4.15",
81
+ "readable-stream": "^4.7.0",
82
+ "tailwindcss": "^3.4.17",
82
83
  "typanion": "3.13.0",
83
- "typescript": "^5.6.3",
84
- "vite": "^4.5.5",
85
- "yup": "^1.4.0",
86
- "zod": "^3.23.8",
87
- "@tinacms/app": "2.1.14",
88
- "@tinacms/metrics": "1.0.8",
89
- "@tinacms/schema-tools": "1.6.9",
90
- "@tinacms/graphql": "1.5.9",
91
- "@tinacms/search": "1.0.36",
92
- "tinacms": "2.5.2"
84
+ "typescript": "^5.7.3",
85
+ "vite": "^4.5.9",
86
+ "yup": "^1.6.1",
87
+ "zod": "^3.24.2",
88
+ "react": "^18.3.1",
89
+ "react-dom": "^18.3.1",
90
+ "@tinacms/app": "0.0.0-db8aa8e-20250228034006",
91
+ "@tinacms/graphql": "0.0.0-db8aa8e-20250228034006",
92
+ "@tinacms/metrics": "1.0.9",
93
+ "@tinacms/schema-tools": "0.0.0-db8aa8e-20250228034006",
94
+ "tinacms": "0.0.0-db8aa8e-20250228034006",
95
+ "@tinacms/search": "0.0.0-db8aa8e-20250228034006"
93
96
  },
94
97
  "publishConfig": {
95
98
  "registry": "https://registry.npmjs.org"