@tinacms/cli 1.4.1 → 1.5.1

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
@@ -28,10 +28,10 @@ __export(src_exports, {
28
28
  default: () => src_default
29
29
  });
30
30
  module.exports = __toCommonJS(src_exports);
31
- var import_clipanion5 = require("clipanion");
31
+ var import_clipanion6 = require("clipanion");
32
32
 
33
33
  // package.json
34
- var version = "1.4.1";
34
+ var version = "1.5.1";
35
35
 
36
36
  // src/next/commands/dev-command/index.ts
37
37
  var import_clipanion = require("clipanion");
@@ -45,7 +45,6 @@ var import_fs_extra = __toESM(require("fs-extra"));
45
45
  var import_path = __toESM(require("path"));
46
46
  var import_os = __toESM(require("os"));
47
47
  var esbuild = __toESM(require("esbuild"));
48
- var url = __toESM(require("url"));
49
48
  var dotenv = __toESM(require("dotenv"));
50
49
  var import_normalize_path = __toESM(require("normalize-path"));
51
50
 
@@ -165,9 +164,14 @@ var GRAPHQL_GQL_FILE = "schema.gql";
165
164
  var SCHEMA_JSON_FILE = "_schema.json";
166
165
  var LOOKUP_JSON_FILE = "_lookup.json";
167
166
  var ConfigManager = class {
168
- constructor(rootPath = process.cwd(), tinaGraphQLVersion) {
167
+ constructor({
168
+ rootPath = process.cwd(),
169
+ tinaGraphQLVersion,
170
+ legacyNoSDK
171
+ }) {
169
172
  this.rootPath = (0, import_normalize_path.default)(rootPath);
170
173
  this.tinaGraphQLVersionFromCLI = tinaGraphQLVersion;
174
+ this.legacyNoSDK = legacyNoSDK;
171
175
  }
172
176
  isUsingTs() {
173
177
  return [".ts", ".tsx"].includes(import_path.default.extname(this.tinaConfigFilePath));
@@ -178,6 +182,13 @@ var ConfigManager = class {
178
182
  hasSeparateContentRoot() {
179
183
  return this.rootPath !== this.contentRootPath;
180
184
  }
185
+ shouldSkipSDK() {
186
+ var _a;
187
+ if (this.legacyNoSDK) {
188
+ return this.legacyNoSDK;
189
+ }
190
+ return ((_a = this.config.client) == null ? void 0 : _a.skip) || false;
191
+ }
181
192
  async processConfig() {
182
193
  this.tinaFolderPath = await this.getTinaFolderPath(this.rootPath);
183
194
  this.envFilePath = import_path.default.resolve(
@@ -272,11 +283,8 @@ var ConfigManager = class {
272
283
  );
273
284
  this.outputHTMLFilePath = import_path.default.join(this.outputFolderPath, "index.html");
274
285
  this.outputGitignorePath = import_path.default.join(this.outputFolderPath, ".gitignore");
275
- this.spaHTMLPath = url.pathToFileURL(
276
- require.resolve("@tinacms/app")
277
- ).pathname;
278
- this.spaRootPath = this.spaHTMLPath.replace("/index.html", "");
279
- this.spaMainPath = import_path.default.join(this.spaRootPath, "src", "main.tsx");
286
+ this.spaMainPath = require.resolve("@tinacms/app");
287
+ this.spaRootPath = import_path.default.join(this.spaMainPath, "..", "..");
280
288
  }
281
289
  async getTinaFolderPath(rootPath) {
282
290
  const tinaFolderPath = import_path.default.join(rootPath, TINA_FOLDER);
@@ -416,166 +424,12 @@ var devHTML = (port) => `<!DOCTYPE html>
416
424
  </html>`;
417
425
 
418
426
  // src/next/commands/dev-command/server/index.ts
419
- var import_body_parser = __toESM(require("body-parser"));
420
- var import_path5 = __toESM(require("path"));
421
- var import_cors = __toESM(require("cors"));
422
427
  var import_vite2 = require("vite");
423
- var import_graphql = require("@tinacms/graphql");
424
-
425
- // src/next/commands/dev-command/server/media.ts
426
- var import_fs_extra2 = __toESM(require("fs-extra"));
427
- var import_path2 = __toESM(require("path"));
428
- var import_busboy = __toESM(require("busboy"));
429
- var createMediaRouter = (config3) => {
430
- const mediaFolder = import_path2.default.join(
431
- config3.rootPath,
432
- config3.publicFolder,
433
- config3.mediaRoot
434
- );
435
- const mediaModel = new MediaModel(config3);
436
- const handleList = async (req, res) => {
437
- const requestURL = new URL(req.url, config3.apiURL);
438
- const folder = requestURL.pathname.replace("/media/list/", "");
439
- const limit = requestURL.searchParams.get("limit");
440
- const cursor = requestURL.searchParams.get("cursor");
441
- const media = await mediaModel.listMedia({
442
- searchPath: folder,
443
- cursor,
444
- limit
445
- });
446
- res.end(JSON.stringify(media));
447
- };
448
- const handleDelete = async (req, res) => {
449
- const file = decodeURIComponent(req.url.slice("/media/".length));
450
- const didDelete = await mediaModel.deleteMedia({ searchPath: file });
451
- res.end(JSON.stringify(didDelete));
452
- };
453
- const handlePost = async function(req, res) {
454
- const bb = (0, import_busboy.default)({ headers: req.headers });
455
- bb.on("file", (name2, file, info) => {
456
- const saveTo = import_path2.default.join(mediaFolder, info.filename);
457
- file.pipe(import_fs_extra2.default.createWriteStream(saveTo));
458
- });
459
- bb.on("error", (error) => {
460
- res.statusCode = 500;
461
- if (error instanceof Error) {
462
- res.end(JSON.stringify({ message: error }));
463
- } else {
464
- res.end(JSON.stringify({ message: "Unknown error while uploading" }));
465
- }
466
- });
467
- bb.on("close", () => {
468
- res.statusCode = 200;
469
- res.end(JSON.stringify({ success: true }));
470
- });
471
- req.pipe(bb);
472
- };
473
- return { handleList, handleDelete, handlePost };
474
- };
475
- var parseMediaFolder = (str) => {
476
- let returnString = str;
477
- if (returnString.startsWith("/"))
478
- returnString = returnString.substr(1);
479
- if (returnString.endsWith("/"))
480
- returnString = returnString.substr(0, returnString.length - 1);
481
- return returnString;
482
- };
483
- var MediaModel = class {
484
- constructor({ rootPath, publicFolder, mediaRoot }) {
485
- this.rootPath = rootPath;
486
- this.mediaRoot = mediaRoot;
487
- this.publicFolder = publicFolder;
488
- }
489
- async listMedia(args) {
490
- try {
491
- const folderPath = (0, import_path2.join)(
492
- this.rootPath,
493
- this.publicFolder,
494
- this.mediaRoot,
495
- args.searchPath
496
- );
497
- const searchPath = parseMediaFolder(args.searchPath);
498
- const filesStr = await import_fs_extra2.default.readdir(folderPath);
499
- const filesProm = filesStr.map(async (file) => {
500
- const filePath = (0, import_path2.join)(folderPath, file);
501
- const stat = await import_fs_extra2.default.stat(filePath);
502
- let src = `/${file}`;
503
- const isFile = stat.isFile();
504
- if (!isFile) {
505
- return {
506
- isFile,
507
- size: stat.size,
508
- src,
509
- filename: file
510
- };
511
- }
512
- if (searchPath) {
513
- src = `/${searchPath}${src}`;
514
- }
515
- if (this.mediaRoot) {
516
- src = `/${this.mediaRoot}${src}`;
517
- }
518
- return {
519
- isFile,
520
- size: stat.size,
521
- src,
522
- filename: file
523
- };
524
- });
525
- const offset = Number(args.cursor) || 0;
526
- const limit = Number(args.limit) || 20;
527
- const rawItems = await Promise.all(filesProm);
528
- const sortedItems = rawItems.sort((a, b) => {
529
- if (a.isFile && !b.isFile) {
530
- return 1;
531
- }
532
- if (!a.isFile && b.isFile) {
533
- return -1;
534
- }
535
- return 0;
536
- });
537
- const limitItems = sortedItems.slice(offset, offset + limit);
538
- const files = limitItems.filter((x) => x.isFile);
539
- const directories = limitItems.filter((x) => !x.isFile).map((x) => x.src);
540
- const cursor = rawItems.length > offset + limit ? String(offset + limit) : null;
541
- return {
542
- files,
543
- directories,
544
- cursor
545
- };
546
- } catch (error) {
547
- console.error(error);
548
- return {
549
- files: [],
550
- directories: [],
551
- error: error == null ? void 0 : error.toString()
552
- };
553
- }
554
- }
555
- async deleteMedia(args) {
556
- try {
557
- const file = (0, import_path2.join)(
558
- this.rootPath,
559
- this.publicFolder,
560
- this.mediaRoot,
561
- args.searchPath
562
- );
563
- await import_fs_extra2.default.stat(file);
564
- await import_fs_extra2.default.remove(file);
565
- return { ok: true };
566
- } catch (error) {
567
- console.error(error);
568
- return { ok: false, message: error == null ? void 0 : error.toString() };
569
- }
570
- }
571
- };
572
-
573
- // src/next/commands/dev-command/server/index.ts
574
- var import_esbuild = require("esbuild");
575
428
 
576
429
  // src/next/vite/index.ts
577
- var import_path4 = __toESM(require("path"));
430
+ var import_path3 = __toESM(require("path"));
578
431
  var import_vite = require("vite");
432
+ var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
579
433
 
580
434
  // src/next/vite/tailwind.ts
581
435
  var import_tailwindcss = __toESM(require("tailwindcss"));
@@ -585,15 +439,15 @@ var import_defaultTheme = __toESM(require("tailwindcss/defaultTheme.js"));
585
439
  var import_typography = __toESM(require("@tailwindcss/typography"));
586
440
  var import_line_clamp = __toESM(require("@tailwindcss/line-clamp"));
587
441
  var import_aspect_ratio = __toESM(require("@tailwindcss/aspect-ratio"));
588
- var import_path3 = __toESM(require("path"));
442
+ var import_path2 = __toESM(require("path"));
589
443
  var tinaTailwind = (spaPath, configFilePath) => {
590
444
  return {
591
445
  name: "vite-plugin-tina",
592
446
  config: (viteConfig) => {
593
447
  const plugins = [];
594
448
  const content2 = [
595
- import_path3.default.join(spaPath, "src/**/*.{vue,js,ts,jsx,tsx,svelte}"),
596
- import_path3.default.join(configFilePath, "../**/*.{vue,js,ts,jsx,tsx,svelte}")
449
+ import_path2.default.join(spaPath, "src/**/*.{vue,js,ts,jsx,tsx,svelte}"),
450
+ import_path2.default.join(configFilePath, "../**/*.{vue,js,ts,jsx,tsx,svelte}")
597
451
  ];
598
452
  const tw = (0, import_tailwindcss.default)({
599
453
  important: ".tina-tailwind",
@@ -837,7 +691,6 @@ var createConfig = async ({
837
691
  database,
838
692
  apiURL,
839
693
  plugins = [],
840
- noSDK,
841
694
  noWatch,
842
695
  rollupOptions
843
696
  }) => {
@@ -862,8 +715,8 @@ var createConfig = async ({
862
715
  TINA_IMPORT: configManager.tinaConfigFilePath,
863
716
  SCHEMA_IMPORT: configManager.generatedGraphQLJSONPath
864
717
  };
865
- if (noSDK) {
866
- alias["CLIENT_IMPORT"] = import_path4.default.join(
718
+ if (configManager.shouldSkipSDK()) {
719
+ alias["CLIENT_IMPORT"] = import_path3.default.join(
867
720
  configManager.spaRootPath,
868
721
  "src",
869
722
  "dummy-client.ts"
@@ -899,12 +752,13 @@ var createConfig = async ({
899
752
  }
900
753
  },
901
754
  build: {
902
- sourcemap: true,
755
+ sourcemap: false,
903
756
  outDir: configManager.outputFolderPath,
904
757
  emptyOutDir: true,
905
758
  rollupOptions
906
759
  },
907
760
  plugins: [
761
+ (0, import_plugin_react.default)(),
908
762
  (0, import_vite.splitVendorChunkPlugin)(),
909
763
  tinaTailwind(configManager.spaRootPath, configManager.tinaConfigFilePath),
910
764
  ...plugins
@@ -913,77 +767,246 @@ var createConfig = async ({
913
767
  return config3;
914
768
  };
915
769
 
916
- // src/next/commands/dev-command/server/index.ts
917
- var createDevServer = async (configManager, database, apiURL, noSDK, noWatch) => {
918
- const plugins = [
919
- {
920
- name: "transform-tsx",
921
- async transform(code, id) {
922
- if (id.startsWith(configManager.rootPath)) {
923
- const extName = import_path5.default.extname(id);
924
- if (extName.startsWith(".tsx") || extName.startsWith(".ts")) {
925
- const result = await (0, import_esbuild.transform)(code, { loader: "tsx" });
926
- return {
927
- code: result.code
928
- };
929
- }
930
- }
770
+ // src/next/vite/plugins.ts
771
+ var import_esbuild = require("esbuild");
772
+ var import_path5 = __toESM(require("path"));
773
+ var import_body_parser = __toESM(require("body-parser"));
774
+ var import_cors = __toESM(require("cors"));
775
+ var import_graphql = require("@tinacms/graphql");
776
+
777
+ // src/next/commands/dev-command/server/media.ts
778
+ var import_fs_extra2 = __toESM(require("fs-extra"));
779
+ var import_path4 = __toESM(require("path"));
780
+ var import_busboy = __toESM(require("busboy"));
781
+ var createMediaRouter = (config3) => {
782
+ const mediaFolder = import_path4.default.join(
783
+ config3.rootPath,
784
+ config3.publicFolder,
785
+ config3.mediaRoot
786
+ );
787
+ const mediaModel = new MediaModel(config3);
788
+ const handleList = async (req, res) => {
789
+ const requestURL = new URL(req.url, config3.apiURL);
790
+ const folder = requestURL.pathname.replace("/media/list/", "");
791
+ const limit = requestURL.searchParams.get("limit");
792
+ const cursor = requestURL.searchParams.get("cursor");
793
+ const media = await mediaModel.listMedia({
794
+ searchPath: folder,
795
+ cursor,
796
+ limit
797
+ });
798
+ res.end(JSON.stringify(media));
799
+ };
800
+ const handleDelete = async (req, res) => {
801
+ const file = decodeURIComponent(req.url.slice("/media/".length));
802
+ const didDelete = await mediaModel.deleteMedia({ searchPath: file });
803
+ res.end(JSON.stringify(didDelete));
804
+ };
805
+ const handlePost = async function(req, res) {
806
+ const bb = (0, import_busboy.default)({ headers: req.headers });
807
+ bb.on("file", (name2, file, info) => {
808
+ const saveTo = import_path4.default.join(mediaFolder, info.filename);
809
+ file.pipe(import_fs_extra2.default.createWriteStream(saveTo));
810
+ });
811
+ bb.on("error", (error) => {
812
+ res.statusCode = 500;
813
+ if (error instanceof Error) {
814
+ res.end(JSON.stringify({ message: error }));
815
+ } else {
816
+ res.end(JSON.stringify({ message: "Unknown error while uploading" }));
817
+ }
818
+ });
819
+ bb.on("close", () => {
820
+ res.statusCode = 200;
821
+ res.end(JSON.stringify({ success: true }));
822
+ });
823
+ req.pipe(bb);
824
+ };
825
+ return { handleList, handleDelete, handlePost };
826
+ };
827
+ var parseMediaFolder = (str) => {
828
+ let returnString = str;
829
+ if (returnString.startsWith("/"))
830
+ returnString = returnString.substr(1);
831
+ if (returnString.endsWith("/"))
832
+ returnString = returnString.substr(0, returnString.length - 1);
833
+ return returnString;
834
+ };
835
+ var MediaModel = class {
836
+ constructor({ rootPath, publicFolder, mediaRoot }) {
837
+ this.rootPath = rootPath;
838
+ this.mediaRoot = mediaRoot;
839
+ this.publicFolder = publicFolder;
840
+ }
841
+ async listMedia(args) {
842
+ try {
843
+ const folderPath = (0, import_path4.join)(
844
+ this.rootPath,
845
+ this.publicFolder,
846
+ this.mediaRoot,
847
+ args.searchPath
848
+ );
849
+ const searchPath = parseMediaFolder(args.searchPath);
850
+ const filesStr = await import_fs_extra2.default.readdir(folderPath);
851
+ const filesProm = filesStr.map(async (file) => {
852
+ const filePath = (0, import_path4.join)(folderPath, file);
853
+ const stat = await import_fs_extra2.default.stat(filePath);
854
+ let src = `/${file}`;
855
+ const isFile = stat.isFile();
856
+ if (!isFile) {
857
+ return {
858
+ isFile,
859
+ size: stat.size,
860
+ src,
861
+ filename: file
862
+ };
863
+ }
864
+ if (searchPath) {
865
+ src = `/${searchPath}${src}`;
866
+ }
867
+ if (this.mediaRoot) {
868
+ src = `/${this.mediaRoot}${src}`;
869
+ }
870
+ return {
871
+ isFile,
872
+ size: stat.size,
873
+ src,
874
+ filename: file
875
+ };
876
+ });
877
+ const offset = Number(args.cursor) || 0;
878
+ const limit = Number(args.limit) || 20;
879
+ const rawItems = await Promise.all(filesProm);
880
+ const sortedItems = rawItems.sort((a, b) => {
881
+ if (a.isFile && !b.isFile) {
882
+ return 1;
883
+ }
884
+ if (!a.isFile && b.isFile) {
885
+ return -1;
886
+ }
887
+ return 0;
888
+ });
889
+ const limitItems = sortedItems.slice(offset, offset + limit);
890
+ const files = limitItems.filter((x) => x.isFile);
891
+ const directories = limitItems.filter((x) => !x.isFile).map((x) => x.src);
892
+ const cursor = rawItems.length > offset + limit ? String(offset + limit) : null;
893
+ return {
894
+ files,
895
+ directories,
896
+ cursor
897
+ };
898
+ } catch (error) {
899
+ console.error(error);
900
+ return {
901
+ files: [],
902
+ directories: [],
903
+ error: error == null ? void 0 : error.toString()
904
+ };
905
+ }
906
+ }
907
+ async deleteMedia(args) {
908
+ try {
909
+ const file = (0, import_path4.join)(
910
+ this.rootPath,
911
+ this.publicFolder,
912
+ this.mediaRoot,
913
+ args.searchPath
914
+ );
915
+ await import_fs_extra2.default.stat(file);
916
+ await import_fs_extra2.default.remove(file);
917
+ return { ok: true };
918
+ } catch (error) {
919
+ console.error(error);
920
+ return { ok: false, message: error == null ? void 0 : error.toString() };
921
+ }
922
+ }
923
+ };
924
+
925
+ // src/next/vite/plugins.ts
926
+ var transformTsxPlugin = ({
927
+ configManager: _configManager
928
+ }) => {
929
+ const plug = {
930
+ name: "transform-tsx",
931
+ async transform(code, id) {
932
+ const extName = import_path5.default.extname(id);
933
+ if (extName.startsWith(".tsx") || extName.startsWith(".ts")) {
934
+ const result = await (0, import_esbuild.transform)(code, { loader: "tsx" });
935
+ return {
936
+ code: result.code
937
+ };
931
938
  }
932
- },
933
- {
934
- name: "graphql-endpoints",
935
- configureServer(server) {
936
- server.middlewares.use((0, import_cors.default)());
937
- server.middlewares.use(import_body_parser.default.json());
938
- server.middlewares.use(async (req, res, next) => {
939
- var _a;
940
- const mediaPaths = (_a = configManager.config.media) == null ? void 0 : _a.tina;
941
- const mediaRouter = createMediaRouter({
942
- rootPath: configManager.rootPath,
943
- apiURL,
944
- publicFolder: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.publicFolder) || ""),
945
- mediaRoot: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.mediaRoot) || "")
946
- });
947
- if (req.url.startsWith("/media/upload")) {
948
- await mediaRouter.handlePost(req, res);
949
- return;
950
- }
951
- if (req.url.startsWith("/media")) {
952
- if (req.method === "DELETE") {
953
- await mediaRouter.handleDelete(req, res);
954
- return;
955
- }
956
- }
957
- if (req.url.startsWith("/media/list")) {
958
- await mediaRouter.handleList(req, res);
959
- return;
960
- }
961
- if (req.url === "/altair") {
962
- res.end(
963
- JSON.stringify({
964
- status: "The GraphQL playground has moved to <your-dev-url>/index.html#/graphql"
965
- })
966
- );
967
- return;
968
- }
969
- if (req.url === "/graphql") {
970
- const { query, variables } = req.body;
971
- const result = await (0, import_graphql.resolve)({
972
- config: {
973
- useRelativeMedia: true
974
- },
975
- database,
976
- query,
977
- variables,
978
- verbose: false
979
- });
980
- res.end(JSON.stringify(result));
939
+ }
940
+ };
941
+ return plug;
942
+ };
943
+ var devServerEndPointsPlugin = ({
944
+ configManager,
945
+ apiURL,
946
+ database
947
+ }) => {
948
+ const plug = {
949
+ name: "graphql-endpoints",
950
+ configureServer(server) {
951
+ server.middlewares.use((0, import_cors.default)());
952
+ server.middlewares.use(import_body_parser.default.json());
953
+ server.middlewares.use(async (req, res, next) => {
954
+ var _a;
955
+ const mediaPaths = (_a = configManager.config.media) == null ? void 0 : _a.tina;
956
+ const mediaRouter = createMediaRouter({
957
+ rootPath: configManager.rootPath,
958
+ apiURL,
959
+ publicFolder: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.publicFolder) || ""),
960
+ mediaRoot: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.mediaRoot) || "")
961
+ });
962
+ if (req.url.startsWith("/media/upload")) {
963
+ await mediaRouter.handlePost(req, res);
964
+ return;
965
+ }
966
+ if (req.url.startsWith("/media")) {
967
+ if (req.method === "DELETE") {
968
+ await mediaRouter.handleDelete(req, res);
981
969
  return;
982
970
  }
983
- next();
984
- });
985
- }
971
+ }
972
+ if (req.url.startsWith("/media/list")) {
973
+ await mediaRouter.handleList(req, res);
974
+ return;
975
+ }
976
+ if (req.url === "/altair") {
977
+ res.end(
978
+ JSON.stringify({
979
+ status: "The GraphQL playground has moved to <your-dev-url>/index.html#/graphql"
980
+ })
981
+ );
982
+ return;
983
+ }
984
+ if (req.url === "/graphql") {
985
+ const { query, variables } = req.body;
986
+ const result = await (0, import_graphql.resolve)({
987
+ config: {
988
+ useRelativeMedia: true
989
+ },
990
+ database,
991
+ query,
992
+ variables,
993
+ verbose: false
994
+ });
995
+ res.end(JSON.stringify(result));
996
+ return;
997
+ }
998
+ next();
999
+ });
986
1000
  }
1001
+ };
1002
+ return plug;
1003
+ };
1004
+
1005
+ // src/next/commands/dev-command/server/index.ts
1006
+ var createDevServer = async (configManager, database, apiURL, noWatch) => {
1007
+ const plugins = [
1008
+ transformTsxPlugin({ configManager }),
1009
+ devServerEndPointsPlugin({ apiURL, configManager, database })
987
1010
  ];
988
1011
  return (0, import_vite2.createServer)(
989
1012
  await createConfig({
@@ -991,7 +1014,6 @@ var createDevServer = async (configManager, database, apiURL, noSDK, noWatch) =>
991
1014
  database,
992
1015
  apiURL,
993
1016
  plugins,
994
- noSDK,
995
1017
  noWatch,
996
1018
  rollupOptions: {
997
1019
  input: configManager.spaMainPath
@@ -1204,14 +1226,12 @@ var Codegen = class {
1204
1226
  configManager,
1205
1227
  port,
1206
1228
  schema,
1207
- noSDK,
1208
1229
  queryDoc,
1209
1230
  fragDoc
1210
1231
  }) {
1211
1232
  this.configManager = configManager;
1212
1233
  this.port = port;
1213
1234
  this.schema = schema;
1214
- this.noSDK = noSDK;
1215
1235
  this.queryDoc = queryDoc;
1216
1236
  this.fragDoc = fragDoc;
1217
1237
  }
@@ -1226,7 +1246,7 @@ var Codegen = class {
1226
1246
  }
1227
1247
  async execute() {
1228
1248
  const apiURL = this.getApiURL();
1229
- if (this.noSDK) {
1249
+ if (this.configManager.shouldSkipSDK()) {
1230
1250
  await this.removeGeneratedFilesIfExists();
1231
1251
  return apiURL;
1232
1252
  }
@@ -1442,7 +1462,7 @@ var createDBServer = (port) => {
1442
1462
  });
1443
1463
  dbServer.listen(port);
1444
1464
  };
1445
- async function createAndInitializeDatabase(configManager, bridgeOverride) {
1465
+ async function createAndInitializeDatabase(configManager, datalayerPort, bridgeOverride) {
1446
1466
  let database;
1447
1467
  const bridge = bridgeOverride || new import_graphql7.FilesystemBridge(configManager.rootPath, configManager.contentRootPath);
1448
1468
  if (configManager.hasSelfHostedConfig() && configManager.config.contentApiUrlOverride) {
@@ -1456,7 +1476,7 @@ async function createAndInitializeDatabase(configManager, bridgeOverride) {
1456
1476
  )} but there was no "contentApiUrlOverride" set. Falling back to built-in datalayer`
1457
1477
  );
1458
1478
  }
1459
- const level = new import_graphql7.TinaLevelClient();
1479
+ const level = new import_graphql7.TinaLevelClient(datalayerPort);
1460
1480
  level.openConnection();
1461
1481
  database = (0, import_graphql7.createDatabase)({
1462
1482
  bridge,
@@ -1511,7 +1531,7 @@ var DevCommand = class extends import_clipanion.Command {
1511
1531
  description: "Specify a port to run the server on. (default 4001)"
1512
1532
  });
1513
1533
  this.datalayerPort = import_clipanion.Option.String("--datalayer-port", "9000", {
1514
- description: "Specify a port to run the datalayer server on. (default 4001)"
1534
+ description: "Specify a port to run the datalayer server on. (default 9000)"
1515
1535
  });
1516
1536
  this.subCommand = import_clipanion.Option.String("-c,--command", {
1517
1537
  description: "The sub-command to run"
@@ -1535,7 +1555,7 @@ var DevCommand = class extends import_clipanion.Command {
1535
1555
  description: "Don't regenerate config on file changes"
1536
1556
  });
1537
1557
  this.noSDK = import_clipanion.Option.Boolean("--noSDK", false, {
1538
- description: "Don't generate the generated client SDK"
1558
+ description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1539
1559
  });
1540
1560
  this.noTelemetry = import_clipanion.Option.Boolean("--noTelemetry", false, {
1541
1561
  description: "Disable anonymous telemetry that is collected"
@@ -1560,7 +1580,15 @@ var DevCommand = class extends import_clipanion.Command {
1560
1580
  "--experimentalDataLayer has been deprecated, the data layer is now built-in automatically"
1561
1581
  );
1562
1582
  }
1563
- const configManager = new ConfigManager(this.rootPath);
1583
+ if (this.noSDK) {
1584
+ logger.warn(
1585
+ "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
1586
+ );
1587
+ }
1588
+ const configManager = new ConfigManager({
1589
+ rootPath: this.rootPath,
1590
+ legacyNoSDK: this.noSDK
1591
+ });
1564
1592
  logger.info("Starting Tina Dev Server");
1565
1593
  createDBServer(Number(this.datalayerPort));
1566
1594
  let database = null;
@@ -1580,7 +1608,10 @@ var DevCommand = class extends import_clipanion.Command {
1580
1608
  }
1581
1609
  }
1582
1610
  if (firstTime) {
1583
- database = await createAndInitializeDatabase(configManager);
1611
+ database = await createAndInitializeDatabase(
1612
+ configManager,
1613
+ Number(this.datalayerPort)
1614
+ );
1584
1615
  } else {
1585
1616
  database.clearCache();
1586
1617
  }
@@ -1605,7 +1636,6 @@ var DevCommand = class extends import_clipanion.Command {
1605
1636
  schema: await (0, import_graphql8.getASTSchema)(database),
1606
1637
  configManager,
1607
1638
  port: Number(this.port),
1608
- noSDK: this.noSDK,
1609
1639
  queryDoc,
1610
1640
  fragDoc
1611
1641
  });
@@ -1642,7 +1672,6 @@ var DevCommand = class extends import_clipanion.Command {
1642
1672
  configManager,
1643
1673
  database,
1644
1674
  apiURL,
1645
- this.noSDK,
1646
1675
  this.noWatch
1647
1676
  );
1648
1677
  await server.listen(Number(this.port));
@@ -1694,7 +1723,7 @@ var DevCommand = class extends import_clipanion.Command {
1694
1723
  ]
1695
1724
  }
1696
1725
  ];
1697
- if (!this.noSDK) {
1726
+ if (!configManager.shouldSkipSDK()) {
1698
1727
  summaryItems.push({
1699
1728
  emoji: "\u{1F916}",
1700
1729
  heading: "Auto-generated files",
@@ -1791,7 +1820,7 @@ var import_graphql9 = require("@tinacms/graphql");
1791
1820
 
1792
1821
  // src/next/commands/build-command/server.ts
1793
1822
  var import_vite4 = require("vite");
1794
- var buildProductionSpa = async (configManager, database, apiURL, noSDK) => {
1823
+ var buildProductionSpa = async (configManager, database, apiURL) => {
1795
1824
  const publicEnv = {};
1796
1825
  Object.keys(process.env).forEach((key) => {
1797
1826
  if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
@@ -1810,10 +1839,10 @@ var buildProductionSpa = async (configManager, database, apiURL, noSDK) => {
1810
1839
  }
1811
1840
  });
1812
1841
  const config3 = await createConfig({
1842
+ plugins: [transformTsxPlugin({ configManager })],
1813
1843
  configManager,
1814
1844
  database,
1815
1845
  apiURL,
1816
- noSDK,
1817
1846
  noWatch: true
1818
1847
  });
1819
1848
  return (0, import_vite4.build)(config3);
@@ -1934,10 +1963,10 @@ var BuildCommand = class extends import_clipanion2.Command {
1934
1963
  description: "increase verbosity of logged output"
1935
1964
  });
1936
1965
  this.noSDK = import_clipanion2.Option.Boolean("--noSDK", false, {
1937
- description: "Don't generate the generated client SDK"
1966
+ description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1938
1967
  });
1939
1968
  this.datalayerPort = import_clipanion2.Option.String("--datalayer-port", "9000", {
1940
- description: "Specify a port to run the datalayer server on. (default 4001)"
1969
+ description: "Specify a port to run the datalayer server on. (default 9000)"
1941
1970
  });
1942
1971
  this.isomorphicGitBridge = import_clipanion2.Option.Boolean("--isomorphicGitBridge", {
1943
1972
  description: "DEPRECATED - Enable Isomorphic Git Bridge Implementation"
@@ -1960,10 +1989,11 @@ var BuildCommand = class extends import_clipanion2.Command {
1960
1989
  process.exit(1);
1961
1990
  }
1962
1991
  async execute() {
1963
- const configManager = new ConfigManager(
1964
- this.rootPath,
1965
- this.tinaGraphQLVersion
1966
- );
1992
+ const configManager = new ConfigManager({
1993
+ rootPath: this.rootPath,
1994
+ tinaGraphQLVersion: this.tinaGraphQLVersion,
1995
+ legacyNoSDK: this.noSDK
1996
+ });
1967
1997
  logger.info("Starting Tina build");
1968
1998
  if (this.isomorphicGitBridge) {
1969
1999
  logger.warn("--isomorphicGitBridge has been deprecated");
@@ -1976,6 +2006,11 @@ var BuildCommand = class extends import_clipanion2.Command {
1976
2006
  if (this.localOption) {
1977
2007
  logger.warn("--local has been deprecated");
1978
2008
  }
2009
+ if (this.noSDK) {
2010
+ logger.warn(
2011
+ "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
2012
+ );
2013
+ }
1979
2014
  try {
1980
2015
  await configManager.processConfig();
1981
2016
  } catch (e) {
@@ -1984,7 +2019,10 @@ var BuildCommand = class extends import_clipanion2.Command {
1984
2019
  process.exit(1);
1985
2020
  }
1986
2021
  createDBServer(Number(this.datalayerPort));
1987
- const database = await createAndInitializeDatabase(configManager);
2022
+ const database = await createAndInitializeDatabase(
2023
+ configManager,
2024
+ Number(this.datalayerPort)
2025
+ );
1988
2026
  const { queryDoc, fragDoc } = await (0, import_graphql9.buildSchema)(
1989
2027
  database,
1990
2028
  configManager.config
@@ -1992,7 +2030,6 @@ var BuildCommand = class extends import_clipanion2.Command {
1992
2030
  const codegen2 = new Codegen({
1993
2031
  schema: await (0, import_graphql9.getASTSchema)(database),
1994
2032
  configManager,
1995
- noSDK: this.noSDK,
1996
2033
  queryDoc,
1997
2034
  fragDoc
1998
2035
  });
@@ -2000,13 +2037,13 @@ var BuildCommand = class extends import_clipanion2.Command {
2000
2037
  await this.checkClientInfo(configManager, apiURL);
2001
2038
  await waitForDB(configManager.config, apiURL, false);
2002
2039
  await this.checkGraphqlSchema(configManager, database, apiURL);
2003
- await buildProductionSpa(configManager, database, apiURL, this.noSDK);
2040
+ await buildProductionSpa(configManager, database, apiURL);
2004
2041
  await import_fs_extra5.default.outputFile(
2005
2042
  configManager.outputGitignorePath,
2006
2043
  "index.html\nassets/"
2007
2044
  );
2008
2045
  const summaryItems = [];
2009
- if (!this.noSDK) {
2046
+ if (!configManager.shouldSkipSDK()) {
2010
2047
  summaryItems.push({
2011
2048
  emoji: "\u{1F916}",
2012
2049
  heading: "Auto-generated files",
@@ -2044,13 +2081,13 @@ var BuildCommand = class extends import_clipanion2.Command {
2044
2081
  const { config: config3 } = configManager;
2045
2082
  const token = config3.token;
2046
2083
  const { clientId, branch, host } = (0, import_schema_tools2.parseURL)(apiURL);
2047
- const url2 = `https://${host}/db/${clientId}/status/${branch}`;
2084
+ const url = `https://${host}/db/${clientId}/status/${branch}`;
2048
2085
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
2049
2086
  let branchKnown = false;
2050
2087
  try {
2051
2088
  const res = await request({
2052
2089
  token,
2053
- url: url2
2090
+ url
2054
2091
  });
2055
2092
  bar2.tick({
2056
2093
  prog: "\u2705"
@@ -2092,7 +2129,7 @@ var BuildCommand = class extends import_clipanion2.Command {
2092
2129
  fn: async () => {
2093
2130
  const res = await request({
2094
2131
  token,
2095
- url: url2
2132
+ url
2096
2133
  });
2097
2134
  if (this.verbose) {
2098
2135
  logger.info(
@@ -2165,8 +2202,8 @@ async function request(args) {
2165
2202
  headers.append("X-API-KEY", args.token);
2166
2203
  }
2167
2204
  headers.append("Content-Type", "application/json");
2168
- const url2 = args == null ? void 0 : args.url;
2169
- const res = await (0, import_node_fetch2.default)(url2, {
2205
+ const url = args == null ? void 0 : args.url;
2206
+ const res = await (0, import_node_fetch2.default)(url, {
2170
2207
  method: "GET",
2171
2208
  headers,
2172
2209
  redirect: "follow"
@@ -2200,7 +2237,7 @@ Message from server: ${json.message}`;
2200
2237
  };
2201
2238
  }
2202
2239
  var fetchRemoteGraphqlSchema = async ({
2203
- url: url2,
2240
+ url,
2204
2241
  token
2205
2242
  }) => {
2206
2243
  const headers = new import_node_fetch2.Headers();
@@ -2209,7 +2246,7 @@ var fetchRemoteGraphqlSchema = async ({
2209
2246
  }
2210
2247
  const body = JSON.stringify({ query: (0, import_graphql10.getIntrospectionQuery)(), variables: {} });
2211
2248
  headers.append("Content-Type", "application/json");
2212
- const res = await (0, import_node_fetch2.default)(url2, {
2249
+ const res = await (0, import_node_fetch2.default)(url, {
2213
2250
  method: "POST",
2214
2251
  headers,
2215
2252
  body
@@ -2220,13 +2257,12 @@ var fetchRemoteGraphqlSchema = async ({
2220
2257
 
2221
2258
  // src/next/commands/audit-command/index.ts
2222
2259
  var import_clipanion3 = require("clipanion");
2223
- var import_graphql13 = require("@tinacms/graphql");
2260
+ var import_graphql12 = require("@tinacms/graphql");
2224
2261
 
2225
2262
  // src/next/commands/audit-command/audit.ts
2226
2263
  var import_prompts = __toESM(require("prompts"));
2227
2264
  var import_metrics = require("@tinacms/metrics");
2228
2265
  var import_graphql11 = require("@tinacms/graphql");
2229
- var import_graphql12 = require("@tinacms/graphql");
2230
2266
  var import_chalk4 = __toESM(require("chalk"));
2231
2267
  var audit = async ({
2232
2268
  database,
@@ -2339,14 +2375,12 @@ var auditDocuments = async (args) => {
2339
2375
  }
2340
2376
  });
2341
2377
  }
2342
- const params = transformDocumentIntoMutationRequestPayload(
2378
+ const tinaSchema = await database.getSchema();
2379
+ const values = mergeValuesWithDefaults(
2343
2380
  docResult.data.document._values,
2344
- {
2345
- includeCollection: true,
2346
- includeTemplate: typeof collection.templates !== "undefined"
2347
- },
2348
2381
  topLevelDefaults
2349
2382
  );
2383
+ const params = tinaSchema.transformPayload(collection.name, values);
2350
2384
  const mutation = `mutation($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
2351
2385
  updateDocument(
2352
2386
  collection: $collection,
@@ -2376,46 +2410,8 @@ var auditDocuments = async (args) => {
2376
2410
  }
2377
2411
  return error;
2378
2412
  };
2379
- var transformDocumentIntoMutationRequestPayload = (document, instructions, defaults) => {
2380
- const { _collection, __typename, _template, ...rest } = document;
2381
- const params = transformParams(rest);
2382
- const paramsWithTemplate = instructions.includeTemplate ? { [_template]: params } : params;
2383
- return instructions.includeCollection ? { [_collection]: { ...defaults, ...filterObject(paramsWithTemplate) } } : { ...defaults, ...filterObject(paramsWithTemplate) };
2384
- };
2385
- var transformParams = (data) => {
2386
- if (["string", "number", "boolean"].includes(typeof data)) {
2387
- return data;
2388
- }
2389
- if (Array.isArray(data)) {
2390
- return data.map((item) => transformParams(item));
2391
- }
2392
- try {
2393
- (0, import_graphql12.assertShape)(
2394
- data,
2395
- (yup) => yup.object({ _template: yup.string().required() })
2396
- );
2397
- const { _template, __typename, ...rest } = data;
2398
- const nested = transformParams(rest);
2399
- return { [_template]: nested };
2400
- } catch (e) {
2401
- if (e.message === "Failed to assertShape - _template is a required field") {
2402
- if (!data) {
2403
- return void 0;
2404
- return [];
2405
- }
2406
- const accum = {};
2407
- Object.entries(data).map(([keyName, value]) => {
2408
- accum[keyName] = transformParams(value);
2409
- });
2410
- return accum;
2411
- } else {
2412
- if (!data) {
2413
- return void 0;
2414
- return [];
2415
- }
2416
- throw e;
2417
- }
2418
- }
2413
+ var mergeValuesWithDefaults = (document, defaults) => {
2414
+ return { ...defaults, ...filterObject(document) };
2419
2415
  };
2420
2416
  function filterObject(obj) {
2421
2417
  const ret = {};
@@ -2424,7 +2420,7 @@ function filterObject(obj) {
2424
2420
  }
2425
2421
 
2426
2422
  // src/next/commands/audit-command/index.ts
2427
- var import_graphql14 = require("@tinacms/graphql");
2423
+ var import_graphql13 = require("@tinacms/graphql");
2428
2424
  var AuditCommand = class extends import_clipanion3.Command {
2429
2425
  constructor() {
2430
2426
  super(...arguments);
@@ -2444,7 +2440,7 @@ var AuditCommand = class extends import_clipanion3.Command {
2444
2440
  description: "Disable anonymous telemetry that is collected"
2445
2441
  });
2446
2442
  this.datalayerPort = import_clipanion3.Option.String("--datalayer-port", "9000", {
2447
- description: "Specify a port to run the datalayer server on. (default 4001)"
2443
+ description: "Specify a port to run the datalayer server on. (default 9000)"
2448
2444
  });
2449
2445
  }
2450
2446
  async catch(error) {
@@ -2455,7 +2451,7 @@ var AuditCommand = class extends import_clipanion3.Command {
2455
2451
  process.exit(1);
2456
2452
  }
2457
2453
  async execute() {
2458
- const configManager = new ConfigManager(this.rootPath);
2454
+ const configManager = new ConfigManager({ rootPath: this.rootPath });
2459
2455
  logger.info("Starting Tina Audit");
2460
2456
  try {
2461
2457
  await configManager.processConfig();
@@ -2466,9 +2462,10 @@ var AuditCommand = class extends import_clipanion3.Command {
2466
2462
  createDBServer(Number(this.datalayerPort));
2467
2463
  const database = await createAndInitializeDatabase(
2468
2464
  configManager,
2469
- this.clean ? void 0 : new import_graphql14.AuditFileSystemBridge(configManager.rootPath)
2465
+ Number(this.datalayerPort),
2466
+ this.clean ? void 0 : new import_graphql13.AuditFileSystemBridge(configManager.rootPath)
2470
2467
  );
2471
- const { tinaSchema, graphQLSchema } = await (0, import_graphql13.buildSchema)(
2468
+ const { tinaSchema, graphQLSchema } = await (0, import_graphql12.buildSchema)(
2472
2469
  database,
2473
2470
  configManager.config
2474
2471
  );
@@ -2506,12 +2503,12 @@ AuditCommand.usage = import_clipanion3.Command.Usage({
2506
2503
  });
2507
2504
 
2508
2505
  // src/next/commands/init-command/index.ts
2509
- var import_clipanion4 = require("clipanion");
2506
+ var import_clipanion5 = require("clipanion");
2510
2507
 
2511
2508
  // src/cmds/init/index.ts
2512
- var import_path9 = __toESM(require("path"));
2509
+ var import_path10 = __toESM(require("path"));
2513
2510
  var import_prettier = require("prettier");
2514
- var import_fs_extra8 = __toESM(require("fs-extra"));
2511
+ var import_fs_extra9 = __toESM(require("fs-extra"));
2515
2512
  var import_prompts2 = __toESM(require("prompts"));
2516
2513
  var import_metrics2 = require("@tinacms/metrics");
2517
2514
 
@@ -2520,19 +2517,19 @@ var nextPostPage = ({
2520
2517
  usingSrc
2521
2518
  }) => `// THIS FILE HAS BEEN GENERATED WITH THE TINA CLI.
2522
2519
  // This is a demo file once you have tina setup feel free to delete this file
2523
-
2520
+
2524
2521
  import Head from 'next/head'
2525
2522
  import { useTina } from 'tinacms/dist/react'
2526
2523
  import { TinaMarkdown } from 'tinacms/dist/rich-text'
2527
- import client from '${usingSrc ? "../" : ""}../../../.tina/__generated__/client'
2528
-
2524
+ import client from '${usingSrc ? "../" : ""}../../../tina/__generated__/client'
2525
+
2529
2526
  const BlogPage = (props) => {
2530
2527
  const { data } = useTina({
2531
2528
  query: props.query,
2532
2529
  variables: props.variables,
2533
2530
  data: props.data,
2534
2531
  })
2535
-
2532
+
2536
2533
  return (
2537
2534
  <>
2538
2535
  <Head>
@@ -2571,7 +2568,7 @@ var nextPostPage = ({
2571
2568
  </>
2572
2569
  )
2573
2570
  }
2574
-
2571
+
2575
2572
  export const getStaticProps = async ({ params }) => {
2576
2573
  let data = {}
2577
2574
  let query = {}
@@ -2584,7 +2581,7 @@ var nextPostPage = ({
2584
2581
  } catch {
2585
2582
  // swallow errors related to document creation
2586
2583
  }
2587
-
2584
+
2588
2585
  return {
2589
2586
  props: {
2590
2587
  variables: variables,
@@ -2594,10 +2591,10 @@ var nextPostPage = ({
2594
2591
  },
2595
2592
  }
2596
2593
  }
2597
-
2594
+
2598
2595
  export const getStaticPaths = async () => {
2599
2596
  const postsListData = await client.queries.postConnection()
2600
-
2597
+
2601
2598
  return {
2602
2599
  paths: postsListData.data.postConnection.edges.map((post) => ({
2603
2600
  params: { filename: post.node._sys.filename },
@@ -2605,9 +2602,9 @@ var nextPostPage = ({
2605
2602
  fallback: false,
2606
2603
  }
2607
2604
  }
2608
-
2605
+
2609
2606
  export default BlogPage
2610
-
2607
+
2611
2608
  const PageSection = (props) => {
2612
2609
  return (
2613
2610
  <>
@@ -2616,11 +2613,11 @@ var nextPostPage = ({
2616
2613
  </>
2617
2614
  )
2618
2615
  }
2619
-
2616
+
2620
2617
  const components = {
2621
2618
  PageSection: PageSection,
2622
2619
  }
2623
-
2620
+
2624
2621
  const ContentSection = ({ content }) => {
2625
2622
  return (
2626
2623
  <div className="relative py-16 bg-white overflow-hidden">
@@ -2750,6 +2747,12 @@ function extendNextScripts(scripts) {
2750
2747
  }
2751
2748
 
2752
2749
  // src/cmds/init/setup-files/config.ts
2750
+ var clientConfig = (isForestryMigration) => {
2751
+ if (isForestryMigration) {
2752
+ return "client: {skip: true},";
2753
+ }
2754
+ return "";
2755
+ };
2753
2756
  var other = (args) => {
2754
2757
  return `
2755
2758
  import { defineConfig } from "tinacms";
@@ -2761,6 +2764,7 @@ export default defineConfig({
2761
2764
  branch,
2762
2765
  clientId: ${args.clientId ? `'${args.clientId}'` : "null"}, // Get this from tina.io
2763
2766
  token: ${args.token ? `'${args.token}'` : "null"}, // Get this from tina.io
2767
+ ${clientConfig(args.isForestryMigration)}
2764
2768
  build: {
2765
2769
  outputFolder: "admin",
2766
2770
  publicFolder: "${args.publicFolder}",
@@ -2803,11 +2807,12 @@ var configExamples = {
2803
2807
 
2804
2808
  // Your hosting provider likely exposes this as an environment variable
2805
2809
  const branch = process.env.HEAD || process.env.VERCEL_GIT_COMMIT_REF || 'main'
2806
-
2810
+
2807
2811
  export default defineConfig({
2808
2812
  branch,
2809
2813
  clientId: ${args.clientId ? `'${args.clientId}'` : "null"}, // Get this from tina.io
2810
2814
  token: ${args.token ? `'${args.token}'` : "null"}, // Get this from tina.io
2815
+ ${clientConfig(args.isForestryMigration)}
2811
2816
  build: {
2812
2817
  outputFolder: "admin",
2813
2818
  publicFolder: "${args.publicFolder}",
@@ -2853,6 +2858,13 @@ var configExamples = {
2853
2858
  jekyll: other
2854
2859
  };
2855
2860
 
2861
+ // src/cmds/forestry-migrate/index.ts
2862
+ var import_fs_extra7 = __toESM(require("fs-extra"));
2863
+ var import_path8 = __toESM(require("path"));
2864
+ var import_js_yaml2 = __toESM(require("js-yaml"));
2865
+ var import_minimatch = __toESM(require("minimatch"));
2866
+ var import_graphql14 = require("@tinacms/graphql");
2867
+
2856
2868
  // src/cmds/forestry-migrate/util/index.ts
2857
2869
  var import_fs_extra6 = __toESM(require("fs-extra"));
2858
2870
  var import_path7 = __toESM(require("path"));
@@ -2866,28 +2878,29 @@ var ErrorSingleton = class {
2866
2878
  static getInstance() {
2867
2879
  if (!ErrorSingleton.instance) {
2868
2880
  ErrorSingleton.instance = new ErrorSingleton();
2869
- ErrorSingleton.instance.allErrorNames = [];
2881
+ ErrorSingleton.instance.collectionNameErrors = [];
2870
2882
  }
2871
2883
  return ErrorSingleton.instance;
2872
2884
  }
2873
2885
  addErrorName(error) {
2874
- this.allErrorNames.push(error);
2886
+ this.collectionNameErrors.push(error);
2875
2887
  }
2876
- printNameErrors() {
2877
- logger.error(
2878
- dangerText("ERROR: TinaCMS only supports alphanumeric field names")
2879
- );
2880
- logger.error(
2881
- `If you wish to edit any of the following fields or template names you will have to update your content and code to use the new name. See ${linkText(
2882
- "https://tina.io/docs/forestry/common-errors/#migrating-fields-with-non-alphanumeric-characters"
2883
- )} for more information.`
2884
- );
2885
- logger.error("The following template and field names have been renamed:`");
2886
- this.allErrorNames.forEach((error) => {
2888
+ printCollectionNameErrors() {
2889
+ var _a;
2890
+ if ((_a = this.collectionNameErrors) == null ? void 0 : _a.length) {
2887
2891
  logger.error(
2888
- `- Content that uses ${error.template}.yaml: ${error.name} -> ${error.newName}`
2892
+ dangerText("ERROR: TinaCMS only supports alphanumeric template names")
2889
2893
  );
2890
- });
2894
+ logger.error("The following templates have been renamed:");
2895
+ this.collectionNameErrors.forEach((error) => {
2896
+ logger.error(`- ${error.template}.yaml -> ${error.newName}`);
2897
+ });
2898
+ logger.error(
2899
+ `If you wish to edit any of the following templates, you will have to update your content and code to use the new name. See ${linkText(
2900
+ "https://tina.io/docs/forestry/common-errors/#migrating-fields-with-non-alphanumeric-characters"
2901
+ )} for more information.`
2902
+ );
2903
+ }
2891
2904
  }
2892
2905
  };
2893
2906
 
@@ -2993,7 +3006,7 @@ var FrontmatterTemplateSchema = import_zod.default.object({
2993
3006
  });
2994
3007
  var transformForestryFieldsToTinaFields = ({
2995
3008
  fields,
2996
- rootPath,
3009
+ pathToForestryConfig,
2997
3010
  template,
2998
3011
  skipBlocks = false
2999
3012
  }) => {
@@ -3065,6 +3078,14 @@ var transformForestryFieldsToTinaFields = ({
3065
3078
  label: forestryField2.label
3066
3079
  };
3067
3080
  break;
3081
+ case "image_gallery":
3082
+ field = {
3083
+ type: "image",
3084
+ ...getTinaFieldsFromName(forestryField2.name),
3085
+ label: forestryField2.label,
3086
+ list: true
3087
+ };
3088
+ break;
3068
3089
  case "select":
3069
3090
  if ((_a = forestryField2.config) == null ? void 0 : _a.options) {
3070
3091
  field = {
@@ -3110,7 +3131,7 @@ var transformForestryFieldsToTinaFields = ({
3110
3131
  label: forestryField2.label,
3111
3132
  fields: transformForestryFieldsToTinaFields({
3112
3133
  fields: forestryField2.fields,
3113
- rootPath,
3134
+ pathToForestryConfig,
3114
3135
  template,
3115
3136
  skipBlocks
3116
3137
  })
@@ -3125,20 +3146,21 @@ var transformForestryFieldsToTinaFields = ({
3125
3146
  fields: transformForestryFieldsToTinaFields({
3126
3147
  fields: forestryField2.fields,
3127
3148
  template,
3128
- rootPath,
3149
+ pathToForestryConfig,
3129
3150
  skipBlocks
3130
3151
  })
3131
3152
  };
3132
3153
  break;
3133
3154
  case "blocks":
3134
- if (skipBlocks)
3155
+ if (skipBlocks) {
3135
3156
  break;
3157
+ }
3136
3158
  const templates = [];
3137
3159
  forestryField2 == null ? void 0 : forestryField2.template_types.forEach((tem) => {
3138
3160
  const { fields: fields2, template: template2 } = getFieldsFromTemplates({
3139
3161
  tem,
3140
3162
  skipBlocks: true,
3141
- rootPath: process.cwd()
3163
+ pathToForestryConfig
3142
3164
  });
3143
3165
  const t = {
3144
3166
  fields: fields2,
@@ -3150,12 +3172,12 @@ var transformForestryFieldsToTinaFields = ({
3150
3172
  field = {
3151
3173
  type: "object",
3152
3174
  list: true,
3175
+ templateKey: "template",
3153
3176
  label: forestryField2.label,
3154
3177
  ...getTinaFieldsFromName(forestryField2.name),
3155
3178
  templates
3156
3179
  };
3157
3180
  break;
3158
- case "image_gallery":
3159
3181
  case "include":
3160
3182
  logger.info(
3161
3183
  warnText(
@@ -3179,9 +3201,9 @@ var transformForestryFieldsToTinaFields = ({
3179
3201
  });
3180
3202
  return tinaFields;
3181
3203
  };
3182
- var getFieldsFromTemplates = ({ tem, rootPath, skipBlocks = false }) => {
3204
+ var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
3183
3205
  const templatePath = import_path7.default.join(
3184
- rootPath,
3206
+ pathToForestryConfig,
3185
3207
  ".forestry",
3186
3208
  "front_matter",
3187
3209
  "templates",
@@ -3201,7 +3223,7 @@ var getFieldsFromTemplates = ({ tem, rootPath, skipBlocks = false }) => {
3201
3223
  const template = parseTemplates({ val: templateObj });
3202
3224
  const fields = transformForestryFieldsToTinaFields({
3203
3225
  fields: template.fields,
3204
- rootPath,
3226
+ pathToForestryConfig,
3205
3227
  template: tem,
3206
3228
  skipBlocks
3207
3229
  });
@@ -3211,25 +3233,12 @@ var parseTemplates = ({ val }) => {
3211
3233
  const template = FrontmatterTemplateSchema.parse(val);
3212
3234
  return template;
3213
3235
  };
3214
- var hasForestryConfig = async ({ rootPath }) => {
3215
- const forestryPath = import_path7.default.join(rootPath, ".forestry", "settings.yml");
3216
- const exists = await import_fs_extra6.default.pathExists(forestryPath);
3217
- return {
3218
- path: forestryPath,
3219
- exists
3220
- };
3221
- };
3222
3236
  var parseSections = ({ val }) => {
3223
3237
  const schema = forestryConfigSchema.parse(val);
3224
3238
  return schema;
3225
3239
  };
3226
3240
 
3227
3241
  // src/cmds/forestry-migrate/index.ts
3228
- var import_fs_extra7 = __toESM(require("fs-extra"));
3229
- var import_path8 = __toESM(require("path"));
3230
- var import_js_yaml2 = __toESM(require("js-yaml"));
3231
- var import_minimatch = __toESM(require("minimatch"));
3232
- var import_graphql15 = require("@tinacms/graphql");
3233
3242
  var BODY_FIELD = {
3234
3243
  type: "rich-text",
3235
3244
  name: "body",
@@ -3240,18 +3249,34 @@ var BODY_FIELD = {
3240
3249
  var stringifyLabel = (label) => {
3241
3250
  return label.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
3242
3251
  };
3243
- var generateAllCollections = async ({
3244
- rootPath
3252
+ var transformForestryMatchToTinaMatch = (match) => {
3253
+ var _a, _b;
3254
+ const newMatch = (_b = (_a = match.replace(" ", "").replace(/\.?(mdx|md|json|yaml|yml|toml)/g, "")) == null ? void 0 : _a.replace(/\..*$/g, "")) == null ? void 0 : _b.replace("{}", "");
3255
+ if (match !== newMatch) {
3256
+ logger.warn(`Warning: Match ${match} was transformed to ${newMatch}`);
3257
+ }
3258
+ return newMatch;
3259
+ };
3260
+ function checkExt(ext) {
3261
+ const extReal = ext.replace(".", "");
3262
+ if (["mdx", "md", "json", "yaml", "yml", "toml"].includes(extReal)) {
3263
+ return extReal;
3264
+ } else {
3265
+ return false;
3266
+ }
3267
+ }
3268
+ var generateAllTemplates = async ({
3269
+ pathToForestryConfig
3245
3270
  }) => {
3246
3271
  const allTemplates = (await import_fs_extra7.default.readdir(
3247
- import_path8.default.join(rootPath, ".forestry", "front_matter", "templates")
3272
+ import_path8.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
3248
3273
  )).map((tem) => import_path8.default.basename(tem, ".yml"));
3249
3274
  const templateMap = /* @__PURE__ */ new Map();
3250
3275
  const proms = allTemplates.map(async (tem) => {
3251
3276
  try {
3252
3277
  const { fields, templateObj } = getFieldsFromTemplates({
3253
3278
  tem,
3254
- rootPath
3279
+ pathToForestryConfig
3255
3280
  });
3256
3281
  templateMap.set(tem, { fields, templateObj });
3257
3282
  } catch (e) {
@@ -3263,159 +3288,249 @@ var generateAllCollections = async ({
3263
3288
  await Promise.all(proms);
3264
3289
  return templateMap;
3265
3290
  };
3266
- var generateCollections = async ({
3267
- forestryPath,
3268
- rootPath
3269
- }) => {
3270
- const templateMap = await generateAllCollections({ rootPath });
3271
- const forestryConfig = await import_fs_extra7.default.readFile(forestryPath);
3272
- const forestryYaml = import_js_yaml2.default.load(forestryConfig.toString());
3273
- const forestrySchema = parseSections({ val: forestryYaml });
3274
- const collections = [];
3275
- const sections = forestrySchema.sections;
3276
- for (let index = 0; index < sections.length; index++) {
3277
- const section = sections[index];
3291
+ var generateCollectionFromForestrySection = (section, templateMap) => {
3292
+ if (section.read_only)
3293
+ return;
3294
+ {
3278
3295
  if (section.read_only)
3279
3296
  return;
3280
- switch (section.type) {
3281
- case "directory":
3282
- const forestryTemplates = (section == null ? void 0 : section.templates) || [];
3283
- if (forestryTemplates.length === 0 && section.create === "all") {
3284
- for (let templateKey of templateMap.keys()) {
3285
- const { templateObj } = templateMap.get(templateKey);
3286
- const pages = templateObj == null ? void 0 : templateObj.pages;
3287
- if (pages) {
3288
- if (pages.some(
3289
- (page) => (0, import_minimatch.default)(page, section.path + "/" + section.match)
3290
- )) {
3291
- forestryTemplates.push(templateKey);
3292
- }
3297
+ const baseCollection = {
3298
+ label: section.label,
3299
+ name: stringifyLabel(section.label),
3300
+ path: section.path
3301
+ };
3302
+ if (section.match) {
3303
+ baseCollection.match = {
3304
+ ...(baseCollection == null ? void 0 : baseCollection.match) || {},
3305
+ include: transformForestryMatchToTinaMatch(section.match)
3306
+ };
3307
+ }
3308
+ if (section.exclude) {
3309
+ baseCollection.match = {
3310
+ ...(baseCollection == null ? void 0 : baseCollection.match) || {},
3311
+ exclude: transformForestryMatchToTinaMatch(section.exclude)
3312
+ };
3313
+ }
3314
+ if (section.type === "directory") {
3315
+ const forestryTemplates = (section == null ? void 0 : section.templates) || [];
3316
+ if (forestryTemplates.length === 0 && section.create === "all") {
3317
+ for (let templateKey of templateMap.keys()) {
3318
+ const { templateObj } = templateMap.get(templateKey);
3319
+ const pages = templateObj == null ? void 0 : templateObj.pages;
3320
+ if (pages) {
3321
+ if (pages.some(
3322
+ (page) => (0, import_minimatch.default)(page, section.path + "/" + section.match)
3323
+ )) {
3324
+ forestryTemplates.push(templateKey);
3293
3325
  }
3294
3326
  }
3295
3327
  }
3296
- if (((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1) {
3297
- const templates = [];
3298
- forestryTemplates.forEach((tem) => {
3299
- var _a;
3300
- try {
3301
- const { fields, templateObj } = templateMap.get(tem);
3302
- templates.push({
3303
- fields: [BODY_FIELD, ...fields],
3304
- label: tem,
3305
- name: stringifyLabel(tem)
3306
- });
3307
- (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
3308
- try {
3309
- const filePath = import_path8.default.join(rootPath, page);
3310
- const extname = import_path8.default.extname(filePath);
3311
- const fileContent = import_fs_extra7.default.readFileSync(filePath).toString();
3312
- const content2 = (0, import_graphql15.parseFile)(
3313
- fileContent,
3314
- extname,
3315
- (yup) => yup.object({})
3316
- );
3317
- const newContent = {
3318
- _template: stringifyLabel(tem),
3319
- ...content2
3320
- };
3321
- import_fs_extra7.default.writeFileSync(
3322
- filePath,
3323
- (0, import_graphql15.stringifyFile)(newContent, extname, true)
3324
- );
3325
- } catch (error) {
3326
- console.log("Error updating file", page);
3327
- }
3328
- });
3329
- } catch (e) {
3330
- console.log("Error parsing template ", tem);
3331
- console.error(e);
3332
- }
3333
- });
3334
- const c = {
3335
- label: section.label,
3336
- name: stringifyLabel(section.label),
3337
- path: section.path,
3338
- templates
3328
+ }
3329
+ const c = ((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1 ? {
3330
+ ...baseCollection,
3331
+ templates: forestryTemplates.map((tem) => {
3332
+ const { fields } = templateMap.get(tem);
3333
+ return {
3334
+ fields: [BODY_FIELD, ...fields],
3335
+ label: tem,
3336
+ name: stringifyLabel(tem)
3339
3337
  };
3340
- if ((section == null ? void 0 : section.create) === "none") {
3341
- c.ui = {
3342
- ...c.ui,
3343
- allowedActions: {
3344
- create: false
3345
- }
3346
- };
3347
- }
3348
- collections.push(c);
3349
- } else {
3350
- const fields = [BODY_FIELD];
3351
- forestryTemplates == null ? void 0 : forestryTemplates.forEach((tem) => {
3352
- var _a;
3338
+ })
3339
+ } : {
3340
+ ...baseCollection,
3341
+ fields: [
3342
+ BODY_FIELD,
3343
+ ...(forestryTemplates || []).flatMap((tem) => {
3353
3344
  try {
3354
- const { fields: additionalFields, templateObj } = templateMap.get(tem);
3355
- fields.push(...additionalFields);
3356
- (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
3357
- try {
3358
- const filePath = import_path8.default.join(rootPath, page);
3359
- const extname = import_path8.default.extname(filePath);
3360
- const fileContent = import_fs_extra7.default.readFileSync(filePath).toString();
3361
- const content2 = (0, import_graphql15.parseFile)(
3362
- fileContent,
3363
- extname,
3364
- (yup) => yup.object({})
3365
- );
3366
- const newContent = {
3367
- _template: stringifyLabel(tem),
3368
- ...content2
3369
- };
3370
- import_fs_extra7.default.writeFileSync(
3371
- filePath,
3372
- (0, import_graphql15.stringifyFile)(newContent, extname, true)
3373
- );
3374
- } catch (error) {
3375
- logger.log("Error updating file", page);
3376
- }
3377
- });
3345
+ const { fields: additionalFields } = templateMap.get(tem);
3346
+ return additionalFields;
3378
3347
  } catch (e) {
3379
3348
  logger.log("Error parsing template ", tem);
3380
- console.error(e);
3349
+ return [];
3381
3350
  }
3382
- });
3383
- const c = {
3384
- label: section.label,
3385
- name: stringifyLabel(section.label),
3386
- path: section.path,
3387
- fields
3388
- };
3389
- if ((section == null ? void 0 : section.create) === "none") {
3390
- c.ui = {
3391
- ...c.ui,
3392
- allowedActions: {
3393
- create: false
3394
- }
3395
- };
3351
+ })
3352
+ ]
3353
+ };
3354
+ if ((section == null ? void 0 : section.create) === "none") {
3355
+ c.ui = {
3356
+ ...c.ui,
3357
+ allowedActions: {
3358
+ create: false
3396
3359
  }
3397
- collections.push(c);
3360
+ };
3361
+ }
3362
+ return c;
3363
+ } else if (section.type === "document") {
3364
+ const filePath = section.path;
3365
+ const extname = import_path8.default.extname(filePath);
3366
+ const fileName = import_path8.default.basename(filePath, extname);
3367
+ const dir = import_path8.default.dirname(filePath);
3368
+ const ext = checkExt(extname);
3369
+ if (ext) {
3370
+ const fields = [];
3371
+ if (ext === "md" || ext === "mdx") {
3372
+ fields.push(BODY_FIELD);
3398
3373
  }
3399
- break;
3400
- case "document":
3401
- console.log(
3374
+ for (let currentTemplateName of templateMap.keys()) {
3375
+ const { templateObj, fields: additionalFields } = templateMap.get(currentTemplateName);
3376
+ const pages = (templateObj == null ? void 0 : templateObj.pages) || [];
3377
+ if (pages.includes(section.path)) {
3378
+ fields.push(...additionalFields);
3379
+ break;
3380
+ }
3381
+ }
3382
+ if (fields.length === 0) {
3383
+ fields.push({
3384
+ name: "dummy",
3385
+ label: "Dummy field",
3386
+ type: "string",
3387
+ description: "This is a dummy field, please replace it with the fields you want to edit. See https://tina.io/docs/schema/ for more info"
3388
+ });
3389
+ logger.warn(
3390
+ warnText(
3391
+ `No fields found for ${section.path}. Please add the fields you want to edit to the ${section.label} collection in the config file.`
3392
+ )
3393
+ );
3394
+ }
3395
+ return {
3396
+ ...baseCollection,
3397
+ path: dir,
3398
+ format: ext,
3399
+ ui: {
3400
+ allowedActions: {
3401
+ create: false,
3402
+ delete: false
3403
+ }
3404
+ },
3405
+ match: {
3406
+ include: fileName
3407
+ },
3408
+ fields
3409
+ };
3410
+ } else {
3411
+ logger.log(
3402
3412
  warnText(
3403
- `Single Document are not supported in TinaCMS yet. Skipping section ${section.label} (${section.path})`
3413
+ `Error: document section has an unsupported file extension: ${extname} in ${section.path}`
3404
3414
  )
3405
3415
  );
3406
- break;
3416
+ }
3417
+ }
3418
+ }
3419
+ };
3420
+ var generateCollections = async ({
3421
+ pathToForestryConfig
3422
+ }) => {
3423
+ const templateMap = await generateAllTemplates({ pathToForestryConfig });
3424
+ const forestryConfig = await import_fs_extra7.default.readFile(
3425
+ import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3426
+ );
3427
+ rewriteTemplateKeysInDocs(templateMap, pathToForestryConfig);
3428
+ return parseSections({ val: import_js_yaml2.default.load(forestryConfig.toString()) }).sections.map(
3429
+ (section) => generateCollectionFromForestrySection(section, templateMap)
3430
+ ).filter((c) => c !== void 0);
3431
+ };
3432
+ var rewriteTemplateKeysInDocs = (templateMap, rootPath) => {
3433
+ var _a;
3434
+ for (const templateKey of templateMap.keys()) {
3435
+ const { templateObj } = templateMap.get(templateKey);
3436
+ (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
3437
+ try {
3438
+ const filePath = import_path8.default.join(page);
3439
+ if (import_fs_extra7.default.lstatSync(filePath).isDirectory()) {
3440
+ return;
3441
+ }
3442
+ const extname = import_path8.default.extname(filePath);
3443
+ const fileContent = import_fs_extra7.default.readFileSync(filePath).toString();
3444
+ const content2 = (0, import_graphql14.parseFile)(fileContent, extname, (yup) => yup.object({}));
3445
+ const newContent = {
3446
+ _template: stringifyLabel(templateKey),
3447
+ ...content2
3448
+ };
3449
+ import_fs_extra7.default.writeFileSync(filePath, (0, import_graphql14.stringifyFile)(newContent, extname, true));
3450
+ } catch (error) {
3451
+ console.log(
3452
+ dangerText("Error updating template -> _template in ", page)
3453
+ );
3454
+ }
3455
+ });
3456
+ }
3457
+ };
3458
+
3459
+ // src/next/commands/codemod-command/index.ts
3460
+ var import_clipanion4 = require("clipanion");
3461
+ var import_fs_extra8 = __toESM(require("fs-extra"));
3462
+ var import_path9 = __toESM(require("path"));
3463
+ var CodemodCommand = class extends import_clipanion4.Command {
3464
+ constructor() {
3465
+ super(...arguments);
3466
+ this.rootPath = import_clipanion4.Option.String("--rootPath", {
3467
+ description: "Specify the root directory to run the CLI from"
3468
+ });
3469
+ this.verbose = import_clipanion4.Option.Boolean("-v,--verbose", false, {
3470
+ description: "increase verbosity of logged output"
3471
+ });
3472
+ }
3473
+ async catch(error) {
3474
+ console.log(error);
3475
+ }
3476
+ async execute() {
3477
+ const mod = this.path[1];
3478
+ if (!mod) {
3479
+ logger.error(
3480
+ "Must specify an additional argument (eg. 'move-tina-folder')"
3481
+ );
3482
+ process.exit(1);
3407
3483
  }
3484
+ const mods = { "move-tina-folder": () => moveTinaFolder(this.rootPath) };
3485
+ const command = mods[mod];
3486
+ if (!command) {
3487
+ logger.error(`Mod not found for ${mod}`);
3488
+ process.exit(1);
3489
+ }
3490
+ await command();
3491
+ }
3492
+ };
3493
+ CodemodCommand.paths = [["codemod"], ["codemod", "move-tina-folder"]];
3494
+ CodemodCommand.usage = import_clipanion4.Command.Usage({
3495
+ category: `Commands`,
3496
+ description: `Use codemods for various Tina tasks`
3497
+ });
3498
+ var moveTinaFolder = async (rootPath = process.cwd()) => {
3499
+ const configManager = new ConfigManager({ rootPath });
3500
+ try {
3501
+ await configManager.processConfig();
3502
+ } catch (e) {
3503
+ logger.error(e.message);
3504
+ process.exit(1);
3505
+ }
3506
+ const tinaDestination = import_path9.default.join(configManager.rootPath, "tina");
3507
+ if (await import_fs_extra8.default.existsSync(tinaDestination)) {
3508
+ logger.info(
3509
+ `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.`
3510
+ );
3511
+ } else {
3512
+ await import_fs_extra8.default.moveSync(configManager.tinaFolderPath, tinaDestination);
3513
+ await writeGitignore(configManager.rootPath);
3514
+ logger.info(
3515
+ "Move to 'tina' folder complete. Be sure to update any imports of the autogenerated client!"
3516
+ );
3408
3517
  }
3409
- return collections;
3518
+ };
3519
+ var writeGitignore = async (rootPath) => {
3520
+ await import_fs_extra8.default.outputFileSync(
3521
+ import_path9.default.join(rootPath, "tina", ".gitignore"),
3522
+ "__generated__"
3523
+ );
3410
3524
  };
3411
3525
 
3412
3526
  // src/cmds/init/index.ts
3413
3527
  async function initStaticTina({
3414
3528
  rootPath,
3529
+ pathToForestryConfig,
3415
3530
  noTelemetry
3416
3531
  }) {
3417
- const baseDir = rootPath;
3418
3532
  logger.level = "info";
3533
+ process.chdir(rootPath);
3419
3534
  const clientId = await chooseClientId();
3420
3535
  let token = null;
3421
3536
  if (clientId) {
@@ -3425,50 +3540,59 @@ async function initStaticTina({
3425
3540
  const framework = await chooseFramework();
3426
3541
  const usingTypescript = await chooseTypescript();
3427
3542
  const publicFolder = await choosePublicFolder({ framework });
3428
- const forestryPath = await hasForestryConfig({ rootPath });
3429
3543
  let collections;
3430
- if (forestryPath.exists) {
3544
+ const hasForestryConfig = await import_fs_extra9.default.pathExists(
3545
+ import_path10.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3546
+ );
3547
+ let isForestryMigration = false;
3548
+ if (hasForestryConfig) {
3431
3549
  collections = await forestryMigrate({
3432
- forestryPath: forestryPath.path,
3433
- rootPath
3550
+ pathToForestryConfig
3434
3551
  });
3552
+ if (collections) {
3553
+ isForestryMigration = true;
3554
+ }
3435
3555
  }
3436
3556
  await reportTelemetry({
3437
3557
  usingTypescript,
3438
- hasForestryConfig: forestryPath.exists,
3558
+ hasForestryConfig,
3439
3559
  noTelemetry
3440
3560
  });
3441
- const hasPackageJSON = await import_fs_extra8.default.pathExistsSync("package.json");
3561
+ const hasPackageJSON = await import_fs_extra9.default.pathExistsSync("package.json");
3442
3562
  if (!hasPackageJSON) {
3443
3563
  await createPackageJSON();
3444
3564
  }
3445
- const hasGitignore = await import_fs_extra8.default.pathExistsSync(".gitignore");
3565
+ const hasGitignore = await import_fs_extra9.default.pathExistsSync(".gitignore");
3446
3566
  if (!hasGitignore) {
3447
- await createGitignore({ baseDir });
3567
+ await createGitignore({ baseDir: "" });
3448
3568
  } else {
3449
3569
  const hasNodeModulesIgnored = await checkGitignoreForNodeModules({
3450
- baseDir
3570
+ baseDir: ""
3451
3571
  });
3452
3572
  if (!hasNodeModulesIgnored) {
3453
- await addNodeModulesToGitignore({ baseDir });
3573
+ await addNodeModulesToGitignore({ baseDir: "" });
3454
3574
  }
3455
3575
  }
3456
3576
  await addDependencies(packageManager);
3457
3577
  await addConfigFile({
3458
- publicFolder,
3459
- baseDir,
3578
+ publicFolder: import_path10.default.join(
3579
+ import_path10.default.relative(process.cwd(), pathToForestryConfig),
3580
+ publicFolder
3581
+ ),
3582
+ baseDir: "",
3460
3583
  usingTypescript,
3461
3584
  framework,
3462
3585
  collections,
3463
3586
  token,
3464
- clientId
3587
+ clientId,
3588
+ isForestryMigration
3465
3589
  });
3466
- if (!forestryPath.exists) {
3467
- await addContentFile({ baseDir });
3590
+ if (!hasForestryConfig) {
3591
+ await addContentFile({ baseDir: "" });
3468
3592
  }
3469
3593
  if (framework.reactive) {
3470
3594
  await addReactiveFile[framework.name]({
3471
- baseDir,
3595
+ baseDir: "",
3472
3596
  framework,
3473
3597
  usingTypescript
3474
3598
  });
@@ -3560,48 +3684,30 @@ var chooseFramework = async () => {
3560
3684
  return option["selection"];
3561
3685
  };
3562
3686
  var forestryMigrate = async ({
3563
- forestryPath,
3564
- rootPath
3687
+ pathToForestryConfig
3565
3688
  }) => {
3566
- logger.info(
3567
- `It looks like you have a ${focusText(
3568
- ".forestry/settings.yml"
3569
- )} file in your project.`
3570
- );
3571
- logger.info(
3572
- `This migration will update some of your content to match tina. Please ${focusText(
3573
- "save a backup of your content"
3574
- )} before doing this migration. (This can be done with git)`
3689
+ logger.info(`Forestry.io configuration found.`);
3690
+ const disclaimer = logText(
3691
+ `Note: This migration will update some of your content to match tina. Please save a backup of your content before doing this migration. (This can be done with git)`
3575
3692
  );
3576
3693
  const option = await (0, import_prompts2.default)({
3577
3694
  name: "selection",
3578
3695
  type: "confirm",
3579
3696
  initial: true,
3580
- message: `Please note that this is a beta version and may contain some issues
3581
- Would you like to migrate your Forestry templates?
3582
- ${logText(
3583
- "Note: This migration will not be perfect, but it will get you started."
3584
- )}`
3697
+ message: `Would you like to migrate your Forestry templates?
3698
+ ${disclaimer}`
3585
3699
  });
3586
3700
  if (!option["selection"]) {
3587
3701
  return null;
3588
3702
  }
3589
- const delay = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
3590
- await spin({
3591
- waitFor: async () => {
3592
- await delay(2e3);
3593
- },
3594
- text: ""
3595
- });
3596
3703
  const collections = await generateCollections({
3597
- forestryPath,
3598
- rootPath
3704
+ pathToForestryConfig
3599
3705
  });
3600
- ErrorSingleton.getInstance().printNameErrors();
3706
+ ErrorSingleton.getInstance().printCollectionNameErrors();
3601
3707
  return JSON.stringify(collections, null, 2);
3602
3708
  };
3603
3709
  var reportTelemetry = async ({
3604
- hasForestryConfig: hasForestryConfig2,
3710
+ hasForestryConfig,
3605
3711
  noTelemetry,
3606
3712
  usingTypescript
3607
3713
  }) => {
@@ -3614,7 +3720,7 @@ var reportTelemetry = async ({
3614
3720
  event: {
3615
3721
  name: "tinacms:cli:init:invoke",
3616
3722
  schemaFileType,
3617
- hasForestryConfig: hasForestryConfig2
3723
+ hasForestryConfig
3618
3724
  }
3619
3725
  });
3620
3726
  };
@@ -3624,22 +3730,22 @@ var createPackageJSON = async () => {
3624
3730
  };
3625
3731
  var createGitignore = async ({ baseDir }) => {
3626
3732
  logger.info(logText("No .gitignore found, creating one"));
3627
- await import_fs_extra8.default.outputFileSync(import_path9.default.join(baseDir, ".gitignore"), "node_modules");
3733
+ await import_fs_extra9.default.outputFileSync(import_path10.default.join(baseDir, ".gitignore"), "node_modules");
3628
3734
  };
3629
3735
  var checkGitignoreForNodeModules = async ({
3630
3736
  baseDir
3631
3737
  }) => {
3632
- const gitignoreContent = await import_fs_extra8.default.readFileSync(import_path9.default.join(baseDir, ".gitignore")).toString();
3738
+ const gitignoreContent = await import_fs_extra9.default.readFileSync(import_path10.default.join(baseDir, ".gitignore")).toString();
3633
3739
  return gitignoreContent.split("\n").some((item) => item === "node_modules");
3634
3740
  };
3635
3741
  var addNodeModulesToGitignore = async ({ baseDir }) => {
3636
3742
  logger.info(logText("Adding node_modules to .gitignore"));
3637
- const gitignoreContent = await import_fs_extra8.default.readFileSync(import_path9.default.join(baseDir, ".gitignore")).toString();
3743
+ const gitignoreContent = await import_fs_extra9.default.readFileSync(import_path10.default.join(baseDir, ".gitignore")).toString();
3638
3744
  const newGitignoreContent = [
3639
3745
  ...gitignoreContent.split("\n"),
3640
3746
  "node_modules"
3641
3747
  ].join("\n");
3642
- await import_fs_extra8.default.writeFileSync(import_path9.default.join(baseDir, ".gitignore"), newGitignoreContent);
3748
+ await import_fs_extra9.default.writeFileSync(import_path10.default.join(baseDir, ".gitignore"), newGitignoreContent);
3643
3749
  };
3644
3750
  var addDependencies = async (packageManager) => {
3645
3751
  logger.info(logText("Adding dependencies, this might take a moment..."));
@@ -3654,12 +3760,12 @@ var addDependencies = async (packageManager) => {
3654
3760
  };
3655
3761
  var addConfigFile = async (args) => {
3656
3762
  const { baseDir, usingTypescript } = args;
3657
- const configPath = import_path9.default.join(
3658
- ".tina",
3763
+ const configPath = import_path10.default.join(
3764
+ "tina",
3659
3765
  `config.${usingTypescript ? "ts" : "js"}`
3660
3766
  );
3661
- const fullConfigPath = import_path9.default.join(baseDir, configPath);
3662
- if (import_fs_extra8.default.pathExistsSync(fullConfigPath)) {
3767
+ const fullConfigPath = import_path10.default.join(baseDir, configPath);
3768
+ if (import_fs_extra9.default.pathExistsSync(fullConfigPath)) {
3663
3769
  const override = await (0, import_prompts2.default)({
3664
3770
  name: "selection",
3665
3771
  type: "confirm",
@@ -3667,23 +3773,24 @@ var addConfigFile = async (args) => {
3667
3773
  });
3668
3774
  if (override["selection"]) {
3669
3775
  logger.info(logText(`Overriding file at ${configPath}.`));
3670
- await import_fs_extra8.default.outputFileSync(fullConfigPath, config2(args));
3776
+ await import_fs_extra9.default.outputFileSync(fullConfigPath, config2(args));
3671
3777
  } else {
3672
3778
  logger.info(logText(`Not overriding file at ${configPath}.`));
3673
3779
  }
3674
3780
  } else {
3675
3781
  logger.info(
3676
3782
  logText(
3677
- `Adding config file at .tina/config.${usingTypescript ? "ts" : "js"}`
3783
+ `Adding config file at tina/config.${usingTypescript ? "ts" : "js"}`
3678
3784
  )
3679
3785
  );
3680
- await import_fs_extra8.default.outputFileSync(fullConfigPath, config2(args));
3786
+ await import_fs_extra9.default.outputFileSync(fullConfigPath, config2(args));
3787
+ await writeGitignore(baseDir);
3681
3788
  }
3682
3789
  };
3683
3790
  var addContentFile = async ({ baseDir }) => {
3684
- const contentPath = import_path9.default.join("content", "posts", "hello-world.md");
3685
- const fullContentPath = import_path9.default.join(baseDir, contentPath);
3686
- if (import_fs_extra8.default.pathExistsSync(fullContentPath)) {
3791
+ const contentPath = import_path10.default.join("content", "posts", "hello-world.md");
3792
+ const fullContentPath = import_path10.default.join(baseDir, contentPath);
3793
+ if (import_fs_extra9.default.pathExistsSync(fullContentPath)) {
3687
3794
  const override = await (0, import_prompts2.default)({
3688
3795
  name: "selection",
3689
3796
  type: "confirm",
@@ -3691,13 +3798,13 @@ var addContentFile = async ({ baseDir }) => {
3691
3798
  });
3692
3799
  if (override["selection"]) {
3693
3800
  logger.info(logText(`Overriding file at ${contentPath}.`));
3694
- await import_fs_extra8.default.outputFileSync(fullContentPath, content);
3801
+ await import_fs_extra9.default.outputFileSync(fullContentPath, content);
3695
3802
  } else {
3696
3803
  logger.info(logText(`Not overriding file at ${contentPath}.`));
3697
3804
  }
3698
3805
  } else {
3699
3806
  logger.info(logText(`Adding content file at ${contentPath}`));
3700
- await import_fs_extra8.default.outputFileSync(fullContentPath, content);
3807
+ await import_fs_extra9.default.outputFileSync(fullContentPath, content);
3701
3808
  }
3702
3809
  };
3703
3810
  var logNextSteps = ({
@@ -3757,20 +3864,20 @@ var addReactiveFile = {
3757
3864
  baseDir,
3758
3865
  usingTypescript
3759
3866
  }) => {
3760
- const usingSrc = !import_fs_extra8.default.pathExistsSync(import_path9.default.join(baseDir, "pages"));
3761
- const pagesPath = import_path9.default.join(baseDir, usingSrc ? "src" : "", "pages");
3762
- const packageJSONPath = import_path9.default.join(baseDir, "package.json");
3763
- const tinaBlogPagePath = import_path9.default.join(pagesPath, "demo", "blog");
3764
- const tinaBlogPagePathFile = import_path9.default.join(
3867
+ const usingSrc = !import_fs_extra9.default.pathExistsSync(import_path10.default.join(baseDir, "pages"));
3868
+ const pagesPath = import_path10.default.join(baseDir, usingSrc ? "src" : "", "pages");
3869
+ const packageJSONPath = import_path10.default.join(baseDir, "package.json");
3870
+ const tinaBlogPagePath = import_path10.default.join(pagesPath, "demo", "blog");
3871
+ const tinaBlogPagePathFile = import_path10.default.join(
3765
3872
  tinaBlogPagePath,
3766
3873
  `[filename].${usingTypescript ? "tsx" : "js"}`
3767
3874
  );
3768
- if (!import_fs_extra8.default.pathExistsSync(tinaBlogPagePathFile)) {
3769
- import_fs_extra8.default.mkdirpSync(tinaBlogPagePath);
3770
- import_fs_extra8.default.writeFileSync(tinaBlogPagePathFile, nextPostPage({ usingSrc }));
3875
+ if (!import_fs_extra9.default.pathExistsSync(tinaBlogPagePathFile)) {
3876
+ import_fs_extra9.default.mkdirpSync(tinaBlogPagePath);
3877
+ import_fs_extra9.default.writeFileSync(tinaBlogPagePathFile, nextPostPage({ usingSrc }));
3771
3878
  }
3772
3879
  logger.info("Adding a nextjs example... \u2705");
3773
- const pack = JSON.parse(import_fs_extra8.default.readFileSync(packageJSONPath).toString());
3880
+ const pack = JSON.parse(import_fs_extra9.default.readFileSync(packageJSONPath).toString());
3774
3881
  const oldScripts = pack.scripts || {};
3775
3882
  const newPack = JSON.stringify(
3776
3883
  {
@@ -3780,7 +3887,7 @@ var addReactiveFile = {
3780
3887
  null,
3781
3888
  2
3782
3889
  );
3783
- import_fs_extra8.default.writeFileSync(packageJSONPath, newPack);
3890
+ import_fs_extra9.default.writeFileSync(packageJSONPath, newPack);
3784
3891
  }
3785
3892
  };
3786
3893
  function execShellCommand(cmd) {
@@ -3796,13 +3903,16 @@ function execShellCommand(cmd) {
3796
3903
  }
3797
3904
 
3798
3905
  // src/next/commands/init-command/index.ts
3799
- var InitCommand = class extends import_clipanion4.Command {
3906
+ var InitCommand = class extends import_clipanion5.Command {
3800
3907
  constructor() {
3801
3908
  super(...arguments);
3802
- this.rootPath = import_clipanion4.Option.String("--rootPath", {
3803
- description: "Specify the root directory to run the CLI from"
3909
+ this.pathToForestryConfig = import_clipanion5.Option.String("--forestryPath", {
3910
+ description: "Specify the relative path to the .forestry directory, if importing an existing forestry site."
3911
+ });
3912
+ this.rootPath = import_clipanion5.Option.String("--rootPath", {
3913
+ description: "Specify the root directory to run the CLI from (defaults to current working directory)"
3804
3914
  });
3805
- this.noTelemetry = import_clipanion4.Option.Boolean("--noTelemetry", false, {
3915
+ this.noTelemetry = import_clipanion5.Option.Boolean("--noTelemetry", false, {
3806
3916
  description: "Disable anonymous telemetry that is collected"
3807
3917
  });
3808
3918
  }
@@ -3812,21 +3922,23 @@ var InitCommand = class extends import_clipanion4.Command {
3812
3922
  process.exit(1);
3813
3923
  }
3814
3924
  async execute() {
3925
+ const rootPath = this.rootPath || process.cwd();
3815
3926
  await initStaticTina({
3816
- rootPath: this.rootPath || process.cwd(),
3927
+ rootPath,
3928
+ pathToForestryConfig: this.pathToForestryConfig || rootPath,
3817
3929
  noTelemetry: this.noTelemetry
3818
3930
  });
3819
3931
  process.exit();
3820
3932
  }
3821
3933
  };
3822
3934
  InitCommand.paths = [["init"]];
3823
- InitCommand.usage = import_clipanion4.Command.Usage({
3935
+ InitCommand.usage = import_clipanion5.Command.Usage({
3824
3936
  category: `Commands`,
3825
3937
  description: `Add Tina to an existing project`
3826
3938
  });
3827
3939
 
3828
3940
  // src/index.ts
3829
- var cli = new import_clipanion5.Cli({
3941
+ var cli = new import_clipanion6.Cli({
3830
3942
  binaryName: `tinacms`,
3831
3943
  binaryLabel: `TinaCMS`,
3832
3944
  binaryVersion: version
@@ -3835,9 +3947,10 @@ cli.register(DevCommand);
3835
3947
  cli.register(BuildCommand);
3836
3948
  cli.register(AuditCommand);
3837
3949
  cli.register(InitCommand);
3838
- cli.register(import_clipanion5.Builtins.DefinitionsCommand);
3839
- cli.register(import_clipanion5.Builtins.HelpCommand);
3840
- cli.register(import_clipanion5.Builtins.VersionCommand);
3950
+ cli.register(CodemodCommand);
3951
+ cli.register(import_clipanion6.Builtins.DefinitionsCommand);
3952
+ cli.register(import_clipanion6.Builtins.HelpCommand);
3953
+ cli.register(import_clipanion6.Builtins.VersionCommand);
3841
3954
  var src_default = cli;
3842
3955
  // Annotate the CommonJS export names for ESM import in node:
3843
3956
  0 && (module.exports = {});