@tinacms/cli 2.5.5 → 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.4";
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;
@@ -816,26 +821,165 @@ var unlinkIfExists = async (filepath) => {
816
821
  };
817
822
 
818
823
  // src/next/config-manager.ts
819
- import fs4 from "fs-extra";
824
+ import { createRequire } from "module";
820
825
  import path5 from "path";
821
826
  import { pathToFileURL } from "url";
822
- import * as esbuild from "esbuild";
823
827
  import * as dotenv from "dotenv";
828
+ import * as esbuild from "esbuild";
829
+ import fs4 from "fs-extra";
824
830
  import normalizePath2 from "normalize-path";
825
- import { createRequire } from "module";
826
831
 
827
- // src/next/resolve-content-root.ts
832
+ // src/next/build-database-esbuild-config.ts
833
+ var buildDatabaseEsbuildConfig = (opts) => ({
834
+ entryPoints: [opts.entryPoint],
835
+ bundle: true,
836
+ platform: "node",
837
+ format: "esm",
838
+ outfile: opts.outfile,
839
+ loader: opts.loader,
840
+ external: opts.external,
841
+ // Provide a require() polyfill for ESM bundles containing CommonJS packages.
842
+ // Some bundled packages (e.g., 'scmp' used by 'mongodb-level') use
843
+ // require('crypto'). When esbuild inlines these CommonJS packages, it keeps
844
+ // the require() calls, but ESM doesn't have a global require. This banner
845
+ // creates one using Node.js's official createRequire API, allowing the
846
+ // bundled CommonJS code to work in ESM.
847
+ banner: {
848
+ js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`
849
+ }
850
+ });
851
+
852
+ // src/next/cache-manager.ts
828
853
  import fs2 from "fs-extra";
829
- import path3 from "path";
854
+ import path2 from "path";
855
+ var buildReadOnlyMountErrorMessage = (cacheParentPath, underlyingError) => `TinaCMS cannot write to ${cacheParentPath}.
856
+
857
+ Tina v3 needs write access to your project's tina/__generated__/.cache/ directory at build time. This usually means your project directory is read-only \u2014 common in some Docker setups (\`:ro\` volumes), AWS Lambda's \`/var/task\`, sandboxed CI runners, or restricted file permissions.
858
+
859
+ To resolve, either:
860
+ - Make the project directory writable (e.g. remount with read-write access, or copy the project to a writable location), or
861
+ - Run \`tinacms build\` against a writable copy of your project and deploy the resulting artifacts.
862
+
863
+ Underlying error: ${underlyingError.code} ${underlyingError.message}`;
864
+ var READONLY_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EROFS", "EPERM"]);
865
+ var prepareCacheLocation = async (generatedFolderPath, now = Date.now()) => {
866
+ const parentPath = path2.join(generatedFolderPath, ".cache");
867
+ try {
868
+ if (await fs2.pathExists(parentPath)) {
869
+ await fs2.remove(parentPath);
870
+ }
871
+ await fs2.ensureDir(parentPath);
872
+ } catch (err) {
873
+ const code = err?.code;
874
+ if (code && READONLY_ERROR_CODES.has(code)) {
875
+ throw new Error(
876
+ buildReadOnlyMountErrorMessage(parentPath, err)
877
+ );
878
+ }
879
+ throw err;
880
+ }
881
+ return {
882
+ parentPath,
883
+ buildPath: path2.join(parentPath, String(now))
884
+ };
885
+ };
886
+ var reapBuildSubdir = (buildSubdirPath, buildParentPath) => {
887
+ fs2.removeSync(buildSubdirPath);
888
+ try {
889
+ fs2.rmdirSync(buildParentPath);
890
+ } catch (err) {
891
+ if (err?.code !== "ENOTEMPTY") throw err;
892
+ }
893
+ };
894
+
895
+ // src/next/config-build-error.ts
896
+ var isObject = (value) => typeof value === "object" && value !== null;
897
+ var isTinaPackage = (specifier) => specifier === "tinacms" || specifier.startsWith("@tinacms/");
898
+ var collectResolveTargets = (text) => {
899
+ if (!text) {
900
+ return [];
901
+ }
902
+ const targets = [];
903
+ const pattern = /Could not resolve "([^"]+)"/g;
904
+ for (const match of text.matchAll(pattern)) {
905
+ targets.push(match[1]);
906
+ }
907
+ return targets;
908
+ };
909
+ var getUnresolvedTinaPackage = (error) => {
910
+ if (!isObject(error)) {
911
+ return null;
912
+ }
913
+ const esbuildError = error;
914
+ const targets = [
915
+ ...(esbuildError.errors ?? []).flatMap(
916
+ (item) => collectResolveTargets(item.text)
917
+ ),
918
+ ...collectResolveTargets(esbuildError.message)
919
+ ];
920
+ return targets.find(isTinaPackage) ?? null;
921
+ };
922
+ var getResolveLocation = (error) => {
923
+ if (!isObject(error)) {
924
+ return null;
925
+ }
926
+ const esbuildError = error;
927
+ const entry = (esbuildError.errors ?? []).find(
928
+ (item) => collectResolveTargets(item.text).some(isTinaPackage)
929
+ );
930
+ return entry?.location ?? null;
931
+ };
932
+ var formatConfigBuildError = ({
933
+ error,
934
+ rootPath
935
+ }) => {
936
+ const unresolvedPackage = getUnresolvedTinaPackage(error);
937
+ if (!unresolvedPackage) {
938
+ return error;
939
+ }
940
+ const lines = [
941
+ `Unable to resolve the "${unresolvedPackage}" package while building your Tina config.`,
942
+ "",
943
+ `Tina looked from: ${rootPath}`
944
+ ];
945
+ const location = getResolveLocation(error);
946
+ if (location?.file) {
947
+ const position = [location.line, location.column].filter((value) => typeof value === "number").join(":");
948
+ lines.push(
949
+ "",
950
+ `Failing import: ${location.file}${position ? `:${position}` : ""}`
951
+ );
952
+ if (location.lineText) {
953
+ lines.push(` ${location.lineText.trim()}`);
954
+ }
955
+ }
956
+ lines.push(
957
+ "",
958
+ "Make sure the TinaCMS packages are installed in this project and that you are running the CLI from the project root.",
959
+ "If they are installed, check parent directories for package-manager files that can interfere with module resolution, such as package.json, node_modules, yarn.lock, or .pnp.cjs."
960
+ );
961
+ return new Error(lines.join("\n"));
962
+ };
963
+
964
+ // src/next/external-resolver.ts
965
+ var EXTERNAL_BASELINE = ["better-sqlite3"];
966
+ var resolveDatabaseExternals = (config2) => {
967
+ const userExternals = config2?.build?.externalDependencies ?? [];
968
+ return [...EXTERNAL_BASELINE, ...userExternals];
969
+ };
970
+
971
+ // src/next/resolve-content-root.ts
972
+ import fs3 from "fs-extra";
973
+ import path4 from "path";
830
974
  import chalk3 from "chalk";
831
975
  import { z } from "zod";
832
976
 
833
977
  // src/utils/path.ts
834
- import path2 from "path";
978
+ import path3 from "path";
835
979
  function stripNativeTrailingSlash(p) {
836
- const { root } = path2.parse(p);
980
+ const { root } = path3.parse(p);
837
981
  let str = p;
838
- while (str.length > root.length && str.endsWith(path2.sep)) {
982
+ while (str.length > root.length && str.endsWith(path3.sep)) {
839
983
  str = str.slice(0, -1);
840
984
  }
841
985
  return str;
@@ -859,9 +1003,9 @@ async function resolveContentRootPath(params) {
859
1003
  return params.rootPath;
860
1004
  }
861
1005
  const fullLocalContentPath = stripNativeTrailingSlash(
862
- path3.join(params.tinaFolderPath, localContentPath)
1006
+ path4.join(params.tinaFolderPath, localContentPath)
863
1007
  );
864
- const exists = await fs2.pathExists(fullLocalContentPath);
1008
+ const exists = await fs3.pathExists(fullLocalContentPath);
865
1009
  if (exists) {
866
1010
  logger.info(`Using separate content repo at ${fullLocalContentPath}`);
867
1011
  return fullLocalContentPath;
@@ -876,76 +1020,6 @@ async function resolveContentRootPath(params) {
876
1020
  return params.rootPath;
877
1021
  }
878
1022
 
879
- // src/next/external-resolver.ts
880
- var EXTERNAL_BASELINE = ["better-sqlite3"];
881
- var resolveDatabaseExternals = (config2) => {
882
- const userExternals = config2?.build?.externalDependencies ?? [];
883
- return [...EXTERNAL_BASELINE, ...userExternals];
884
- };
885
-
886
- // src/next/cache-manager.ts
887
- import fs3 from "fs-extra";
888
- import path4 from "path";
889
- var buildReadOnlyMountErrorMessage = (cacheParentPath, underlyingError) => `TinaCMS cannot write to ${cacheParentPath}.
890
-
891
- Tina v3 needs write access to your project's tina/__generated__/.cache/ directory at build time. This usually means your project directory is read-only \u2014 common in some Docker setups (\`:ro\` volumes), AWS Lambda's \`/var/task\`, sandboxed CI runners, or restricted file permissions.
892
-
893
- To resolve, either:
894
- - Make the project directory writable (e.g. remount with read-write access, or copy the project to a writable location), or
895
- - Run \`tinacms build\` against a writable copy of your project and deploy the resulting artifacts.
896
-
897
- Underlying error: ${underlyingError.code} ${underlyingError.message}`;
898
- var READONLY_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EROFS", "EPERM"]);
899
- var prepareCacheLocation = async (generatedFolderPath, now = Date.now()) => {
900
- const parentPath = path4.join(generatedFolderPath, ".cache");
901
- try {
902
- if (await fs3.pathExists(parentPath)) {
903
- await fs3.remove(parentPath);
904
- }
905
- await fs3.ensureDir(parentPath);
906
- } catch (err) {
907
- const code = err?.code;
908
- if (code && READONLY_ERROR_CODES.has(code)) {
909
- throw new Error(
910
- buildReadOnlyMountErrorMessage(parentPath, err)
911
- );
912
- }
913
- throw err;
914
- }
915
- return {
916
- parentPath,
917
- buildPath: path4.join(parentPath, String(now))
918
- };
919
- };
920
- var reapBuildSubdir = (buildSubdirPath, buildParentPath) => {
921
- fs3.removeSync(buildSubdirPath);
922
- try {
923
- fs3.rmdirSync(buildParentPath);
924
- } catch (err) {
925
- if (err?.code !== "ENOTEMPTY") throw err;
926
- }
927
- };
928
-
929
- // src/next/build-database-esbuild-config.ts
930
- var buildDatabaseEsbuildConfig = (opts) => ({
931
- entryPoints: [opts.entryPoint],
932
- bundle: true,
933
- platform: "node",
934
- format: "esm",
935
- outfile: opts.outfile,
936
- loader: opts.loader,
937
- external: opts.external,
938
- // Provide a require() polyfill for ESM bundles containing CommonJS packages.
939
- // Some bundled packages (e.g., 'scmp' used by 'mongodb-level') use
940
- // require('crypto'). When esbuild inlines these CommonJS packages, it keeps
941
- // the require() calls, but ESM doesn't have a global require. This banner
942
- // creates one using Node.js's official createRequire API, allowing the
943
- // bundled CommonJS code to work in ESM.
944
- banner: {
945
- js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`
946
- }
947
- });
948
-
949
1023
  // src/next/config-manager.ts
950
1024
  var TINA_FOLDER = "tina";
951
1025
  var LEGACY_TINA_FOLDER = ".tina";
@@ -1250,14 +1324,21 @@ var ConfigManager = class {
1250
1324
  const buildDir = path5.join(this.generatedCachePath, "database");
1251
1325
  const outfile = path5.join(buildDir, "database.build.mjs");
1252
1326
  const external = resolveDatabaseExternals(this.config);
1253
- await esbuild.build(
1254
- buildDatabaseEsbuildConfig({
1255
- entryPoint: this.selfHostedDatabaseFilePath,
1256
- outfile,
1257
- external,
1258
- loader: loaders
1259
- })
1260
- );
1327
+ try {
1328
+ await esbuild.build(
1329
+ buildDatabaseEsbuildConfig({
1330
+ entryPoint: this.selfHostedDatabaseFilePath,
1331
+ outfile,
1332
+ external,
1333
+ loader: loaders
1334
+ })
1335
+ );
1336
+ } catch (e) {
1337
+ throw formatConfigBuildError({
1338
+ error: e,
1339
+ rootPath: path5.resolve(this.rootPath)
1340
+ });
1341
+ }
1261
1342
  const result = await import(pathToFileURL(outfile).href);
1262
1343
  reapBuildSubdir(buildDir, this.generatedCachePath);
1263
1344
  return result.default;
@@ -1274,20 +1355,26 @@ var ConfigManager = class {
1274
1355
  const esmRequireBanner = {
1275
1356
  js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`
1276
1357
  };
1358
+ const resolvedRootPath = path5.resolve(this.rootPath);
1277
1359
  fs4.outputFileSync(tempTSConfigFile, "{}");
1278
- const result2 = await esbuild.build({
1279
- entryPoints: [configFilePath],
1280
- bundle: true,
1281
- target: ["esnext"],
1282
- platform: "browser",
1283
- format: "esm",
1284
- logLevel: "silent",
1285
- packages: "external",
1286
- ignoreAnnotations: true,
1287
- outfile: preBuildConfigPath,
1288
- loader: loaders,
1289
- metafile: true
1290
- });
1360
+ let result2;
1361
+ try {
1362
+ result2 = await esbuild.build({
1363
+ entryPoints: [configFilePath],
1364
+ bundle: true,
1365
+ target: ["esnext"],
1366
+ platform: "browser",
1367
+ format: "esm",
1368
+ logLevel: "silent",
1369
+ packages: "external",
1370
+ ignoreAnnotations: true,
1371
+ outfile: preBuildConfigPath,
1372
+ loader: loaders,
1373
+ metafile: true
1374
+ });
1375
+ } catch (e) {
1376
+ throw formatConfigBuildError({ error: e, rootPath: resolvedRootPath });
1377
+ }
1291
1378
  const flattenedList = [];
1292
1379
  Object.keys(result2.metafile.inputs).forEach((key) => {
1293
1380
  if (key.includes("node_modules") || key.includes("__generated__")) {
@@ -1295,27 +1382,31 @@ var ConfigManager = class {
1295
1382
  }
1296
1383
  flattenedList.push(key);
1297
1384
  });
1298
- await esbuild.build({
1299
- entryPoints: [configFilePath],
1300
- bundle: true,
1301
- target: ["esnext"],
1302
- logLevel: "silent",
1303
- platform: "node",
1304
- format: "esm",
1305
- outfile,
1306
- loader: loaders,
1307
- banner: esmRequireBanner
1308
- });
1309
- await esbuild.build({
1310
- entryPoints: [outfile],
1311
- bundle: true,
1312
- logLevel: "silent",
1313
- platform: "node",
1314
- target: ["esnext"],
1315
- format: "esm",
1316
- outfile: outfile2,
1317
- loader: loaders
1318
- });
1385
+ try {
1386
+ await esbuild.build({
1387
+ entryPoints: [configFilePath],
1388
+ bundle: true,
1389
+ target: ["esnext"],
1390
+ logLevel: "silent",
1391
+ platform: "node",
1392
+ format: "esm",
1393
+ outfile,
1394
+ loader: loaders,
1395
+ banner: esmRequireBanner
1396
+ });
1397
+ await esbuild.build({
1398
+ entryPoints: [outfile],
1399
+ bundle: true,
1400
+ logLevel: "silent",
1401
+ platform: "node",
1402
+ target: ["esnext"],
1403
+ format: "esm",
1404
+ outfile: outfile2,
1405
+ loader: loaders
1406
+ });
1407
+ } catch (e) {
1408
+ throw formatConfigBuildError({ error: e, rootPath: resolvedRootPath });
1409
+ }
1319
1410
  let result;
1320
1411
  try {
1321
1412
  result = await import(pathToFileURL(outfile2).href);
@@ -1414,294 +1505,23 @@ async function createAndInitializeDatabase(configManager, datalayerPort, bridgeO
1414
1505
  return database;
1415
1506
  }
1416
1507
 
1417
- // src/next/commands/baseCommands.ts
1418
- import { Command, Option } from "clipanion";
1419
- import chalk4 from "chalk";
1420
-
1421
- // src/utils/start-subprocess.ts
1422
- import childProcess from "child_process";
1423
- var startSubprocess2 = async ({ command: command2 }) => {
1424
- if (typeof command2 === "string") {
1425
- const commands = command2.split(" ");
1426
- const firstCommand = commands[0];
1427
- const args = commands.slice(1) || [];
1428
- const ps = childProcess.spawn(firstCommand, args, {
1429
- stdio: "inherit",
1430
- shell: true
1431
- });
1432
- ps.on("error", (code) => {
1433
- logger.error(
1434
- dangerText(
1435
- `An error has occurred in the Next.js child process. Error message below`
1436
- )
1437
- );
1438
- logger.error(`name: ${code.name}
1439
- 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";
1440
1513
 
1441
- stack: ${code.stack || "No stack was provided"}`);
1442
- });
1443
- ps.on("close", (code) => {
1444
- logger.info(`child process exited with code ${code}`);
1445
- process.exit(code);
1446
- });
1447
- return ps;
1448
- }
1449
- };
1450
-
1451
- // src/next/commands/baseCommands.ts
1452
- import { getChangedFiles, getSha, shaExists } from "@tinacms/graphql";
1453
- import fs5 from "fs-extra";
1454
- var BaseCommand = class extends Command {
1455
- experimentalDataLayer = Option.Boolean("--experimentalData", {
1456
- description: "DEPRECATED - Build the server with additional data querying capabilities"
1457
- });
1458
- isomorphicGitBridge = Option.Boolean("--isomorphicGitBridge", {
1459
- description: "DEPRECATED - Enable Isomorphic Git Bridge Implementation"
1460
- });
1461
- port = Option.String("-p,--port", "4001", {
1462
- description: "Specify a port to run the server on. (default 4001)"
1463
- });
1464
- datalayerPort = Option.String("--datalayer-port", "9000", {
1465
- description: "Specify a port to run the datalayer server on. (default 9000)"
1466
- });
1467
- subCommand = Option.String("-c,--command", {
1468
- description: "The sub-command to run"
1469
- });
1470
- rootPath = Option.String("--rootPath", {
1471
- description: "Specify the root directory to run the CLI from (defaults to current working directory)"
1472
- });
1473
- verbose = Option.Boolean("-v,--verbose", false, {
1474
- description: "increase verbosity of logged output"
1475
- });
1476
- noSDK = Option.Boolean("--noSDK", false, {
1477
- description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1478
- });
1479
- noTelemetry = Option.Boolean("--noTelemetry", false, {
1480
- description: "Disable anonymous telemetry that is collected"
1481
- });
1482
- async startSubCommand() {
1483
- let subProc;
1484
- if (this.subCommand) {
1485
- subProc = await startSubprocess2({ command: this.subCommand });
1486
- logger.info(
1487
- `Running web application with command: ${chalk4.cyan(this.subCommand)}`
1488
- );
1489
- }
1490
- function exitHandler(options, exitCode) {
1491
- if (subProc) {
1492
- subProc.kill();
1493
- }
1494
- process.exit();
1495
- }
1496
- process.on("exit", exitHandler);
1497
- process.on("SIGINT", exitHandler);
1498
- process.on("SIGUSR1", exitHandler);
1499
- process.on("SIGUSR2", exitHandler);
1500
- process.on("uncaughtException", (error) => {
1501
- logger.error(`Uncaught exception ${error.name}`);
1502
- console.error(error);
1503
- });
1504
- }
1505
- logDeprecationWarnings() {
1506
- if (this.isomorphicGitBridge) {
1507
- logger.warn("--isomorphicGitBridge has been deprecated");
1508
- }
1509
- if (this.experimentalDataLayer) {
1510
- logger.warn(
1511
- "--experimentalDataLayer has been deprecated, the data layer is now built-in automatically"
1512
- );
1513
- }
1514
- if (this.noSDK) {
1515
- logger.warn(
1516
- "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
1517
- );
1518
- }
1519
- }
1520
- async indexContentWithSpinner({
1521
- database,
1522
- graphQLSchema,
1523
- tinaSchema,
1524
- configManager,
1525
- partialReindex,
1526
- text
1527
- }) {
1528
- const textToUse = text || "Indexing local files";
1529
- const warnings = [];
1530
- await spin({
1531
- waitFor: async () => {
1532
- const rootPath = configManager.rootPath;
1533
- let sha;
1534
- try {
1535
- sha = await getSha({ fs: fs5, dir: rootPath });
1536
- } catch (e) {
1537
- if (partialReindex) {
1538
- console.error(
1539
- "Failed to get sha. NOTE: `--partial-reindex` only supported for git repositories"
1540
- );
1541
- throw e;
1542
- }
1543
- }
1544
- const lastSha = await database.getMetadata("lastSha");
1545
- const exists = lastSha && await shaExists({ fs: fs5, dir: rootPath, sha: lastSha });
1546
- let res;
1547
- if (partialReindex && lastSha && exists && sha) {
1548
- const pathFilter = {};
1549
- if (configManager.isUsingLegacyFolder) {
1550
- pathFilter[".tina/__generated__/_schema.json"] = {};
1551
- } else {
1552
- pathFilter["tina/tina-lock.json"] = {};
1553
- }
1554
- for (const collection of tinaSchema.getCollections()) {
1555
- pathFilter[collection.path] = {
1556
- matches: collection.match?.exclude || collection.match?.include ? tinaSchema.getMatches({ collection }) : void 0
1557
- };
1558
- }
1559
- const { added, modified, deleted } = await getChangedFiles({
1560
- fs: fs5,
1561
- dir: rootPath,
1562
- from: lastSha,
1563
- to: sha,
1564
- pathFilter
1565
- });
1566
- const tinaPathUpdates = modified.filter(
1567
- (path20) => path20.startsWith(".tina/__generated__/_schema.json") || path20.startsWith("tina/tina-lock.json")
1568
- );
1569
- if (tinaPathUpdates.length > 0) {
1570
- res = await database.indexContent({
1571
- graphQLSchema,
1572
- tinaSchema
1573
- });
1574
- } else {
1575
- if (added.length > 0 || modified.length > 0) {
1576
- await database.indexContentByPaths([...added, ...modified]);
1577
- }
1578
- if (deleted.length > 0) {
1579
- await database.deleteContentByPaths(deleted);
1580
- }
1581
- }
1582
- } else {
1583
- res = await database.indexContent({
1584
- graphQLSchema,
1585
- tinaSchema
1586
- });
1587
- }
1588
- if (sha) {
1589
- await database.setMetadata("lastSha", sha);
1590
- }
1591
- if (res?.warnings) {
1592
- warnings.push(...res.warnings);
1593
- }
1594
- },
1595
- text: textToUse
1596
- });
1597
- if (warnings.length > 0) {
1598
- logger.warn(`Indexing completed with ${warnings.length} warning(s)`);
1599
- warnings.forEach((warning) => {
1600
- logger.warn(warnText(`${warning}`));
1601
- });
1602
- }
1603
- }
1604
- };
1605
-
1606
- // src/next/commands/dev-command/html.ts
1607
- var errorHTML = `<style type="text/css">
1608
- #no-assets-placeholder body {
1609
- font-family: sans-serif;
1610
- font-size: 16px;
1611
- line-height: 1.4;
1612
- color: #333;
1613
- background-color: #f5f5f5;
1614
- }
1615
- #no-assets-placeholder {
1616
- max-width: 600px;
1617
- margin: 0 auto;
1618
- padding: 40px;
1619
- text-align: center;
1620
- background-color: #fff;
1621
- box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
1622
- }
1623
- #no-assets-placeholder h1 {
1624
- font-size: 24px;
1625
- margin-bottom: 20px;
1626
- }
1627
- #no-assets-placeholder p {
1628
- margin-bottom: 10px;
1629
- }
1630
- #no-assets-placeholder a {
1631
- color: #0077cc;
1632
- text-decoration: none;
1633
- }
1634
- #no-assets-placeholder a:hover {
1635
- text-decoration: underline;
1636
- }
1637
- </style>
1638
- <div id="no-assets-placeholder">
1639
- <h1>Failed loading TinaCMS assets</h1>
1640
- <p>
1641
- Your TinaCMS configuration may be misconfigured, and we could not load
1642
- the assets for this page.
1643
- </p>
1644
- <p>
1645
- 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.
1646
- </p>
1647
- </div>
1648
- </div>`.trim().replace(/[\r\n\s]+/g, " ");
1649
- var devHTML = (port) => `<!DOCTYPE html>
1650
- <html lang="en">
1651
- <head>
1652
- <meta charset="UTF-8" />
1653
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1654
- <title>TinaCMS</title>
1655
- </head>
1656
-
1657
- <!-- if development -->
1658
- <script type="module">
1659
- import RefreshRuntime from 'http://localhost:${port}/@react-refresh'
1660
- RefreshRuntime.injectIntoGlobalHook(window)
1661
- window.$RefreshReg$ = () => {}
1662
- window.$RefreshSig$ = () => (type) => type
1663
- window.__vite_plugin_react_preamble_installed__ = true
1664
- </script>
1665
- <script type="module" src="http://localhost:${port}/@vite/client"></script>
1666
- <script>
1667
- function handleLoadError() {
1668
- // Assets have failed to load
1669
- document.getElementById('root').innerHTML = '${errorHTML}';
1670
- }
1671
- </script>
1672
- <script
1673
- type="module"
1674
- src="http://localhost:${port}/src/main.tsx"
1675
- onerror="handleLoadError()"
1676
- ></script>
1677
- <body class="tina-tailwind">
1678
- <div id="root"></div>
1679
- </body>
1680
- </html>`;
1681
-
1682
- // src/next/commands/dev-command/server/index.ts
1683
- import { createServer as createViteServer } from "vite";
1684
-
1685
- // src/next/vite/index.ts
1686
- import path7 from "node:path";
1687
- import react from "@vitejs/plugin-react";
1688
- import fs6 from "fs-extra";
1689
- import normalizePath3 from "normalize-path";
1690
- import {
1691
- splitVendorChunkPlugin
1692
- } from "vite";
1693
-
1694
- // src/next/vite/cors.ts
1695
- var LOCALHOST_RE = /^https?:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/;
1696
- 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+)?$/;
1697
- function expandOrigins(raw) {
1698
- const hasPrivate = raw.some((o) => o === "private");
1699
- const filtered = raw.filter((o) => o !== "private");
1700
- return hasPrivate ? [...filtered, PRIVATE_NETWORK_RE] : filtered;
1701
- }
1702
- function isOriginAllowed(origin, allowedOrigins = []) {
1703
- if (!origin) {
1704
- return true;
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;
1705
1525
  }
1706
1526
  if (LOCALHOST_RE.test(origin)) {
1707
1527
  return true;
@@ -2034,15 +1854,15 @@ async function listFilesRecursively({
2034
1854
  config2.publicFolder,
2035
1855
  directoryPath
2036
1856
  );
2037
- const exists = await fs6.pathExists(fullDirectoryPath);
1857
+ const exists = await fs5.pathExists(fullDirectoryPath);
2038
1858
  if (!exists) {
2039
1859
  return { "0": [] };
2040
1860
  }
2041
- const items = await fs6.readdir(fullDirectoryPath);
1861
+ const items = await fs5.readdir(fullDirectoryPath);
2042
1862
  const staticMediaItems = [];
2043
1863
  for (const item of items) {
2044
1864
  const itemPath = path7.join(fullDirectoryPath, item);
2045
- const stats = await fs6.promises.lstat(itemPath);
1865
+ const stats = await fs5.promises.lstat(itemPath);
2046
1866
  const staticMediaItem = {
2047
1867
  id: item,
2048
1868
  filename: item,
@@ -2074,6 +1894,12 @@ async function listFilesRecursively({
2074
1894
  }
2075
1895
  return chunkArrayIntoObject(staticMediaItems, 20);
2076
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
+ };
2077
1903
  var createConfig = async ({
2078
1904
  configManager,
2079
1905
  apiURL,
@@ -2092,9 +1918,9 @@ var createConfig = async ({
2092
1918
  config: configManager.config.media.tina,
2093
1919
  roothPath: configManager.rootPath
2094
1920
  });
2095
- await fs6.outputFile(staticMediaPath, JSON.stringify(staticMedia, null, 2));
1921
+ await fs5.outputFile(staticMediaPath, JSON.stringify(staticMedia, null, 2));
2096
1922
  } else {
2097
- await fs6.outputFile(staticMediaPath, `[]`);
1923
+ await fs5.outputFile(staticMediaPath, `[]`);
2098
1924
  }
2099
1925
  const alias = {
2100
1926
  TINA_IMPORT: configManager.prebuildFilePath,
@@ -2114,17 +1940,11 @@ var createConfig = async ({
2114
1940
  } else {
2115
1941
  alias["CLIENT_IMPORT"] = configManager.isUsingTs() ? configManager.generatedTypesTSFilePath : configManager.generatedTypesJSFilePath;
2116
1942
  }
2117
- let basePath;
2118
- if (configManager.config.build.basePath) {
2119
- basePath = configManager.config.build.basePath;
2120
- }
2121
1943
  const fullVersion = configManager.getTinaGraphQLVersion();
2122
1944
  const version2 = `${fullVersion.major}.${fullVersion.minor}`;
2123
1945
  const config2 = {
2124
1946
  root: configManager.spaRootPath,
2125
- base: `/${basePath ? `${normalizePath3(basePath)}/` : ""}${normalizePath3(
2126
- configManager.config.build.outputFolder
2127
- )}/`,
1947
+ base: getBasePath(configManager),
2128
1948
  appType: "spa",
2129
1949
  resolve: {
2130
1950
  alias,
@@ -2141,11 +1961,13 @@ var createConfig = async ({
2141
1961
  * - `process.env.__NEXT_CROSS_ORIGIN`
2142
1962
  * - `process.env.__NEXT_I18N_SUPPORT`
2143
1963
  *
2144
- * Also, interestingly some of the advice for handling this doesn't work, references to replacing
2145
- * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
2146
- * 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.
2147
1969
  */
2148
- "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1970
+ "process.env": JSON.stringify(publicEnv),
2149
1971
  // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
2150
1972
  "process.platform": `"${process.platform}"`,
2151
1973
  __API_URL__: `"${apiURL}"`,
@@ -2196,18 +2018,12 @@ var createConfig = async ({
2196
2018
  rollupOptions
2197
2019
  },
2198
2020
  plugins: [
2199
- /**
2200
- * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
2201
- * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
2202
- */
2203
2021
  react({
2204
2022
  babel: {
2205
2023
  // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
2206
2024
  compact: true
2207
- },
2208
- fastRefresh: false
2025
+ }
2209
2026
  }),
2210
- splitVendorChunkPlugin(),
2211
2027
  tinaTailwind(configManager.spaRootPath, configManager.prebuildFilePath),
2212
2028
  ...plugins
2213
2029
  ]
@@ -2215,9 +2031,446 @@ var createConfig = async ({
2215
2031
  return config2;
2216
2032
  };
2217
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
+
2218
2471
  // src/next/vite/plugins.ts
2219
- import fs8 from "fs";
2220
- import path9 from "path";
2472
+ import fs9 from "fs";
2473
+ import path11 from "path";
2221
2474
  import { createFilter } from "@rollup/pluginutils";
2222
2475
  import { resolve as gqlResolve } from "@tinacms/graphql";
2223
2476
  import bodyParser from "body-parser";
@@ -2226,11 +2479,12 @@ import { transform as esbuildTransform } from "esbuild";
2226
2479
  import { transformWithEsbuild } from "vite";
2227
2480
 
2228
2481
  // src/next/commands/dev-command/server/media.ts
2229
- import path8, { join } from "path";
2482
+ import { randomUUID } from "crypto";
2483
+ import path10, { join } from "path";
2230
2484
  import busboy from "busboy";
2231
- import fs7 from "fs-extra";
2485
+ import fs8 from "fs-extra";
2232
2486
  var createMediaRouter = (config2) => {
2233
- const mediaFolder = path8.join(
2487
+ const mediaFolder = path10.join(
2234
2488
  config2.rootPath,
2235
2489
  config2.publicFolder,
2236
2490
  config2.mediaRoot
@@ -2244,10 +2498,12 @@ var createMediaRouter = (config2) => {
2244
2498
  );
2245
2499
  const limit = requestURL.searchParams.get("limit");
2246
2500
  const cursor = requestURL.searchParams.get("cursor");
2501
+ const search = requestURL.searchParams.get("search");
2247
2502
  const media = await mediaModel.listMedia({
2248
2503
  searchPath: folder,
2249
2504
  cursor,
2250
- limit
2505
+ limit,
2506
+ search
2251
2507
  });
2252
2508
  res.end(JSON.stringify(media));
2253
2509
  } catch (error) {
@@ -2273,6 +2529,39 @@ var createMediaRouter = (config2) => {
2273
2529
  throw error;
2274
2530
  }
2275
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
+ };
2276
2565
  const handlePost = async function(req, res) {
2277
2566
  const bb = busboy({ headers: req.headers });
2278
2567
  let responded = false;
@@ -2294,8 +2583,8 @@ var createMediaRouter = (config2) => {
2294
2583
  );
2295
2584
  return;
2296
2585
  }
2297
- await fs7.ensureDir(path8.dirname(saveTo));
2298
- file.pipe(fs7.createWriteStream(saveTo));
2586
+ await fs8.ensureDir(path10.dirname(saveTo));
2587
+ file.pipe(fs8.createWriteStream(saveTo));
2299
2588
  });
2300
2589
  bb.on("error", (error) => {
2301
2590
  responded = true;
@@ -2313,7 +2602,7 @@ var createMediaRouter = (config2) => {
2313
2602
  });
2314
2603
  req.pipe(bb);
2315
2604
  };
2316
- return { handleList, handleDelete, handlePost };
2605
+ return { handleList, handleDelete, handlePost, handleRename };
2317
2606
  };
2318
2607
  var parseMediaFolder = (str) => {
2319
2608
  let returnString = str;
@@ -2322,21 +2611,35 @@ var parseMediaFolder = (str) => {
2322
2611
  returnString = returnString.substr(0, returnString.length - 1);
2323
2612
  return returnString;
2324
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 || "");
2325
2628
  var ENCODED_TRAVERSAL_RE = /%2e%2e|%2f|%5c/i;
2326
2629
  function resolveRealPath(candidate) {
2327
2630
  try {
2328
- return fs7.realpathSync(candidate);
2631
+ return fs8.realpathSync(candidate);
2329
2632
  } catch {
2330
- const parent = path8.dirname(candidate);
2633
+ const parent = path10.dirname(candidate);
2331
2634
  if (parent === candidate) return candidate;
2332
- return path8.join(resolveRealPath(parent), path8.basename(candidate));
2635
+ return path10.join(resolveRealPath(parent), path10.basename(candidate));
2333
2636
  }
2334
2637
  }
2335
2638
  function assertSymlinkWithinBase(resolved, resolvedBase, userPath) {
2336
2639
  try {
2337
- const realBase = fs7.realpathSync(resolvedBase);
2640
+ const realBase = fs8.realpathSync(resolvedBase);
2338
2641
  const realResolved = resolveRealPath(resolved);
2339
- if (realResolved !== realBase && !realResolved.startsWith(realBase + path8.sep)) {
2642
+ if (realResolved !== realBase && !realResolved.startsWith(realBase + path10.sep)) {
2340
2643
  throw new PathTraversalError(userPath);
2341
2644
  }
2342
2645
  } catch (err) {
@@ -2347,13 +2650,13 @@ function resolveWithinBase(userPath, baseDir) {
2347
2650
  if (ENCODED_TRAVERSAL_RE.test(userPath)) {
2348
2651
  throw new PathTraversalError(userPath);
2349
2652
  }
2350
- const resolvedBase = path8.resolve(baseDir);
2351
- const resolved = path8.resolve(path8.join(baseDir, userPath));
2653
+ const resolvedBase = path10.resolve(baseDir);
2654
+ const resolved = path10.resolve(path10.join(baseDir, userPath));
2352
2655
  if (resolved === resolvedBase) {
2353
2656
  assertSymlinkWithinBase(resolved, resolvedBase, userPath);
2354
2657
  return resolvedBase;
2355
2658
  }
2356
- if (resolved.startsWith(resolvedBase + path8.sep)) {
2659
+ if (resolved.startsWith(resolvedBase + path10.sep)) {
2357
2660
  assertSymlinkWithinBase(resolved, resolvedBase, userPath);
2358
2661
  return resolved;
2359
2662
  }
@@ -2363,12 +2666,12 @@ function resolveStrictlyWithinBase(userPath, baseDir) {
2363
2666
  if (ENCODED_TRAVERSAL_RE.test(userPath)) {
2364
2667
  throw new PathTraversalError(userPath);
2365
2668
  }
2366
- const resolvedBase = path8.resolve(baseDir) + path8.sep;
2367
- 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));
2368
2671
  if (!resolved.startsWith(resolvedBase)) {
2369
2672
  throw new PathTraversalError(userPath);
2370
2673
  }
2371
- assertSymlinkWithinBase(resolved, path8.resolve(baseDir), userPath);
2674
+ assertSymlinkWithinBase(resolved, path10.resolve(baseDir), userPath);
2372
2675
  return resolved;
2373
2676
  }
2374
2677
  var MediaModel = class {
@@ -2385,16 +2688,27 @@ var MediaModel = class {
2385
2688
  const mediaBase = join(this.rootPath, this.publicFolder, this.mediaRoot);
2386
2689
  const validatedPath = resolveWithinBase(args.searchPath, mediaBase);
2387
2690
  const searchPath = parseMediaFolder(args.searchPath);
2388
- if (!await fs7.pathExists(validatedPath)) {
2691
+ if (!await fs8.pathExists(validatedPath)) {
2389
2692
  return {
2390
2693
  files: [],
2391
2694
  directories: []
2392
2695
  };
2393
2696
  }
2394
- 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);
2395
2709
  const filesProm = filesStr.map(async (file) => {
2396
2710
  const filePath = join(validatedPath, file);
2397
- const stat = await fs7.stat(filePath);
2711
+ const stat = await fs8.stat(filePath);
2398
2712
  let src = `/${file}`;
2399
2713
  const isFile = stat.isFile();
2400
2714
  if (!isFile) {
@@ -2430,10 +2744,11 @@ var MediaModel = class {
2430
2744
  }
2431
2745
  return 0;
2432
2746
  });
2433
- const limitItems = sortedItems.slice(offset, offset + limit);
2434
- const files = limitItems.filter((x) => x.isFile);
2435
- const directories = limitItems.filter((x) => !x.isFile).map((x) => x.src);
2436
- 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;
2437
2752
  return {
2438
2753
  files,
2439
2754
  directories,
@@ -2449,12 +2764,156 @@ var MediaModel = class {
2449
2764
  };
2450
2765
  }
2451
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
+ }
2452
2911
  async deleteMedia(args) {
2453
2912
  try {
2454
2913
  const mediaBase = join(this.rootPath, this.publicFolder, this.mediaRoot);
2455
2914
  const file = resolveStrictlyWithinBase(args.searchPath, mediaBase);
2456
- await fs7.stat(file);
2457
- await fs7.remove(file);
2915
+ await fs8.stat(file);
2916
+ await fs8.remove(file);
2458
2917
  return { ok: true };
2459
2918
  } catch (error) {
2460
2919
  if (error instanceof PathTraversalError) throw error;
@@ -2562,7 +3021,7 @@ var transformTsxPlugin = ({
2562
3021
  const plug = {
2563
3022
  name: "transform-tsx",
2564
3023
  async transform(code, id) {
2565
- const extName = path9.extname(id);
3024
+ const extName = path11.extname(id);
2566
3025
  if (extName.startsWith(".tsx") || extName.startsWith(".ts")) {
2567
3026
  const result = await esbuildTransform(code, { loader: "tsx" });
2568
3027
  return {
@@ -2573,6 +3032,7 @@ var transformTsxPlugin = ({
2573
3032
  };
2574
3033
  return plug;
2575
3034
  };
3035
+ var isMediaRenameRequest = (req) => req.method === "POST" && (req.url || "").split("?")[0] === "/media/rename";
2576
3036
  var devServerEndPointsPlugin = ({
2577
3037
  configManager,
2578
3038
  apiURL,
@@ -2585,6 +3045,7 @@ var devServerEndPointsPlugin = ({
2585
3045
  const isStateChangingRequest = (req) => {
2586
3046
  const url = req.url || "";
2587
3047
  if (url.startsWith("/media/upload")) return true;
3048
+ if (isMediaRenameRequest(req)) return true;
2588
3049
  if (url.startsWith("/media") && req.method === "DELETE") return true;
2589
3050
  if (url.startsWith("/graphql") && req.method === "POST") return true;
2590
3051
  if ((url.startsWith("/searchIndex") || url.startsWith("/v2/searchIndex")) && (req.method === "POST" || req.method === "DELETE"))
@@ -2622,6 +3083,10 @@ var devServerEndPointsPlugin = ({
2622
3083
  await mediaRouter.handlePost(req, res);
2623
3084
  return;
2624
3085
  }
3086
+ if (isMediaRenameRequest(req)) {
3087
+ await mediaRouter.handleRename(req, res);
3088
+ return;
3089
+ }
2625
3090
  if (req.url.startsWith("/media")) {
2626
3091
  if (req.method === "DELETE") {
2627
3092
  await mediaRouter.handleDelete(req, res);
@@ -2686,7 +3151,7 @@ function viteTransformExtension({
2686
3151
  async transform(code, id) {
2687
3152
  if (filter(id)) {
2688
3153
  const { transform: transform2 } = await import("@svgr/core");
2689
- const svgCode = await fs8.promises.readFile(
3154
+ const svgCode = await fs9.promises.readFile(
2690
3155
  id.replace(/\?.*$/, ""),
2691
3156
  "utf8"
2692
3157
  );
@@ -2797,6 +3262,7 @@ var DevCommand = class extends BaseCommand {
2797
3262
  });
2798
3263
  logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2799
3264
  this.logDeprecationWarnings();
3265
+ this.warnOnVersionSkew(configManager.rootPath);
2800
3266
  createDBServer(Number(this.datalayerPort));
2801
3267
  let database = null;
2802
3268
  const dbLock = async (fn) => {
@@ -2836,13 +3302,13 @@ var DevCommand = class extends BaseCommand {
2836
3302
  });
2837
3303
  const apiURL2 = await codegen2.execute();
2838
3304
  if (!configManager.isUsingLegacyFolder) {
2839
- const schemaObject = await fs9.readJSON(
3305
+ const schemaObject = await fs10.readJSON(
2840
3306
  configManager.generatedSchemaJSONPath
2841
3307
  );
2842
- const lookupObject = await fs9.readJSON(
3308
+ const lookupObject = await fs10.readJSON(
2843
3309
  configManager.generatedLookupJSONPath
2844
3310
  );
2845
- const graphqlSchemaObject = await fs9.readJSON(
3311
+ const graphqlSchemaObject = await fs10.readJSON(
2846
3312
  configManager.generatedGraphQLJSONPath
2847
3313
  );
2848
3314
  const tinaLockFilename = "tina-lock.json";
@@ -2851,8 +3317,8 @@ var DevCommand = class extends BaseCommand {
2851
3317
  lookup: lookupObject,
2852
3318
  graphql: graphqlSchemaObject
2853
3319
  });
2854
- fs9.writeFileSync(
2855
- path10.join(configManager.tinaFolderPath, tinaLockFilename),
3320
+ fs10.writeFileSync(
3321
+ path12.join(configManager.tinaFolderPath, tinaLockFilename),
2856
3322
  tinaLockContent
2857
3323
  );
2858
3324
  }
@@ -2896,8 +3362,11 @@ ${dangerText(e.message)}
2896
3362
  const { apiURL, graphQLSchema, tinaSchema } = await setup({
2897
3363
  firstTime: true
2898
3364
  });
2899
- await fs9.outputFile(configManager.outputHTMLFilePath, devHTML(this.port));
2900
- await fs9.outputFile(
3365
+ await fs10.outputFile(
3366
+ configManager.outputHTMLFilePath,
3367
+ devHTML(this.port, getBasePath(configManager))
3368
+ );
3369
+ await fs10.outputFile(
2901
3370
  configManager.outputGitignorePath,
2902
3371
  "index.html\nassets/"
2903
3372
  );
@@ -3042,7 +3511,7 @@ ${dangerText(e.message)}
3042
3511
  watchContentFiles(configManager, database, databaseLock, searchIndexer) {
3043
3512
  const collectionContentFiles = [];
3044
3513
  configManager.config.schema.collections.forEach((collection) => {
3045
- const collectionGlob = `${path10.join(
3514
+ const collectionGlob = `${path12.join(
3046
3515
  configManager.contentRootPath,
3047
3516
  collection.path
3048
3517
  )}/**/*.${collection.format || "md"}`;
@@ -3092,8 +3561,10 @@ ${dangerText(e.message)}
3092
3561
 
3093
3562
  // src/next/commands/build-command/index.ts
3094
3563
  import crypto from "crypto";
3095
- import path11 from "path";
3096
- import { diff } from "@graphql-inspector/core";
3564
+ import path13 from "path";
3565
+ import {
3566
+ diff
3567
+ } from "@graphql-inspector/core";
3097
3568
  import { FilesystemBridge as FilesystemBridge3, buildSchema as buildSchema2 } from "@tinacms/graphql";
3098
3569
  import { parseURL as parseURL2 } from "@tinacms/schema-tools";
3099
3570
  import {
@@ -3101,7 +3572,7 @@ import {
3101
3572
  TinaCMSSearchIndexClient
3102
3573
  } from "@tinacms/search";
3103
3574
  import { Command as Command3, Option as Option3 } from "clipanion";
3104
- import fs10 from "fs-extra";
3575
+ import fs11 from "fs-extra";
3105
3576
  import {
3106
3577
  buildASTSchema as buildASTSchema2,
3107
3578
  buildClientSchema,
@@ -3121,6 +3592,78 @@ var getFaqLink = (type) => {
3121
3592
  }
3122
3593
  };
3123
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
+
3124
3667
  // src/utils/sleep.ts
3125
3668
  function timeout(ms) {
3126
3669
  return new Promise((resolve2) => setTimeout(resolve2, ms));
@@ -3238,75 +3781,6 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
3238
3781
  });
3239
3782
  };
3240
3783
 
3241
- // src/utils/posthog.ts
3242
- import { randomUUID } from "node:crypto";
3243
- import { PostHog } from "posthog-node";
3244
-
3245
- // src/utils/fetchPostHogConfig.ts
3246
- async function fetchPostHogConfig(endpointUrl) {
3247
- try {
3248
- const response = await fetch(endpointUrl, {
3249
- method: "GET",
3250
- headers: {
3251
- "Content-Type": "application/json"
3252
- },
3253
- // Cap latency for offline / firewalled developers. Endpoint is
3254
- // typically single-digit ms when reachable; a timeout returns {}
3255
- // and disables telemetry for this run, which is the right behavior.
3256
- signal: AbortSignal.timeout(2e3)
3257
- });
3258
- if (!response.ok) {
3259
- throw new Error(`Failed to fetch PostHog config: ${response.statusText}`);
3260
- }
3261
- const config2 = await response.json();
3262
- return {
3263
- POSTHOG_API_KEY: config2.api_key,
3264
- POSTHOG_ENDPOINT: config2.host
3265
- };
3266
- } catch {
3267
- return {};
3268
- }
3269
- }
3270
-
3271
- // src/utils/posthog.ts
3272
- function generateSessionId() {
3273
- return randomUUID();
3274
- }
3275
- var BuildInvokeEvent = "tinacms-cli-build-invoke";
3276
- var BuildFinishedEvent = "tinacms-cli-build-finished";
3277
- async function initializePostHog(configEndpoint, disableGeoip) {
3278
- if (process.env.TINA_DEV === "true") return null;
3279
- let apiKey;
3280
- let endpoint;
3281
- if (configEndpoint) {
3282
- const config2 = await fetchPostHogConfig(configEndpoint);
3283
- apiKey = config2.POSTHOG_API_KEY;
3284
- endpoint = config2.POSTHOG_ENDPOINT;
3285
- }
3286
- if (!apiKey) return null;
3287
- return new PostHog(apiKey, {
3288
- host: endpoint,
3289
- disableGeoip: disableGeoip ?? true
3290
- });
3291
- }
3292
- function postHogCapture(client, distinctId, event, properties) {
3293
- if (!client) {
3294
- return;
3295
- }
3296
- try {
3297
- client.capture({
3298
- distinctId,
3299
- event,
3300
- properties: {
3301
- ...properties,
3302
- system: "tinacms/cli"
3303
- }
3304
- });
3305
- } catch (error) {
3306
- console.error("Error capturing event:", error);
3307
- }
3308
- }
3309
-
3310
3784
  // src/next/commands/build-command/index.ts
3311
3785
  var BuildCommand = class extends BaseCommand {
3312
3786
  static paths = [["build"]];
@@ -3372,6 +3846,7 @@ var BuildCommand = class extends BaseCommand {
3372
3846
  tinaGraphQLVersion: this.tinaGraphQLVersion,
3373
3847
  legacyNoSDK: this.noSDK
3374
3848
  });
3849
+ this.warnOnVersionSkew(configManager.rootPath);
3375
3850
  if (this.previewName && !this.previewBaseBranch) {
3376
3851
  logger.error(
3377
3852
  `${dangerText(
@@ -3565,7 +4040,7 @@ ${dangerText(e.message)}
3565
4040
  }
3566
4041
  }
3567
4042
  await buildProductionSpa(configManager, database, codegen2.productionUrl);
3568
- await fs10.outputFile(
4043
+ await fs11.outputFile(
3569
4044
  configManager.outputGitignorePath,
3570
4045
  "index.html\nassets/"
3571
4046
  );
@@ -3950,7 +4425,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3950
4425
  }
3951
4426
  const localTinaSchema = JSON.parse(
3952
4427
  await database.bridge.get(
3953
- path11.join(database.tinaDirectory, "__generated__", "_schema.json")
4428
+ path13.join(database.tinaDirectory, "__generated__", "_schema.json")
3954
4429
  )
3955
4430
  );
3956
4431
  localTinaSchema.version = void 0;
@@ -4313,19 +4788,19 @@ var AuditCommand = class extends Command4 {
4313
4788
  import { Command as Command6, Option as Option6 } from "clipanion";
4314
4789
 
4315
4790
  // src/cmds/init/detectEnvironment.ts
4316
- import fs12 from "fs-extra";
4317
- import path13 from "path";
4791
+ import fs13 from "fs-extra";
4792
+ import path15 from "path";
4318
4793
 
4319
4794
  // src/cmds/init/astro-config-detect.ts
4320
- import fs11 from "fs";
4321
- import path12 from "path";
4795
+ import fs12 from "fs";
4796
+ import path14 from "path";
4322
4797
  var isDefaultAstroConfig = (source) => {
4323
4798
  const stripped = source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/\s+/g, " ").trim();
4324
4799
  return /^import\s*\{\s*defineConfig\s*\}\s*from\s*['"]astro\/config['"]\s*;?\s*export\s+default\s+defineConfig\(\s*\{\s*\}\s*\)\s*;?$/.test(
4325
4800
  stripped
4326
4801
  );
4327
4802
  };
4328
- 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)));
4329
4804
  var parseAstroMajor = (version2) => {
4330
4805
  const match = version2 ? String(version2).match(/(\d+)/) : null;
4331
4806
  return match ? Number(match[1]) : void 0;
@@ -4341,20 +4816,20 @@ var checkGitignoreForItem = async ({
4341
4816
  baseDir,
4342
4817
  line
4343
4818
  }) => {
4344
- const gitignoreContent = fs12.readFileSync(path13.join(baseDir, ".gitignore")).toString();
4819
+ const gitignoreContent = fs13.readFileSync(path15.join(baseDir, ".gitignore")).toString();
4345
4820
  return gitignoreContent.split("\n").some((item) => item === line);
4346
4821
  };
4347
4822
  var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
4348
4823
  const result = {
4349
- fullPathTS: path13.join(
4824
+ fullPathTS: path15.join(
4350
4825
  parentPath,
4351
4826
  `${name2}.${opts?.typescriptSuffix || opts?.extensionOverride || "ts"}`
4352
4827
  ),
4353
- fullPathJS: path13.join(
4828
+ fullPathJS: path15.join(
4354
4829
  parentPath,
4355
4830
  `${name2}.${opts?.extensionOverride || "js"}`
4356
4831
  ),
4357
- fullPathOverride: opts?.extensionOverride ? path13.join(parentPath, `${name2}.${opts?.extensionOverride}`) : "",
4832
+ fullPathOverride: opts?.extensionOverride ? path15.join(parentPath, `${name2}.${opts?.extensionOverride}`) : "",
4358
4833
  generatedFileType,
4359
4834
  name: name2,
4360
4835
  parentPath,
@@ -4372,8 +4847,8 @@ var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
4372
4847
  };
4373
4848
  }
4374
4849
  };
4375
- result.typescriptExists = await fs12.pathExists(result.fullPathTS);
4376
- result.javascriptExists = await fs12.pathExists(result.fullPathJS);
4850
+ result.typescriptExists = await fs13.pathExists(result.fullPathTS);
4851
+ result.javascriptExists = await fs13.pathExists(result.fullPathJS);
4377
4852
  return result;
4378
4853
  };
4379
4854
  var detectEnvironment = async ({
@@ -4382,21 +4857,21 @@ var detectEnvironment = async ({
4382
4857
  rootPath,
4383
4858
  debug = false
4384
4859
  }) => {
4385
- const hasForestryConfig = await fs12.pathExists(
4386
- path13.join(pathToForestryConfig, ".forestry", "settings.yml")
4860
+ const hasForestryConfig = await fs13.pathExists(
4861
+ path15.join(pathToForestryConfig, ".forestry", "settings.yml")
4387
4862
  );
4388
- const sampleContentPath = path13.join(
4863
+ const sampleContentPath = path15.join(
4389
4864
  baseDir,
4390
4865
  "content",
4391
4866
  "posts",
4392
4867
  "hello-world.md"
4393
4868
  );
4394
- const usingSrc = fs12.pathExistsSync(path13.join(baseDir, "src")) && (fs12.pathExistsSync(path13.join(baseDir, "src", "app")) || fs12.pathExistsSync(path13.join(baseDir, "src", "pages")));
4395
- 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");
4396
4871
  const tinaConfigExists = Boolean(
4397
4872
  // Does the tina folder exist?
4398
- await fs12.pathExists(tinaFolder) && // Does the tina folder contain a config file?
4399
- (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"))
4400
4875
  );
4401
4876
  const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
4402
4877
  Boolean
@@ -4408,12 +4883,12 @@ var detectEnvironment = async ({
4408
4883
  "next-api-handler": await makeGeneratedFile(
4409
4884
  "[...routes]",
4410
4885
  "next-api-handler",
4411
- path13.join(...pagesDir, "api", "tina")
4886
+ path15.join(...pagesDir, "api", "tina")
4412
4887
  ),
4413
4888
  "reactive-example": await makeGeneratedFile(
4414
4889
  "[filename]",
4415
4890
  "reactive-example",
4416
- path13.join(...pagesDir, "demo", "blog"),
4891
+ path15.join(...pagesDir, "demo", "blog"),
4417
4892
  {
4418
4893
  typescriptSuffix: "tsx"
4419
4894
  }
@@ -4421,24 +4896,24 @@ var detectEnvironment = async ({
4421
4896
  "users-json": await makeGeneratedFile(
4422
4897
  "index",
4423
4898
  "users-json",
4424
- path13.join(baseDir, "content", "users"),
4899
+ path15.join(baseDir, "content", "users"),
4425
4900
  { extensionOverride: "json" }
4426
4901
  ),
4427
4902
  "sample-content": await makeGeneratedFile(
4428
4903
  "hello-world",
4429
4904
  "sample-content",
4430
- path13.join(baseDir, "content", "posts"),
4905
+ path15.join(baseDir, "content", "posts"),
4431
4906
  { extensionOverride: "md" }
4432
4907
  )
4433
4908
  };
4434
- const hasSampleContent = await fs12.pathExists(sampleContentPath);
4435
- const hasPackageJSON = await fs12.pathExists("package.json");
4909
+ const hasSampleContent = await fs13.pathExists(sampleContentPath);
4910
+ const hasPackageJSON = await fs13.pathExists("package.json");
4436
4911
  let hasTinaDeps = false;
4437
4912
  let hasReactDep = false;
4438
4913
  let astroMajor;
4439
4914
  if (hasPackageJSON) {
4440
4915
  try {
4441
- const packageJSON = await fs12.readJSON("package.json");
4916
+ const packageJSON = await fs13.readJSON("package.json");
4442
4917
  const deps = [];
4443
4918
  if (packageJSON?.dependencies) {
4444
4919
  deps.push(...Object.keys(packageJSON.dependencies));
@@ -4461,7 +4936,7 @@ var detectEnvironment = async ({
4461
4936
  );
4462
4937
  }
4463
4938
  }
4464
- const hasGitIgnore = await fs12.pathExists(path13.join(".gitignore"));
4939
+ const hasGitIgnore = await fs13.pathExists(path15.join(".gitignore"));
4465
4940
  const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
4466
4941
  const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
4467
4942
  const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
@@ -4471,9 +4946,9 @@ var detectEnvironment = async ({
4471
4946
  });
4472
4947
  let frontMatterFormat;
4473
4948
  if (hasForestryConfig) {
4474
- const hugoConfigPath = path13.join(rootPath, "config.toml");
4475
- if (await fs12.pathExists(hugoConfigPath)) {
4476
- 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");
4477
4952
  const metaDataFormat = hugoConfig.toString().match(/metaDataFormat = "(.*)"/)?.[1];
4478
4953
  if (metaDataFormat && (metaDataFormat === "yaml" || metaDataFormat === "toml" || metaDataFormat === "json")) {
4479
4954
  frontMatterFormat = metaDataFormat;
@@ -5098,6 +5573,7 @@ var CLICommand = class {
5098
5573
  constructor(handler) {
5099
5574
  this.handler = handler;
5100
5575
  }
5576
+ handler;
5101
5577
  async execute(params) {
5102
5578
  await this.handler.setup(params);
5103
5579
  const environment = await this.handler.detectEnvironment(params);
@@ -5107,19 +5583,19 @@ var CLICommand = class {
5107
5583
  };
5108
5584
 
5109
5585
  // src/cmds/init/apply.ts
5110
- import path18 from "path";
5586
+ import path20 from "path";
5111
5587
 
5112
5588
  // src/cmds/forestry-migrate/index.ts
5113
- import fs14 from "fs-extra";
5114
- import path15 from "path";
5589
+ import fs15 from "fs-extra";
5590
+ import path17 from "path";
5115
5591
  import yaml2 from "js-yaml";
5116
5592
  import pkg from "minimatch";
5117
5593
  import { parseFile, stringifyFile } from "@tinacms/graphql";
5118
5594
  import { CONTENT_FORMATS } from "@tinacms/schema-tools";
5119
5595
 
5120
5596
  // src/cmds/forestry-migrate/util/index.ts
5121
- import fs13 from "fs-extra";
5122
- import path14 from "path";
5597
+ import fs14 from "fs-extra";
5598
+ import path16 from "path";
5123
5599
  import yaml from "js-yaml";
5124
5600
  import z2 from "zod";
5125
5601
 
@@ -5561,7 +6037,7 @@ var transformForestryFieldsToTinaFields = ({
5561
6037
  return tinaFields;
5562
6038
  };
5563
6039
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
5564
- const templatePath = path14.join(
6040
+ const templatePath = path16.join(
5565
6041
  pathToForestryConfig,
5566
6042
  ".forestry",
5567
6043
  "front_matter",
@@ -5570,7 +6046,7 @@ var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false })
5570
6046
  );
5571
6047
  let templateString = "";
5572
6048
  try {
5573
- templateString = fs13.readFileSync(templatePath).toString();
6049
+ templateString = fs14.readFileSync(templatePath).toString();
5574
6050
  } catch {
5575
6051
  throw new Error(
5576
6052
  `Could not find template ${tem} at ${templatePath}
@@ -5629,9 +6105,9 @@ function checkExt(ext) {
5629
6105
  var generateAllTemplates = async ({
5630
6106
  pathToForestryConfig
5631
6107
  }) => {
5632
- const allTemplates = (await fs14.readdir(
5633
- path15.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
5634
- )).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"));
5635
6111
  const templateMap = /* @__PURE__ */ new Map();
5636
6112
  const proms = allTemplates.map(async (tem) => {
5637
6113
  try {
@@ -5776,9 +6252,9 @@ var generateCollectionFromForestrySection = (args) => {
5776
6252
  return c;
5777
6253
  } else if (section.type === "document") {
5778
6254
  const filePath = section.path;
5779
- const extname = path15.extname(filePath);
5780
- const fileName = path15.basename(filePath, extname);
5781
- const dir = path15.dirname(filePath);
6255
+ const extname = path17.extname(filePath);
6256
+ const fileName = path17.basename(filePath, extname);
6257
+ const dir = path17.dirname(filePath);
5782
6258
  const ext = checkExt(extname);
5783
6259
  if (ext) {
5784
6260
  const fields = [];
@@ -5840,8 +6316,8 @@ var generateCollections = async ({
5840
6316
  templateMap,
5841
6317
  usingTypescript
5842
6318
  });
5843
- const forestryConfig = await fs14.readFile(
5844
- path15.join(pathToForestryConfig, ".forestry", "settings.yml")
6319
+ const forestryConfig = await fs15.readFile(
6320
+ path17.join(pathToForestryConfig, ".forestry", "settings.yml")
5845
6321
  );
5846
6322
  rewriteTemplateKeysInDocs({
5847
6323
  templateMap,
@@ -5871,12 +6347,12 @@ var rewriteTemplateKeysInDocs = (args) => {
5871
6347
  const { templateObj } = templateMap.get(templateKey);
5872
6348
  templateObj?.pages?.forEach((page) => {
5873
6349
  try {
5874
- const filePath = path15.join(page);
5875
- if (fs14.lstatSync(filePath).isDirectory()) {
6350
+ const filePath = path17.join(page);
6351
+ if (fs15.lstatSync(filePath).isDirectory()) {
5876
6352
  return;
5877
6353
  }
5878
- const extname = path15.extname(filePath);
5879
- const fileContent = fs14.readFileSync(filePath).toString();
6354
+ const extname = path17.extname(filePath);
6355
+ const fileContent = fs15.readFileSync(filePath).toString();
5880
6356
  const content = parseFile(
5881
6357
  fileContent,
5882
6358
  extname,
@@ -5887,7 +6363,7 @@ var rewriteTemplateKeysInDocs = (args) => {
5887
6363
  _template: stringifyLabel(templateKey),
5888
6364
  ...content
5889
6365
  };
5890
- fs14.writeFileSync(
6366
+ fs15.writeFileSync(
5891
6367
  filePath,
5892
6368
  stringifyFile(newContent, extname, true, markdownParseConfig)
5893
6369
  );
@@ -5902,12 +6378,12 @@ var rewriteTemplateKeysInDocs = (args) => {
5902
6378
 
5903
6379
  // src/cmds/init/apply.ts
5904
6380
  import { Telemetry as Telemetry3 } from "@tinacms/metrics";
5905
- import fs18 from "fs-extra";
6381
+ import fs19 from "fs-extra";
5906
6382
 
5907
6383
  // src/next/commands/codemod-command/index.ts
5908
6384
  import { Command as Command5, Option as Option5 } from "clipanion";
5909
- import fs15 from "fs-extra";
5910
- import path16 from "path";
6385
+ import fs16 from "fs-extra";
6386
+ import path18 from "path";
5911
6387
  var CodemodCommand = class extends Command5 {
5912
6388
  static paths = [["codemod"], ["codemod", "move-tina-folder"]];
5913
6389
  rootPath = Option5.String("--rootPath", {
@@ -5948,13 +6424,13 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5948
6424
  logger.error(e.message);
5949
6425
  process.exit(1);
5950
6426
  }
5951
- const tinaDestination = path16.join(configManager.rootPath, "tina");
5952
- if (await fs15.existsSync(tinaDestination)) {
6427
+ const tinaDestination = path18.join(configManager.rootPath, "tina");
6428
+ if (await fs16.existsSync(tinaDestination)) {
5953
6429
  logger.info(
5954
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.`
5955
6431
  );
5956
6432
  } else {
5957
- await fs15.moveSync(configManager.tinaFolderPath, tinaDestination);
6433
+ await fs16.moveSync(configManager.tinaFolderPath, tinaDestination);
5958
6434
  await writeGitignore(configManager.rootPath);
5959
6435
  logger.info(
5960
6436
  "Move to 'tina' folder complete. Be sure to update any imports of the autogenerated client!"
@@ -5962,8 +6438,8 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
5962
6438
  }
5963
6439
  };
5964
6440
  var writeGitignore = async (rootPath) => {
5965
- await fs15.outputFileSync(
5966
- path16.join(rootPath, "tina", ".gitignore"),
6441
+ await fs16.outputFileSync(
6442
+ path18.join(rootPath, "tina", ".gitignore"),
5967
6443
  "__generated__"
5968
6444
  );
5969
6445
  };
@@ -6022,7 +6498,7 @@ const BlogPage = (props) => {
6022
6498
  {' '}
6023
6499
  Check out this guide
6024
6500
  </a>{' '}
6025
- to see how add TinaCMS to an existing Next.js site.
6501
+ to see how to add TinaCMS to an existing Next.js site.
6026
6502
  </div>
6027
6503
  </div>
6028
6504
  </>
@@ -6474,8 +6950,8 @@ function extendAstroScripts(scripts) {
6474
6950
  }
6475
6951
 
6476
6952
  // src/cmds/init/astro-visual-editing.ts
6477
- import fs16 from "fs-extra";
6478
- import path17 from "path";
6953
+ import fs17 from "fs-extra";
6954
+ import path19 from "path";
6479
6955
  var TS_NOCHECK = "// @ts-nocheck (generated types/client appear after your first tinacms dev run)\n";
6480
6956
  var DEMO_FILES = {
6481
6957
  "src/lib/tina/data.ts": `${TS_NOCHECK}import { requestWithMetadata } from '@tinacms/astro/data';
@@ -6746,8 +7222,8 @@ var ASTRO_CONFIG_FILES = [
6746
7222
  "astro.config.cjs",
6747
7223
  "astro.config.cts"
6748
7224
  ];
6749
- var findAstroConfig = (baseDir) => ASTRO_CONFIG_FILES.map((file) => path17.join(baseDir, file)).find(
6750
- (p) => fs16.existsSync(p)
7225
+ var findAstroConfig = (baseDir) => ASTRO_CONFIG_FILES.map((file) => path19.join(baseDir, file)).find(
7226
+ (p) => fs17.existsSync(p)
6751
7227
  );
6752
7228
  var setupAstroVisualEditing = ({
6753
7229
  baseDir
@@ -6765,17 +7241,17 @@ var setupAstroVisualEditing = ({
6765
7241
  return { configHandled: true, demoScaffolded: false };
6766
7242
  }
6767
7243
  for (const rel of relPaths) {
6768
- fs16.outputFileSync(path17.join(baseDir, rel), DEMO_FILES[rel]);
7244
+ fs17.outputFileSync(path19.join(baseDir, rel), DEMO_FILES[rel]);
6769
7245
  }
6770
7246
  logger.info("Adding a visual-editing demo at /tinacms-demo... \u2705");
6771
7247
  const configPath = findAstroConfig(baseDir);
6772
7248
  if (!configPath) {
6773
- fs16.writeFileSync(path17.join(baseDir, "astro.config.mjs"), ASTRO_CONFIG);
7249
+ fs17.writeFileSync(path19.join(baseDir, "astro.config.mjs"), ASTRO_CONFIG);
6774
7250
  logger.info("Creating astro.config for visual editing... \u2705");
6775
7251
  return { configHandled: true, demoScaffolded: true };
6776
7252
  }
6777
- if (isDefaultAstroConfig(fs16.readFileSync(configPath).toString())) {
6778
- fs16.writeFileSync(configPath, ASTRO_CONFIG);
7253
+ if (isDefaultAstroConfig(fs17.readFileSync(configPath).toString())) {
7254
+ fs17.writeFileSync(configPath, ASTRO_CONFIG);
6779
7255
  logger.info("Wiring astro.config for visual editing... \u2705");
6780
7256
  return { configHandled: true, demoScaffolded: true };
6781
7257
  }
@@ -6787,7 +7263,7 @@ var logAstroConfigGuidance = () => {
6787
7263
 
6788
7264
  // src/cmds/init/codegen/index.ts
6789
7265
  import ts2 from "typescript";
6790
- import fs17 from "fs-extra";
7266
+ import fs18 from "fs-extra";
6791
7267
 
6792
7268
  // src/cmds/init/codegen/util.ts
6793
7269
  import ts from "typescript";
@@ -7024,7 +7500,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
7024
7500
  const pathToConfig = configFile.resolve(config2.typescript).path;
7025
7501
  const sourceFile = ts2.createSourceFile(
7026
7502
  pathToConfig,
7027
- fs17.readFileSync(pathToConfig, "utf8"),
7503
+ fs18.readFileSync(pathToConfig, "utf8"),
7028
7504
  config2.typescript ? ts2.ScriptTarget.Latest : ts2.ScriptTarget.ESNext
7029
7505
  );
7030
7506
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
@@ -7074,7 +7550,7 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
7074
7550
  )
7075
7551
  ].map((visitor) => makeTransformer(visitor))
7076
7552
  );
7077
- return fs17.writeFile(
7553
+ return fs18.writeFile(
7078
7554
  pathToConfig,
7079
7555
  ts2.createPrinter({ omitTrailingSemicolon: true }).printFile(transformedSourceFileResult.transformed[0])
7080
7556
  );
@@ -7200,8 +7676,8 @@ async function apply({
7200
7676
  await addConfigFile({
7201
7677
  configArgs: {
7202
7678
  config: config2,
7203
- publicFolder: path18.join(
7204
- path18.relative(process.cwd(), pathToForestryConfig),
7679
+ publicFolder: path20.join(
7680
+ path20.relative(process.cwd(), pathToForestryConfig),
7205
7681
  config2.publicFolder
7206
7682
  ),
7207
7683
  collections,
@@ -7278,8 +7754,8 @@ var createPackageJSON = async () => {
7278
7754
  };
7279
7755
  var createGitignore = async ({ baseDir }) => {
7280
7756
  logger.info(logText("No .gitignore found, creating one"));
7281
- fs18.outputFileSync(
7282
- path18.join(baseDir, ".gitignore"),
7757
+ fs19.outputFileSync(
7758
+ path20.join(baseDir, ".gitignore"),
7283
7759
  "node_modules\ntina/__generated__\n"
7284
7760
  );
7285
7761
  };
@@ -7288,11 +7764,11 @@ var updateGitIgnore = async ({
7288
7764
  items
7289
7765
  }) => {
7290
7766
  logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
7291
- const gitignoreContent = fs18.readFileSync(path18.join(baseDir, ".gitignore")).toString();
7767
+ const gitignoreContent = fs19.readFileSync(path20.join(baseDir, ".gitignore")).toString();
7292
7768
  const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
7293
7769
  "\n"
7294
7770
  );
7295
- await fs18.writeFile(path18.join(baseDir, ".gitignore"), newGitignoreContent);
7771
+ await fs19.writeFile(path20.join(baseDir, ".gitignore"), newGitignoreContent);
7296
7772
  };
7297
7773
  var addDependencies = async (config2, env, params) => {
7298
7774
  const { packageManager } = config2;
@@ -7369,22 +7845,22 @@ var writeGeneratedFile = async ({
7369
7845
  content,
7370
7846
  typescript
7371
7847
  }) => {
7372
- const { exists, path: path20, parentPath } = generatedFile.resolve(typescript);
7848
+ const { exists, path: path22, parentPath } = generatedFile.resolve(typescript);
7373
7849
  if (exists) {
7374
7850
  if (overwrite) {
7375
- logger.info(`Overwriting file at ${path20}... \u2705`);
7376
- fs18.outputFileSync(path20, content);
7851
+ logger.info(`Overwriting file at ${path22}... \u2705`);
7852
+ fs19.outputFileSync(path22, content);
7377
7853
  } else {
7378
- logger.info(`Not overwriting file at ${path20}.`);
7854
+ logger.info(`Not overwriting file at ${path22}.`);
7379
7855
  logger.info(
7380
- logText(`Please add the following to ${path20}:
7856
+ logText(`Please add the following to ${path22}:
7381
7857
  ${indentText(content)}}`)
7382
7858
  );
7383
7859
  }
7384
7860
  } else {
7385
- logger.info(`Adding file at ${path20}... \u2705`);
7386
- await fs18.ensureDir(parentPath);
7387
- fs18.outputFileSync(path20, content);
7861
+ logger.info(`Adding file at ${path22}... \u2705`);
7862
+ await fs19.ensureDir(parentPath);
7863
+ fs19.outputFileSync(path22, content);
7388
7864
  }
7389
7865
  };
7390
7866
  var addConfigFile = async ({
@@ -7462,7 +7938,7 @@ var addContentFile = async ({
7462
7938
  return () => ({
7463
7939
  exists: env.sampleContentExists,
7464
7940
  path: env.sampleContentPath,
7465
- parentPath: path18.dirname(env.sampleContentPath)
7941
+ parentPath: path20.dirname(env.sampleContentPath)
7466
7942
  });
7467
7943
  }
7468
7944
  },
@@ -7486,10 +7962,10 @@ ${titleText(" TinaCMS ")} backend initialized!`));
7486
7962
  return `${x.key}=${x.value || "***"}`;
7487
7963
  }).join("\n") + `
7488
7964
  TINA_PUBLIC_IS_LOCAL=true`;
7489
- const envFile = path18.join(process.cwd(), ".env");
7490
- if (!fs18.existsSync(envFile)) {
7965
+ const envFile = path20.join(process.cwd(), ".env");
7966
+ if (!fs19.existsSync(envFile)) {
7491
7967
  logger.info(`Adding .env file to your project... \u2705`);
7492
- fs18.writeFileSync(envFile, envFileText);
7968
+ fs19.writeFileSync(envFile, envFileText);
7493
7969
  } else {
7494
7970
  logger.info(
7495
7971
  "Please add the following environment variables to your .env file"
@@ -7566,7 +8042,7 @@ var addReactiveFile = {
7566
8042
  baseDir,
7567
8043
  dataLayer
7568
8044
  }) => {
7569
- const packageJsonPath = path18.join(baseDir, "package.json");
8045
+ const packageJsonPath = path20.join(baseDir, "package.json");
7570
8046
  await writeGeneratedFile({
7571
8047
  generatedFile,
7572
8048
  typescript: config2.typescript,
@@ -7579,7 +8055,7 @@ var addReactiveFile = {
7579
8055
  })
7580
8056
  });
7581
8057
  logger.info("Adding a nextjs example... \u2705");
7582
- const packageJson = JSON.parse(fs18.readFileSync(packageJsonPath).toString());
8058
+ const packageJson = JSON.parse(fs19.readFileSync(packageJsonPath).toString());
7583
8059
  const scripts = packageJson.scripts || {};
7584
8060
  const updatedPackageJson = JSON.stringify(
7585
8061
  {
@@ -7592,15 +8068,15 @@ var addReactiveFile = {
7592
8068
  null,
7593
8069
  2
7594
8070
  );
7595
- fs18.writeFileSync(packageJsonPath, updatedPackageJson);
8071
+ fs19.writeFileSync(packageJsonPath, updatedPackageJson);
7596
8072
  }
7597
8073
  };
7598
8074
  var updateAstroPackageJson = async ({ baseDir }) => {
7599
- const packageJsonPath = path18.join(baseDir, "package.json");
7600
- if (!fs18.existsSync(packageJsonPath)) {
8075
+ const packageJsonPath = path20.join(baseDir, "package.json");
8076
+ if (!fs19.existsSync(packageJsonPath)) {
7601
8077
  return;
7602
8078
  }
7603
- const packageJson = JSON.parse(fs18.readFileSync(packageJsonPath).toString());
8079
+ const packageJson = JSON.parse(fs19.readFileSync(packageJsonPath).toString());
7604
8080
  const scripts = packageJson.scripts || {};
7605
8081
  const updatedPackageJson = JSON.stringify(
7606
8082
  {
@@ -7610,7 +8086,7 @@ var updateAstroPackageJson = async ({ baseDir }) => {
7610
8086
  null,
7611
8087
  2
7612
8088
  );
7613
- fs18.writeFileSync(packageJsonPath, updatedPackageJson);
8089
+ fs19.writeFileSync(packageJsonPath, updatedPackageJson);
7614
8090
  logger.info("Updating package.json scripts for Astro... \u2705");
7615
8091
  };
7616
8092
  function execShellCommand(cmd) {
@@ -7810,8 +8286,8 @@ var SearchIndexCommand = class extends Command7 {
7810
8286
  import { Command as Command8, Option as Option8 } from "clipanion";
7811
8287
 
7812
8288
  // src/next/commands/doctor-command/doctor.ts
7813
- import path19 from "path";
7814
- import fs19 from "fs-extra";
8289
+ import path21 from "path";
8290
+ import fs20 from "fs-extra";
7815
8291
  import yaml3 from "js-yaml";
7816
8292
  var DEPENDENCY_TYPES = [
7817
8293
  "dependencies",
@@ -7826,7 +8302,7 @@ var LOCAL_REFERENCE_PREFIXES = [
7826
8302
  "portal:",
7827
8303
  "workspace:"
7828
8304
  ];
7829
- function isTinaPackage(name2) {
8305
+ function isTinaPackage2(name2) {
7830
8306
  return name2 === "tinacms" || name2 === "create-tina-app" || name2.startsWith("@tinacms/") || name2.startsWith("tinacms-") || name2.startsWith("next-tinacms-");
7831
8307
  }
7832
8308
  function getTinaDependencies(packageJson) {
@@ -7835,7 +8311,7 @@ function getTinaDependencies(packageJson) {
7835
8311
  for (const [name2, declared] of Object.entries(
7836
8312
  packageJson[dependencyType] || {}
7837
8313
  )) {
7838
- if (!isTinaPackage(name2) || dependencies.has(name2)) continue;
8314
+ if (!isTinaPackage2(name2) || dependencies.has(name2)) continue;
7839
8315
  dependencies.set(name2, { name: name2, declared, dependencyType });
7840
8316
  }
7841
8317
  }
@@ -7844,11 +8320,11 @@ function getTinaDependencies(packageJson) {
7844
8320
  );
7845
8321
  }
7846
8322
  async function readProjectPackageJson(rootPath) {
7847
- const packageJsonPath = path19.join(rootPath, "package.json");
7848
- if (!await fs19.pathExists(packageJsonPath)) {
8323
+ const packageJsonPath = path21.join(rootPath, "package.json");
8324
+ if (!await fs20.pathExists(packageJsonPath)) {
7849
8325
  throw new Error(`No package.json found at ${packageJsonPath}`);
7850
8326
  }
7851
- return fs19.readJSON(packageJsonPath);
8327
+ return fs20.readJSON(packageJsonPath);
7852
8328
  }
7853
8329
  async function resolveInstalledVersions({
7854
8330
  rootPath,
@@ -7971,14 +8447,14 @@ function isLocalReference(version2) {
7971
8447
  );
7972
8448
  }
7973
8449
  async function readNodeModulesVersion(rootPath, packageName) {
7974
- const packageJsonPath = path19.join(
8450
+ const packageJsonPath = path21.join(
7975
8451
  rootPath,
7976
8452
  "node_modules",
7977
8453
  ...packageName.split("/"),
7978
8454
  "package.json"
7979
8455
  );
7980
- if (!await fs19.pathExists(packageJsonPath)) return void 0;
7981
- const packageJson = await fs19.readJSON(packageJsonPath);
8456
+ if (!await fs20.pathExists(packageJsonPath)) return void 0;
8457
+ const packageJson = await fs20.readJSON(packageJsonPath);
7982
8458
  return typeof packageJson.version === "string" ? packageJson.version : void 0;
7983
8459
  }
7984
8460
  async function readLockfileVersions(rootPath) {
@@ -7994,54 +8470,54 @@ async function readLockfileVersions(rootPath) {
7994
8470
  return /* @__PURE__ */ new Map();
7995
8471
  }
7996
8472
  async function readPackageLockVersions(rootPath) {
7997
- const lockfilePath = path19.join(rootPath, "package-lock.json");
8473
+ const lockfilePath = path21.join(rootPath, "package-lock.json");
7998
8474
  const versions = /* @__PURE__ */ new Map();
7999
- if (!await fs19.pathExists(lockfilePath)) return versions;
8000
- const lockfile = await fs19.readJSON(lockfilePath);
8475
+ if (!await fs20.pathExists(lockfilePath)) return versions;
8476
+ const lockfile = await fs20.readJSON(lockfilePath);
8001
8477
  for (const [key, value] of Object.entries(lockfile.packages || {})) {
8002
8478
  if (!key.startsWith("node_modules/")) continue;
8003
8479
  const name2 = key.replace(/^node_modules\//, "");
8004
8480
  const version2 = value.version;
8005
- if (isTinaPackage(name2) && typeof version2 === "string") {
8481
+ if (isTinaPackage2(name2) && typeof version2 === "string") {
8006
8482
  versions.set(name2, version2);
8007
8483
  }
8008
8484
  }
8009
8485
  for (const [name2, value] of Object.entries(lockfile.dependencies || {})) {
8010
8486
  const version2 = value.version;
8011
- if (isTinaPackage(name2) && typeof version2 === "string") {
8487
+ if (isTinaPackage2(name2) && typeof version2 === "string") {
8012
8488
  versions.set(name2, version2);
8013
8489
  }
8014
8490
  }
8015
8491
  return versions;
8016
8492
  }
8017
8493
  async function readPnpmLockVersions(rootPath) {
8018
- const lockfilePath = path19.join(rootPath, "pnpm-lock.yaml");
8494
+ const lockfilePath = path21.join(rootPath, "pnpm-lock.yaml");
8019
8495
  const versions = /* @__PURE__ */ new Map();
8020
- if (!await fs19.pathExists(lockfilePath)) return versions;
8021
- 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"));
8022
8498
  const rootImporter = lockfile?.importers?.["."];
8023
8499
  for (const dependencyType of DEPENDENCY_TYPES) {
8024
8500
  for (const [name2, value] of Object.entries(
8025
8501
  rootImporter?.[dependencyType] || {}
8026
8502
  )) {
8027
- if (!isTinaPackage(name2)) continue;
8503
+ if (!isTinaPackage2(name2)) continue;
8028
8504
  const version2 = typeof value === "string" ? value : typeof value.version === "string" ? value.version : void 0;
8029
8505
  if (version2) versions.set(name2, normalizeInstalledVersion(version2));
8030
8506
  }
8031
8507
  }
8032
8508
  for (const key of Object.keys(lockfile?.packages || {})) {
8033
8509
  const parsed = parsePnpmPackageKey(key);
8034
- if (parsed && isTinaPackage(parsed.name) && !versions.has(parsed.name)) {
8510
+ if (parsed && isTinaPackage2(parsed.name) && !versions.has(parsed.name)) {
8035
8511
  versions.set(parsed.name, parsed.version);
8036
8512
  }
8037
8513
  }
8038
8514
  return versions;
8039
8515
  }
8040
8516
  async function readYarnLockVersions(rootPath) {
8041
- const lockfilePath = path19.join(rootPath, "yarn.lock");
8517
+ const lockfilePath = path21.join(rootPath, "yarn.lock");
8042
8518
  const versions = /* @__PURE__ */ new Map();
8043
- if (!await fs19.pathExists(lockfilePath)) return versions;
8044
- const contents = await fs19.readFile(lockfilePath, "utf8");
8519
+ if (!await fs20.pathExists(lockfilePath)) return versions;
8520
+ const contents = await fs20.readFile(lockfilePath, "utf8");
8045
8521
  if (contents.includes("__metadata:")) {
8046
8522
  return readYarnBerryLockVersions(contents);
8047
8523
  }
@@ -8055,7 +8531,7 @@ async function readYarnLockVersions(rootPath) {
8055
8531
  const version2 = line.match(/^\s+version\s+"([^"]+)"/)?.[1];
8056
8532
  if (!version2) continue;
8057
8533
  for (const name2 of activeNames) {
8058
- if (isTinaPackage(name2) && !versions.has(name2)) {
8534
+ if (isTinaPackage2(name2) && !versions.has(name2)) {
8059
8535
  versions.set(name2, version2);
8060
8536
  }
8061
8537
  }
@@ -8069,7 +8545,7 @@ function readYarnBerryLockVersions(contents) {
8069
8545
  if (descriptor === "__metadata") continue;
8070
8546
  const name2 = extractYarnBerryPackageName(descriptor);
8071
8547
  const version2 = getYarnBerryInstalledVersion(descriptor, value?.version);
8072
- if (name2 && isTinaPackage(name2) && version2) {
8548
+ if (name2 && isTinaPackage2(name2) && version2) {
8073
8549
  versions.set(name2, version2);
8074
8550
  }
8075
8551
  }