@tinacms/cli 2.5.6 → 2.6.0

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
@@ -2,17 +2,17 @@
2
2
  import { Cli, Builtins } from "clipanion";
3
3
 
4
4
  // package.json
5
- var version = "2.5.6";
5
+ var version = "2.6.0";
6
6
 
7
7
  // src/next/commands/dev-command/index.ts
8
- import path10 from "path";
8
+ import path12 from "path";
9
9
  import { FilesystemBridge as FilesystemBridge2, buildSchema } from "@tinacms/graphql";
10
10
  import { Telemetry } from "@tinacms/metrics";
11
11
  import { LocalSearchIndexClient, SearchIndexer } from "@tinacms/search";
12
- import AsyncLock from "async-lock";
13
12
  import chokidar from "chokidar";
14
13
  import { Command as Command2, Option as Option2 } from "clipanion";
15
- import fs9 from "fs-extra";
14
+ import fs10 from "fs-extra";
15
+ import { AsyncLock } from "tinacms/dist/client";
16
16
 
17
17
  // src/logger/index.ts
18
18
  import chalk from "chalk";
@@ -191,9 +191,12 @@ var titleText = chalk2.bgHex("d2f1f8").hex("ec4816");
191
191
  var CONFIRMATION_TEXT = chalk2.dim("enter to confirm");
192
192
 
193
193
  // src/next/codegen/index.ts
194
- import fs from "fs-extra";
195
194
  import path from "path";
195
+ import { mapUserFields } from "@tinacms/graphql";
196
+ import { transform } from "esbuild";
197
+ import fs from "fs-extra";
196
198
  import { buildASTSchema, printSchema as printSchema2 } from "graphql";
199
+ import normalizePath from "normalize-path";
197
200
 
198
201
  // src/next/codegen/codegen/index.ts
199
202
  import { parse, printSchema } from "graphql";
@@ -369,6 +372,9 @@ var plugin = (schema, documents, config2) => {
369
372
  };
370
373
 
371
374
  // src/next/codegen/codegen/index.ts
375
+ var reexportExact = (types) => `${types}
376
+ export type { Exact };
377
+ `;
372
378
  var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath = process.cwd(), apiURL) => {
373
379
  let docs = [];
374
380
  let fragDocs = [];
@@ -379,7 +385,11 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
379
385
  filename: process.cwd(),
380
386
  schema: parse(printSchema(schema)),
381
387
  documents: [...docs, ...fragDocs],
382
- config: {},
388
+ config: {
389
+ // The JSON scalar still carries rich-text bodies, which callers pass
390
+ // straight to <TinaMarkdown/>; codegen's `unknown` default won't assign.
391
+ defaultScalarType: "any"
392
+ },
383
393
  plugins: [
384
394
  { typescript: {} },
385
395
  { typescriptOperations: {} },
@@ -401,7 +411,7 @@ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath =
401
411
  AddGeneratedClient: AddGeneratedClient(apiURL)
402
412
  }
403
413
  });
404
- return res;
414
+ return reexportExact(res);
405
415
  };
406
416
  var loadGraphQLDocuments = async (globPath) => {
407
417
  let result = [];
@@ -423,11 +433,6 @@ var loadGraphQLDocuments = async (globPath) => {
423
433
  return result;
424
434
  };
425
435
 
426
- // src/next/codegen/index.ts
427
- import { transform } from "esbuild";
428
- import { mapUserFields } from "@tinacms/graphql";
429
- import normalizePath from "normalize-path";
430
-
431
436
  // src/next/codegen/stripSearchTokenFromConfig.ts
432
437
  function stripSearchTokenFromConfig(config2) {
433
438
  const cfg = config2;
@@ -1500,339 +1505,68 @@ async function createAndInitializeDatabase(configManager, datalayerPort, bridgeO
1500
1505
  return database;
1501
1506
  }
1502
1507
 
1503
- // src/next/commands/baseCommands.ts
1504
- import { Command, Option } from "clipanion";
1505
- import chalk4 from "chalk";
1506
-
1507
- // src/utils/start-subprocess.ts
1508
- import childProcess from "child_process";
1509
- var startSubprocess2 = async ({ command: command2 }) => {
1510
- if (typeof command2 === "string") {
1511
- const commands = command2.split(" ");
1512
- const firstCommand = commands[0];
1513
- const args = commands.slice(1) || [];
1514
- const ps = childProcess.spawn(firstCommand, args, {
1515
- stdio: "inherit",
1516
- shell: true
1517
- });
1518
- ps.on("error", (code) => {
1519
- logger.error(
1520
- dangerText(
1521
- `An error has occurred in the Next.js child process. Error message below`
1522
- )
1523
- );
1524
- logger.error(`name: ${code.name}
1525
- message: ${code.message}
1508
+ // src/next/vite/index.ts
1509
+ import path7 from "node:path";
1510
+ import react from "@vitejs/plugin-react";
1511
+ import fs5 from "fs-extra";
1512
+ import normalizePath3 from "normalize-path";
1526
1513
 
1527
- stack: ${code.stack || "No stack was provided"}`);
1528
- });
1529
- ps.on("close", (code) => {
1530
- logger.info(`child process exited with code ${code}`);
1531
- process.exit(code);
1532
- });
1533
- return ps;
1514
+ // src/next/vite/cors.ts
1515
+ var LOCALHOST_RE = /^https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/;
1516
+ var PRIVATE_NETWORK_RE = /^https?:\/\/(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})(:\d+)?$/;
1517
+ function expandOrigins(raw) {
1518
+ const hasPrivate = raw.some((o) => o === "private");
1519
+ const filtered = raw.filter((o) => o !== "private");
1520
+ return hasPrivate ? [...filtered, PRIVATE_NETWORK_RE] : filtered;
1521
+ }
1522
+ function isOriginAllowed(origin, allowedOrigins = []) {
1523
+ if (!origin) {
1524
+ return true;
1534
1525
  }
1535
- };
1536
-
1537
- // src/next/commands/baseCommands.ts
1538
- import { getChangedFiles, getSha, shaExists } from "@tinacms/graphql";
1539
- import fs5 from "fs-extra";
1540
- var BaseCommand = class extends Command {
1541
- experimentalDataLayer = Option.Boolean("--experimentalData", {
1542
- description: "DEPRECATED - Build the server with additional data querying capabilities"
1543
- });
1544
- isomorphicGitBridge = Option.Boolean("--isomorphicGitBridge", {
1545
- description: "DEPRECATED - Enable Isomorphic Git Bridge Implementation"
1546
- });
1547
- port = Option.String("-p,--port", "4001", {
1548
- description: "Specify a port to run the server on. (default 4001)"
1549
- });
1550
- datalayerPort = Option.String("--datalayer-port", "9000", {
1551
- description: "Specify a port to run the datalayer server on. (default 9000)"
1552
- });
1553
- subCommand = Option.String("-c,--command", {
1554
- description: "The sub-command to run"
1555
- });
1556
- rootPath = Option.String("--rootPath", {
1557
- description: "Specify the root directory to run the CLI from (defaults to current working directory)"
1558
- });
1559
- verbose = Option.Boolean("-v,--verbose", false, {
1560
- description: "increase verbosity of logged output"
1561
- });
1562
- noSDK = Option.Boolean("--noSDK", false, {
1563
- description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1564
- });
1565
- noTelemetry = Option.Boolean("--noTelemetry", false, {
1566
- description: "Disable anonymous telemetry that is collected"
1567
- });
1568
- async startSubCommand() {
1569
- let subProc;
1570
- if (this.subCommand) {
1571
- subProc = await startSubprocess2({ command: this.subCommand });
1572
- logger.info(
1573
- `Running web application with command: ${chalk4.cyan(this.subCommand)}`
1574
- );
1575
- }
1576
- function exitHandler(options, exitCode) {
1577
- if (subProc) {
1578
- subProc.kill();
1579
- }
1580
- process.exit();
1581
- }
1582
- process.on("exit", exitHandler);
1583
- process.on("SIGINT", exitHandler);
1584
- process.on("SIGUSR1", exitHandler);
1585
- process.on("SIGUSR2", exitHandler);
1586
- process.on("uncaughtException", (error) => {
1587
- logger.error(`Uncaught exception ${error.name}`);
1588
- console.error(error);
1589
- });
1526
+ if (LOCALHOST_RE.test(origin)) {
1527
+ return true;
1590
1528
  }
1591
- logDeprecationWarnings() {
1592
- if (this.isomorphicGitBridge) {
1593
- logger.warn("--isomorphicGitBridge has been deprecated");
1594
- }
1595
- if (this.experimentalDataLayer) {
1596
- logger.warn(
1597
- "--experimentalDataLayer has been deprecated, the data layer is now built-in automatically"
1598
- );
1599
- }
1600
- if (this.noSDK) {
1601
- logger.warn(
1602
- "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
1603
- );
1529
+ for (const allowed of expandOrigins(allowedOrigins)) {
1530
+ if (typeof allowed === "string") {
1531
+ if (allowed === origin) {
1532
+ return true;
1533
+ }
1534
+ } else {
1535
+ allowed.lastIndex = 0;
1536
+ if (allowed.test(origin)) {
1537
+ return true;
1538
+ }
1604
1539
  }
1605
1540
  }
1606
- async indexContentWithSpinner({
1607
- database,
1608
- graphQLSchema,
1609
- tinaSchema,
1610
- configManager,
1611
- partialReindex,
1612
- text
1613
- }) {
1614
- const textToUse = text || "Indexing local files";
1615
- const warnings = [];
1616
- await spin({
1617
- waitFor: async () => {
1618
- const rootPath = configManager.rootPath;
1619
- let sha;
1620
- try {
1621
- sha = await getSha({ fs: fs5, dir: rootPath });
1622
- } catch (e) {
1623
- if (partialReindex) {
1624
- console.error(
1625
- "Failed to get sha. NOTE: `--partial-reindex` only supported for git repositories"
1626
- );
1627
- throw e;
1628
- }
1629
- }
1630
- const lastSha = await database.getMetadata("lastSha");
1631
- const exists = lastSha && await shaExists({ fs: fs5, dir: rootPath, sha: lastSha });
1632
- let res;
1633
- if (partialReindex && lastSha && exists && sha) {
1634
- const pathFilter = {};
1635
- if (configManager.isUsingLegacyFolder) {
1636
- pathFilter[".tina/__generated__/_schema.json"] = {};
1637
- } else {
1638
- pathFilter["tina/tina-lock.json"] = {};
1639
- }
1640
- for (const collection of tinaSchema.getCollections()) {
1641
- pathFilter[collection.path] = {
1642
- matches: collection.match?.exclude || collection.match?.include ? tinaSchema.getMatches({ collection }) : void 0
1643
- };
1644
- }
1645
- const { added, modified, deleted } = await getChangedFiles({
1646
- fs: fs5,
1647
- dir: rootPath,
1648
- from: lastSha,
1649
- to: sha,
1650
- pathFilter
1651
- });
1652
- const tinaPathUpdates = modified.filter(
1653
- (path20) => path20.startsWith(".tina/__generated__/_schema.json") || path20.startsWith("tina/tina-lock.json")
1654
- );
1655
- if (tinaPathUpdates.length > 0) {
1656
- res = await database.indexContent({
1657
- graphQLSchema,
1658
- tinaSchema
1659
- });
1660
- } else {
1661
- if (added.length > 0 || modified.length > 0) {
1662
- await database.indexContentByPaths([...added, ...modified]);
1663
- }
1664
- if (deleted.length > 0) {
1665
- await database.deleteContentByPaths(deleted);
1666
- }
1667
- }
1541
+ return false;
1542
+ }
1543
+ function buildCorsOriginCheck(allowedOrigins = []) {
1544
+ return (origin, callback) => {
1545
+ callback(null, isOriginAllowed(origin, allowedOrigins));
1546
+ };
1547
+ }
1548
+
1549
+ // src/next/vite/filterPublicEnv.ts
1550
+ function filterPublicEnv(env = process.env) {
1551
+ const publicEnv = {};
1552
+ Object.keys(env).forEach((key) => {
1553
+ if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
1554
+ try {
1555
+ const value = env[key];
1556
+ if (typeof value === "string") {
1557
+ publicEnv[key] = value;
1668
1558
  } else {
1669
- res = await database.indexContent({
1670
- graphQLSchema,
1671
- tinaSchema
1672
- });
1673
- }
1674
- if (sha) {
1675
- await database.setMetadata("lastSha", sha);
1676
- }
1677
- if (res?.warnings) {
1678
- warnings.push(...res.warnings);
1559
+ publicEnv[key] = JSON.stringify(value);
1679
1560
  }
1680
- },
1681
- text: textToUse
1682
- });
1683
- if (warnings.length > 0) {
1684
- logger.warn(`Indexing completed with ${warnings.length} warning(s)`);
1685
- warnings.forEach((warning) => {
1686
- logger.warn(warnText(`${warning}`));
1687
- });
1561
+ } catch (error) {
1562
+ console.warn(
1563
+ `Could not stringify public env process.env.${key} env variable`
1564
+ );
1565
+ console.warn(error);
1566
+ }
1688
1567
  }
1689
- }
1690
- };
1691
-
1692
- // src/next/commands/dev-command/html.ts
1693
- var errorHTML = `<style type="text/css">
1694
- #no-assets-placeholder body {
1695
- font-family: sans-serif;
1696
- font-size: 16px;
1697
- line-height: 1.4;
1698
- color: #333;
1699
- background-color: #f5f5f5;
1700
- }
1701
- #no-assets-placeholder {
1702
- max-width: 600px;
1703
- margin: 0 auto;
1704
- padding: 40px;
1705
- text-align: center;
1706
- background-color: #fff;
1707
- box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
1708
- }
1709
- #no-assets-placeholder h1 {
1710
- font-size: 24px;
1711
- margin-bottom: 20px;
1712
- }
1713
- #no-assets-placeholder p {
1714
- margin-bottom: 10px;
1715
- }
1716
- #no-assets-placeholder a {
1717
- color: #0077cc;
1718
- text-decoration: none;
1719
- }
1720
- #no-assets-placeholder a:hover {
1721
- text-decoration: underline;
1722
- }
1723
- </style>
1724
- <div id="no-assets-placeholder">
1725
- <h1>Failed loading TinaCMS assets</h1>
1726
- <p>
1727
- Your TinaCMS configuration may be misconfigured, and we could not load
1728
- the assets for this page.
1729
- </p>
1730
- <p>
1731
- Please visit <a href="https://tina.io/docs/r/FAQ/#13-how-do-i-resolve-failed-loading-tinacms-assets-error">this doc</a> for help.
1732
- </p>
1733
- </div>
1734
- </div>`.trim().replace(/[\r\n\s]+/g, " ");
1735
- var devHTML = (port) => `<!DOCTYPE html>
1736
- <html lang="en">
1737
- <head>
1738
- <meta charset="UTF-8" />
1739
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1740
- <title>TinaCMS</title>
1741
- </head>
1742
-
1743
- <!-- if development -->
1744
- <script type="module">
1745
- import RefreshRuntime from 'http://localhost:${port}/@react-refresh'
1746
- RefreshRuntime.injectIntoGlobalHook(window)
1747
- window.$RefreshReg$ = () => {}
1748
- window.$RefreshSig$ = () => (type) => type
1749
- window.__vite_plugin_react_preamble_installed__ = true
1750
- </script>
1751
- <script type="module" src="http://localhost:${port}/@vite/client"></script>
1752
- <script>
1753
- function handleLoadError() {
1754
- // Assets have failed to load
1755
- document.getElementById('root').innerHTML = '${errorHTML}';
1756
- }
1757
- </script>
1758
- <script
1759
- type="module"
1760
- src="http://localhost:${port}/src/main.tsx"
1761
- onerror="handleLoadError()"
1762
- ></script>
1763
- <body class="tina-tailwind">
1764
- <div id="root"></div>
1765
- </body>
1766
- </html>`;
1767
-
1768
- // src/next/commands/dev-command/server/index.ts
1769
- import { createServer as createViteServer } from "vite";
1770
-
1771
- // src/next/vite/index.ts
1772
- import path7 from "node:path";
1773
- import react from "@vitejs/plugin-react";
1774
- import fs6 from "fs-extra";
1775
- import normalizePath3 from "normalize-path";
1776
- import {
1777
- splitVendorChunkPlugin
1778
- } from "vite";
1779
-
1780
- // src/next/vite/cors.ts
1781
- var LOCALHOST_RE = /^https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/;
1782
- var PRIVATE_NETWORK_RE = /^https?:\/\/(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})(:\d+)?$/;
1783
- function expandOrigins(raw) {
1784
- const hasPrivate = raw.some((o) => o === "private");
1785
- const filtered = raw.filter((o) => o !== "private");
1786
- return hasPrivate ? [...filtered, PRIVATE_NETWORK_RE] : filtered;
1787
- }
1788
- function isOriginAllowed(origin, allowedOrigins = []) {
1789
- if (!origin) {
1790
- return true;
1791
- }
1792
- if (LOCALHOST_RE.test(origin)) {
1793
- return true;
1794
- }
1795
- for (const allowed of expandOrigins(allowedOrigins)) {
1796
- if (typeof allowed === "string") {
1797
- if (allowed === origin) {
1798
- return true;
1799
- }
1800
- } else {
1801
- allowed.lastIndex = 0;
1802
- if (allowed.test(origin)) {
1803
- return true;
1804
- }
1805
- }
1806
- }
1807
- return false;
1808
- }
1809
- function buildCorsOriginCheck(allowedOrigins = []) {
1810
- return (origin, callback) => {
1811
- callback(null, isOriginAllowed(origin, allowedOrigins));
1812
- };
1813
- }
1814
-
1815
- // src/next/vite/filterPublicEnv.ts
1816
- function filterPublicEnv(env = process.env) {
1817
- const publicEnv = {};
1818
- Object.keys(env).forEach((key) => {
1819
- if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
1820
- try {
1821
- const value = env[key];
1822
- if (typeof value === "string") {
1823
- publicEnv[key] = value;
1824
- } else {
1825
- publicEnv[key] = JSON.stringify(value);
1826
- }
1827
- } catch (error) {
1828
- console.warn(
1829
- `Could not stringify public env process.env.${key} env variable`
1830
- );
1831
- console.warn(error);
1832
- }
1833
- }
1834
- });
1835
- return publicEnv;
1568
+ });
1569
+ return publicEnv;
1836
1570
  }
1837
1571
 
1838
1572
  // src/next/vite/tailwind.ts
@@ -2120,15 +1854,15 @@ async function listFilesRecursively({
2120
1854
  config2.publicFolder,
2121
1855
  directoryPath
2122
1856
  );
2123
- const exists = await fs6.pathExists(fullDirectoryPath);
1857
+ const exists = await fs5.pathExists(fullDirectoryPath);
2124
1858
  if (!exists) {
2125
1859
  return { "0": [] };
2126
1860
  }
2127
- const items = await fs6.readdir(fullDirectoryPath);
1861
+ const items = await fs5.readdir(fullDirectoryPath);
2128
1862
  const staticMediaItems = [];
2129
1863
  for (const item of items) {
2130
1864
  const itemPath = path7.join(fullDirectoryPath, item);
2131
- const stats = await fs6.promises.lstat(itemPath);
1865
+ const stats = await fs5.promises.lstat(itemPath);
2132
1866
  const staticMediaItem = {
2133
1867
  id: item,
2134
1868
  filename: item,
@@ -2160,6 +1894,12 @@ async function listFilesRecursively({
2160
1894
  }
2161
1895
  return chunkArrayIntoObject(staticMediaItems, 20);
2162
1896
  }
1897
+ var getBasePath = (configManager) => {
1898
+ const basePath = configManager.config.build.basePath;
1899
+ return `/${basePath ? `${normalizePath3(basePath)}/` : ""}${normalizePath3(
1900
+ configManager.config.build.outputFolder
1901
+ )}/`;
1902
+ };
2163
1903
  var createConfig = async ({
2164
1904
  configManager,
2165
1905
  apiURL,
@@ -2178,9 +1918,9 @@ var createConfig = async ({
2178
1918
  config: configManager.config.media.tina,
2179
1919
  roothPath: configManager.rootPath
2180
1920
  });
2181
- await fs6.outputFile(staticMediaPath, JSON.stringify(staticMedia, null, 2));
1921
+ await fs5.outputFile(staticMediaPath, JSON.stringify(staticMedia, null, 2));
2182
1922
  } else {
2183
- await fs6.outputFile(staticMediaPath, `[]`);
1923
+ await fs5.outputFile(staticMediaPath, `[]`);
2184
1924
  }
2185
1925
  const alias = {
2186
1926
  TINA_IMPORT: configManager.prebuildFilePath,
@@ -2200,17 +1940,11 @@ var createConfig = async ({
2200
1940
  } else {
2201
1941
  alias["CLIENT_IMPORT"] = configManager.isUsingTs() ? configManager.generatedTypesTSFilePath : configManager.generatedTypesJSFilePath;
2202
1942
  }
2203
- let basePath;
2204
- if (configManager.config.build.basePath) {
2205
- basePath = configManager.config.build.basePath;
2206
- }
2207
1943
  const fullVersion = configManager.getTinaGraphQLVersion();
2208
1944
  const version2 = `${fullVersion.major}.${fullVersion.minor}`;
2209
1945
  const config2 = {
2210
1946
  root: configManager.spaRootPath,
2211
- base: `/${basePath ? `${normalizePath3(basePath)}/` : ""}${normalizePath3(
2212
- configManager.config.build.outputFolder
2213
- )}/`,
1947
+ base: getBasePath(configManager),
2214
1948
  appType: "spa",
2215
1949
  resolve: {
2216
1950
  alias,
@@ -2227,11 +1961,13 @@ var createConfig = async ({
2227
1961
  * - `process.env.__NEXT_CROSS_ORIGIN`
2228
1962
  * - `process.env.__NEXT_I18N_SUPPORT`
2229
1963
  *
2230
- * Also, interestingly some of the advice for handling this doesn't work, references to replacing
2231
- * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
2232
- * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1964
+ * esbuild >=0.25 (bundled by vite >=6) requires define values to be
1965
+ * entity names or JS literals; the `new Object(...)` workaround is
1966
+ * rejected. A plain JSON object literal is safe: esbuild hoists it
1967
+ * into a variable before substituting, so the historical `{}.`
1968
+ * browser-syntax problem can't occur.
2233
1969
  */
2234
- "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1970
+ "process.env": JSON.stringify(publicEnv),
2235
1971
  // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
2236
1972
  "process.platform": `"${process.platform}"`,
2237
1973
  __API_URL__: `"${apiURL}"`,
@@ -2282,18 +2018,12 @@ var createConfig = async ({
2282
2018
  rollupOptions
2283
2019
  },
2284
2020
  plugins: [
2285
- /**
2286
- * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
2287
- * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
2288
- */
2289
2021
  react({
2290
2022
  babel: {
2291
2023
  // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
2292
2024
  compact: true
2293
- },
2294
- fastRefresh: false
2025
+ }
2295
2026
  }),
2296
- splitVendorChunkPlugin(),
2297
2027
  tinaTailwind(configManager.spaRootPath, configManager.prebuildFilePath),
2298
2028
  ...plugins
2299
2029
  ]
@@ -2301,9 +2031,446 @@ var createConfig = async ({
2301
2031
  return config2;
2302
2032
  };
2303
2033
 
2034
+ // src/next/commands/baseCommands.ts
2035
+ import { createRequire as createRequire3 } from "module";
2036
+ import path9 from "path";
2037
+ import { fileURLToPath } from "url";
2038
+ import chalk4 from "chalk";
2039
+ import { Command, Option } from "clipanion";
2040
+ import { getChangedFiles, getSha, shaExists } from "@tinacms/graphql";
2041
+ import fs7 from "fs-extra";
2042
+
2043
+ // src/utils/start-subprocess.ts
2044
+ import childProcess from "child_process";
2045
+ var startSubprocess2 = async ({ command: command2 }) => {
2046
+ if (typeof command2 === "string") {
2047
+ const commands = command2.split(" ");
2048
+ const firstCommand = commands[0];
2049
+ const args = commands.slice(1) || [];
2050
+ const ps = childProcess.spawn(firstCommand, args, {
2051
+ stdio: "inherit",
2052
+ shell: true
2053
+ });
2054
+ ps.on("error", (code) => {
2055
+ logger.error(
2056
+ dangerText(
2057
+ `An error has occurred in the Next.js child process. Error message below`
2058
+ )
2059
+ );
2060
+ logger.error(`name: ${code.name}
2061
+ message: ${code.message}
2062
+
2063
+ stack: ${code.stack || "No stack was provided"}`);
2064
+ });
2065
+ ps.on("close", (code) => {
2066
+ logger.info(`child process exited with code ${code}`);
2067
+ process.exit(code);
2068
+ });
2069
+ return ps;
2070
+ }
2071
+ };
2072
+
2073
+ // src/next/version-coherence.ts
2074
+ import path8 from "path";
2075
+ import fs6 from "fs-extra";
2076
+ var CORE_PACKAGES = [
2077
+ "tinacms",
2078
+ "@tinacms/graphql",
2079
+ "@tinacms/schema-tools"
2080
+ ];
2081
+ var PLAIN_SEMVER = /^(\d+)\.(\d+)\.(\d+)$/;
2082
+ var parsePlainVersion = (version2) => {
2083
+ const match = PLAIN_SEMVER.exec(version2);
2084
+ if (!match) {
2085
+ return void 0;
2086
+ }
2087
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
2088
+ };
2089
+ var compareVersions = (a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
2090
+ var satisfiesDeclaredRange = (version2, spec) => {
2091
+ const resolved = parsePlainVersion(version2);
2092
+ if (!resolved) {
2093
+ return void 0;
2094
+ }
2095
+ const isCaret = spec.startsWith("^");
2096
+ const base = parsePlainVersion(isCaret ? spec.slice(1) : spec);
2097
+ if (!base) {
2098
+ return void 0;
2099
+ }
2100
+ if (!isCaret) {
2101
+ return compareVersions(resolved, base) === 0;
2102
+ }
2103
+ if (resolved[0] !== base[0]) {
2104
+ return false;
2105
+ }
2106
+ if (base[0] === 0) {
2107
+ if (resolved[1] !== base[1]) {
2108
+ return false;
2109
+ }
2110
+ if (base[1] === 0 && resolved[2] !== base[2]) {
2111
+ return false;
2112
+ }
2113
+ }
2114
+ return compareVersions(resolved, base) >= 0;
2115
+ };
2116
+ var readPackageJson = (dir) => {
2117
+ try {
2118
+ return fs6.readJSONSync(path8.join(dir, "package.json"));
2119
+ } catch (_) {
2120
+ return void 0;
2121
+ }
2122
+ };
2123
+ var findPackageJsonAbove = (startDir, packageName) => {
2124
+ let dir = startDir;
2125
+ while (true) {
2126
+ const packageJson = readPackageJson(dir);
2127
+ if (packageJson?.name === packageName && packageJson.version) {
2128
+ return { dir, packageJson };
2129
+ }
2130
+ const parent = path8.dirname(dir);
2131
+ if (parent === dir) {
2132
+ return void 0;
2133
+ }
2134
+ dir = parent;
2135
+ }
2136
+ };
2137
+ var findInNodeModulesAbove = (packageName, fromDir) => {
2138
+ let dir = fromDir;
2139
+ while (true) {
2140
+ const candidate = path8.join(dir, "node_modules", ...packageName.split("/"));
2141
+ const packageJson = readPackageJson(candidate);
2142
+ if (packageJson?.name === packageName && packageJson.version) {
2143
+ return { version: packageJson.version, dir: candidate };
2144
+ }
2145
+ const parent = path8.dirname(dir);
2146
+ if (parent === dir) {
2147
+ return void 0;
2148
+ }
2149
+ dir = parent;
2150
+ }
2151
+ };
2152
+ var resolvePackage = (packageName, fromDir, resolveEntry) => {
2153
+ try {
2154
+ const entry = resolveEntry(packageName, fromDir);
2155
+ const found = findPackageJsonAbove(path8.dirname(entry), packageName);
2156
+ if (found?.packageJson.version) {
2157
+ return { version: found.packageJson.version, dir: found.dir };
2158
+ }
2159
+ } catch (_) {
2160
+ return findInNodeModulesAbove(packageName, fromDir);
2161
+ }
2162
+ return void 0;
2163
+ };
2164
+ var getVersionCoherenceWarnings = (input) => {
2165
+ const warnings = [];
2166
+ for (const name2 of CORE_PACKAGES) {
2167
+ const spec = input.cliDependencies[name2];
2168
+ const resolved = input.resolvedFromProject[name2];
2169
+ if (!spec || !resolved) {
2170
+ continue;
2171
+ }
2172
+ if (satisfiesDeclaredRange(resolved.version, spec) === false) {
2173
+ warnings.push(
2174
+ `${name2}@${resolved.version} is installed, but @tinacms/cli@${input.cliVersion} expects ${name2}@${spec}`
2175
+ );
2176
+ }
2177
+ }
2178
+ const fromProject = input.resolvedFromProject["tinacms"];
2179
+ const fromApp = input.tinacmsResolvedFromApp;
2180
+ if (fromProject && fromApp && fromProject.version !== fromApp.version) {
2181
+ warnings.push(
2182
+ `multiple copies of tinacms are installed: ${fromProject.version} (${fromProject.dir}) and ${fromApp.version} (${fromApp.dir}) - the admin UI bundles only one of them`
2183
+ );
2184
+ }
2185
+ return warnings;
2186
+ };
2187
+ var collectVersionCoherenceWarnings = ({
2188
+ rootPath,
2189
+ cliModuleDir,
2190
+ resolveEntry
2191
+ }) => {
2192
+ try {
2193
+ const cli2 = findPackageJsonAbove(cliModuleDir, "@tinacms/cli");
2194
+ if (!cli2?.packageJson.version) {
2195
+ return [];
2196
+ }
2197
+ const resolvedFromProject = {};
2198
+ for (const name2 of CORE_PACKAGES) {
2199
+ resolvedFromProject[name2] = resolvePackage(name2, rootPath, resolveEntry);
2200
+ }
2201
+ const app = resolvePackage("@tinacms/app", cliModuleDir, resolveEntry);
2202
+ const tinacmsResolvedFromApp = app ? resolvePackage("tinacms", app.dir, resolveEntry) : void 0;
2203
+ return getVersionCoherenceWarnings({
2204
+ cliVersion: cli2.packageJson.version,
2205
+ cliDependencies: cli2.packageJson.dependencies || {},
2206
+ resolvedFromProject,
2207
+ tinacmsResolvedFromApp
2208
+ });
2209
+ } catch (_) {
2210
+ return [];
2211
+ }
2212
+ };
2213
+
2214
+ // src/next/commands/baseCommands.ts
2215
+ var BaseCommand = class extends Command {
2216
+ experimentalDataLayer = Option.Boolean("--experimentalData", {
2217
+ description: "DEPRECATED - Build the server with additional data querying capabilities"
2218
+ });
2219
+ isomorphicGitBridge = Option.Boolean("--isomorphicGitBridge", {
2220
+ description: "DEPRECATED - Enable Isomorphic Git Bridge Implementation"
2221
+ });
2222
+ port = Option.String("-p,--port", "4001", {
2223
+ description: "Specify a port to run the server on. (default 4001)"
2224
+ });
2225
+ datalayerPort = Option.String("--datalayer-port", "9000", {
2226
+ description: "Specify a port to run the datalayer server on. (default 9000)"
2227
+ });
2228
+ subCommand = Option.String("-c,--command", {
2229
+ description: "The sub-command to run"
2230
+ });
2231
+ rootPath = Option.String("--rootPath", {
2232
+ description: "Specify the root directory to run the CLI from (defaults to current working directory)"
2233
+ });
2234
+ verbose = Option.Boolean("-v,--verbose", false, {
2235
+ description: "increase verbosity of logged output"
2236
+ });
2237
+ noSDK = Option.Boolean("--noSDK", false, {
2238
+ description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
2239
+ });
2240
+ noTelemetry = Option.Boolean("--noTelemetry", false, {
2241
+ description: "Disable anonymous telemetry that is collected"
2242
+ });
2243
+ async startSubCommand() {
2244
+ let subProc;
2245
+ if (this.subCommand) {
2246
+ subProc = await startSubprocess2({ command: this.subCommand });
2247
+ logger.info(
2248
+ `Running web application with command: ${chalk4.cyan(this.subCommand)}`
2249
+ );
2250
+ }
2251
+ function exitHandler(options, exitCode) {
2252
+ if (subProc) {
2253
+ subProc.kill();
2254
+ }
2255
+ process.exit();
2256
+ }
2257
+ process.on("exit", exitHandler);
2258
+ process.on("SIGINT", exitHandler);
2259
+ process.on("SIGUSR1", exitHandler);
2260
+ process.on("SIGUSR2", exitHandler);
2261
+ process.on("uncaughtException", (error) => {
2262
+ logger.error(`Uncaught exception ${error.name}`);
2263
+ console.error(error);
2264
+ });
2265
+ }
2266
+ warnOnVersionSkew(rootPath) {
2267
+ try {
2268
+ const moduleDir = path9.dirname(fileURLToPath(import.meta.url));
2269
+ const require2 = createRequire3(import.meta.url);
2270
+ const warnings = collectVersionCoherenceWarnings({
2271
+ rootPath,
2272
+ cliModuleDir: moduleDir,
2273
+ resolveEntry: (packageName, fromDir) => require2.resolve(packageName, { paths: [fromDir] })
2274
+ });
2275
+ if (warnings.length > 0) {
2276
+ logger.warn(
2277
+ warnText("WARN: TinaCMS package version mismatch detected:")
2278
+ );
2279
+ warnings.forEach((warning) => {
2280
+ logger.warn(warnText(` - ${warning}`));
2281
+ });
2282
+ logger.warn(
2283
+ warnText(
2284
+ "A held-back package (stale lockfile entry, partial upgrade, pnpm minimumReleaseAge) can leave the admin UI on an older tinacms where newer documented features are silently missing. Upgrade the packages above to matching releases and reinstall."
2285
+ )
2286
+ );
2287
+ }
2288
+ } catch (_) {
2289
+ }
2290
+ }
2291
+ logDeprecationWarnings() {
2292
+ if (this.isomorphicGitBridge) {
2293
+ logger.warn("--isomorphicGitBridge has been deprecated");
2294
+ }
2295
+ if (this.experimentalDataLayer) {
2296
+ logger.warn(
2297
+ "--experimentalDataLayer has been deprecated, the data layer is now built-in automatically"
2298
+ );
2299
+ }
2300
+ if (this.noSDK) {
2301
+ logger.warn(
2302
+ "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
2303
+ );
2304
+ }
2305
+ }
2306
+ async indexContentWithSpinner({
2307
+ database,
2308
+ graphQLSchema,
2309
+ tinaSchema,
2310
+ configManager,
2311
+ partialReindex,
2312
+ text
2313
+ }) {
2314
+ const textToUse = text || "Indexing local files";
2315
+ const warnings = [];
2316
+ await spin({
2317
+ waitFor: async () => {
2318
+ const rootPath = configManager.rootPath;
2319
+ let sha;
2320
+ try {
2321
+ sha = await getSha({ fs: fs7, dir: rootPath });
2322
+ } catch (e) {
2323
+ if (partialReindex) {
2324
+ console.error(
2325
+ "Failed to get sha. NOTE: `--partial-reindex` only supported for git repositories"
2326
+ );
2327
+ throw e;
2328
+ }
2329
+ }
2330
+ const lastSha = await database.getMetadata("lastSha");
2331
+ const exists = lastSha && await shaExists({ fs: fs7, dir: rootPath, sha: lastSha });
2332
+ let res;
2333
+ if (partialReindex && lastSha && exists && sha) {
2334
+ const pathFilter = {};
2335
+ if (configManager.isUsingLegacyFolder) {
2336
+ pathFilter[".tina/__generated__/_schema.json"] = {};
2337
+ } else {
2338
+ pathFilter["tina/tina-lock.json"] = {};
2339
+ }
2340
+ for (const collection of tinaSchema.getCollections()) {
2341
+ pathFilter[collection.path] = {
2342
+ matches: collection.match?.exclude || collection.match?.include ? tinaSchema.getMatches({ collection }) : void 0
2343
+ };
2344
+ }
2345
+ const { added, modified, deleted } = await getChangedFiles({
2346
+ fs: fs7,
2347
+ dir: rootPath,
2348
+ from: lastSha,
2349
+ to: sha,
2350
+ pathFilter
2351
+ });
2352
+ const tinaPathUpdates = modified.filter(
2353
+ (path22) => path22.startsWith(".tina/__generated__/_schema.json") || path22.startsWith("tina/tina-lock.json")
2354
+ );
2355
+ if (tinaPathUpdates.length > 0) {
2356
+ res = await database.indexContent({
2357
+ graphQLSchema,
2358
+ tinaSchema
2359
+ });
2360
+ } else {
2361
+ if (added.length > 0 || modified.length > 0) {
2362
+ await database.indexContentByPaths([...added, ...modified]);
2363
+ }
2364
+ if (deleted.length > 0) {
2365
+ await database.deleteContentByPaths(deleted);
2366
+ }
2367
+ }
2368
+ } else {
2369
+ res = await database.indexContent({
2370
+ graphQLSchema,
2371
+ tinaSchema
2372
+ });
2373
+ }
2374
+ if (sha) {
2375
+ await database.setMetadata("lastSha", sha);
2376
+ }
2377
+ if (res?.warnings) {
2378
+ warnings.push(...res.warnings);
2379
+ }
2380
+ },
2381
+ text: textToUse
2382
+ });
2383
+ if (warnings.length > 0) {
2384
+ logger.warn(`Indexing completed with ${warnings.length} warning(s)`);
2385
+ warnings.forEach((warning) => {
2386
+ logger.warn(warnText(`${warning}`));
2387
+ });
2388
+ }
2389
+ }
2390
+ };
2391
+
2392
+ // src/next/commands/dev-command/html.ts
2393
+ var errorHTML = `<style type="text/css">
2394
+ #no-assets-placeholder body {
2395
+ font-family: sans-serif;
2396
+ font-size: 16px;
2397
+ line-height: 1.4;
2398
+ color: #333;
2399
+ background-color: #f5f5f5;
2400
+ }
2401
+ #no-assets-placeholder {
2402
+ max-width: 600px;
2403
+ margin: 0 auto;
2404
+ padding: 40px;
2405
+ text-align: center;
2406
+ background-color: #fff;
2407
+ box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
2408
+ }
2409
+ #no-assets-placeholder h1 {
2410
+ font-size: 24px;
2411
+ margin-bottom: 20px;
2412
+ }
2413
+ #no-assets-placeholder p {
2414
+ margin-bottom: 10px;
2415
+ }
2416
+ #no-assets-placeholder a {
2417
+ color: #0077cc;
2418
+ text-decoration: none;
2419
+ }
2420
+ #no-assets-placeholder a:hover {
2421
+ text-decoration: underline;
2422
+ }
2423
+ </style>
2424
+ <div id="no-assets-placeholder">
2425
+ <h1>Failed loading TinaCMS assets</h1>
2426
+ <p>
2427
+ Your TinaCMS configuration may be misconfigured, and we could not load
2428
+ the assets for this page.
2429
+ </p>
2430
+ <p>
2431
+ Please visit <a href="https://tina.io/docs/r/FAQ/#13-how-do-i-resolve-failed-loading-tinacms-assets-error">this doc</a> for help.
2432
+ </p>
2433
+ </div>
2434
+ </div>`.trim().replace(/[\r\n\s]+/g, " ");
2435
+ var devHTML = (port, basePath) => `<!DOCTYPE html>
2436
+ <html lang="en">
2437
+ <head>
2438
+ <meta charset="UTF-8" />
2439
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
2440
+ <title>TinaCMS</title>
2441
+ </head>
2442
+
2443
+ <!-- if development -->
2444
+ <script type="module">
2445
+ import RefreshRuntime from 'http://localhost:${port}${basePath}@react-refresh'
2446
+ RefreshRuntime.injectIntoGlobalHook(window)
2447
+ window.$RefreshReg$ = () => {}
2448
+ window.$RefreshSig$ = () => (type) => type
2449
+ window.__vite_plugin_react_preamble_installed__ = true
2450
+ </script>
2451
+ <script type="module" src="http://localhost:${port}${basePath}@vite/client"></script>
2452
+ <script>
2453
+ function handleLoadError() {
2454
+ // Assets have failed to load
2455
+ document.getElementById('root').innerHTML = '${errorHTML}';
2456
+ }
2457
+ </script>
2458
+ <script
2459
+ type="module"
2460
+ src="http://localhost:${port}${basePath}src/main.tsx"
2461
+ onerror="handleLoadError()"
2462
+ ></script>
2463
+ <body class="tina-tailwind">
2464
+ <div id="root"></div>
2465
+ </body>
2466
+ </html>`;
2467
+
2468
+ // src/next/commands/dev-command/server/index.ts
2469
+ import { createServer as createViteServer } from "vite";
2470
+
2304
2471
  // src/next/vite/plugins.ts
2305
- import fs8 from "fs";
2306
- import path9 from "path";
2472
+ import fs9 from "fs";
2473
+ import path11 from "path";
2307
2474
  import { createFilter } from "@rollup/pluginutils";
2308
2475
  import { resolve as gqlResolve } from "@tinacms/graphql";
2309
2476
  import bodyParser from "body-parser";
@@ -2312,11 +2479,12 @@ import { transform as esbuildTransform } from "esbuild";
2312
2479
  import { transformWithEsbuild } from "vite";
2313
2480
 
2314
2481
  // src/next/commands/dev-command/server/media.ts
2315
- import path8, { join } from "path";
2482
+ import { randomUUID } from "crypto";
2483
+ import path10, { join } from "path";
2316
2484
  import busboy from "busboy";
2317
- import fs7 from "fs-extra";
2485
+ import fs8 from "fs-extra";
2318
2486
  var createMediaRouter = (config2) => {
2319
- const mediaFolder = path8.join(
2487
+ const mediaFolder = path10.join(
2320
2488
  config2.rootPath,
2321
2489
  config2.publicFolder,
2322
2490
  config2.mediaRoot
@@ -2330,10 +2498,12 @@ var createMediaRouter = (config2) => {
2330
2498
  );
2331
2499
  const limit = requestURL.searchParams.get("limit");
2332
2500
  const cursor = requestURL.searchParams.get("cursor");
2501
+ const search = requestURL.searchParams.get("search");
2333
2502
  const media = await mediaModel.listMedia({
2334
2503
  searchPath: folder,
2335
2504
  cursor,
2336
- limit
2505
+ limit,
2506
+ search
2337
2507
  });
2338
2508
  res.end(JSON.stringify(media));
2339
2509
  } catch (error) {
@@ -2359,6 +2529,39 @@ var createMediaRouter = (config2) => {
2359
2529
  throw error;
2360
2530
  }
2361
2531
  };
2532
+ const handleRename = async (req, res) => {
2533
+ const body = req.body;
2534
+ const { from, to } = body || {};
2535
+ if (typeof from !== "string" || typeof to !== "string" || !from || !to) {
2536
+ res.statusCode = 400;
2537
+ res.end(
2538
+ JSON.stringify({
2539
+ code: "INVALID_FILENAME",
2540
+ message: 'Both "from" and "to" are required.'
2541
+ })
2542
+ );
2543
+ return;
2544
+ }
2545
+ try {
2546
+ const result = await mediaModel.renameMedia({ from, to });
2547
+ if ("code" in result) {
2548
+ res.statusCode = RENAME_ERROR_STATUS[result.code];
2549
+ res.end(JSON.stringify({ code: result.code, message: result.message }));
2550
+ return;
2551
+ }
2552
+ res.statusCode = 200;
2553
+ res.end(JSON.stringify({ success: true, from, to }));
2554
+ } catch (error) {
2555
+ if (error instanceof PathTraversalError) {
2556
+ res.statusCode = 403;
2557
+ res.end(
2558
+ JSON.stringify({ code: "INVALID_PATH", message: error.message })
2559
+ );
2560
+ return;
2561
+ }
2562
+ throw error;
2563
+ }
2564
+ };
2362
2565
  const handlePost = async function(req, res) {
2363
2566
  const bb = busboy({ headers: req.headers });
2364
2567
  let responded = false;
@@ -2380,8 +2583,8 @@ var createMediaRouter = (config2) => {
2380
2583
  );
2381
2584
  return;
2382
2585
  }
2383
- await fs7.ensureDir(path8.dirname(saveTo));
2384
- file.pipe(fs7.createWriteStream(saveTo));
2586
+ await fs8.ensureDir(path10.dirname(saveTo));
2587
+ file.pipe(fs8.createWriteStream(saveTo));
2385
2588
  });
2386
2589
  bb.on("error", (error) => {
2387
2590
  responded = true;
@@ -2399,7 +2602,7 @@ var createMediaRouter = (config2) => {
2399
2602
  });
2400
2603
  req.pipe(bb);
2401
2604
  };
2402
- return { handleList, handleDelete, handlePost };
2605
+ return { handleList, handleDelete, handlePost, handleRename };
2403
2606
  };
2404
2607
  var parseMediaFolder = (str) => {
2405
2608
  let returnString = str;
@@ -2408,21 +2611,35 @@ var parseMediaFolder = (str) => {
2408
2611
  returnString = returnString.substr(0, returnString.length - 1);
2409
2612
  return returnString;
2410
2613
  };
2614
+ var RENAME_ERROR_STATUS = {
2615
+ NOT_FOUND: 404,
2616
+ NAME_COLLISION: 409,
2617
+ UNSUPPORTED: 400,
2618
+ BACKEND_FAILURE: 500
2619
+ };
2620
+ var StagedRenameError = class extends Error {
2621
+ constructor(stagingName) {
2622
+ super(`Left the file as "${stagingName}" in the same folder.`);
2623
+ this.stagingName = stagingName;
2624
+ }
2625
+ stagingName;
2626
+ };
2627
+ var isDestinationExistsError = (error) => error?.code === "EEXIST" || /dest already exists/i.test(error?.message || "");
2411
2628
  var ENCODED_TRAVERSAL_RE = /%2e%2e|%2f|%5c/i;
2412
2629
  function resolveRealPath(candidate) {
2413
2630
  try {
2414
- return fs7.realpathSync(candidate);
2631
+ return fs8.realpathSync(candidate);
2415
2632
  } catch {
2416
- const parent = path8.dirname(candidate);
2633
+ const parent = path10.dirname(candidate);
2417
2634
  if (parent === candidate) return candidate;
2418
- return path8.join(resolveRealPath(parent), path8.basename(candidate));
2635
+ return path10.join(resolveRealPath(parent), path10.basename(candidate));
2419
2636
  }
2420
2637
  }
2421
2638
  function assertSymlinkWithinBase(resolved, resolvedBase, userPath) {
2422
2639
  try {
2423
- const realBase = fs7.realpathSync(resolvedBase);
2640
+ const realBase = fs8.realpathSync(resolvedBase);
2424
2641
  const realResolved = resolveRealPath(resolved);
2425
- if (realResolved !== realBase && !realResolved.startsWith(realBase + path8.sep)) {
2642
+ if (realResolved !== realBase && !realResolved.startsWith(realBase + path10.sep)) {
2426
2643
  throw new PathTraversalError(userPath);
2427
2644
  }
2428
2645
  } catch (err) {
@@ -2433,13 +2650,13 @@ function resolveWithinBase(userPath, baseDir) {
2433
2650
  if (ENCODED_TRAVERSAL_RE.test(userPath)) {
2434
2651
  throw new PathTraversalError(userPath);
2435
2652
  }
2436
- const resolvedBase = path8.resolve(baseDir);
2437
- const resolved = path8.resolve(path8.join(baseDir, userPath));
2653
+ const resolvedBase = path10.resolve(baseDir);
2654
+ const resolved = path10.resolve(path10.join(baseDir, userPath));
2438
2655
  if (resolved === resolvedBase) {
2439
2656
  assertSymlinkWithinBase(resolved, resolvedBase, userPath);
2440
2657
  return resolvedBase;
2441
2658
  }
2442
- if (resolved.startsWith(resolvedBase + path8.sep)) {
2659
+ if (resolved.startsWith(resolvedBase + path10.sep)) {
2443
2660
  assertSymlinkWithinBase(resolved, resolvedBase, userPath);
2444
2661
  return resolved;
2445
2662
  }
@@ -2449,12 +2666,12 @@ function resolveStrictlyWithinBase(userPath, baseDir) {
2449
2666
  if (ENCODED_TRAVERSAL_RE.test(userPath)) {
2450
2667
  throw new PathTraversalError(userPath);
2451
2668
  }
2452
- const resolvedBase = path8.resolve(baseDir) + path8.sep;
2453
- const resolved = path8.resolve(path8.join(baseDir, userPath));
2669
+ const resolvedBase = path10.resolve(baseDir) + path10.sep;
2670
+ const resolved = path10.resolve(path10.join(baseDir, userPath));
2454
2671
  if (!resolved.startsWith(resolvedBase)) {
2455
2672
  throw new PathTraversalError(userPath);
2456
2673
  }
2457
- assertSymlinkWithinBase(resolved, path8.resolve(baseDir), userPath);
2674
+ assertSymlinkWithinBase(resolved, path10.resolve(baseDir), userPath);
2458
2675
  return resolved;
2459
2676
  }
2460
2677
  var MediaModel = class {
@@ -2471,16 +2688,27 @@ var MediaModel = class {
2471
2688
  const mediaBase = join(this.rootPath, this.publicFolder, this.mediaRoot);
2472
2689
  const validatedPath = resolveWithinBase(args.searchPath, mediaBase);
2473
2690
  const searchPath = parseMediaFolder(args.searchPath);
2474
- if (!await fs7.pathExists(validatedPath)) {
2691
+ if (!await fs8.pathExists(validatedPath)) {
2475
2692
  return {
2476
2693
  files: [],
2477
2694
  directories: []
2478
2695
  };
2479
2696
  }
2480
- const filesStr = await fs7.readdir(validatedPath);
2697
+ const search = args.search?.trim().toLowerCase();
2698
+ if (search) {
2699
+ return await this.searchMedia({
2700
+ mediaBase,
2701
+ validatedPath,
2702
+ searchPath,
2703
+ search,
2704
+ cursor: args.cursor,
2705
+ limit: args.limit
2706
+ });
2707
+ }
2708
+ const filesStr = await fs8.readdir(validatedPath);
2481
2709
  const filesProm = filesStr.map(async (file) => {
2482
2710
  const filePath = join(validatedPath, file);
2483
- const stat = await fs7.stat(filePath);
2711
+ const stat = await fs8.stat(filePath);
2484
2712
  let src = `/${file}`;
2485
2713
  const isFile = stat.isFile();
2486
2714
  if (!isFile) {
@@ -2516,10 +2744,11 @@ var MediaModel = class {
2516
2744
  }
2517
2745
  return 0;
2518
2746
  });
2519
- const limitItems = sortedItems.slice(offset, offset + limit);
2520
- const files = limitItems.filter((x) => x.isFile);
2521
- const directories = limitItems.filter((x) => !x.isFile).map((x) => x.src);
2522
- const cursor = rawItems.length > offset + limit ? String(offset + limit) : null;
2747
+ const allDirectories = sortedItems.filter((x) => !x.isFile).map((x) => x.src);
2748
+ const allFiles = sortedItems.filter((x) => x.isFile);
2749
+ const directories = offset === 0 ? allDirectories : [];
2750
+ const files = allFiles.slice(offset, offset + limit);
2751
+ const cursor = allFiles.length > offset + limit ? String(offset + limit) : null;
2523
2752
  return {
2524
2753
  files,
2525
2754
  directories,
@@ -2535,12 +2764,156 @@ var MediaModel = class {
2535
2764
  };
2536
2765
  }
2537
2766
  }
2767
+ async searchMedia({
2768
+ mediaBase,
2769
+ validatedPath,
2770
+ searchPath,
2771
+ search,
2772
+ cursor,
2773
+ limit
2774
+ }) {
2775
+ const resolvedBase = path10.resolve(mediaBase);
2776
+ const files = [];
2777
+ const directories = [];
2778
+ const visitedDirs = /* @__PURE__ */ new Set([resolveRealPath(validatedPath)]);
2779
+ const walk = async (dir, relPrefix) => {
2780
+ let entries;
2781
+ try {
2782
+ entries = await fs8.readdir(dir);
2783
+ } catch {
2784
+ return;
2785
+ }
2786
+ const stats = await Promise.all(
2787
+ entries.map(async (entry) => {
2788
+ const absPath = join(dir, entry);
2789
+ try {
2790
+ assertSymlinkWithinBase(absPath, resolvedBase, absPath);
2791
+ } catch {
2792
+ return null;
2793
+ }
2794
+ try {
2795
+ return { entry, absPath, stat: await fs8.stat(absPath) };
2796
+ } catch {
2797
+ return null;
2798
+ }
2799
+ })
2800
+ );
2801
+ for (const entryStat of stats) {
2802
+ if (!entryStat) continue;
2803
+ const { entry, absPath, stat } = entryStat;
2804
+ const relPath = relPrefix ? `${relPrefix}/${entry}` : entry;
2805
+ if (stat.isDirectory()) {
2806
+ const realDir = resolveRealPath(absPath);
2807
+ if (visitedDirs.has(realDir)) continue;
2808
+ visitedDirs.add(realDir);
2809
+ if (entry.toLowerCase().includes(search)) {
2810
+ directories.push(`/${relPath}`);
2811
+ }
2812
+ await walk(absPath, relPath);
2813
+ continue;
2814
+ }
2815
+ if (!relPath.toLowerCase().includes(search)) continue;
2816
+ let src = `/${relPath}`;
2817
+ if (searchPath) src = `/${searchPath}${src}`;
2818
+ if (this.mediaRoot) src = `/${this.mediaRoot}${src}`;
2819
+ files.push({ src, filename: relPath, size: stat.size });
2820
+ }
2821
+ };
2822
+ await walk(validatedPath, "");
2823
+ files.sort((a, b) => a.filename.localeCompare(b.filename));
2824
+ directories.sort();
2825
+ const offset = Number(cursor) || 0;
2826
+ const pageSize = Number(limit) || 20;
2827
+ return {
2828
+ files: files.slice(offset, offset + pageSize),
2829
+ directories: offset === 0 ? directories : [],
2830
+ cursor: files.length > offset + pageSize ? String(offset + pageSize) : null
2831
+ };
2832
+ }
2833
+ /**
2834
+ * @security Both paths go through `resolveStrictlyWithinBase`, which rejects
2835
+ * traversal, symlink escapes and the media root itself.
2836
+ */
2837
+ async renameMedia(args) {
2838
+ const mediaBase = join(this.rootPath, this.publicFolder, this.mediaRoot);
2839
+ const source = resolveStrictlyWithinBase(args.from, mediaBase);
2840
+ const destination = resolveStrictlyWithinBase(args.to, mediaBase);
2841
+ try {
2842
+ const stats = await fs8.stat(source);
2843
+ if (stats.isDirectory()) {
2844
+ return {
2845
+ ok: false,
2846
+ code: "UNSUPPORTED",
2847
+ message: "Renaming folders is not supported."
2848
+ };
2849
+ }
2850
+ } catch {
2851
+ return {
2852
+ ok: false,
2853
+ code: "NOT_FOUND",
2854
+ message: `"${args.from}" does not exist.`
2855
+ };
2856
+ }
2857
+ const isCaseOnlyRename = source !== destination && source.toLowerCase() === destination.toLowerCase();
2858
+ if (!isCaseOnlyRename && await fs8.pathExists(destination)) {
2859
+ return {
2860
+ ok: false,
2861
+ code: "NAME_COLLISION",
2862
+ message: `"${args.to}" already exists.`
2863
+ };
2864
+ }
2865
+ try {
2866
+ await fs8.ensureDir(path10.dirname(destination));
2867
+ if (isCaseOnlyRename) {
2868
+ await this.renameViaStaging(source, destination);
2869
+ } else {
2870
+ await fs8.move(source, destination, { overwrite: false });
2871
+ }
2872
+ return { ok: true };
2873
+ } catch (error) {
2874
+ if (isDestinationExistsError(error)) {
2875
+ return {
2876
+ ok: false,
2877
+ code: "NAME_COLLISION",
2878
+ message: `"${args.to}" already exists.`
2879
+ };
2880
+ }
2881
+ console.error(error);
2882
+ return {
2883
+ ok: false,
2884
+ code: "BACKEND_FAILURE",
2885
+ message: error instanceof StagedRenameError ? `Failed to rename the file. ${error.message}` : "Failed to rename the file."
2886
+ };
2887
+ }
2888
+ }
2889
+ /**
2890
+ * A case-insensitive filesystem can treat `a.jpg` -> `A.jpg` as a no-op, so
2891
+ * hop through a unique sibling name. On failure the source is put back; if
2892
+ * even that fails the file survives under the staging name, which
2893
+ * StagedRenameError reports rather than leaving it to be found by accident.
2894
+ */
2895
+ async renameViaStaging(source, destination) {
2896
+ const stagingName = `.tina-rename-${randomUUID()}`;
2897
+ const staging = join(path10.dirname(source), stagingName);
2898
+ await fs8.move(source, staging, { overwrite: false });
2899
+ try {
2900
+ await fs8.move(staging, destination, { overwrite: false });
2901
+ } catch (error) {
2902
+ try {
2903
+ await fs8.move(staging, source, { overwrite: false });
2904
+ } catch (restoreError) {
2905
+ console.error(restoreError);
2906
+ throw new StagedRenameError(stagingName);
2907
+ }
2908
+ throw error;
2909
+ }
2910
+ }
2538
2911
  async deleteMedia(args) {
2539
2912
  try {
2540
2913
  const mediaBase = join(this.rootPath, this.publicFolder, this.mediaRoot);
2541
2914
  const file = resolveStrictlyWithinBase(args.searchPath, mediaBase);
2542
- await fs7.stat(file);
2543
- await fs7.remove(file);
2915
+ await fs8.stat(file);
2916
+ await fs8.remove(file);
2544
2917
  return { ok: true };
2545
2918
  } catch (error) {
2546
2919
  if (error instanceof PathTraversalError) throw error;
@@ -2648,7 +3021,7 @@ var transformTsxPlugin = ({
2648
3021
  const plug = {
2649
3022
  name: "transform-tsx",
2650
3023
  async transform(code, id) {
2651
- const extName = path9.extname(id);
3024
+ const extName = path11.extname(id);
2652
3025
  if (extName.startsWith(".tsx") || extName.startsWith(".ts")) {
2653
3026
  const result = await esbuildTransform(code, { loader: "tsx" });
2654
3027
  return {
@@ -2659,6 +3032,7 @@ var transformTsxPlugin = ({
2659
3032
  };
2660
3033
  return plug;
2661
3034
  };
3035
+ var isMediaRenameRequest = (req) => req.method === "POST" && (req.url || "").split("?")[0] === "/media/rename";
2662
3036
  var devServerEndPointsPlugin = ({
2663
3037
  configManager,
2664
3038
  apiURL,
@@ -2671,6 +3045,7 @@ var devServerEndPointsPlugin = ({
2671
3045
  const isStateChangingRequest = (req) => {
2672
3046
  const url = req.url || "";
2673
3047
  if (url.startsWith("/media/upload")) return true;
3048
+ if (isMediaRenameRequest(req)) return true;
2674
3049
  if (url.startsWith("/media") && req.method === "DELETE") return true;
2675
3050
  if (url.startsWith("/graphql") && req.method === "POST") return true;
2676
3051
  if ((url.startsWith("/searchIndex") || url.startsWith("/v2/searchIndex")) && (req.method === "POST" || req.method === "DELETE"))
@@ -2708,6 +3083,10 @@ var devServerEndPointsPlugin = ({
2708
3083
  await mediaRouter.handlePost(req, res);
2709
3084
  return;
2710
3085
  }
3086
+ if (isMediaRenameRequest(req)) {
3087
+ await mediaRouter.handleRename(req, res);
3088
+ return;
3089
+ }
2711
3090
  if (req.url.startsWith("/media")) {
2712
3091
  if (req.method === "DELETE") {
2713
3092
  await mediaRouter.handleDelete(req, res);
@@ -2772,7 +3151,7 @@ function viteTransformExtension({
2772
3151
  async transform(code, id) {
2773
3152
  if (filter(id)) {
2774
3153
  const { transform: transform2 } = await import("@svgr/core");
2775
- const svgCode = await fs8.promises.readFile(
3154
+ const svgCode = await fs9.promises.readFile(
2776
3155
  id.replace(/\?.*$/, ""),
2777
3156
  "utf8"
2778
3157
  );
@@ -2883,6 +3262,7 @@ var DevCommand = class extends BaseCommand {
2883
3262
  });
2884
3263
  logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2885
3264
  this.logDeprecationWarnings();
3265
+ this.warnOnVersionSkew(configManager.rootPath);
2886
3266
  createDBServer(Number(this.datalayerPort));
2887
3267
  let database = null;
2888
3268
  const dbLock = async (fn) => {
@@ -2922,13 +3302,13 @@ var DevCommand = class extends BaseCommand {
2922
3302
  });
2923
3303
  const apiURL2 = await codegen2.execute();
2924
3304
  if (!configManager.isUsingLegacyFolder) {
2925
- const schemaObject = await fs9.readJSON(
3305
+ const schemaObject = await fs10.readJSON(
2926
3306
  configManager.generatedSchemaJSONPath
2927
3307
  );
2928
- const lookupObject = await fs9.readJSON(
3308
+ const lookupObject = await fs10.readJSON(
2929
3309
  configManager.generatedLookupJSONPath
2930
3310
  );
2931
- const graphqlSchemaObject = await fs9.readJSON(
3311
+ const graphqlSchemaObject = await fs10.readJSON(
2932
3312
  configManager.generatedGraphQLJSONPath
2933
3313
  );
2934
3314
  const tinaLockFilename = "tina-lock.json";
@@ -2937,8 +3317,8 @@ var DevCommand = class extends BaseCommand {
2937
3317
  lookup: lookupObject,
2938
3318
  graphql: graphqlSchemaObject
2939
3319
  });
2940
- fs9.writeFileSync(
2941
- path10.join(configManager.tinaFolderPath, tinaLockFilename),
3320
+ fs10.writeFileSync(
3321
+ path12.join(configManager.tinaFolderPath, tinaLockFilename),
2942
3322
  tinaLockContent
2943
3323
  );
2944
3324
  }
@@ -2982,8 +3362,11 @@ ${dangerText(e.message)}
2982
3362
  const { apiURL, graphQLSchema, tinaSchema } = await setup({
2983
3363
  firstTime: true
2984
3364
  });
2985
- await fs9.outputFile(configManager.outputHTMLFilePath, devHTML(this.port));
2986
- await fs9.outputFile(
3365
+ await fs10.outputFile(
3366
+ configManager.outputHTMLFilePath,
3367
+ devHTML(this.port, getBasePath(configManager))
3368
+ );
3369
+ await fs10.outputFile(
2987
3370
  configManager.outputGitignorePath,
2988
3371
  "index.html\nassets/"
2989
3372
  );
@@ -3128,7 +3511,7 @@ ${dangerText(e.message)}
3128
3511
  watchContentFiles(configManager, database, databaseLock, searchIndexer) {
3129
3512
  const collectionContentFiles = [];
3130
3513
  configManager.config.schema.collections.forEach((collection) => {
3131
- const collectionGlob = `${path10.join(
3514
+ const collectionGlob = `${path12.join(
3132
3515
  configManager.contentRootPath,
3133
3516
  collection.path
3134
3517
  )}/**/*.${collection.format || "md"}`;
@@ -3178,8 +3561,10 @@ ${dangerText(e.message)}
3178
3561
 
3179
3562
  // src/next/commands/build-command/index.ts
3180
3563
  import crypto from "crypto";
3181
- import path11 from "path";
3182
- import { diff } from "@graphql-inspector/core";
3564
+ import path13 from "path";
3565
+ import {
3566
+ diff
3567
+ } from "@graphql-inspector/core";
3183
3568
  import { FilesystemBridge as FilesystemBridge3, buildSchema as buildSchema2 } from "@tinacms/graphql";
3184
3569
  import { parseURL as parseURL2 } from "@tinacms/schema-tools";
3185
3570
  import {
@@ -3187,7 +3572,7 @@ import {
3187
3572
  TinaCMSSearchIndexClient
3188
3573
  } from "@tinacms/search";
3189
3574
  import { Command as Command3, Option as Option3 } from "clipanion";
3190
- import fs10 from "fs-extra";
3575
+ import fs11 from "fs-extra";
3191
3576
  import {
3192
3577
  buildASTSchema as buildASTSchema2,
3193
3578
  buildClientSchema,
@@ -3207,6 +3592,78 @@ var getFaqLink = (type) => {
3207
3592
  }
3208
3593
  };
3209
3594
 
3595
+ // src/utils/posthog.ts
3596
+ import { randomUUID as randomUUID2 } from "node:crypto";
3597
+ import { PostHog } from "posthog-node";
3598
+
3599
+ // src/utils/fetchPostHogConfig.ts
3600
+ async function fetchPostHogConfig(endpointUrl) {
3601
+ try {
3602
+ const response = await fetch(endpointUrl, {
3603
+ method: "GET",
3604
+ headers: {
3605
+ "Content-Type": "application/json"
3606
+ },
3607
+ // Cap latency for offline / firewalled developers. Endpoint is
3608
+ // typically single-digit ms when reachable; a timeout returns {}
3609
+ // and disables telemetry for this run, which is the right behavior.
3610
+ signal: AbortSignal.timeout(2e3)
3611
+ });
3612
+ if (!response.ok) {
3613
+ throw new Error(`Failed to fetch PostHog config: ${response.statusText}`);
3614
+ }
3615
+ const config2 = await response.json();
3616
+ return {
3617
+ POSTHOG_API_KEY: config2.api_key,
3618
+ POSTHOG_ENDPOINT: config2.host
3619
+ };
3620
+ } catch {
3621
+ return {};
3622
+ }
3623
+ }
3624
+
3625
+ // src/utils/posthog.ts
3626
+ function generateSessionId() {
3627
+ return randomUUID2();
3628
+ }
3629
+ var BuildInvokeEvent = "tinacms-cli-build-invoke";
3630
+ var BuildFinishedEvent = "tinacms-cli-build-finished";
3631
+ async function initializePostHog(configEndpoint, disableGeoip) {
3632
+ if (process.env.TINA_DEV === "true") return null;
3633
+ let apiKey;
3634
+ let endpoint;
3635
+ if (configEndpoint) {
3636
+ const config2 = await fetchPostHogConfig(configEndpoint);
3637
+ apiKey = config2.POSTHOG_API_KEY;
3638
+ endpoint = config2.POSTHOG_ENDPOINT;
3639
+ }
3640
+ if (!apiKey) return null;
3641
+ return new PostHog(apiKey, {
3642
+ host: endpoint,
3643
+ disableGeoip: disableGeoip ?? true
3644
+ });
3645
+ }
3646
+ function postHogCapture(client, distinctId, event, properties) {
3647
+ if (!client) {
3648
+ return;
3649
+ }
3650
+ try {
3651
+ client.capture({
3652
+ distinctId,
3653
+ event,
3654
+ properties: {
3655
+ ...properties,
3656
+ system: "tinacms/cli",
3657
+ // Bill as anonymous events: distinctId is a throwaway per-run UUID, so
3658
+ // person profiles would be single-use junk at ~4x the event price.
3659
+ $process_person_profile: false
3660
+ }
3661
+ });
3662
+ } catch (error) {
3663
+ console.error("Error capturing event:", error);
3664
+ }
3665
+ }
3666
+
3210
3667
  // src/utils/sleep.ts
3211
3668
  function timeout(ms) {
3212
3669
  return new Promise((resolve2) => setTimeout(resolve2, ms));
@@ -3324,75 +3781,6 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
3324
3781
  });
3325
3782
  };
3326
3783
 
3327
- // src/utils/posthog.ts
3328
- import { randomUUID } from "node:crypto";
3329
- import { PostHog } from "posthog-node";
3330
-
3331
- // src/utils/fetchPostHogConfig.ts
3332
- async function fetchPostHogConfig(endpointUrl) {
3333
- try {
3334
- const response = await fetch(endpointUrl, {
3335
- method: "GET",
3336
- headers: {
3337
- "Content-Type": "application/json"
3338
- },
3339
- // Cap latency for offline / firewalled developers. Endpoint is
3340
- // typically single-digit ms when reachable; a timeout returns {}
3341
- // and disables telemetry for this run, which is the right behavior.
3342
- signal: AbortSignal.timeout(2e3)
3343
- });
3344
- if (!response.ok) {
3345
- throw new Error(`Failed to fetch PostHog config: ${response.statusText}`);
3346
- }
3347
- const config2 = await response.json();
3348
- return {
3349
- POSTHOG_API_KEY: config2.api_key,
3350
- POSTHOG_ENDPOINT: config2.host
3351
- };
3352
- } catch {
3353
- return {};
3354
- }
3355
- }
3356
-
3357
- // src/utils/posthog.ts
3358
- function generateSessionId() {
3359
- return randomUUID();
3360
- }
3361
- var BuildInvokeEvent = "tinacms-cli-build-invoke";
3362
- var BuildFinishedEvent = "tinacms-cli-build-finished";
3363
- async function initializePostHog(configEndpoint, disableGeoip) {
3364
- if (process.env.TINA_DEV === "true") return null;
3365
- let apiKey;
3366
- let endpoint;
3367
- if (configEndpoint) {
3368
- const config2 = await fetchPostHogConfig(configEndpoint);
3369
- apiKey = config2.POSTHOG_API_KEY;
3370
- endpoint = config2.POSTHOG_ENDPOINT;
3371
- }
3372
- if (!apiKey) return null;
3373
- return new PostHog(apiKey, {
3374
- host: endpoint,
3375
- disableGeoip: disableGeoip ?? true
3376
- });
3377
- }
3378
- function postHogCapture(client, distinctId, event, properties) {
3379
- if (!client) {
3380
- return;
3381
- }
3382
- try {
3383
- client.capture({
3384
- distinctId,
3385
- event,
3386
- properties: {
3387
- ...properties,
3388
- system: "tinacms/cli"
3389
- }
3390
- });
3391
- } catch (error) {
3392
- console.error("Error capturing event:", error);
3393
- }
3394
- }
3395
-
3396
3784
  // src/next/commands/build-command/index.ts
3397
3785
  var BuildCommand = class extends BaseCommand {
3398
3786
  static paths = [["build"]];
@@ -3458,6 +3846,7 @@ var BuildCommand = class extends BaseCommand {
3458
3846
  tinaGraphQLVersion: this.tinaGraphQLVersion,
3459
3847
  legacyNoSDK: this.noSDK
3460
3848
  });
3849
+ this.warnOnVersionSkew(configManager.rootPath);
3461
3850
  if (this.previewName && !this.previewBaseBranch) {
3462
3851
  logger.error(
3463
3852
  `${dangerText(
@@ -3651,7 +4040,7 @@ ${dangerText(e.message)}
3651
4040
  }
3652
4041
  }
3653
4042
  await buildProductionSpa(configManager, database, codegen2.productionUrl);
3654
- await fs10.outputFile(
4043
+ await fs11.outputFile(
3655
4044
  configManager.outputGitignorePath,
3656
4045
  "index.html\nassets/"
3657
4046
  );
@@ -4036,7 +4425,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
4036
4425
  }
4037
4426
  const localTinaSchema = JSON.parse(
4038
4427
  await database.bridge.get(
4039
- path11.join(database.tinaDirectory, "__generated__", "_schema.json")
4428
+ path13.join(database.tinaDirectory, "__generated__", "_schema.json")
4040
4429
  )
4041
4430
  );
4042
4431
  localTinaSchema.version = void 0;
@@ -4399,19 +4788,19 @@ var AuditCommand = class extends Command4 {
4399
4788
  import { Command as Command6, Option as Option6 } from "clipanion";
4400
4789
 
4401
4790
  // src/cmds/init/detectEnvironment.ts
4402
- import fs12 from "fs-extra";
4403
- import path13 from "path";
4791
+ import fs13 from "fs-extra";
4792
+ import path15 from "path";
4404
4793
 
4405
4794
  // src/cmds/init/astro-config-detect.ts
4406
- import fs11 from "fs";
4407
- import path12 from "path";
4795
+ import fs12 from "fs";
4796
+ import path14 from "path";
4408
4797
  var isDefaultAstroConfig = (source) => {
4409
4798
  const stripped = source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/\s+/g, " ").trim();
4410
4799
  return /^import\s*\{\s*defineConfig\s*\}\s*from\s*['"]astro\/config['"]\s*;?\s*export\s+default\s+defineConfig\(\s*\{\s*\}\s*\)\s*;?$/.test(
4411
4800
  stripped
4412
4801
  );
4413
4802
  };
4414
- var findExistingPaths = (baseDir, relPaths) => relPaths.filter((rel) => fs11.existsSync(path12.join(baseDir, rel)));
4803
+ var findExistingPaths = (baseDir, relPaths) => relPaths.filter((rel) => fs12.existsSync(path14.join(baseDir, rel)));
4415
4804
  var parseAstroMajor = (version2) => {
4416
4805
  const match = version2 ? String(version2).match(/(\d+)/) : null;
4417
4806
  return match ? Number(match[1]) : void 0;
@@ -4427,20 +4816,20 @@ var checkGitignoreForItem = async ({
4427
4816
  baseDir,
4428
4817
  line
4429
4818
  }) => {
4430
- const gitignoreContent = fs12.readFileSync(path13.join(baseDir, ".gitignore")).toString();
4819
+ const gitignoreContent = fs13.readFileSync(path15.join(baseDir, ".gitignore")).toString();
4431
4820
  return gitignoreContent.split("\n").some((item) => item === line);
4432
4821
  };
4433
4822
  var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
4434
4823
  const result = {
4435
- fullPathTS: path13.join(
4824
+ fullPathTS: path15.join(
4436
4825
  parentPath,
4437
4826
  `${name2}.${opts?.typescriptSuffix || opts?.extensionOverride || "ts"}`
4438
4827
  ),
4439
- fullPathJS: path13.join(
4828
+ fullPathJS: path15.join(
4440
4829
  parentPath,
4441
4830
  `${name2}.${opts?.extensionOverride || "js"}`
4442
4831
  ),
4443
- fullPathOverride: opts?.extensionOverride ? path13.join(parentPath, `${name2}.${opts?.extensionOverride}`) : "",
4832
+ fullPathOverride: opts?.extensionOverride ? path15.join(parentPath, `${name2}.${opts?.extensionOverride}`) : "",
4444
4833
  generatedFileType,
4445
4834
  name: name2,
4446
4835
  parentPath,
@@ -4458,8 +4847,8 @@ var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
4458
4847
  };
4459
4848
  }
4460
4849
  };
4461
- result.typescriptExists = await fs12.pathExists(result.fullPathTS);
4462
- result.javascriptExists = await fs12.pathExists(result.fullPathJS);
4850
+ result.typescriptExists = await fs13.pathExists(result.fullPathTS);
4851
+ result.javascriptExists = await fs13.pathExists(result.fullPathJS);
4463
4852
  return result;
4464
4853
  };
4465
4854
  var detectEnvironment = async ({
@@ -4468,21 +4857,21 @@ var detectEnvironment = async ({
4468
4857
  rootPath,
4469
4858
  debug = false
4470
4859
  }) => {
4471
- const hasForestryConfig = await fs12.pathExists(
4472
- path13.join(pathToForestryConfig, ".forestry", "settings.yml")
4860
+ const hasForestryConfig = await fs13.pathExists(
4861
+ path15.join(pathToForestryConfig, ".forestry", "settings.yml")
4473
4862
  );
4474
- const sampleContentPath = path13.join(
4863
+ const sampleContentPath = path15.join(
4475
4864
  baseDir,
4476
4865
  "content",
4477
4866
  "posts",
4478
4867
  "hello-world.md"
4479
4868
  );
4480
- const usingSrc = fs12.pathExistsSync(path13.join(baseDir, "src")) && (fs12.pathExistsSync(path13.join(baseDir, "src", "app")) || fs12.pathExistsSync(path13.join(baseDir, "src", "pages")));
4481
- const tinaFolder = path13.join(baseDir, "tina");
4869
+ const usingSrc = fs13.pathExistsSync(path15.join(baseDir, "src")) && (fs13.pathExistsSync(path15.join(baseDir, "src", "app")) || fs13.pathExistsSync(path15.join(baseDir, "src", "pages")));
4870
+ const tinaFolder = path15.join(baseDir, "tina");
4482
4871
  const tinaConfigExists = Boolean(
4483
4872
  // Does the tina folder exist?
4484
- await fs12.pathExists(tinaFolder) && // Does the tina folder contain a config file?
4485
- (await fs12.readdir(tinaFolder)).find((x) => x.includes("config"))
4873
+ await fs13.pathExists(tinaFolder) && // Does the tina folder contain a config file?
4874
+ (await fs13.readdir(tinaFolder)).find((x) => x.includes("config"))
4486
4875
  );
4487
4876
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
4488
4877
  Boolean
@@ -4494,12 +4883,12 @@ var detectEnvironment = async ({
4494
4883
  "next-api-handler": await makeGeneratedFile(
4495
4884
  "[...routes]",
4496
4885
  "next-api-handler",
4497
- path13.join(...pagesDir, "api", "tina")
4886
+ path15.join(...pagesDir, "api", "tina")
4498
4887
  ),
4499
4888
  "reactive-example": await makeGeneratedFile(
4500
4889
  "[filename]",
4501
4890
  "reactive-example",
4502
- path13.join(...pagesDir, "demo", "blog"),
4891
+ path15.join(...pagesDir, "demo", "blog"),
4503
4892
  {
4504
4893
  typescriptSuffix: "tsx"
4505
4894
  }
@@ -4507,24 +4896,24 @@ var detectEnvironment = async ({
4507
4896
  "users-json": await makeGeneratedFile(
4508
4897
  "index",
4509
4898
  "users-json",
4510
- path13.join(baseDir, "content", "users"),
4899
+ path15.join(baseDir, "content", "users"),
4511
4900
  { extensionOverride: "json" }
4512
4901
  ),
4513
4902
  "sample-content": await makeGeneratedFile(
4514
4903
  "hello-world",
4515
4904
  "sample-content",
4516
- path13.join(baseDir, "content", "posts"),
4905
+ path15.join(baseDir, "content", "posts"),
4517
4906
  { extensionOverride: "md" }
4518
4907
  )
4519
4908
  };
4520
- const hasSampleContent = await fs12.pathExists(sampleContentPath);
4521
- const hasPackageJSON = await fs12.pathExists("package.json");
4909
+ const hasSampleContent = await fs13.pathExists(sampleContentPath);
4910
+ const hasPackageJSON = await fs13.pathExists("package.json");
4522
4911
  let hasTinaDeps = false;
4523
4912
  let hasReactDep = false;
4524
4913
  let astroMajor;
4525
4914
  if (hasPackageJSON) {
4526
4915
  try {
4527
- const packageJSON = await fs12.readJSON("package.json");
4916
+ const packageJSON = await fs13.readJSON("package.json");
4528
4917
  const deps = [];
4529
4918
  if (packageJSON?.dependencies) {
4530
4919
  deps.push(...Object.keys(packageJSON.dependencies));
@@ -4547,7 +4936,7 @@ var detectEnvironment = async ({
4547
4936
  );
4548
4937
  }
4549
4938
  }
4550
- const hasGitIgnore = await fs12.pathExists(path13.join(".gitignore"));
4939
+ const hasGitIgnore = await fs13.pathExists(path15.join(".gitignore"));
4551
4940
  const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
4552
4941
  const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
4553
4942
  const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
@@ -4557,9 +4946,9 @@ var detectEnvironment = async ({
4557
4946
  });
4558
4947
  let frontMatterFormat;
4559
4948
  if (hasForestryConfig) {
4560
- const hugoConfigPath = path13.join(rootPath, "config.toml");
4561
- if (await fs12.pathExists(hugoConfigPath)) {
4562
- const hugoConfig = await fs12.readFile(hugoConfigPath, "utf8");
4949
+ const hugoConfigPath = path15.join(rootPath, "config.toml");
4950
+ if (await fs13.pathExists(hugoConfigPath)) {
4951
+ const hugoConfig = await fs13.readFile(hugoConfigPath, "utf8");
4563
4952
  const metaDataFormat = hugoConfig.toString().match(/metaDataFormat = "(.*)"/)?.[1];
4564
4953
  if (metaDataFormat && (metaDataFormat === "yaml" || metaDataFormat === "toml" || metaDataFormat === "json")) {
4565
4954
  frontMatterFormat = metaDataFormat;
@@ -5184,6 +5573,7 @@ var CLICommand = class {
5184
5573
  constructor(handler) {
5185
5574
  this.handler = handler;
5186
5575
  }
5576
+ handler;
5187
5577
  async execute(params) {
5188
5578
  await this.handler.setup(params);
5189
5579
  const environment = await this.handler.detectEnvironment(params);
@@ -5193,19 +5583,19 @@ var CLICommand = class {
5193
5583
  };
5194
5584
 
5195
5585
  // src/cmds/init/apply.ts
5196
- import path18 from "path";
5586
+ import path20 from "path";
5197
5587
 
5198
5588
  // src/cmds/forestry-migrate/index.ts
5199
- import fs14 from "fs-extra";
5200
- import path15 from "path";
5589
+ import fs15 from "fs-extra";
5590
+ import path17 from "path";
5201
5591
  import yaml2 from "js-yaml";
5202
5592
  import pkg from "minimatch";
5203
5593
  import { parseFile, stringifyFile } from "@tinacms/graphql";
5204
5594
  import { CONTENT_FORMATS } from "@tinacms/schema-tools";
5205
5595
 
5206
5596
  // src/cmds/forestry-migrate/util/index.ts
5207
- import fs13 from "fs-extra";
5208
- import path14 from "path";
5597
+ import fs14 from "fs-extra";
5598
+ import path16 from "path";
5209
5599
  import yaml from "js-yaml";
5210
5600
  import z2 from "zod";
5211
5601
 
@@ -5647,7 +6037,7 @@ var transformForestryFieldsToTinaFields = ({
5647
6037
  return tinaFields;
5648
6038
  };
5649
6039
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
5650
- const templatePath = path14.join(
6040
+ const templatePath = path16.join(
5651
6041
  pathToForestryConfig,
5652
6042
  ".forestry",
5653
6043
  "front_matter",
@@ -5656,7 +6046,7 @@ var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false })
5656
6046
  );
5657
6047
  let templateString = "";
5658
6048
  try {
5659
- templateString = fs13.readFileSync(templatePath).toString();
6049
+ templateString = fs14.readFileSync(templatePath).toString();
5660
6050
  } catch {
5661
6051
  throw new Error(
5662
6052
  `Could not find template ${tem} at ${templatePath}
@@ -5715,9 +6105,9 @@ function checkExt(ext) {
5715
6105
  var generateAllTemplates = async ({
5716
6106
  pathToForestryConfig
5717
6107
  }) => {
5718
- const allTemplates = (await fs14.readdir(
5719
- path15.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
5720
- )).map((tem) => path15.basename(tem, ".yml"));
6108
+ const allTemplates = (await fs15.readdir(
6109
+ path17.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
6110
+ )).map((tem) => path17.basename(tem, ".yml"));
5721
6111
  const templateMap = /* @__PURE__ */ new Map();
5722
6112
  const proms = allTemplates.map(async (tem) => {
5723
6113
  try {
@@ -5862,9 +6252,9 @@ var generateCollectionFromForestrySection = (args) => {
5862
6252
  return c;
5863
6253
  } else if (section.type === "document") {
5864
6254
  const filePath = section.path;
5865
- const extname = path15.extname(filePath);
5866
- const fileName = path15.basename(filePath, extname);
5867
- const dir = path15.dirname(filePath);
6255
+ const extname = path17.extname(filePath);
6256
+ const fileName = path17.basename(filePath, extname);
6257
+ const dir = path17.dirname(filePath);
5868
6258
  const ext = checkExt(extname);
5869
6259
  if (ext) {
5870
6260
  const fields = [];
@@ -5926,8 +6316,8 @@ var generateCollections = async ({
5926
6316
  templateMap,
5927
6317
  usingTypescript
5928
6318
  });
5929
- const forestryConfig = await fs14.readFile(
5930
- path15.join(pathToForestryConfig, ".forestry", "settings.yml")
6319
+ const forestryConfig = await fs15.readFile(
6320
+ path17.join(pathToForestryConfig, ".forestry", "settings.yml")
5931
6321
  );
5932
6322
  rewriteTemplateKeysInDocs({
5933
6323
  templateMap,
@@ -5957,12 +6347,12 @@ var rewriteTemplateKeysInDocs = (args) => {
5957
6347
  const { templateObj } = templateMap.get(templateKey);
5958
6348
  templateObj?.pages?.forEach((page) => {
5959
6349
  try {
5960
- const filePath = path15.join(page);
5961
- if (fs14.lstatSync(filePath).isDirectory()) {
6350
+ const filePath = path17.join(page);
6351
+ if (fs15.lstatSync(filePath).isDirectory()) {
5962
6352
  return;
5963
6353
  }
5964
- const extname = path15.extname(filePath);
5965
- const fileContent = fs14.readFileSync(filePath).toString();
6354
+ const extname = path17.extname(filePath);
6355
+ const fileContent = fs15.readFileSync(filePath).toString();
5966
6356
  const content = parseFile(
5967
6357
  fileContent,
5968
6358
  extname,
@@ -5973,7 +6363,7 @@ var rewriteTemplateKeysInDocs = (args) => {
5973
6363
  _template: stringifyLabel(templateKey),
5974
6364
  ...content
5975
6365
  };
5976
- fs14.writeFileSync(
6366
+ fs15.writeFileSync(
5977
6367
  filePath,
5978
6368
  stringifyFile(newContent, extname, true, markdownParseConfig)
5979
6369
  );
@@ -5988,12 +6378,12 @@ var rewriteTemplateKeysInDocs = (args) => {
5988
6378
 
5989
6379
  // src/cmds/init/apply.ts
5990
6380
  import { Telemetry as Telemetry3 } from "@tinacms/metrics";
5991
- import fs18 from "fs-extra";
6381
+ import fs19 from "fs-extra";
5992
6382
 
5993
6383
  // src/next/commands/codemod-command/index.ts
5994
6384
  import { Command as Command5, Option as Option5 } from "clipanion";
5995
- import fs15 from "fs-extra";
5996
- import path16 from "path";
6385
+ import fs16 from "fs-extra";
6386
+ import path18 from "path";
5997
6387
  var CodemodCommand = class extends Command5 {
5998
6388
  static paths = [["codemod"], ["codemod", "move-tina-folder"]];
5999
6389
  rootPath = Option5.String("--rootPath", {
@@ -6034,13 +6424,13 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
6034
6424
  logger.error(e.message);
6035
6425
  process.exit(1);
6036
6426
  }
6037
- const tinaDestination = path16.join(configManager.rootPath, "tina");
6038
- if (await fs15.existsSync(tinaDestination)) {
6427
+ const tinaDestination = path18.join(configManager.rootPath, "tina");
6428
+ if (await fs16.existsSync(tinaDestination)) {
6039
6429
  logger.info(
6040
6430
  `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.`
6041
6431
  );
6042
6432
  } else {
6043
- await fs15.moveSync(configManager.tinaFolderPath, tinaDestination);
6433
+ await fs16.moveSync(configManager.tinaFolderPath, tinaDestination);
6044
6434
  await writeGitignore(configManager.rootPath);
6045
6435
  logger.info(
6046
6436
  "Move to 'tina' folder complete. Be sure to update any imports of the autogenerated client!"
@@ -6048,8 +6438,8 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
6048
6438
  }
6049
6439
  };
6050
6440
  var writeGitignore = async (rootPath) => {
6051
- await fs15.outputFileSync(
6052
- path16.join(rootPath, "tina", ".gitignore"),
6441
+ await fs16.outputFileSync(
6442
+ path18.join(rootPath, "tina", ".gitignore"),
6053
6443
  "__generated__"
6054
6444
  );
6055
6445
  };
@@ -6108,7 +6498,7 @@ const BlogPage = (props) => {
6108
6498
  {' '}
6109
6499
  Check out this guide
6110
6500
  </a>{' '}
6111
- to see how add TinaCMS to an existing Next.js site.
6501
+ to see how to add TinaCMS to an existing Next.js site.
6112
6502
  </div>
6113
6503
  </div>
6114
6504
  </>
@@ -6560,8 +6950,8 @@ function extendAstroScripts(scripts) {
6560
6950
  }
6561
6951
 
6562
6952
  // src/cmds/init/astro-visual-editing.ts
6563
- import fs16 from "fs-extra";
6564
- import path17 from "path";
6953
+ import fs17 from "fs-extra";
6954
+ import path19 from "path";
6565
6955
  var TS_NOCHECK = "// @ts-nocheck (generated types/client appear after your first tinacms dev run)\n";
6566
6956
  var DEMO_FILES = {
6567
6957
  "src/lib/tina/data.ts": `${TS_NOCHECK}import { requestWithMetadata } from '@tinacms/astro/data';
@@ -6832,8 +7222,8 @@ var ASTRO_CONFIG_FILES = [
6832
7222
  "astro.config.cjs",
6833
7223
  "astro.config.cts"
6834
7224
  ];
6835
- var findAstroConfig = (baseDir) => ASTRO_CONFIG_FILES.map((file) => path17.join(baseDir, file)).find(
6836
- (p) => fs16.existsSync(p)
7225
+ var findAstroConfig = (baseDir) => ASTRO_CONFIG_FILES.map((file) => path19.join(baseDir, file)).find(
7226
+ (p) => fs17.existsSync(p)
6837
7227
  );
6838
7228
  var setupAstroVisualEditing = ({
6839
7229
  baseDir
@@ -6851,17 +7241,17 @@ var setupAstroVisualEditing = ({
6851
7241
  return { configHandled: true, demoScaffolded: false };
6852
7242
  }
6853
7243
  for (const rel of relPaths) {
6854
- fs16.outputFileSync(path17.join(baseDir, rel), DEMO_FILES[rel]);
7244
+ fs17.outputFileSync(path19.join(baseDir, rel), DEMO_FILES[rel]);
6855
7245
  }
6856
7246
  logger.info("Adding a visual-editing demo at /tinacms-demo... \u2705");
6857
7247
  const configPath = findAstroConfig(baseDir);
6858
7248
  if (!configPath) {
6859
- fs16.writeFileSync(path17.join(baseDir, "astro.config.mjs"), ASTRO_CONFIG);
7249
+ fs17.writeFileSync(path19.join(baseDir, "astro.config.mjs"), ASTRO_CONFIG);
6860
7250
  logger.info("Creating astro.config for visual editing... \u2705");
6861
7251
  return { configHandled: true, demoScaffolded: true };
6862
7252
  }
6863
- if (isDefaultAstroConfig(fs16.readFileSync(configPath).toString())) {
6864
- fs16.writeFileSync(configPath, ASTRO_CONFIG);
7253
+ if (isDefaultAstroConfig(fs17.readFileSync(configPath).toString())) {
7254
+ fs17.writeFileSync(configPath, ASTRO_CONFIG);
6865
7255
  logger.info("Wiring astro.config for visual editing... \u2705");
6866
7256
  return { configHandled: true, demoScaffolded: true };
6867
7257
  }
@@ -6873,7 +7263,7 @@ var logAstroConfigGuidance = () => {
6873
7263
 
6874
7264
  // src/cmds/init/codegen/index.ts
6875
7265
  import ts2 from "typescript";
6876
- import fs17 from "fs-extra";
7266
+ import fs18 from "fs-extra";
6877
7267
 
6878
7268
  // src/cmds/init/codegen/util.ts
6879
7269
  import ts from "typescript";
@@ -7110,7 +7500,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
7110
7500
  const pathToConfig = configFile.resolve(config2.typescript).path;
7111
7501
  const sourceFile = ts2.createSourceFile(
7112
7502
  pathToConfig,
7113
- fs17.readFileSync(pathToConfig, "utf8"),
7503
+ fs18.readFileSync(pathToConfig, "utf8"),
7114
7504
  config2.typescript ? ts2.ScriptTarget.Latest : ts2.ScriptTarget.ESNext
7115
7505
  );
7116
7506
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
@@ -7160,7 +7550,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
7160
7550
  )
7161
7551
  ].map((visitor) => makeTransformer(visitor))
7162
7552
  );
7163
- return fs17.writeFile(
7553
+ return fs18.writeFile(
7164
7554
  pathToConfig,
7165
7555
  ts2.createPrinter({ omitTrailingSemicolon: true }).printFile(transformedSourceFileResult.transformed[0])
7166
7556
  );
@@ -7286,8 +7676,8 @@ async function apply({
7286
7676
  await addConfigFile({
7287
7677
  configArgs: {
7288
7678
  config: config2,
7289
- publicFolder: path18.join(
7290
- path18.relative(process.cwd(), pathToForestryConfig),
7679
+ publicFolder: path20.join(
7680
+ path20.relative(process.cwd(), pathToForestryConfig),
7291
7681
  config2.publicFolder
7292
7682
  ),
7293
7683
  collections,
@@ -7364,8 +7754,8 @@ var createPackageJSON = async () => {
7364
7754
  };
7365
7755
  var createGitignore = async ({ baseDir }) => {
7366
7756
  logger.info(logText("No .gitignore found, creating one"));
7367
- fs18.outputFileSync(
7368
- path18.join(baseDir, ".gitignore"),
7757
+ fs19.outputFileSync(
7758
+ path20.join(baseDir, ".gitignore"),
7369
7759
  "node_modules\ntina/__generated__\n"
7370
7760
  );
7371
7761
  };
@@ -7374,11 +7764,11 @@ var updateGitIgnore = async ({
7374
7764
  items
7375
7765
  }) => {
7376
7766
  logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
7377
- const gitignoreContent = fs18.readFileSync(path18.join(baseDir, ".gitignore")).toString();
7767
+ const gitignoreContent = fs19.readFileSync(path20.join(baseDir, ".gitignore")).toString();
7378
7768
  const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
7379
7769
  "\n"
7380
7770
  );
7381
- await fs18.writeFile(path18.join(baseDir, ".gitignore"), newGitignoreContent);
7771
+ await fs19.writeFile(path20.join(baseDir, ".gitignore"), newGitignoreContent);
7382
7772
  };
7383
7773
  var addDependencies = async (config2, env, params) => {
7384
7774
  const { packageManager } = config2;
@@ -7455,22 +7845,22 @@ var writeGeneratedFile = async ({
7455
7845
  content,
7456
7846
  typescript
7457
7847
  }) => {
7458
- const { exists, path: path20, parentPath } = generatedFile.resolve(typescript);
7848
+ const { exists, path: path22, parentPath } = generatedFile.resolve(typescript);
7459
7849
  if (exists) {
7460
7850
  if (overwrite) {
7461
- logger.info(`Overwriting file at ${path20}... \u2705`);
7462
- fs18.outputFileSync(path20, content);
7851
+ logger.info(`Overwriting file at ${path22}... \u2705`);
7852
+ fs19.outputFileSync(path22, content);
7463
7853
  } else {
7464
- logger.info(`Not overwriting file at ${path20}.`);
7854
+ logger.info(`Not overwriting file at ${path22}.`);
7465
7855
  logger.info(
7466
- logText(`Please add the following to ${path20}:
7856
+ logText(`Please add the following to ${path22}:
7467
7857
  ${indentText(content)}}`)
7468
7858
  );
7469
7859
  }
7470
7860
  } else {
7471
- logger.info(`Adding file at ${path20}... \u2705`);
7472
- await fs18.ensureDir(parentPath);
7473
- fs18.outputFileSync(path20, content);
7861
+ logger.info(`Adding file at ${path22}... \u2705`);
7862
+ await fs19.ensureDir(parentPath);
7863
+ fs19.outputFileSync(path22, content);
7474
7864
  }
7475
7865
  };
7476
7866
  var addConfigFile = async ({
@@ -7548,7 +7938,7 @@ var addContentFile = async ({
7548
7938
  return () => ({
7549
7939
  exists: env.sampleContentExists,
7550
7940
  path: env.sampleContentPath,
7551
- parentPath: path18.dirname(env.sampleContentPath)
7941
+ parentPath: path20.dirname(env.sampleContentPath)
7552
7942
  });
7553
7943
  }
7554
7944
  },
@@ -7572,10 +7962,10 @@ ${titleText(" TinaCMS ")} backend initialized!`));
7572
7962
  return `${x.key}=${x.value || "***"}`;
7573
7963
  }).join("\n") + `
7574
7964
  TINA_PUBLIC_IS_LOCAL=true`;
7575
- const envFile = path18.join(process.cwd(), ".env");
7576
- if (!fs18.existsSync(envFile)) {
7965
+ const envFile = path20.join(process.cwd(), ".env");
7966
+ if (!fs19.existsSync(envFile)) {
7577
7967
  logger.info(`Adding .env file to your project... \u2705`);
7578
- fs18.writeFileSync(envFile, envFileText);
7968
+ fs19.writeFileSync(envFile, envFileText);
7579
7969
  } else {
7580
7970
  logger.info(
7581
7971
  "Please add the following environment variables to your .env file"
@@ -7652,7 +8042,7 @@ var addReactiveFile = {
7652
8042
  baseDir,
7653
8043
  dataLayer
7654
8044
  }) => {
7655
- const packageJsonPath = path18.join(baseDir, "package.json");
8045
+ const packageJsonPath = path20.join(baseDir, "package.json");
7656
8046
  await writeGeneratedFile({
7657
8047
  generatedFile,
7658
8048
  typescript: config2.typescript,
@@ -7665,7 +8055,7 @@ var addReactiveFile = {
7665
8055
  })
7666
8056
  });
7667
8057
  logger.info("Adding a nextjs example... \u2705");
7668
- const packageJson = JSON.parse(fs18.readFileSync(packageJsonPath).toString());
8058
+ const packageJson = JSON.parse(fs19.readFileSync(packageJsonPath).toString());
7669
8059
  const scripts = packageJson.scripts || {};
7670
8060
  const updatedPackageJson = JSON.stringify(
7671
8061
  {
@@ -7678,15 +8068,15 @@ var addReactiveFile = {
7678
8068
  null,
7679
8069
  2
7680
8070
  );
7681
- fs18.writeFileSync(packageJsonPath, updatedPackageJson);
8071
+ fs19.writeFileSync(packageJsonPath, updatedPackageJson);
7682
8072
  }
7683
8073
  };
7684
8074
  var updateAstroPackageJson = async ({ baseDir }) => {
7685
- const packageJsonPath = path18.join(baseDir, "package.json");
7686
- if (!fs18.existsSync(packageJsonPath)) {
8075
+ const packageJsonPath = path20.join(baseDir, "package.json");
8076
+ if (!fs19.existsSync(packageJsonPath)) {
7687
8077
  return;
7688
8078
  }
7689
- const packageJson = JSON.parse(fs18.readFileSync(packageJsonPath).toString());
8079
+ const packageJson = JSON.parse(fs19.readFileSync(packageJsonPath).toString());
7690
8080
  const scripts = packageJson.scripts || {};
7691
8081
  const updatedPackageJson = JSON.stringify(
7692
8082
  {
@@ -7696,7 +8086,7 @@ var updateAstroPackageJson = async ({ baseDir }) => {
7696
8086
  null,
7697
8087
  2
7698
8088
  );
7699
- fs18.writeFileSync(packageJsonPath, updatedPackageJson);
8089
+ fs19.writeFileSync(packageJsonPath, updatedPackageJson);
7700
8090
  logger.info("Updating package.json scripts for Astro... \u2705");
7701
8091
  };
7702
8092
  function execShellCommand(cmd) {
@@ -7896,8 +8286,8 @@ var SearchIndexCommand = class extends Command7 {
7896
8286
  import { Command as Command8, Option as Option8 } from "clipanion";
7897
8287
 
7898
8288
  // src/next/commands/doctor-command/doctor.ts
7899
- import path19 from "path";
7900
- import fs19 from "fs-extra";
8289
+ import path21 from "path";
8290
+ import fs20 from "fs-extra";
7901
8291
  import yaml3 from "js-yaml";
7902
8292
  var DEPENDENCY_TYPES = [
7903
8293
  "dependencies",
@@ -7930,11 +8320,11 @@ function getTinaDependencies(packageJson) {
7930
8320
  );
7931
8321
  }
7932
8322
  async function readProjectPackageJson(rootPath) {
7933
- const packageJsonPath = path19.join(rootPath, "package.json");
7934
- if (!await fs19.pathExists(packageJsonPath)) {
8323
+ const packageJsonPath = path21.join(rootPath, "package.json");
8324
+ if (!await fs20.pathExists(packageJsonPath)) {
7935
8325
  throw new Error(`No package.json found at ${packageJsonPath}`);
7936
8326
  }
7937
- return fs19.readJSON(packageJsonPath);
8327
+ return fs20.readJSON(packageJsonPath);
7938
8328
  }
7939
8329
  async function resolveInstalledVersions({
7940
8330
  rootPath,
@@ -8057,14 +8447,14 @@ function isLocalReference(version2) {
8057
8447
  );
8058
8448
  }
8059
8449
  async function readNodeModulesVersion(rootPath, packageName) {
8060
- const packageJsonPath = path19.join(
8450
+ const packageJsonPath = path21.join(
8061
8451
  rootPath,
8062
8452
  "node_modules",
8063
8453
  ...packageName.split("/"),
8064
8454
  "package.json"
8065
8455
  );
8066
- if (!await fs19.pathExists(packageJsonPath)) return void 0;
8067
- const packageJson = await fs19.readJSON(packageJsonPath);
8456
+ if (!await fs20.pathExists(packageJsonPath)) return void 0;
8457
+ const packageJson = await fs20.readJSON(packageJsonPath);
8068
8458
  return typeof packageJson.version === "string" ? packageJson.version : void 0;
8069
8459
  }
8070
8460
  async function readLockfileVersions(rootPath) {
@@ -8080,10 +8470,10 @@ async function readLockfileVersions(rootPath) {
8080
8470
  return /* @__PURE__ */ new Map();
8081
8471
  }
8082
8472
  async function readPackageLockVersions(rootPath) {
8083
- const lockfilePath = path19.join(rootPath, "package-lock.json");
8473
+ const lockfilePath = path21.join(rootPath, "package-lock.json");
8084
8474
  const versions = /* @__PURE__ */ new Map();
8085
- if (!await fs19.pathExists(lockfilePath)) return versions;
8086
- const lockfile = await fs19.readJSON(lockfilePath);
8475
+ if (!await fs20.pathExists(lockfilePath)) return versions;
8476
+ const lockfile = await fs20.readJSON(lockfilePath);
8087
8477
  for (const [key, value] of Object.entries(lockfile.packages || {})) {
8088
8478
  if (!key.startsWith("node_modules/")) continue;
8089
8479
  const name2 = key.replace(/^node_modules\//, "");
@@ -8101,10 +8491,10 @@ async function readPackageLockVersions(rootPath) {
8101
8491
  return versions;
8102
8492
  }
8103
8493
  async function readPnpmLockVersions(rootPath) {
8104
- const lockfilePath = path19.join(rootPath, "pnpm-lock.yaml");
8494
+ const lockfilePath = path21.join(rootPath, "pnpm-lock.yaml");
8105
8495
  const versions = /* @__PURE__ */ new Map();
8106
- if (!await fs19.pathExists(lockfilePath)) return versions;
8107
- const lockfile = yaml3.load(await fs19.readFile(lockfilePath, "utf8"));
8496
+ if (!await fs20.pathExists(lockfilePath)) return versions;
8497
+ const lockfile = yaml3.load(await fs20.readFile(lockfilePath, "utf8"));
8108
8498
  const rootImporter = lockfile?.importers?.["."];
8109
8499
  for (const dependencyType of DEPENDENCY_TYPES) {
8110
8500
  for (const [name2, value] of Object.entries(
@@ -8124,10 +8514,10 @@ async function readPnpmLockVersions(rootPath) {
8124
8514
  return versions;
8125
8515
  }
8126
8516
  async function readYarnLockVersions(rootPath) {
8127
- const lockfilePath = path19.join(rootPath, "yarn.lock");
8517
+ const lockfilePath = path21.join(rootPath, "yarn.lock");
8128
8518
  const versions = /* @__PURE__ */ new Map();
8129
- if (!await fs19.pathExists(lockfilePath)) return versions;
8130
- const contents = await fs19.readFile(lockfilePath, "utf8");
8519
+ if (!await fs20.pathExists(lockfilePath)) return versions;
8520
+ const contents = await fs20.readFile(lockfilePath, "utf8");
8131
8521
  if (contents.includes("__metadata:")) {
8132
8522
  return readYarnBerryLockVersions(contents);
8133
8523
  }