@tinacms/cli 2.5.4 → 2.5.6

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,7 +2,7 @@
2
2
  import { Cli, Builtins } from "clipanion";
3
3
 
4
4
  // package.json
5
- var version = "2.5.3";
5
+ var version = "2.5.6";
6
6
 
7
7
  // src/next/commands/dev-command/index.ts
8
8
  import path10 from "path";
@@ -816,26 +816,165 @@ var unlinkIfExists = async (filepath) => {
816
816
  };
817
817
 
818
818
  // src/next/config-manager.ts
819
- import fs4 from "fs-extra";
819
+ import { createRequire } from "module";
820
820
  import path5 from "path";
821
821
  import { pathToFileURL } from "url";
822
- import * as esbuild from "esbuild";
823
822
  import * as dotenv from "dotenv";
823
+ import * as esbuild from "esbuild";
824
+ import fs4 from "fs-extra";
824
825
  import normalizePath2 from "normalize-path";
825
- import { createRequire } from "module";
826
826
 
827
- // src/next/resolve-content-root.ts
827
+ // src/next/build-database-esbuild-config.ts
828
+ var buildDatabaseEsbuildConfig = (opts) => ({
829
+ entryPoints: [opts.entryPoint],
830
+ bundle: true,
831
+ platform: "node",
832
+ format: "esm",
833
+ outfile: opts.outfile,
834
+ loader: opts.loader,
835
+ external: opts.external,
836
+ // Provide a require() polyfill for ESM bundles containing CommonJS packages.
837
+ // Some bundled packages (e.g., 'scmp' used by 'mongodb-level') use
838
+ // require('crypto'). When esbuild inlines these CommonJS packages, it keeps
839
+ // the require() calls, but ESM doesn't have a global require. This banner
840
+ // creates one using Node.js's official createRequire API, allowing the
841
+ // bundled CommonJS code to work in ESM.
842
+ banner: {
843
+ js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`
844
+ }
845
+ });
846
+
847
+ // src/next/cache-manager.ts
828
848
  import fs2 from "fs-extra";
829
- import path3 from "path";
849
+ import path2 from "path";
850
+ var buildReadOnlyMountErrorMessage = (cacheParentPath, underlyingError) => `TinaCMS cannot write to ${cacheParentPath}.
851
+
852
+ 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.
853
+
854
+ To resolve, either:
855
+ - Make the project directory writable (e.g. remount with read-write access, or copy the project to a writable location), or
856
+ - Run \`tinacms build\` against a writable copy of your project and deploy the resulting artifacts.
857
+
858
+ Underlying error: ${underlyingError.code} ${underlyingError.message}`;
859
+ var READONLY_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EROFS", "EPERM"]);
860
+ var prepareCacheLocation = async (generatedFolderPath, now = Date.now()) => {
861
+ const parentPath = path2.join(generatedFolderPath, ".cache");
862
+ try {
863
+ if (await fs2.pathExists(parentPath)) {
864
+ await fs2.remove(parentPath);
865
+ }
866
+ await fs2.ensureDir(parentPath);
867
+ } catch (err) {
868
+ const code = err?.code;
869
+ if (code && READONLY_ERROR_CODES.has(code)) {
870
+ throw new Error(
871
+ buildReadOnlyMountErrorMessage(parentPath, err)
872
+ );
873
+ }
874
+ throw err;
875
+ }
876
+ return {
877
+ parentPath,
878
+ buildPath: path2.join(parentPath, String(now))
879
+ };
880
+ };
881
+ var reapBuildSubdir = (buildSubdirPath, buildParentPath) => {
882
+ fs2.removeSync(buildSubdirPath);
883
+ try {
884
+ fs2.rmdirSync(buildParentPath);
885
+ } catch (err) {
886
+ if (err?.code !== "ENOTEMPTY") throw err;
887
+ }
888
+ };
889
+
890
+ // src/next/config-build-error.ts
891
+ var isObject = (value) => typeof value === "object" && value !== null;
892
+ var isTinaPackage = (specifier) => specifier === "tinacms" || specifier.startsWith("@tinacms/");
893
+ var collectResolveTargets = (text) => {
894
+ if (!text) {
895
+ return [];
896
+ }
897
+ const targets = [];
898
+ const pattern = /Could not resolve "([^"]+)"/g;
899
+ for (const match of text.matchAll(pattern)) {
900
+ targets.push(match[1]);
901
+ }
902
+ return targets;
903
+ };
904
+ var getUnresolvedTinaPackage = (error) => {
905
+ if (!isObject(error)) {
906
+ return null;
907
+ }
908
+ const esbuildError = error;
909
+ const targets = [
910
+ ...(esbuildError.errors ?? []).flatMap(
911
+ (item) => collectResolveTargets(item.text)
912
+ ),
913
+ ...collectResolveTargets(esbuildError.message)
914
+ ];
915
+ return targets.find(isTinaPackage) ?? null;
916
+ };
917
+ var getResolveLocation = (error) => {
918
+ if (!isObject(error)) {
919
+ return null;
920
+ }
921
+ const esbuildError = error;
922
+ const entry = (esbuildError.errors ?? []).find(
923
+ (item) => collectResolveTargets(item.text).some(isTinaPackage)
924
+ );
925
+ return entry?.location ?? null;
926
+ };
927
+ var formatConfigBuildError = ({
928
+ error,
929
+ rootPath
930
+ }) => {
931
+ const unresolvedPackage = getUnresolvedTinaPackage(error);
932
+ if (!unresolvedPackage) {
933
+ return error;
934
+ }
935
+ const lines = [
936
+ `Unable to resolve the "${unresolvedPackage}" package while building your Tina config.`,
937
+ "",
938
+ `Tina looked from: ${rootPath}`
939
+ ];
940
+ const location = getResolveLocation(error);
941
+ if (location?.file) {
942
+ const position = [location.line, location.column].filter((value) => typeof value === "number").join(":");
943
+ lines.push(
944
+ "",
945
+ `Failing import: ${location.file}${position ? `:${position}` : ""}`
946
+ );
947
+ if (location.lineText) {
948
+ lines.push(` ${location.lineText.trim()}`);
949
+ }
950
+ }
951
+ lines.push(
952
+ "",
953
+ "Make sure the TinaCMS packages are installed in this project and that you are running the CLI from the project root.",
954
+ "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."
955
+ );
956
+ return new Error(lines.join("\n"));
957
+ };
958
+
959
+ // src/next/external-resolver.ts
960
+ var EXTERNAL_BASELINE = ["better-sqlite3"];
961
+ var resolveDatabaseExternals = (config2) => {
962
+ const userExternals = config2?.build?.externalDependencies ?? [];
963
+ return [...EXTERNAL_BASELINE, ...userExternals];
964
+ };
965
+
966
+ // src/next/resolve-content-root.ts
967
+ import fs3 from "fs-extra";
968
+ import path4 from "path";
830
969
  import chalk3 from "chalk";
831
970
  import { z } from "zod";
832
971
 
833
972
  // src/utils/path.ts
834
- import path2 from "path";
973
+ import path3 from "path";
835
974
  function stripNativeTrailingSlash(p) {
836
- const { root } = path2.parse(p);
975
+ const { root } = path3.parse(p);
837
976
  let str = p;
838
- while (str.length > root.length && str.endsWith(path2.sep)) {
977
+ while (str.length > root.length && str.endsWith(path3.sep)) {
839
978
  str = str.slice(0, -1);
840
979
  }
841
980
  return str;
@@ -859,9 +998,9 @@ async function resolveContentRootPath(params) {
859
998
  return params.rootPath;
860
999
  }
861
1000
  const fullLocalContentPath = stripNativeTrailingSlash(
862
- path3.join(params.tinaFolderPath, localContentPath)
1001
+ path4.join(params.tinaFolderPath, localContentPath)
863
1002
  );
864
- const exists = await fs2.pathExists(fullLocalContentPath);
1003
+ const exists = await fs3.pathExists(fullLocalContentPath);
865
1004
  if (exists) {
866
1005
  logger.info(`Using separate content repo at ${fullLocalContentPath}`);
867
1006
  return fullLocalContentPath;
@@ -876,76 +1015,6 @@ async function resolveContentRootPath(params) {
876
1015
  return params.rootPath;
877
1016
  }
878
1017
 
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
1018
  // src/next/config-manager.ts
950
1019
  var TINA_FOLDER = "tina";
951
1020
  var LEGACY_TINA_FOLDER = ".tina";
@@ -1250,14 +1319,21 @@ var ConfigManager = class {
1250
1319
  const buildDir = path5.join(this.generatedCachePath, "database");
1251
1320
  const outfile = path5.join(buildDir, "database.build.mjs");
1252
1321
  const external = resolveDatabaseExternals(this.config);
1253
- await esbuild.build(
1254
- buildDatabaseEsbuildConfig({
1255
- entryPoint: this.selfHostedDatabaseFilePath,
1256
- outfile,
1257
- external,
1258
- loader: loaders
1259
- })
1260
- );
1322
+ try {
1323
+ await esbuild.build(
1324
+ buildDatabaseEsbuildConfig({
1325
+ entryPoint: this.selfHostedDatabaseFilePath,
1326
+ outfile,
1327
+ external,
1328
+ loader: loaders
1329
+ })
1330
+ );
1331
+ } catch (e) {
1332
+ throw formatConfigBuildError({
1333
+ error: e,
1334
+ rootPath: path5.resolve(this.rootPath)
1335
+ });
1336
+ }
1261
1337
  const result = await import(pathToFileURL(outfile).href);
1262
1338
  reapBuildSubdir(buildDir, this.generatedCachePath);
1263
1339
  return result.default;
@@ -1274,20 +1350,26 @@ var ConfigManager = class {
1274
1350
  const esmRequireBanner = {
1275
1351
  js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`
1276
1352
  };
1353
+ const resolvedRootPath = path5.resolve(this.rootPath);
1277
1354
  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
- });
1355
+ let result2;
1356
+ try {
1357
+ result2 = await esbuild.build({
1358
+ entryPoints: [configFilePath],
1359
+ bundle: true,
1360
+ target: ["esnext"],
1361
+ platform: "browser",
1362
+ format: "esm",
1363
+ logLevel: "silent",
1364
+ packages: "external",
1365
+ ignoreAnnotations: true,
1366
+ outfile: preBuildConfigPath,
1367
+ loader: loaders,
1368
+ metafile: true
1369
+ });
1370
+ } catch (e) {
1371
+ throw formatConfigBuildError({ error: e, rootPath: resolvedRootPath });
1372
+ }
1291
1373
  const flattenedList = [];
1292
1374
  Object.keys(result2.metafile.inputs).forEach((key) => {
1293
1375
  if (key.includes("node_modules") || key.includes("__generated__")) {
@@ -1295,27 +1377,31 @@ var ConfigManager = class {
1295
1377
  }
1296
1378
  flattenedList.push(key);
1297
1379
  });
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
- });
1380
+ try {
1381
+ await esbuild.build({
1382
+ entryPoints: [configFilePath],
1383
+ bundle: true,
1384
+ target: ["esnext"],
1385
+ logLevel: "silent",
1386
+ platform: "node",
1387
+ format: "esm",
1388
+ outfile,
1389
+ loader: loaders,
1390
+ banner: esmRequireBanner
1391
+ });
1392
+ await esbuild.build({
1393
+ entryPoints: [outfile],
1394
+ bundle: true,
1395
+ logLevel: "silent",
1396
+ platform: "node",
1397
+ target: ["esnext"],
1398
+ format: "esm",
1399
+ outfile: outfile2,
1400
+ loader: loaders
1401
+ });
1402
+ } catch (e) {
1403
+ throw formatConfigBuildError({ error: e, rootPath: resolvedRootPath });
1404
+ }
1319
1405
  let result;
1320
1406
  try {
1321
1407
  result = await import(pathToFileURL(outfile2).href);
@@ -7826,7 +7912,7 @@ var LOCAL_REFERENCE_PREFIXES = [
7826
7912
  "portal:",
7827
7913
  "workspace:"
7828
7914
  ];
7829
- function isTinaPackage(name2) {
7915
+ function isTinaPackage2(name2) {
7830
7916
  return name2 === "tinacms" || name2 === "create-tina-app" || name2.startsWith("@tinacms/") || name2.startsWith("tinacms-") || name2.startsWith("next-tinacms-");
7831
7917
  }
7832
7918
  function getTinaDependencies(packageJson) {
@@ -7835,7 +7921,7 @@ function getTinaDependencies(packageJson) {
7835
7921
  for (const [name2, declared] of Object.entries(
7836
7922
  packageJson[dependencyType] || {}
7837
7923
  )) {
7838
- if (!isTinaPackage(name2) || dependencies.has(name2)) continue;
7924
+ if (!isTinaPackage2(name2) || dependencies.has(name2)) continue;
7839
7925
  dependencies.set(name2, { name: name2, declared, dependencyType });
7840
7926
  }
7841
7927
  }
@@ -8002,13 +8088,13 @@ async function readPackageLockVersions(rootPath) {
8002
8088
  if (!key.startsWith("node_modules/")) continue;
8003
8089
  const name2 = key.replace(/^node_modules\//, "");
8004
8090
  const version2 = value.version;
8005
- if (isTinaPackage(name2) && typeof version2 === "string") {
8091
+ if (isTinaPackage2(name2) && typeof version2 === "string") {
8006
8092
  versions.set(name2, version2);
8007
8093
  }
8008
8094
  }
8009
8095
  for (const [name2, value] of Object.entries(lockfile.dependencies || {})) {
8010
8096
  const version2 = value.version;
8011
- if (isTinaPackage(name2) && typeof version2 === "string") {
8097
+ if (isTinaPackage2(name2) && typeof version2 === "string") {
8012
8098
  versions.set(name2, version2);
8013
8099
  }
8014
8100
  }
@@ -8024,14 +8110,14 @@ async function readPnpmLockVersions(rootPath) {
8024
8110
  for (const [name2, value] of Object.entries(
8025
8111
  rootImporter?.[dependencyType] || {}
8026
8112
  )) {
8027
- if (!isTinaPackage(name2)) continue;
8113
+ if (!isTinaPackage2(name2)) continue;
8028
8114
  const version2 = typeof value === "string" ? value : typeof value.version === "string" ? value.version : void 0;
8029
8115
  if (version2) versions.set(name2, normalizeInstalledVersion(version2));
8030
8116
  }
8031
8117
  }
8032
8118
  for (const key of Object.keys(lockfile?.packages || {})) {
8033
8119
  const parsed = parsePnpmPackageKey(key);
8034
- if (parsed && isTinaPackage(parsed.name) && !versions.has(parsed.name)) {
8120
+ if (parsed && isTinaPackage2(parsed.name) && !versions.has(parsed.name)) {
8035
8121
  versions.set(parsed.name, parsed.version);
8036
8122
  }
8037
8123
  }
@@ -8055,7 +8141,7 @@ async function readYarnLockVersions(rootPath) {
8055
8141
  const version2 = line.match(/^\s+version\s+"([^"]+)"/)?.[1];
8056
8142
  if (!version2) continue;
8057
8143
  for (const name2 of activeNames) {
8058
- if (isTinaPackage(name2) && !versions.has(name2)) {
8144
+ if (isTinaPackage2(name2) && !versions.has(name2)) {
8059
8145
  versions.set(name2, version2);
8060
8146
  }
8061
8147
  }
@@ -8069,7 +8155,7 @@ function readYarnBerryLockVersions(contents) {
8069
8155
  if (descriptor === "__metadata") continue;
8070
8156
  const name2 = extractYarnBerryPackageName(descriptor);
8071
8157
  const version2 = getYarnBerryInstalledVersion(descriptor, value?.version);
8072
- if (name2 && isTinaPackage(name2) && version2) {
8158
+ if (name2 && isTinaPackage2(name2) && version2) {
8073
8159
  versions.set(name2, version2);
8074
8160
  }
8075
8161
  }
@@ -0,0 +1,4 @@
1
+ export declare const formatConfigBuildError: ({ error, rootPath, }: {
2
+ error: unknown;
3
+ rootPath: string;
4
+ }) => unknown;
@@ -1,5 +1,5 @@
1
- import type { Loader } from 'esbuild';
2
1
  import { Config } from '@tinacms/schema-tools';
2
+ import type { Loader } from 'esbuild';
3
3
  export declare const TINA_FOLDER = "tina";
4
4
  export declare const LEGACY_TINA_FOLDER = ".tina";
5
5
  export declare const GENERATED_FOLDER = "__generated__";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tinacms/cli",
3
3
  "type": "module",
4
- "version": "2.5.4",
4
+ "version": "2.5.6",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
7
7
  "files": [
@@ -91,12 +91,12 @@
91
91
  "vite": "^4.5.9",
92
92
  "yup": "^1.6.1",
93
93
  "zod": "^3.24.2",
94
- "@tinacms/app": "2.5.8",
95
- "@tinacms/metrics": "2.1.1",
96
- "@tinacms/schema-tools": "2.8.3",
97
- "tinacms": "3.10.0",
98
- "@tinacms/search": "1.2.21",
99
- "@tinacms/graphql": "2.4.7"
94
+ "@tinacms/app": "^2.5.10",
95
+ "@tinacms/graphql": "^2.4.9",
96
+ "@tinacms/schema-tools": "^2.8.3",
97
+ "@tinacms/search": "^1.2.23",
98
+ "tinacms": "^3.11.0",
99
+ "@tinacms/metrics": "^2.1.1"
100
100
  },
101
101
  "publishConfig": {
102
102
  "registry": "https://registry.npmjs.org"