@tinacms/cli 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ module.exports = __toCommonJS(src_exports);
31
31
  var import_clipanion5 = require("clipanion");
32
32
 
33
33
  // package.json
34
- var version = "1.4.1";
34
+ var version = "1.5.0";
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
- }
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
+ };
930
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
  }
@@ -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;
@@ -1605,7 +1633,6 @@ var DevCommand = class extends import_clipanion.Command {
1605
1633
  schema: await (0, import_graphql8.getASTSchema)(database),
1606
1634
  configManager,
1607
1635
  port: Number(this.port),
1608
- noSDK: this.noSDK,
1609
1636
  queryDoc,
1610
1637
  fragDoc
1611
1638
  });
@@ -1642,7 +1669,6 @@ var DevCommand = class extends import_clipanion.Command {
1642
1669
  configManager,
1643
1670
  database,
1644
1671
  apiURL,
1645
- this.noSDK,
1646
1672
  this.noWatch
1647
1673
  );
1648
1674
  await server.listen(Number(this.port));
@@ -1694,7 +1720,7 @@ var DevCommand = class extends import_clipanion.Command {
1694
1720
  ]
1695
1721
  }
1696
1722
  ];
1697
- if (!this.noSDK) {
1723
+ if (!configManager.shouldSkipSDK()) {
1698
1724
  summaryItems.push({
1699
1725
  emoji: "\u{1F916}",
1700
1726
  heading: "Auto-generated files",
@@ -1791,7 +1817,7 @@ var import_graphql9 = require("@tinacms/graphql");
1791
1817
 
1792
1818
  // src/next/commands/build-command/server.ts
1793
1819
  var import_vite4 = require("vite");
1794
- var buildProductionSpa = async (configManager, database, apiURL, noSDK) => {
1820
+ var buildProductionSpa = async (configManager, database, apiURL) => {
1795
1821
  const publicEnv = {};
1796
1822
  Object.keys(process.env).forEach((key) => {
1797
1823
  if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
@@ -1810,10 +1836,10 @@ var buildProductionSpa = async (configManager, database, apiURL, noSDK) => {
1810
1836
  }
1811
1837
  });
1812
1838
  const config3 = await createConfig({
1839
+ plugins: [transformTsxPlugin({ configManager })],
1813
1840
  configManager,
1814
1841
  database,
1815
1842
  apiURL,
1816
- noSDK,
1817
1843
  noWatch: true
1818
1844
  });
1819
1845
  return (0, import_vite4.build)(config3);
@@ -1934,7 +1960,7 @@ var BuildCommand = class extends import_clipanion2.Command {
1934
1960
  description: "increase verbosity of logged output"
1935
1961
  });
1936
1962
  this.noSDK = import_clipanion2.Option.Boolean("--noSDK", false, {
1937
- description: "Don't generate the generated client SDK"
1963
+ description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1938
1964
  });
1939
1965
  this.datalayerPort = import_clipanion2.Option.String("--datalayer-port", "9000", {
1940
1966
  description: "Specify a port to run the datalayer server on. (default 4001)"
@@ -1960,10 +1986,11 @@ var BuildCommand = class extends import_clipanion2.Command {
1960
1986
  process.exit(1);
1961
1987
  }
1962
1988
  async execute() {
1963
- const configManager = new ConfigManager(
1964
- this.rootPath,
1965
- this.tinaGraphQLVersion
1966
- );
1989
+ const configManager = new ConfigManager({
1990
+ rootPath: this.rootPath,
1991
+ tinaGraphQLVersion: this.tinaGraphQLVersion,
1992
+ legacyNoSDK: this.noSDK
1993
+ });
1967
1994
  logger.info("Starting Tina build");
1968
1995
  if (this.isomorphicGitBridge) {
1969
1996
  logger.warn("--isomorphicGitBridge has been deprecated");
@@ -1976,6 +2003,11 @@ var BuildCommand = class extends import_clipanion2.Command {
1976
2003
  if (this.localOption) {
1977
2004
  logger.warn("--local has been deprecated");
1978
2005
  }
2006
+ if (this.noSDK) {
2007
+ logger.warn(
2008
+ "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
2009
+ );
2010
+ }
1979
2011
  try {
1980
2012
  await configManager.processConfig();
1981
2013
  } catch (e) {
@@ -1992,7 +2024,6 @@ var BuildCommand = class extends import_clipanion2.Command {
1992
2024
  const codegen2 = new Codegen({
1993
2025
  schema: await (0, import_graphql9.getASTSchema)(database),
1994
2026
  configManager,
1995
- noSDK: this.noSDK,
1996
2027
  queryDoc,
1997
2028
  fragDoc
1998
2029
  });
@@ -2000,13 +2031,13 @@ var BuildCommand = class extends import_clipanion2.Command {
2000
2031
  await this.checkClientInfo(configManager, apiURL);
2001
2032
  await waitForDB(configManager.config, apiURL, false);
2002
2033
  await this.checkGraphqlSchema(configManager, database, apiURL);
2003
- await buildProductionSpa(configManager, database, apiURL, this.noSDK);
2034
+ await buildProductionSpa(configManager, database, apiURL);
2004
2035
  await import_fs_extra5.default.outputFile(
2005
2036
  configManager.outputGitignorePath,
2006
2037
  "index.html\nassets/"
2007
2038
  );
2008
2039
  const summaryItems = [];
2009
- if (!this.noSDK) {
2040
+ if (!configManager.shouldSkipSDK()) {
2010
2041
  summaryItems.push({
2011
2042
  emoji: "\u{1F916}",
2012
2043
  heading: "Auto-generated files",
@@ -2044,13 +2075,13 @@ var BuildCommand = class extends import_clipanion2.Command {
2044
2075
  const { config: config3 } = configManager;
2045
2076
  const token = config3.token;
2046
2077
  const { clientId, branch, host } = (0, import_schema_tools2.parseURL)(apiURL);
2047
- const url2 = `https://${host}/db/${clientId}/status/${branch}`;
2078
+ const url = `https://${host}/db/${clientId}/status/${branch}`;
2048
2079
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
2049
2080
  let branchKnown = false;
2050
2081
  try {
2051
2082
  const res = await request({
2052
2083
  token,
2053
- url: url2
2084
+ url
2054
2085
  });
2055
2086
  bar2.tick({
2056
2087
  prog: "\u2705"
@@ -2092,7 +2123,7 @@ var BuildCommand = class extends import_clipanion2.Command {
2092
2123
  fn: async () => {
2093
2124
  const res = await request({
2094
2125
  token,
2095
- url: url2
2126
+ url
2096
2127
  });
2097
2128
  if (this.verbose) {
2098
2129
  logger.info(
@@ -2165,8 +2196,8 @@ async function request(args) {
2165
2196
  headers.append("X-API-KEY", args.token);
2166
2197
  }
2167
2198
  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, {
2199
+ const url = args == null ? void 0 : args.url;
2200
+ const res = await (0, import_node_fetch2.default)(url, {
2170
2201
  method: "GET",
2171
2202
  headers,
2172
2203
  redirect: "follow"
@@ -2200,7 +2231,7 @@ Message from server: ${json.message}`;
2200
2231
  };
2201
2232
  }
2202
2233
  var fetchRemoteGraphqlSchema = async ({
2203
- url: url2,
2234
+ url,
2204
2235
  token
2205
2236
  }) => {
2206
2237
  const headers = new import_node_fetch2.Headers();
@@ -2209,7 +2240,7 @@ var fetchRemoteGraphqlSchema = async ({
2209
2240
  }
2210
2241
  const body = JSON.stringify({ query: (0, import_graphql10.getIntrospectionQuery)(), variables: {} });
2211
2242
  headers.append("Content-Type", "application/json");
2212
- const res = await (0, import_node_fetch2.default)(url2, {
2243
+ const res = await (0, import_node_fetch2.default)(url, {
2213
2244
  method: "POST",
2214
2245
  headers,
2215
2246
  body
@@ -2220,13 +2251,12 @@ var fetchRemoteGraphqlSchema = async ({
2220
2251
 
2221
2252
  // src/next/commands/audit-command/index.ts
2222
2253
  var import_clipanion3 = require("clipanion");
2223
- var import_graphql13 = require("@tinacms/graphql");
2254
+ var import_graphql12 = require("@tinacms/graphql");
2224
2255
 
2225
2256
  // src/next/commands/audit-command/audit.ts
2226
2257
  var import_prompts = __toESM(require("prompts"));
2227
2258
  var import_metrics = require("@tinacms/metrics");
2228
2259
  var import_graphql11 = require("@tinacms/graphql");
2229
- var import_graphql12 = require("@tinacms/graphql");
2230
2260
  var import_chalk4 = __toESM(require("chalk"));
2231
2261
  var audit = async ({
2232
2262
  database,
@@ -2339,14 +2369,12 @@ var auditDocuments = async (args) => {
2339
2369
  }
2340
2370
  });
2341
2371
  }
2342
- const params = transformDocumentIntoMutationRequestPayload(
2372
+ const tinaSchema = await database.getSchema();
2373
+ const values = mergeValuesWithDefaults(
2343
2374
  docResult.data.document._values,
2344
- {
2345
- includeCollection: true,
2346
- includeTemplate: typeof collection.templates !== "undefined"
2347
- },
2348
2375
  topLevelDefaults
2349
2376
  );
2377
+ const params = tinaSchema.transformPayload(collection.name, values);
2350
2378
  const mutation = `mutation($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
2351
2379
  updateDocument(
2352
2380
  collection: $collection,
@@ -2376,46 +2404,8 @@ var auditDocuments = async (args) => {
2376
2404
  }
2377
2405
  return error;
2378
2406
  };
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
- }
2407
+ var mergeValuesWithDefaults = (document, defaults) => {
2408
+ return { ...defaults, ...filterObject(document) };
2419
2409
  };
2420
2410
  function filterObject(obj) {
2421
2411
  const ret = {};
@@ -2424,7 +2414,7 @@ function filterObject(obj) {
2424
2414
  }
2425
2415
 
2426
2416
  // src/next/commands/audit-command/index.ts
2427
- var import_graphql14 = require("@tinacms/graphql");
2417
+ var import_graphql13 = require("@tinacms/graphql");
2428
2418
  var AuditCommand = class extends import_clipanion3.Command {
2429
2419
  constructor() {
2430
2420
  super(...arguments);
@@ -2455,7 +2445,7 @@ var AuditCommand = class extends import_clipanion3.Command {
2455
2445
  process.exit(1);
2456
2446
  }
2457
2447
  async execute() {
2458
- const configManager = new ConfigManager(this.rootPath);
2448
+ const configManager = new ConfigManager({ rootPath: this.rootPath });
2459
2449
  logger.info("Starting Tina Audit");
2460
2450
  try {
2461
2451
  await configManager.processConfig();
@@ -2466,9 +2456,9 @@ var AuditCommand = class extends import_clipanion3.Command {
2466
2456
  createDBServer(Number(this.datalayerPort));
2467
2457
  const database = await createAndInitializeDatabase(
2468
2458
  configManager,
2469
- this.clean ? void 0 : new import_graphql14.AuditFileSystemBridge(configManager.rootPath)
2459
+ this.clean ? void 0 : new import_graphql13.AuditFileSystemBridge(configManager.rootPath)
2470
2460
  );
2471
- const { tinaSchema, graphQLSchema } = await (0, import_graphql13.buildSchema)(
2461
+ const { tinaSchema, graphQLSchema } = await (0, import_graphql12.buildSchema)(
2472
2462
  database,
2473
2463
  configManager.config
2474
2464
  );
@@ -2853,6 +2843,13 @@ var configExamples = {
2853
2843
  jekyll: other
2854
2844
  };
2855
2845
 
2846
+ // src/cmds/forestry-migrate/index.ts
2847
+ var import_fs_extra7 = __toESM(require("fs-extra"));
2848
+ var import_path8 = __toESM(require("path"));
2849
+ var import_js_yaml2 = __toESM(require("js-yaml"));
2850
+ var import_minimatch = __toESM(require("minimatch"));
2851
+ var import_graphql14 = require("@tinacms/graphql");
2852
+
2856
2853
  // src/cmds/forestry-migrate/util/index.ts
2857
2854
  var import_fs_extra6 = __toESM(require("fs-extra"));
2858
2855
  var import_path7 = __toESM(require("path"));
@@ -2866,28 +2863,29 @@ var ErrorSingleton = class {
2866
2863
  static getInstance() {
2867
2864
  if (!ErrorSingleton.instance) {
2868
2865
  ErrorSingleton.instance = new ErrorSingleton();
2869
- ErrorSingleton.instance.allErrorNames = [];
2866
+ ErrorSingleton.instance.collectionNameErrors = [];
2870
2867
  }
2871
2868
  return ErrorSingleton.instance;
2872
2869
  }
2873
2870
  addErrorName(error) {
2874
- this.allErrorNames.push(error);
2871
+ this.collectionNameErrors.push(error);
2875
2872
  }
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) => {
2873
+ printCollectionNameErrors() {
2874
+ var _a;
2875
+ if ((_a = this.collectionNameErrors) == null ? void 0 : _a.length) {
2887
2876
  logger.error(
2888
- `- Content that uses ${error.template}.yaml: ${error.name} -> ${error.newName}`
2877
+ dangerText("ERROR: TinaCMS only supports alphanumeric template names")
2889
2878
  );
2890
- });
2879
+ logger.error("The following templates have been renamed:");
2880
+ this.collectionNameErrors.forEach((error) => {
2881
+ logger.error(`- ${error.template}.yaml -> ${error.newName}`);
2882
+ });
2883
+ logger.error(
2884
+ `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(
2885
+ "https://tina.io/docs/forestry/common-errors/#migrating-fields-with-non-alphanumeric-characters"
2886
+ )} for more information.`
2887
+ );
2888
+ }
2891
2889
  }
2892
2890
  };
2893
2891
 
@@ -2993,11 +2991,12 @@ var FrontmatterTemplateSchema = import_zod.default.object({
2993
2991
  });
2994
2992
  var transformForestryFieldsToTinaFields = ({
2995
2993
  fields,
2996
- rootPath,
2994
+ pathToForestryConfig,
2997
2995
  template,
2998
2996
  skipBlocks = false
2999
2997
  }) => {
3000
2998
  const tinaFields = [];
2999
+ const blockFields = [];
3001
3000
  fields == null ? void 0 : fields.forEach((forestryField2) => {
3002
3001
  var _a, _b, _c, _d;
3003
3002
  if (forestryField2.name === "menu") {
@@ -3065,6 +3064,14 @@ var transformForestryFieldsToTinaFields = ({
3065
3064
  label: forestryField2.label
3066
3065
  };
3067
3066
  break;
3067
+ case "image_gallery":
3068
+ field = {
3069
+ type: "image",
3070
+ ...getTinaFieldsFromName(forestryField2.name),
3071
+ label: forestryField2.label,
3072
+ list: true
3073
+ };
3074
+ break;
3068
3075
  case "select":
3069
3076
  if ((_a = forestryField2.config) == null ? void 0 : _a.options) {
3070
3077
  field = {
@@ -3110,7 +3117,7 @@ var transformForestryFieldsToTinaFields = ({
3110
3117
  label: forestryField2.label,
3111
3118
  fields: transformForestryFieldsToTinaFields({
3112
3119
  fields: forestryField2.fields,
3113
- rootPath,
3120
+ pathToForestryConfig,
3114
3121
  template,
3115
3122
  skipBlocks
3116
3123
  })
@@ -3125,20 +3132,22 @@ var transformForestryFieldsToTinaFields = ({
3125
3132
  fields: transformForestryFieldsToTinaFields({
3126
3133
  fields: forestryField2.fields,
3127
3134
  template,
3128
- rootPath,
3135
+ pathToForestryConfig,
3129
3136
  skipBlocks
3130
3137
  })
3131
3138
  };
3132
3139
  break;
3133
3140
  case "blocks":
3134
- if (skipBlocks)
3141
+ if (skipBlocks) {
3142
+ blockFields.push(forestryField2.name);
3135
3143
  break;
3144
+ }
3136
3145
  const templates = [];
3137
3146
  forestryField2 == null ? void 0 : forestryField2.template_types.forEach((tem) => {
3138
3147
  const { fields: fields2, template: template2 } = getFieldsFromTemplates({
3139
3148
  tem,
3140
3149
  skipBlocks: true,
3141
- rootPath: process.cwd()
3150
+ pathToForestryConfig
3142
3151
  });
3143
3152
  const t = {
3144
3153
  fields: fields2,
@@ -3155,7 +3164,6 @@ var transformForestryFieldsToTinaFields = ({
3155
3164
  templates
3156
3165
  };
3157
3166
  break;
3158
- case "image_gallery":
3159
3167
  case "include":
3160
3168
  logger.info(
3161
3169
  warnText(
@@ -3177,11 +3185,22 @@ var transformForestryFieldsToTinaFields = ({
3177
3185
  tinaFields.push(field);
3178
3186
  }
3179
3187
  });
3188
+ if (blockFields.length > 0) {
3189
+ logger.info(
3190
+ warnText(
3191
+ `Skipping blocks field${blockFields.length > 1 ? "s" : ""}: ${blockFields.map((b) => `"${b}"`).join(
3192
+ ", "
3193
+ )}" in ${template}.yaml. Blocks fields need to be manually imported: ${linkText(
3194
+ "https://tina.io/docs/forestry/common-errors/#migrating-blocks"
3195
+ )}`
3196
+ )
3197
+ );
3198
+ }
3180
3199
  return tinaFields;
3181
3200
  };
3182
- var getFieldsFromTemplates = ({ tem, rootPath, skipBlocks = false }) => {
3201
+ var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = true }) => {
3183
3202
  const templatePath = import_path7.default.join(
3184
- rootPath,
3203
+ pathToForestryConfig,
3185
3204
  ".forestry",
3186
3205
  "front_matter",
3187
3206
  "templates",
@@ -3201,7 +3220,7 @@ var getFieldsFromTemplates = ({ tem, rootPath, skipBlocks = false }) => {
3201
3220
  const template = parseTemplates({ val: templateObj });
3202
3221
  const fields = transformForestryFieldsToTinaFields({
3203
3222
  fields: template.fields,
3204
- rootPath,
3223
+ pathToForestryConfig,
3205
3224
  template: tem,
3206
3225
  skipBlocks
3207
3226
  });
@@ -3211,25 +3230,12 @@ var parseTemplates = ({ val }) => {
3211
3230
  const template = FrontmatterTemplateSchema.parse(val);
3212
3231
  return template;
3213
3232
  };
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
3233
  var parseSections = ({ val }) => {
3223
3234
  const schema = forestryConfigSchema.parse(val);
3224
3235
  return schema;
3225
3236
  };
3226
3237
 
3227
3238
  // 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
3239
  var BODY_FIELD = {
3234
3240
  type: "rich-text",
3235
3241
  name: "body",
@@ -3240,18 +3246,34 @@ var BODY_FIELD = {
3240
3246
  var stringifyLabel = (label) => {
3241
3247
  return label.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
3242
3248
  };
3243
- var generateAllCollections = async ({
3244
- rootPath
3249
+ var transformForestryMatchToTinaMatch = (match) => {
3250
+ var _a, _b;
3251
+ 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("{}", "");
3252
+ if (match !== newMatch) {
3253
+ logger.warn(`Warning: Match ${match} was transformed to ${newMatch}`);
3254
+ }
3255
+ return newMatch;
3256
+ };
3257
+ function checkExt(ext) {
3258
+ const extReal = ext.replace(".", "");
3259
+ if (["mdx", "md", "json", "yaml", "yml", "toml"].includes(extReal)) {
3260
+ return extReal;
3261
+ } else {
3262
+ return false;
3263
+ }
3264
+ }
3265
+ var generateAllTemplates = async ({
3266
+ pathToForestryConfig
3245
3267
  }) => {
3246
3268
  const allTemplates = (await import_fs_extra7.default.readdir(
3247
- import_path8.default.join(rootPath, ".forestry", "front_matter", "templates")
3269
+ import_path8.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
3248
3270
  )).map((tem) => import_path8.default.basename(tem, ".yml"));
3249
3271
  const templateMap = /* @__PURE__ */ new Map();
3250
3272
  const proms = allTemplates.map(async (tem) => {
3251
3273
  try {
3252
3274
  const { fields, templateObj } = getFieldsFromTemplates({
3253
3275
  tem,
3254
- rootPath
3276
+ pathToForestryConfig
3255
3277
  });
3256
3278
  templateMap.set(tem, { fields, templateObj });
3257
3279
  } catch (e) {
@@ -3263,158 +3285,176 @@ var generateAllCollections = async ({
3263
3285
  await Promise.all(proms);
3264
3286
  return templateMap;
3265
3287
  };
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];
3288
+ var generateCollectionFromForestrySection = (section, templateMap) => {
3289
+ if (section.read_only)
3290
+ return;
3291
+ {
3278
3292
  if (section.read_only)
3279
3293
  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
- }
3294
+ const baseCollection = {
3295
+ label: section.label,
3296
+ name: stringifyLabel(section.label),
3297
+ path: section.path
3298
+ };
3299
+ if (section.match) {
3300
+ baseCollection.match = {
3301
+ ...(baseCollection == null ? void 0 : baseCollection.match) || {},
3302
+ include: transformForestryMatchToTinaMatch(section.match)
3303
+ };
3304
+ }
3305
+ if (section.exclude) {
3306
+ baseCollection.match = {
3307
+ ...(baseCollection == null ? void 0 : baseCollection.match) || {},
3308
+ exclude: transformForestryMatchToTinaMatch(section.exclude)
3309
+ };
3310
+ }
3311
+ if (section.type === "directory") {
3312
+ const forestryTemplates = (section == null ? void 0 : section.templates) || [];
3313
+ if (forestryTemplates.length === 0 && section.create === "all") {
3314
+ for (let templateKey of templateMap.keys()) {
3315
+ const { templateObj } = templateMap.get(templateKey);
3316
+ const pages = templateObj == null ? void 0 : templateObj.pages;
3317
+ if (pages) {
3318
+ if (pages.some(
3319
+ (page) => (0, import_minimatch.default)(page, section.path + "/" + section.match)
3320
+ )) {
3321
+ forestryTemplates.push(templateKey);
3293
3322
  }
3294
3323
  }
3295
3324
  }
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
3325
+ }
3326
+ const c = ((forestryTemplates == null ? void 0 : forestryTemplates.length) || 0) > 1 ? {
3327
+ ...baseCollection,
3328
+ templates: forestryTemplates.map((tem) => {
3329
+ const { fields } = templateMap.get(tem);
3330
+ return {
3331
+ fields: [BODY_FIELD, ...fields],
3332
+ label: tem,
3333
+ name: stringifyLabel(tem)
3339
3334
  };
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;
3335
+ })
3336
+ } : {
3337
+ ...baseCollection,
3338
+ fields: [
3339
+ BODY_FIELD,
3340
+ ...(forestryTemplates || []).flatMap((tem) => {
3353
3341
  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
- });
3342
+ const { fields: additionalFields } = templateMap.get(tem);
3343
+ return additionalFields;
3378
3344
  } catch (e) {
3379
3345
  logger.log("Error parsing template ", tem);
3380
- console.error(e);
3346
+ return [];
3381
3347
  }
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
- };
3348
+ })
3349
+ ]
3350
+ };
3351
+ if ((section == null ? void 0 : section.create) === "none") {
3352
+ c.ui = {
3353
+ ...c.ui,
3354
+ allowedActions: {
3355
+ create: false
3356
+ }
3357
+ };
3358
+ }
3359
+ return c;
3360
+ } else if (section.type === "document") {
3361
+ const filePath = section.path;
3362
+ const extname = import_path8.default.extname(filePath);
3363
+ const fileName = import_path8.default.basename(filePath, extname);
3364
+ const dir = import_path8.default.dirname(filePath);
3365
+ const ext = checkExt(extname);
3366
+ if (ext) {
3367
+ const fields = [];
3368
+ if (ext === "md" || ext === "mdx") {
3369
+ fields.push(BODY_FIELD);
3370
+ }
3371
+ for (let currentTemplateName of templateMap.keys()) {
3372
+ const { templateObj, fields: additionalFields } = templateMap.get(currentTemplateName);
3373
+ const pages = (templateObj == null ? void 0 : templateObj.pages) || [];
3374
+ if (pages.includes(section.path)) {
3375
+ fields.push(...additionalFields);
3376
+ break;
3396
3377
  }
3397
- collections.push(c);
3398
3378
  }
3399
- break;
3400
- case "document":
3401
- console.log(
3379
+ if (fields.length === 0) {
3380
+ fields.push({
3381
+ name: "dummy",
3382
+ label: "Dummy field",
3383
+ type: "string",
3384
+ 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"
3385
+ });
3386
+ logger.warn(
3387
+ warnText(
3388
+ `No fields found for ${section.path}. Please add the fields you want to edit to the ${section.label} collection in the config file.`
3389
+ )
3390
+ );
3391
+ }
3392
+ return {
3393
+ ...baseCollection,
3394
+ path: dir,
3395
+ format: ext,
3396
+ ui: {
3397
+ allowedActions: {
3398
+ create: false,
3399
+ delete: false
3400
+ }
3401
+ },
3402
+ match: {
3403
+ include: fileName
3404
+ },
3405
+ fields
3406
+ };
3407
+ } else {
3408
+ logger.log(
3402
3409
  warnText(
3403
- `Single Document are not supported in TinaCMS yet. Skipping section ${section.label} (${section.path})`
3410
+ `Error: document section has an unsupported file extension: ${extname} in ${section.path}`
3404
3411
  )
3405
3412
  );
3406
- break;
3413
+ }
3407
3414
  }
3408
3415
  }
3409
- return collections;
3416
+ };
3417
+ var generateCollections = async ({
3418
+ pathToForestryConfig
3419
+ }) => {
3420
+ const templateMap = await generateAllTemplates({ pathToForestryConfig });
3421
+ const forestryConfig = await import_fs_extra7.default.readFile(
3422
+ import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3423
+ );
3424
+ rewriteTemplateKeysInDocs(templateMap, pathToForestryConfig);
3425
+ return parseSections({ val: import_js_yaml2.default.load(forestryConfig.toString()) }).sections.map(
3426
+ (section) => generateCollectionFromForestrySection(section, templateMap)
3427
+ ).filter((c) => c !== void 0);
3428
+ };
3429
+ var rewriteTemplateKeysInDocs = (templateMap, rootPath) => {
3430
+ var _a;
3431
+ for (const templateKey of templateMap.keys()) {
3432
+ const { templateObj } = templateMap.get(templateKey);
3433
+ (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
3434
+ try {
3435
+ const filePath = import_path8.default.join(page);
3436
+ const extname = import_path8.default.extname(filePath);
3437
+ const fileContent = import_fs_extra7.default.readFileSync(filePath).toString();
3438
+ const content2 = (0, import_graphql14.parseFile)(fileContent, extname, (yup) => yup.object({}));
3439
+ const newContent = {
3440
+ _template: stringifyLabel(templateKey),
3441
+ ...content2
3442
+ };
3443
+ import_fs_extra7.default.writeFileSync(filePath, (0, import_graphql14.stringifyFile)(newContent, extname, true));
3444
+ } catch (error) {
3445
+ console.log(
3446
+ dangerText("Error updating template -> _template in ", page)
3447
+ );
3448
+ }
3449
+ });
3450
+ }
3410
3451
  };
3411
3452
 
3412
3453
  // src/cmds/init/index.ts
3413
3454
  async function initStaticTina({
3414
- rootPath,
3455
+ pathToForestryConfig,
3415
3456
  noTelemetry
3416
3457
  }) {
3417
- const baseDir = rootPath;
3418
3458
  logger.level = "info";
3419
3459
  const clientId = await chooseClientId();
3420
3460
  let token = null;
@@ -3425,17 +3465,18 @@ async function initStaticTina({
3425
3465
  const framework = await chooseFramework();
3426
3466
  const usingTypescript = await chooseTypescript();
3427
3467
  const publicFolder = await choosePublicFolder({ framework });
3428
- const forestryPath = await hasForestryConfig({ rootPath });
3429
3468
  let collections;
3430
- if (forestryPath.exists) {
3469
+ const hasForestryConfig = await import_fs_extra8.default.pathExists(
3470
+ import_path9.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3471
+ );
3472
+ if (hasForestryConfig) {
3431
3473
  collections = await forestryMigrate({
3432
- forestryPath: forestryPath.path,
3433
- rootPath
3474
+ pathToForestryConfig
3434
3475
  });
3435
3476
  }
3436
3477
  await reportTelemetry({
3437
3478
  usingTypescript,
3438
- hasForestryConfig: forestryPath.exists,
3479
+ hasForestryConfig,
3439
3480
  noTelemetry
3440
3481
  });
3441
3482
  const hasPackageJSON = await import_fs_extra8.default.pathExistsSync("package.json");
@@ -3444,31 +3485,34 @@ async function initStaticTina({
3444
3485
  }
3445
3486
  const hasGitignore = await import_fs_extra8.default.pathExistsSync(".gitignore");
3446
3487
  if (!hasGitignore) {
3447
- await createGitignore({ baseDir });
3488
+ await createGitignore({ baseDir: "" });
3448
3489
  } else {
3449
3490
  const hasNodeModulesIgnored = await checkGitignoreForNodeModules({
3450
- baseDir
3491
+ baseDir: ""
3451
3492
  });
3452
3493
  if (!hasNodeModulesIgnored) {
3453
- await addNodeModulesToGitignore({ baseDir });
3494
+ await addNodeModulesToGitignore({ baseDir: "" });
3454
3495
  }
3455
3496
  }
3456
3497
  await addDependencies(packageManager);
3457
3498
  await addConfigFile({
3458
- publicFolder,
3459
- baseDir,
3499
+ publicFolder: import_path9.default.join(
3500
+ import_path9.default.relative(process.cwd(), pathToForestryConfig),
3501
+ publicFolder
3502
+ ),
3503
+ baseDir: "",
3460
3504
  usingTypescript,
3461
3505
  framework,
3462
3506
  collections,
3463
3507
  token,
3464
3508
  clientId
3465
3509
  });
3466
- if (!forestryPath.exists) {
3467
- await addContentFile({ baseDir });
3510
+ if (!hasForestryConfig) {
3511
+ await addContentFile({ baseDir: "" });
3468
3512
  }
3469
3513
  if (framework.reactive) {
3470
3514
  await addReactiveFile[framework.name]({
3471
- baseDir,
3515
+ baseDir: "",
3472
3516
  framework,
3473
3517
  usingTypescript
3474
3518
  });
@@ -3560,48 +3604,30 @@ var chooseFramework = async () => {
3560
3604
  return option["selection"];
3561
3605
  };
3562
3606
  var forestryMigrate = async ({
3563
- forestryPath,
3564
- rootPath
3607
+ pathToForestryConfig
3565
3608
  }) => {
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)`
3609
+ logger.info(`Forestry.io configuration found.`);
3610
+ const disclaimer = logText(
3611
+ `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
3612
  );
3576
3613
  const option = await (0, import_prompts2.default)({
3577
3614
  name: "selection",
3578
3615
  type: "confirm",
3579
3616
  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
- )}`
3617
+ message: `Would you like to migrate your Forestry templates?
3618
+ ${disclaimer}`
3585
3619
  });
3586
3620
  if (!option["selection"]) {
3587
3621
  return null;
3588
3622
  }
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
3623
  const collections = await generateCollections({
3597
- forestryPath,
3598
- rootPath
3624
+ pathToForestryConfig
3599
3625
  });
3600
- ErrorSingleton.getInstance().printNameErrors();
3626
+ ErrorSingleton.getInstance().printCollectionNameErrors();
3601
3627
  return JSON.stringify(collections, null, 2);
3602
3628
  };
3603
3629
  var reportTelemetry = async ({
3604
- hasForestryConfig: hasForestryConfig2,
3630
+ hasForestryConfig,
3605
3631
  noTelemetry,
3606
3632
  usingTypescript
3607
3633
  }) => {
@@ -3614,7 +3640,7 @@ var reportTelemetry = async ({
3614
3640
  event: {
3615
3641
  name: "tinacms:cli:init:invoke",
3616
3642
  schemaFileType,
3617
- hasForestryConfig: hasForestryConfig2
3643
+ hasForestryConfig
3618
3644
  }
3619
3645
  });
3620
3646
  };
@@ -3799,8 +3825,8 @@ function execShellCommand(cmd) {
3799
3825
  var InitCommand = class extends import_clipanion4.Command {
3800
3826
  constructor() {
3801
3827
  super(...arguments);
3802
- this.rootPath = import_clipanion4.Option.String("--rootPath", {
3803
- description: "Specify the root directory to run the CLI from"
3828
+ this.pathToForestryConfig = import_clipanion4.Option.String("--forestryPath", {
3829
+ description: "Specify the relative path to the .forestry directory, if importing an existing forestry site."
3804
3830
  });
3805
3831
  this.noTelemetry = import_clipanion4.Option.Boolean("--noTelemetry", false, {
3806
3832
  description: "Disable anonymous telemetry that is collected"
@@ -3813,7 +3839,7 @@ var InitCommand = class extends import_clipanion4.Command {
3813
3839
  }
3814
3840
  async execute() {
3815
3841
  await initStaticTina({
3816
- rootPath: this.rootPath || process.cwd(),
3842
+ pathToForestryConfig: this.pathToForestryConfig || process.cwd(),
3817
3843
  noTelemetry: this.noTelemetry
3818
3844
  });
3819
3845
  process.exit();