@tinacms/cli 1.5.32 → 1.5.33

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,14 +31,14 @@ module.exports = __toCommonJS(src_exports);
31
31
  var import_clipanion8 = require("clipanion");
32
32
 
33
33
  // package.json
34
- var version = "1.5.32";
34
+ var version = "1.5.33";
35
35
 
36
36
  // src/next/commands/dev-command/index.ts
37
37
  var import_clipanion2 = require("clipanion");
38
38
  var import_fs_extra6 = __toESM(require("fs-extra"));
39
39
  var import_path7 = __toESM(require("path"));
40
40
  var import_chokidar = __toESM(require("chokidar"));
41
- var import_graphql9 = require("@tinacms/graphql");
41
+ var import_graphql10 = require("@tinacms/graphql");
42
42
 
43
43
  // src/next/config-manager.ts
44
44
  var import_fs_extra = __toESM(require("fs-extra"));
@@ -105,17 +105,17 @@ ${import_chalk.default.gray(
105
105
  `
106
106
  );
107
107
  };
108
- var summary = (content2) => {
108
+ var summary = (content) => {
109
109
  const outString = [];
110
110
  let longestKey = 0;
111
- content2.items.forEach((item) => {
111
+ content.items.forEach((item) => {
112
112
  item.subItems.forEach((subItem) => {
113
113
  if (subItem.key.length > longestKey) {
114
114
  longestKey = subItem.key.length;
115
115
  }
116
116
  });
117
117
  });
118
- content2.items.forEach((item) => {
118
+ content.items.forEach((item) => {
119
119
  outString.push(`${item.emoji} ${import_chalk.default.cyan(item.heading)}`);
120
120
  item.subItems.forEach((subItem) => {
121
121
  const spaces = longestKey - subItem.key.length + 4;
@@ -128,9 +128,9 @@ var summary = (content2) => {
128
128
  outString.push(``);
129
129
  });
130
130
  if (process.env.CI) {
131
- logger.info(JSON.stringify(content2, null, 2));
131
+ logger.info(JSON.stringify(content, null, 2));
132
132
  } else {
133
- note(outString.join("\n"), content2.heading);
133
+ note(outString.join("\n"), content.heading);
134
134
  }
135
135
  };
136
136
  var unicode = isUnicodeSupported();
@@ -261,6 +261,22 @@ var ConfigManager = class {
261
261
  this.generatedFolderPath,
262
262
  "client.js"
263
263
  );
264
+ this.generatedClientDFilePath = import_path.default.join(
265
+ this.generatedFolderPath,
266
+ "client.d.ts"
267
+ );
268
+ this.generatedDatabaseClientDFilePath = import_path.default.join(
269
+ this.generatedFolderPath,
270
+ "databaseClient.d.ts"
271
+ );
272
+ this.generatedDatabaseClientTSFilePath = import_path.default.join(
273
+ this.generatedFolderPath,
274
+ "databaseClient.ts"
275
+ );
276
+ this.generatedDatabaseClientJSFilePath = import_path.default.join(
277
+ this.generatedFolderPath,
278
+ "databaseClient.js"
279
+ );
264
280
  const clientExists = this.isUsingTs() ? await import_fs_extra.default.pathExists(this.generatedClientTSFilePath) : await import_fs_extra.default.pathExists(this.generatedClientJSFilePath);
265
281
  if (!clientExists) {
266
282
  const file = "export default ()=>({})\nexport const client = ()=>({})";
@@ -270,12 +286,12 @@ var ConfigManager = class {
270
286
  await import_fs_extra.default.outputFile(this.generatedClientJSFilePath, file);
271
287
  }
272
288
  }
273
- const { config: config3, prebuildPath, watchList } = await this.loadConfigFile(
289
+ const { config: config2, prebuildPath, watchList } = await this.loadConfigFile(
274
290
  this.generatedFolderPath,
275
291
  this.tinaConfigFilePath
276
292
  );
277
293
  this.watchList = watchList;
278
- this.config = config3;
294
+ this.config = config2;
279
295
  this.prebuildFilePath = prebuildPath;
280
296
  this.publicFolderPath = import_path.default.join(
281
297
  this.rootPath,
@@ -382,7 +398,7 @@ var ConfigManager = class {
382
398
  return;
383
399
  }
384
400
  const filepathWithExtension = `${filepath}.${ext}`;
385
- const exists = await import_fs_extra.default.existsSync(filepathWithExtension);
401
+ const exists = import_fs_extra.default.existsSync(filepathWithExtension);
386
402
  if (exists) {
387
403
  result = filepathWithExtension;
388
404
  }
@@ -401,7 +417,7 @@ var ConfigManager = class {
401
417
  loader: loaders
402
418
  });
403
419
  const result = require(outfile);
404
- await import_fs_extra.default.removeSync(outfile);
420
+ import_fs_extra.default.removeSync(outfile);
405
421
  return result.default;
406
422
  }
407
423
  async loadConfigFile(generatedFolderPath, configFilePath) {
@@ -410,7 +426,7 @@ var ConfigManager = class {
410
426
  const outfile = import_path.default.join(tmpdir, "config.build.jsx");
411
427
  const outfile2 = import_path.default.join(tmpdir, "config.build.js");
412
428
  const tempTSConfigFile = import_path.default.join(tmpdir, "tsconfig.json");
413
- await import_fs_extra.default.outputFileSync(tempTSConfigFile, "{}");
429
+ import_fs_extra.default.outputFileSync(tempTSConfigFile, "{}");
414
430
  const result2 = await esbuild.build({
415
431
  entryPoints: [configFilePath],
416
432
  bundle: true,
@@ -448,9 +464,16 @@ var ConfigManager = class {
448
464
  outfile: outfile2,
449
465
  loader: loaders
450
466
  });
451
- const result = require(outfile2);
452
- await import_fs_extra.default.removeSync(outfile);
453
- await import_fs_extra.default.removeSync(outfile2);
467
+ let result;
468
+ try {
469
+ result = require(outfile2);
470
+ } catch (e) {
471
+ console.error("Unexpected error loading config");
472
+ console.error(e);
473
+ throw e;
474
+ }
475
+ import_fs_extra.default.removeSync(outfile);
476
+ import_fs_extra.default.removeSync(outfile2);
454
477
  return {
455
478
  config: result.default,
456
479
  prebuildPath: prebuild,
@@ -572,6 +595,9 @@ var cmdText = import_chalk3.default.inverse;
572
595
  var indentedCmd = (str) => {
573
596
  return ` \u2503 ` + str;
574
597
  };
598
+ var indentText = (str) => {
599
+ return String(str).split("\n").map((line) => ` ${line}`).join("\n");
600
+ };
575
601
  var logText = import_chalk3.default.italic.gray;
576
602
  var warnText = import_chalk3.default.yellowBright.bgBlack;
577
603
  var titleText = import_chalk3.default.bgHex("d2f1f8").hex("ec4816");
@@ -597,7 +623,7 @@ var tinaTailwind = (spaPath, prebuildFilePath) => {
597
623
  name: "vite-plugin-tina",
598
624
  config: (viteConfig) => {
599
625
  const plugins = [];
600
- const content2 = [
626
+ const content = [
601
627
  import_path2.default.join(spaPath, "src/**/*.{vue,js,ts,jsx,tsx,svelte}"),
602
628
  prebuildFilePath,
603
629
  require.resolve("tinacms")
@@ -815,7 +841,7 @@ var tinaTailwind = (spaPath, prebuildFilePath) => {
815
841
  }
816
842
  }
817
843
  },
818
- content: content2,
844
+ content,
819
845
  plugins: [(0, import_typography.default)({ className: "tina-prose" }), import_aspect_ratio.default]
820
846
  });
821
847
  plugins.push(tw);
@@ -834,12 +860,12 @@ var tinaTailwind = (spaPath, prebuildFilePath) => {
834
860
  var import_normalize_path2 = __toESM(require("normalize-path"));
835
861
  async function listFilesRecursively({
836
862
  directoryPath,
837
- config: config3,
863
+ config: config2,
838
864
  roothPath
839
865
  }) {
840
866
  const fullDirectoryPath = import_path3.default.join(
841
867
  roothPath,
842
- config3.publicFolder,
868
+ config2.publicFolder,
843
869
  directoryPath
844
870
  );
845
871
  const exists = await import_fs_extra2.default.pathExists(fullDirectoryPath);
@@ -855,7 +881,7 @@ async function listFilesRecursively({
855
881
  id: item,
856
882
  filename: item,
857
883
  type: stats.isDirectory() ? "dir" : "file",
858
- directory: `${directoryPath.replace(config3.mediaRoot, "")}`,
884
+ directory: `${directoryPath.replace(config2.mediaRoot, "")}`,
859
885
  src: `/${import_path3.default.join(directoryPath, item)}`,
860
886
  thumbnails: {
861
887
  "75x75": `/${import_path3.default.join(directoryPath, item)}`,
@@ -866,7 +892,7 @@ async function listFilesRecursively({
866
892
  if (stats.isDirectory()) {
867
893
  staticMediaItem.children = await listFilesRecursively({
868
894
  directoryPath: import_path3.default.join(directoryPath, item),
869
- config: config3,
895
+ config: config2,
870
896
  roothPath
871
897
  });
872
898
  }
@@ -940,7 +966,7 @@ var createConfig = async ({
940
966
  if (configManager.config.build.basePath) {
941
967
  basePath = configManager.config.build.basePath;
942
968
  }
943
- const config3 = {
969
+ const config2 = {
944
970
  root: configManager.spaRootPath,
945
971
  base: `/${basePath ? `${(0, import_normalize_path2.default)(basePath)}/` : ""}${(0, import_normalize_path2.default)(
946
972
  configManager.config.build.outputFolder
@@ -992,7 +1018,7 @@ var createConfig = async ({
992
1018
  ...plugins
993
1019
  ]
994
1020
  };
995
- return config3;
1021
+ return config2;
996
1022
  };
997
1023
 
998
1024
  // src/next/vite/plugins.ts
@@ -1009,15 +1035,15 @@ var import_graphql = require("@tinacms/graphql");
1009
1035
  var import_fs_extra3 = __toESM(require("fs-extra"));
1010
1036
  var import_path4 = __toESM(require("path"));
1011
1037
  var import_busboy = __toESM(require("busboy"));
1012
- var createMediaRouter = (config3) => {
1038
+ var createMediaRouter = (config2) => {
1013
1039
  const mediaFolder = import_path4.default.join(
1014
- config3.rootPath,
1015
- config3.publicFolder,
1016
- config3.mediaRoot
1040
+ config2.rootPath,
1041
+ config2.publicFolder,
1042
+ config2.mediaRoot
1017
1043
  );
1018
- const mediaModel = new MediaModel(config3);
1044
+ const mediaModel = new MediaModel(config2);
1019
1045
  const handleList = async (req, res) => {
1020
- const requestURL = new URL(req.url, config3.apiURL);
1046
+ const requestURL = new URL(req.url, config2.apiURL);
1021
1047
  const folder = requestURL.pathname.replace("/media/list/", "");
1022
1048
  const limit = requestURL.searchParams.get("limit");
1023
1049
  const cursor = requestURL.searchParams.get("cursor");
@@ -1164,7 +1190,7 @@ var MediaModel = class {
1164
1190
 
1165
1191
  // src/next/commands/dev-command/server/searchIndex.ts
1166
1192
  var createSearchIndexRouter = ({
1167
- config: config3,
1193
+ config: config2,
1168
1194
  searchIndex
1169
1195
  }) => {
1170
1196
  const put = async (req, res) => {
@@ -1174,7 +1200,7 @@ var createSearchIndexRouter = ({
1174
1200
  res.end(JSON.stringify({ result }));
1175
1201
  };
1176
1202
  const get = async (req, res) => {
1177
- const requestURL = new URL(req.url, config3.apiURL);
1203
+ const requestURL = new URL(req.url, config2.apiURL);
1178
1204
  const query = requestURL.searchParams.get("q");
1179
1205
  const optionsParam = requestURL.searchParams.get("options");
1180
1206
  let options = {
@@ -1195,7 +1221,7 @@ var createSearchIndexRouter = ({
1195
1221
  }
1196
1222
  };
1197
1223
  const del = async (req, res) => {
1198
- const requestURL = new URL(req.url, config3.apiURL);
1224
+ const requestURL = new URL(req.url, config2.apiURL);
1199
1225
  const docId = requestURL.pathname.split("/").filter(Boolean).slice(1).join("/");
1200
1226
  const result = await searchIndex.DELETE(docId);
1201
1227
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -1492,7 +1518,7 @@ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBas
1492
1518
  };
1493
1519
 
1494
1520
  // src/next/codegen/codegen/sdkPlugin/index.ts
1495
- var plugin = (schema, documents, config3) => {
1521
+ var plugin = (schema, documents, config2) => {
1496
1522
  const allAst = (0, import_graphql4.concatAST)(
1497
1523
  documents.reduce((prev, v) => {
1498
1524
  return [...prev, v.document];
@@ -1507,9 +1533,9 @@ var plugin = (schema, documents, config3) => {
1507
1533
  onType: fragmentDef.typeCondition.name.value,
1508
1534
  isExternal: false
1509
1535
  })),
1510
- ...config3.externalFragments || []
1536
+ ...config2.externalFragments || []
1511
1537
  ];
1512
- const visitor = new GenericSdkVisitor(schema, allFragments, config3);
1538
+ const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1513
1539
  const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1514
1540
  return {
1515
1541
  content: [
@@ -1573,6 +1599,7 @@ var loadGraphQLDocuments = async (globPath) => {
1573
1599
 
1574
1600
  // src/next/codegen/index.ts
1575
1601
  var import_esbuild2 = require("esbuild");
1602
+ var import_graphql7 = require("@tinacms/graphql");
1576
1603
  var TINA_HOST = "content.tinajs.io";
1577
1604
  var Codegen = class {
1578
1605
  constructor({
@@ -1645,6 +1672,7 @@ var Codegen = class {
1645
1672
  );
1646
1673
  await maybeWarnFragmentSize(this.configManager.generatedFragmentsFilePath);
1647
1674
  const { clientString } = await this.genClient();
1675
+ const databaseClientString = this.configManager.hasSelfHostedConfig() ? await this.genDatabaseClient() : "";
1648
1676
  const { codeString, schemaString } = await this.genTypes();
1649
1677
  await import_fs_extra4.default.outputFile(
1650
1678
  this.configManager.generatedGraphQLGQLPath,
@@ -1659,6 +1687,12 @@ var Codegen = class {
1659
1687
  this.configManager.generatedClientTSFilePath,
1660
1688
  clientString
1661
1689
  );
1690
+ if (this.configManager.hasSelfHostedConfig()) {
1691
+ await import_fs_extra4.default.outputFile(
1692
+ this.configManager.generatedDatabaseClientTSFilePath,
1693
+ databaseClientString
1694
+ );
1695
+ }
1662
1696
  await unlinkIfExists(this.configManager.generatedClientJSFilePath);
1663
1697
  await unlinkIfExists(this.configManager.generatedTypesDFilePath);
1664
1698
  await unlinkIfExists(this.configManager.generatedTypesJSFilePath);
@@ -1667,17 +1701,38 @@ var Codegen = class {
1667
1701
  this.configManager.generatedTypesDFilePath,
1668
1702
  codeString
1669
1703
  );
1670
- const jsCode = await (0, import_esbuild2.transform)(codeString, { loader: "ts" });
1704
+ const jsTypes = await (0, import_esbuild2.transform)(codeString, { loader: "ts" });
1671
1705
  await import_fs_extra4.default.outputFile(
1672
1706
  this.configManager.generatedTypesJSFilePath,
1673
- jsCode.code
1707
+ jsTypes.code
1674
1708
  );
1675
1709
  await import_fs_extra4.default.outputFile(
1676
- this.configManager.generatedClientJSFilePath,
1710
+ this.configManager.generatedClientDFilePath,
1677
1711
  clientString
1678
1712
  );
1713
+ const jsClient = await (0, import_esbuild2.transform)(clientString, { loader: "ts" });
1714
+ await import_fs_extra4.default.outputFile(
1715
+ this.configManager.generatedClientJSFilePath,
1716
+ jsClient.code
1717
+ );
1679
1718
  await unlinkIfExists(this.configManager.generatedTypesTSFilePath);
1680
1719
  await unlinkIfExists(this.configManager.generatedClientTSFilePath);
1720
+ if (this.configManager.hasSelfHostedConfig()) {
1721
+ const jsDatabaseClient = await (0, import_esbuild2.transform)(databaseClientString, {
1722
+ loader: "ts"
1723
+ });
1724
+ await import_fs_extra4.default.outputFile(
1725
+ this.configManager.generatedDatabaseClientJSFilePath,
1726
+ jsDatabaseClient.code
1727
+ );
1728
+ await import_fs_extra4.default.outputFile(
1729
+ this.configManager.generatedDatabaseClientDFilePath,
1730
+ databaseClientString
1731
+ );
1732
+ await unlinkIfExists(
1733
+ this.configManager.generatedDatabaseClientTSFilePath
1734
+ );
1735
+ }
1681
1736
  }
1682
1737
  return apiURL;
1683
1738
  }
@@ -1717,6 +1772,95 @@ var Codegen = class {
1717
1772
  throw new Error("apiURL not set. Please run execute() first");
1718
1773
  return this.apiURL;
1719
1774
  }
1775
+ async genDatabaseClient() {
1776
+ var _a, _b;
1777
+ const authCollection = this.tinaSchema.getCollections().find((c) => c.isAuthCollection);
1778
+ let authFields = [];
1779
+ if (authCollection) {
1780
+ const usersFields = (0, import_graphql7.mapUserFields)(authCollection, []);
1781
+ if (usersFields.length === 0) {
1782
+ throw new Error("No user field found");
1783
+ }
1784
+ if (usersFields.length > 1) {
1785
+ throw new Error("Only one user field is allowed");
1786
+ }
1787
+ authFields = (_b = (_a = usersFields[0]) == null ? void 0 : _a.collectable) == null ? void 0 : _b.fields.map((f) => {
1788
+ if (f.type !== "password" && f.type !== "object") {
1789
+ if (f.uid) {
1790
+ return `id:${f.name}`;
1791
+ } else {
1792
+ return `${f.name}`;
1793
+ }
1794
+ } else if (f.type === "password") {
1795
+ return `_password: ${f.name} { passwordChangeRequired }`;
1796
+ }
1797
+ });
1798
+ }
1799
+ return `// @ts-nocheck
1800
+ import { resolve } from "@tinacms/datalayer";
1801
+ import type { TinaClient } from "tinacms/dist/client";
1802
+
1803
+ import { queries } from "./types";
1804
+ import database from "../database";
1805
+
1806
+ export async function databaseRequest({ query, variables, user }) {
1807
+ const result = await resolve({
1808
+ config: {
1809
+ useRelativeMedia: true,
1810
+ },
1811
+ database,
1812
+ query,
1813
+ variables,
1814
+ verbose: true,
1815
+ ctxUser: user,
1816
+ });
1817
+
1818
+ return result;
1819
+ }
1820
+
1821
+ export async function authenticate({ username, password }) {
1822
+ return databaseRequest({
1823
+ query: \`query auth($username:String!, $password:String!) {
1824
+ authenticate(sub:$username, password:$password) {
1825
+ ${authFields.join(" ")}
1826
+ }
1827
+ }\`,
1828
+ variables: { username, password },
1829
+ })
1830
+ }
1831
+
1832
+ export async function authorize(user: { sub: string }) {
1833
+ return databaseRequest({
1834
+ query: \`query authz { authorize { ${authFields.join(" ")}} }\`,
1835
+ variables: {},
1836
+ user
1837
+ })
1838
+ }
1839
+
1840
+ function createDatabaseClient<GenQueries = Record<string, unknown>>({
1841
+ queries,
1842
+ }: {
1843
+ queries: (client: {
1844
+ request: TinaClient<GenQueries>["request"];
1845
+ }) => GenQueries;
1846
+ }) {
1847
+ const request = async ({ query, variables, user }) => {
1848
+ const data = await databaseRequest({ query, variables, user });
1849
+ return { data: data.data as any, query, variables, errors: data.errors || null };
1850
+ };
1851
+ const q = queries({
1852
+ request,
1853
+ });
1854
+ return { queries: q, request, authenticate, authorize };
1855
+ }
1856
+
1857
+ export const databaseClient = createDatabaseClient({ queries });
1858
+
1859
+ export const client = databaseClient;
1860
+
1861
+ export default databaseClient;
1862
+ `;
1863
+ }
1720
1864
  async genClient() {
1721
1865
  var _a, _b, _c;
1722
1866
  const token = (_a = this.configManager.config) == null ? void 0 : _a.token;
@@ -1748,7 +1892,7 @@ export default client;
1748
1892
  ${typescriptTypes}
1749
1893
  `;
1750
1894
  const schemaString = `# DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
1751
- ${await (0, import_graphql6.printSchema)(this.schema)}
1895
+ ${(0, import_graphql6.printSchema)(this.schema)}
1752
1896
  schema {
1753
1897
  query: Query
1754
1898
  mutation: Mutation
@@ -1758,7 +1902,7 @@ schema {
1758
1902
  }
1759
1903
  };
1760
1904
  var maybeWarnFragmentSize = async (filepath) => {
1761
- if (await (await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
1905
+ if ((await import_fs_extra4.default.stat(filepath)).size > 100 * 1024) {
1762
1906
  console.warn(
1763
1907
  "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
1764
1908
  );
@@ -1773,13 +1917,13 @@ var maybeWarnFragmentSize = async (filepath) => {
1773
1917
  }
1774
1918
  };
1775
1919
  var unlinkIfExists = async (filepath) => {
1776
- if (await import_fs_extra4.default.existsSync(filepath)) {
1777
- await import_fs_extra4.default.unlinkSync(filepath);
1920
+ if (import_fs_extra4.default.existsSync(filepath)) {
1921
+ import_fs_extra4.default.unlinkSync(filepath);
1778
1922
  }
1779
1923
  };
1780
1924
 
1781
1925
  // src/next/database.ts
1782
- var import_graphql7 = require("@tinacms/graphql");
1926
+ var import_graphql8 = require("@tinacms/graphql");
1783
1927
  var import_readable_stream = require("readable-stream");
1784
1928
  var import_net = require("net");
1785
1929
  var import_many_level = require("many-level");
@@ -1805,7 +1949,7 @@ var createDBServer = (port) => {
1805
1949
  };
1806
1950
  async function createAndInitializeDatabase(configManager, datalayerPort, bridgeOverride) {
1807
1951
  let database;
1808
- const bridge = bridgeOverride || new import_graphql7.FilesystemBridge(configManager.rootPath, configManager.contentRootPath);
1952
+ const bridge = bridgeOverride || new import_graphql8.FilesystemBridge(configManager.rootPath, configManager.contentRootPath);
1809
1953
  if (configManager.hasSelfHostedConfig() && configManager.config.contentApiUrlOverride) {
1810
1954
  database = await configManager.loadDatabaseFile();
1811
1955
  database.bridge = bridge;
@@ -1817,9 +1961,9 @@ async function createAndInitializeDatabase(configManager, datalayerPort, bridgeO
1817
1961
  )} but there was no "contentApiUrlOverride" set. Falling back to built-in datalayer`
1818
1962
  );
1819
1963
  }
1820
- const level = new import_graphql7.TinaLevelClient(datalayerPort);
1964
+ const level = new import_graphql8.TinaLevelClient(datalayerPort);
1821
1965
  level.openConnection();
1822
- database = (0, import_graphql7.createDatabase)({
1966
+ database = (0, import_graphql8.createDatabaseInternal)({
1823
1967
  bridge,
1824
1968
  level,
1825
1969
  tinaDirectory: configManager.isUsingLegacyFolder ? LEGACY_TINA_FOLDER : TINA_FOLDER
@@ -1834,9 +1978,9 @@ var import_chalk4 = __toESM(require("chalk"));
1834
1978
 
1835
1979
  // src/utils/start-subprocess.ts
1836
1980
  var import_child_process = __toESM(require("child_process"));
1837
- var startSubprocess2 = async ({ command }) => {
1838
- if (typeof command === "string") {
1839
- const commands = command.split(" ");
1981
+ var startSubprocess2 = async ({ command: command2 }) => {
1982
+ if (typeof command2 === "string") {
1983
+ const commands = command2.split(" ");
1840
1984
  const firstCommand = commands[0];
1841
1985
  const args = commands.slice(1) || [];
1842
1986
  const ps = import_child_process.default.spawn(firstCommand, args, {
@@ -1899,7 +2043,7 @@ function spin({
1899
2043
  }
1900
2044
 
1901
2045
  // src/next/commands/baseCommands.ts
1902
- var import_graphql8 = require("@tinacms/graphql");
2046
+ var import_graphql9 = require("@tinacms/graphql");
1903
2047
  var import_fs_extra5 = __toESM(require("fs-extra"));
1904
2048
  var BaseCommand = class extends import_clipanion.Command {
1905
2049
  constructor() {
@@ -1984,7 +2128,7 @@ var BaseCommand = class extends import_clipanion.Command {
1984
2128
  const rootPath = configManager.rootPath;
1985
2129
  let sha;
1986
2130
  try {
1987
- sha = await (0, import_graphql8.getSha)({ fs: import_fs_extra5.default, dir: rootPath });
2131
+ sha = await (0, import_graphql9.getSha)({ fs: import_fs_extra5.default, dir: rootPath });
1988
2132
  } catch (e) {
1989
2133
  if (partialReindex) {
1990
2134
  console.error(
@@ -1994,7 +2138,7 @@ var BaseCommand = class extends import_clipanion.Command {
1994
2138
  }
1995
2139
  }
1996
2140
  const lastSha = await database.getMetadata("lastSha");
1997
- const exists = lastSha && await (0, import_graphql8.shaExists)({ fs: import_fs_extra5.default, dir: rootPath, sha: lastSha });
2141
+ const exists = lastSha && await (0, import_graphql9.shaExists)({ fs: import_fs_extra5.default, dir: rootPath, sha: lastSha });
1998
2142
  let res;
1999
2143
  if (partialReindex && lastSha && exists && sha) {
2000
2144
  const pathFilter = {};
@@ -2008,7 +2152,7 @@ var BaseCommand = class extends import_clipanion.Command {
2008
2152
  matches: ((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include) ? tinaSchema.getMatches({ collection }) : void 0
2009
2153
  };
2010
2154
  }
2011
- const { added, modified, deleted } = await (0, import_graphql8.getChangedFiles)({
2155
+ const { added, modified, deleted } = await (0, import_graphql9.getChangedFiles)({
2012
2156
  fs: import_fs_extra5.default,
2013
2157
  dir: rootPath,
2014
2158
  from: lastSha,
@@ -2016,7 +2160,7 @@ var BaseCommand = class extends import_clipanion.Command {
2016
2160
  pathFilter
2017
2161
  });
2018
2162
  const tinaPathUpdates = modified.filter(
2019
- (path12) => path12.startsWith(".tina/__generated__/_schema.json") || path12.startsWith("tina/tina-lock.json")
2163
+ (path13) => path13.startsWith(".tina/__generated__/_schema.json") || path13.startsWith("tina/tina-lock.json")
2020
2164
  );
2021
2165
  if (tinaPathUpdates.length > 0) {
2022
2166
  res = await database.indexContent({
@@ -2104,7 +2248,7 @@ var DevCommand = class extends BaseCommand {
2104
2248
  } else {
2105
2249
  database.clearCache();
2106
2250
  }
2107
- const { tinaSchema: tinaSchema2, graphQLSchema: graphQLSchema2, lookup, queryDoc, fragDoc } = await (0, import_graphql9.buildSchema)(configManager.config);
2251
+ const { tinaSchema: tinaSchema2, graphQLSchema: graphQLSchema2, lookup, queryDoc, fragDoc } = await (0, import_graphql10.buildSchema)(configManager.config);
2108
2252
  const codegen2 = new Codegen({
2109
2253
  isLocal: true,
2110
2254
  configManager,
@@ -2198,7 +2342,7 @@ ${dangerText(e.message)}
2198
2342
  await server.listen(Number(this.port));
2199
2343
  const searchIndexer = new import_search.SearchIndexer({
2200
2344
  batchSize: ((_e = configManager.config.search) == null ? void 0 : _e.indexBatchSize) || 100,
2201
- bridge: new import_graphql9.FilesystemBridge(
2345
+ bridge: new import_graphql10.FilesystemBridge(
2202
2346
  configManager.rootPath,
2203
2347
  configManager.contentRootPath
2204
2348
  ),
@@ -2344,7 +2488,7 @@ var import_node_fetch2 = __toESM(require("node-fetch"));
2344
2488
  var import_clipanion3 = require("clipanion");
2345
2489
  var import_progress2 = __toESM(require("progress"));
2346
2490
  var import_fs_extra7 = __toESM(require("fs-extra"));
2347
- var import_graphql10 = require("@tinacms/graphql");
2491
+ var import_graphql11 = require("@tinacms/graphql");
2348
2492
 
2349
2493
  // src/next/commands/build-command/server.ts
2350
2494
  var import_vite5 = require("vite");
@@ -2366,19 +2510,19 @@ var buildProductionSpa = async (configManager, database, apiURL) => {
2366
2510
  }
2367
2511
  }
2368
2512
  });
2369
- const config3 = await createConfig({
2513
+ const config2 = await createConfig({
2370
2514
  plugins: [transformTsxPlugin({ configManager }), viteTransformExtension()],
2371
2515
  configManager,
2372
2516
  database,
2373
2517
  apiURL,
2374
2518
  noWatch: true
2375
2519
  });
2376
- return (0, import_vite5.build)(config3);
2520
+ return (0, import_vite5.build)(config2);
2377
2521
  };
2378
2522
 
2379
2523
  // src/next/commands/build-command/index.ts
2380
2524
  var import_schema_tools2 = require("@tinacms/schema-tools");
2381
- var import_graphql11 = require("graphql");
2525
+ var import_graphql12 = require("graphql");
2382
2526
  var import_core2 = require("@graphql-inspector/core");
2383
2527
 
2384
2528
  // src/next/commands/build-command/waitForDB.ts
@@ -2410,8 +2554,8 @@ var IndexFailedError = class extends Error {
2410
2554
  this.name = "IndexFailedError";
2411
2555
  }
2412
2556
  };
2413
- var waitForDB = async (config3, apiUrl, verbose) => {
2414
- const token = config3.token;
2557
+ var waitForDB = async (config2, apiUrl, verbose) => {
2558
+ const token = config2.token;
2415
2559
  const { clientId, branch, isLocalClient, host } = (0, import_schema_tools.parseURL)(apiUrl);
2416
2560
  if (isLocalClient || !host || !clientId || !branch) {
2417
2561
  if (verbose) {
@@ -2533,7 +2677,7 @@ ${dangerText(e.message)}`);
2533
2677
  configManager,
2534
2678
  Number(this.datalayerPort)
2535
2679
  );
2536
- const { queryDoc, fragDoc, graphQLSchema, tinaSchema, lookup } = await (0, import_graphql10.buildSchema)(configManager.config);
2680
+ const { queryDoc, fragDoc, graphQLSchema, tinaSchema, lookup } = await (0, import_graphql11.buildSchema)(configManager.config);
2537
2681
  const codegen2 = new Codegen({
2538
2682
  configManager,
2539
2683
  port: this.localOption ? Number(this.port) : void 0,
@@ -2630,7 +2774,7 @@ ${dangerText(e.message)}
2630
2774
  }
2631
2775
  const searchIndexer = new import_search2.SearchIndexer({
2632
2776
  batchSize: ((_s = configManager.config.search) == null ? void 0 : _s.indexBatchSize) || 100,
2633
- bridge: new import_graphql10.FilesystemBridge(
2777
+ bridge: new import_graphql11.FilesystemBridge(
2634
2778
  configManager.rootPath,
2635
2779
  configManager.contentRootPath
2636
2780
  ),
@@ -2697,8 +2841,8 @@ ${dangerText(e.message)}
2697
2841
  }
2698
2842
  }
2699
2843
  async checkClientInfo(configManager, apiURL) {
2700
- const { config: config3 } = configManager;
2701
- const token = config3.token;
2844
+ const { config: config2 } = configManager;
2845
+ const token = config2.token;
2702
2846
  const { clientId, branch, host } = (0, import_schema_tools2.parseURL)(apiURL);
2703
2847
  const url = `https://${host}/db/${clientId}/status/${branch}`;
2704
2848
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
@@ -2724,11 +2868,11 @@ ${dangerText(e.message)}
2724
2868
  subItems: [
2725
2869
  {
2726
2870
  key: "clientId",
2727
- value: config3.clientId
2871
+ value: config2.clientId
2728
2872
  },
2729
2873
  {
2730
2874
  key: "token",
2731
- value: config3.token
2875
+ value: config2.token
2732
2876
  }
2733
2877
  ]
2734
2878
  }
@@ -2782,8 +2926,8 @@ ${dangerText(e.message)}
2782
2926
  "Checking local GraphQL Schema matches server. :prog",
2783
2927
  1
2784
2928
  );
2785
- const { config: config3 } = configManager;
2786
- const token = config3.token;
2929
+ const { config: config2 } = configManager;
2930
+ const token = config2.token;
2787
2931
  const remoteSchema = await fetchRemoteGraphqlSchema({
2788
2932
  url: apiURL,
2789
2933
  token
@@ -2793,16 +2937,16 @@ ${dangerText(e.message)}
2793
2937
  prog: "\u274C"
2794
2938
  });
2795
2939
  let errorMessage = `The remote GraphQL schema does not exist. Check indexing for this branch.`;
2796
- if (config3 == null ? void 0 : config3.branch) {
2940
+ if (config2 == null ? void 0 : config2.branch) {
2797
2941
  errorMessage += `
2798
2942
 
2799
- Additional info: Branch: ${config3.branch}, Client ID: ${config3.clientId} `;
2943
+ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
2800
2944
  }
2801
2945
  throw new Error(errorMessage);
2802
2946
  }
2803
- const remoteGqlSchema = (0, import_graphql11.buildClientSchema)(remoteSchema);
2947
+ const remoteGqlSchema = (0, import_graphql12.buildClientSchema)(remoteSchema);
2804
2948
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
2805
- const localGraphqlSchema = (0, import_graphql11.buildASTSchema)(localSchemaDocument);
2949
+ const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
2806
2950
  try {
2807
2951
  const diffResult = await (0, import_core2.diff)(localGraphqlSchema, remoteGqlSchema);
2808
2952
  if (diffResult.length === 0) {
@@ -2814,10 +2958,10 @@ Additional info: Branch: ${config3.branch}, Client ID: ${config3.clientId} `;
2814
2958
  prog: "\u274C"
2815
2959
  });
2816
2960
  let errorMessage = `The local GraphQL schema doesn't match the remote GraphQL schema. Please push up your changes to GitHub to update your remote GraphQL schema.`;
2817
- if (config3 == null ? void 0 : config3.branch) {
2961
+ if (config2 == null ? void 0 : config2.branch) {
2818
2962
  errorMessage += `
2819
2963
 
2820
- Additional info: Branch: ${config3.branch}, Client ID: ${config3.clientId} `;
2964
+ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
2821
2965
  }
2822
2966
  throw new Error(errorMessage);
2823
2967
  }
@@ -2887,7 +3031,7 @@ var fetchRemoteGraphqlSchema = async ({
2887
3031
  if (token) {
2888
3032
  headers.append("X-API-KEY", token);
2889
3033
  }
2890
- const body = JSON.stringify({ query: (0, import_graphql11.getIntrospectionQuery)(), variables: {} });
3034
+ const body = JSON.stringify({ query: (0, import_graphql12.getIntrospectionQuery)(), variables: {} });
2891
3035
  headers.append("Content-Type", "application/json");
2892
3036
  const res = await (0, import_node_fetch2.default)(url, {
2893
3037
  method: "POST",
@@ -2900,12 +3044,12 @@ var fetchRemoteGraphqlSchema = async ({
2900
3044
 
2901
3045
  // src/next/commands/audit-command/index.ts
2902
3046
  var import_clipanion4 = require("clipanion");
2903
- var import_graphql13 = require("@tinacms/graphql");
3047
+ var import_graphql14 = require("@tinacms/graphql");
2904
3048
 
2905
3049
  // src/next/commands/audit-command/audit.ts
2906
3050
  var import_prompts = __toESM(require("prompts"));
2907
3051
  var import_metrics = require("@tinacms/metrics");
2908
- var import_graphql12 = require("@tinacms/graphql");
3052
+ var import_graphql13 = require("@tinacms/graphql");
2909
3053
  var import_chalk5 = __toESM(require("chalk"));
2910
3054
  var audit = async ({
2911
3055
  database,
@@ -2990,7 +3134,7 @@ var auditDocuments = async (args) => {
2990
3134
  }
2991
3135
  }
2992
3136
  }`;
2993
- const docResult = await (0, import_graphql12.resolve)({
3137
+ const docResult = await (0, import_graphql13.resolve)({
2994
3138
  database,
2995
3139
  query: documentQuery,
2996
3140
  variables: {},
@@ -3031,7 +3175,7 @@ var auditDocuments = async (args) => {
3031
3175
  params: $params
3032
3176
  ){__typename}
3033
3177
  }`;
3034
- const mutationRes = await (0, import_graphql12.resolve)({
3178
+ const mutationRes = await (0, import_graphql13.resolve)({
3035
3179
  database,
3036
3180
  query: mutation,
3037
3181
  variables: {
@@ -3063,7 +3207,7 @@ function filterObject(obj) {
3063
3207
  }
3064
3208
 
3065
3209
  // src/next/commands/audit-command/index.ts
3066
- var import_graphql14 = require("@tinacms/graphql");
3210
+ var import_graphql15 = require("@tinacms/graphql");
3067
3211
  var AuditCommand = class extends import_clipanion4.Command {
3068
3212
  constructor() {
3069
3213
  super(...arguments);
@@ -3106,9 +3250,9 @@ var AuditCommand = class extends import_clipanion4.Command {
3106
3250
  const database = await createAndInitializeDatabase(
3107
3251
  configManager,
3108
3252
  Number(this.datalayerPort),
3109
- this.clean ? void 0 : new import_graphql14.AuditFileSystemBridge(configManager.rootPath)
3253
+ this.clean ? void 0 : new import_graphql15.AuditFileSystemBridge(configManager.rootPath)
3110
3254
  );
3111
- const { tinaSchema, graphQLSchema, lookup } = await (0, import_graphql13.buildSchema)(
3255
+ const { tinaSchema, graphQLSchema, lookup } = await (0, import_graphql14.buildSchema)(
3112
3256
  configManager.config
3113
3257
  );
3114
3258
  const warnings = [];
@@ -3148,381 +3292,752 @@ AuditCommand.usage = import_clipanion4.Command.Usage({
3148
3292
  // src/next/commands/init-command/index.ts
3149
3293
  var import_clipanion6 = require("clipanion");
3150
3294
 
3151
- // src/cmds/init/index.ts
3152
- var import_path11 = __toESM(require("path"));
3153
- var import_prettier2 = require("prettier");
3154
- var import_fs_extra11 = __toESM(require("fs-extra"));
3155
- var import_prompts2 = __toESM(require("prompts"));
3156
- var import_metrics2 = require("@tinacms/metrics");
3157
-
3158
- // src/cmds/init/setup-files/index.ts
3159
- var nextPostPage = ({
3160
- usingSrc
3161
- }) => `// THIS FILE HAS BEEN GENERATED WITH THE TINA CLI.
3162
- // This is a demo file once you have tina setup feel free to delete this file
3163
-
3164
- import Head from 'next/head'
3165
- import { useTina } from 'tinacms/dist/react'
3166
- import { TinaMarkdown } from 'tinacms/dist/rich-text'
3167
- import client from '${usingSrc ? "../" : ""}../../../tina/__generated__/client'
3168
-
3169
- const BlogPage = (props) => {
3170
- const { data } = useTina({
3171
- query: props.query,
3172
- variables: props.variables,
3173
- data: props.data,
3174
- })
3175
-
3176
- return (
3177
- <>
3178
- <Head>
3179
- {/* Tailwind CDN */}
3180
- <link
3181
- rel="stylesheet"
3182
- href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.7/tailwind.min.css"
3183
- integrity="sha512-y6ZMKFUQrn+UUEVoqYe8ApScqbjuhjqzTuwUMEGMDuhS2niI8KA3vhH2LenreqJXQS+iIXVTRL2iaNfJbDNA1Q=="
3184
- crossOrigin="anonymous"
3185
- referrerPolicy="no-referrer"
3186
- />
3187
- </Head>
3188
- <div>
3189
- <div
3190
- style={{
3191
- textAlign: 'center',
3192
- }}
3193
- >
3194
- <h1 className="text-3xl m-8 text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
3195
- {data.post.title}
3196
- </h1>
3197
- <ContentSection content={data.post.body}></ContentSection>
3198
- </div>
3199
- <div className="bg-green-100 text-center">
3200
- Lost and looking for a place to start?
3201
- <a
3202
- href="https://tina.io/guides/tina-cloud/getting-started/overview/"
3203
- className="text-blue-500 underline"
3204
- >
3205
- {' '}
3206
- Check out this guide
3207
- </a>{' '}
3208
- to see how add TinaCMS to an existing Next.js site.
3209
- </div>
3210
- </div>
3211
- </>
3295
+ // src/cmds/init/detectEnvironment.ts
3296
+ var import_fs_extra8 = __toESM(require("fs-extra"));
3297
+ var import_path8 = __toESM(require("path"));
3298
+ var checkGitignoreForItem = async ({
3299
+ baseDir,
3300
+ line
3301
+ }) => {
3302
+ const gitignoreContent = import_fs_extra8.default.readFileSync(import_path8.default.join(baseDir, ".gitignore")).toString();
3303
+ return gitignoreContent.split("\n").some((item) => item === line);
3304
+ };
3305
+ var makeGeneratedFile = async (name2, generatedFileType, parentPath, opts) => {
3306
+ const result = {
3307
+ fullPathTS: import_path8.default.join(
3308
+ parentPath,
3309
+ `${name2}.${(opts == null ? void 0 : opts.typescriptSuffix) || (opts == null ? void 0 : opts.extensionOverride) || "ts"}`
3310
+ ),
3311
+ fullPathJS: import_path8.default.join(
3312
+ parentPath,
3313
+ `${name2}.${(opts == null ? void 0 : opts.extensionOverride) || "js"}`
3314
+ ),
3315
+ fullPathOverride: (opts == null ? void 0 : opts.extensionOverride) ? import_path8.default.join(parentPath, `${name2}.${opts == null ? void 0 : opts.extensionOverride}`) : "",
3316
+ generatedFileType,
3317
+ name: name2,
3318
+ parentPath,
3319
+ typescriptExists: false,
3320
+ javascriptExists: false,
3321
+ get resolve() {
3322
+ return (typescript) => typescript ? {
3323
+ exists: this.typescriptExists,
3324
+ path: this.fullPathTS,
3325
+ parentPath: this.parentPath
3326
+ } : {
3327
+ exists: this.javascriptExists,
3328
+ path: this.fullPathJS,
3329
+ parentPath: this.parentPath
3330
+ };
3331
+ }
3332
+ };
3333
+ result.typescriptExists = await import_fs_extra8.default.pathExists(result.fullPathTS);
3334
+ result.javascriptExists = await import_fs_extra8.default.pathExists(result.fullPathJS);
3335
+ return result;
3336
+ };
3337
+ var detectEnvironment = async ({
3338
+ baseDir = "",
3339
+ pathToForestryConfig,
3340
+ rootPath,
3341
+ debug = false
3342
+ }) => {
3343
+ var _a;
3344
+ const hasForestryConfig = await import_fs_extra8.default.pathExists(
3345
+ import_path8.default.join(pathToForestryConfig, ".forestry", "settings.yml")
3346
+ );
3347
+ const sampleContentPath = import_path8.default.join(
3348
+ baseDir,
3349
+ "content",
3350
+ "posts",
3351
+ "hello-world.md"
3352
+ );
3353
+ const usingSrc = import_fs_extra8.default.pathExistsSync(import_path8.default.join(baseDir, "src")) && (import_fs_extra8.default.pathExistsSync(import_path8.default.join(baseDir, "src", "app")) || import_fs_extra8.default.pathExistsSync(import_path8.default.join(baseDir, "src", "pages")));
3354
+ const tinaFolder = import_path8.default.join(baseDir, "tina");
3355
+ const tinaConfigExists = Boolean(
3356
+ await import_fs_extra8.default.pathExists(tinaFolder) && (await import_fs_extra8.default.readdir(tinaFolder)).find((x) => x.includes("config"))
3357
+ );
3358
+ const pagesDir = [baseDir, usingSrc ? "src" : false, "pages"].filter(
3359
+ Boolean
3360
+ );
3361
+ const generatedFiles = {
3362
+ config: await makeGeneratedFile("config", "config", tinaFolder),
3363
+ database: await makeGeneratedFile("database", "database", tinaFolder),
3364
+ templates: await makeGeneratedFile("templates", "templates", tinaFolder),
3365
+ "next-api-handler": await makeGeneratedFile(
3366
+ "[...routes]",
3367
+ "next-api-handler",
3368
+ import_path8.default.join(...pagesDir, "api", "tina")
3369
+ ),
3370
+ "reactive-example": await makeGeneratedFile(
3371
+ "[filename]",
3372
+ "reactive-example",
3373
+ import_path8.default.join(...pagesDir, "demo", "blog"),
3374
+ {
3375
+ typescriptSuffix: "tsx"
3376
+ }
3377
+ ),
3378
+ "users-json": await makeGeneratedFile(
3379
+ "index",
3380
+ "users-json",
3381
+ import_path8.default.join(baseDir, "content", "users"),
3382
+ { extensionOverride: "json" }
3383
+ ),
3384
+ "sample-content": await makeGeneratedFile(
3385
+ "hello-world",
3386
+ "sample-content",
3387
+ import_path8.default.join(baseDir, "content", "posts"),
3388
+ { extensionOverride: "md" }
3212
3389
  )
3213
- }
3214
-
3215
- export const getStaticProps = async ({ params }) => {
3216
- let data = {}
3217
- let query = {}
3218
- let variables = { relativePath: \`\${params.filename}.md\` }
3390
+ };
3391
+ const hasSampleContent = await import_fs_extra8.default.pathExists(sampleContentPath);
3392
+ const hasPackageJSON = await import_fs_extra8.default.pathExists("package.json");
3393
+ let hasTinaDeps = false;
3394
+ if (hasPackageJSON) {
3219
3395
  try {
3220
- const res = await client.queries.post(variables)
3221
- query = res.query
3222
- data = res.data
3223
- variables = res.variables
3224
- } catch {
3225
- // swallow errors related to document creation
3226
- }
3227
-
3228
- return {
3229
- props: {
3230
- variables: variables,
3231
- data: data,
3232
- query: query,
3233
- //myOtherProp: 'some-other-data',
3234
- },
3396
+ const packageJSON = await import_fs_extra8.default.readJSON("package.json");
3397
+ const deps = [];
3398
+ if (packageJSON == null ? void 0 : packageJSON.dependencies) {
3399
+ deps.push(...Object.keys(packageJSON.dependencies));
3400
+ }
3401
+ if (packageJSON == null ? void 0 : packageJSON.devDependencies) {
3402
+ deps.push(...Object.keys(packageJSON.devDependencies));
3403
+ }
3404
+ if (deps.includes("@tinacms/cli") && deps.includes("tinacms")) {
3405
+ hasTinaDeps = true;
3406
+ }
3407
+ } catch (e) {
3408
+ logger.error(
3409
+ "Error reading package.json assuming that no Tina dependencies are installed"
3410
+ );
3235
3411
  }
3236
3412
  }
3237
-
3238
- export const getStaticPaths = async () => {
3239
- const postsListData = await client.queries.postConnection()
3240
-
3241
- return {
3242
- paths: postsListData.data.postConnection.edges.map((post) => ({
3243
- params: { filename: post.node._sys.filename },
3244
- })),
3245
- fallback: false,
3413
+ const hasGitIgnore = await import_fs_extra8.default.pathExists(import_path8.default.join(".gitignore"));
3414
+ const hasGitIgnoreNodeModules = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: "node_modules" });
3415
+ const hasEnvTina = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env.tina" });
3416
+ const hasGitIgnoreEnv = hasGitIgnore && await checkGitignoreForItem({ baseDir, line: ".env" });
3417
+ let frontMatterFormat;
3418
+ if (hasForestryConfig) {
3419
+ const hugoConfigPath = import_path8.default.join(rootPath, "config.toml");
3420
+ if (await import_fs_extra8.default.pathExists(hugoConfigPath)) {
3421
+ const hugoConfig = await import_fs_extra8.default.readFile(hugoConfigPath, "utf8");
3422
+ const metaDataFormat = (_a = hugoConfig.match(/metaDataFormat = "(.*)"/)) == null ? void 0 : _a[1];
3423
+ if (metaDataFormat && (metaDataFormat === "yaml" || metaDataFormat === "toml" || metaDataFormat === "json")) {
3424
+ frontMatterFormat = metaDataFormat;
3425
+ }
3246
3426
  }
3247
3427
  }
3248
-
3249
- export default BlogPage
3250
-
3251
- const PageSection = (props) => {
3252
- return (
3253
- <>
3254
- <h2>{props.heading}</h2>
3255
- <p>{props.content}</p>
3256
- </>
3257
- )
3258
- }
3259
-
3260
- const components = {
3261
- PageSection: PageSection,
3262
- }
3263
-
3264
- const ContentSection = ({ content }) => {
3265
- return (
3266
- <div className="relative py-16 bg-white overflow-hidden">
3267
- <div className="hidden lg:block lg:absolute lg:inset-y-0 lg:h-full lg:w-full">
3268
- <div
3269
- className="relative h-full text-lg max-w-prose mx-auto"
3270
- aria-hidden="true"
3271
- >
3272
- <svg
3273
- className="absolute top-12 left-full transform translate-x-32"
3274
- width={404}
3275
- height={384}
3276
- fill="none"
3277
- viewBox="0 0 404 384"
3278
- >
3279
- <defs>
3280
- <pattern
3281
- id="74b3fd99-0a6f-4271-bef2-e80eeafdf357"
3282
- x={0}
3283
- y={0}
3284
- width={20}
3285
- height={20}
3286
- patternUnits="userSpaceOnUse"
3287
- >
3288
- <rect
3289
- x={0}
3290
- y={0}
3291
- width={4}
3292
- height={4}
3293
- className="text-gray-200"
3294
- fill="currentColor"
3295
- />
3296
- </pattern>
3297
- </defs>
3298
- <rect
3299
- width={404}
3300
- height={384}
3301
- fill="url(#74b3fd99-0a6f-4271-bef2-e80eeafdf357)"
3302
- />
3303
- </svg>
3304
- <svg
3305
- className="absolute top-1/2 right-full transform -translate-y-1/2 -translate-x-32"
3306
- width={404}
3307
- height={384}
3308
- fill="none"
3309
- viewBox="0 0 404 384"
3310
- >
3311
- <defs>
3312
- <pattern
3313
- id="f210dbf6-a58d-4871-961e-36d5016a0f49"
3314
- x={0}
3315
- y={0}
3316
- width={20}
3317
- height={20}
3318
- patternUnits="userSpaceOnUse"
3319
- >
3320
- <rect
3321
- x={0}
3322
- y={0}
3323
- width={4}
3324
- height={4}
3325
- className="text-gray-200"
3326
- fill="currentColor"
3327
- />
3328
- </pattern>
3329
- </defs>
3330
- <rect
3331
- width={404}
3332
- height={384}
3333
- fill="url(#f210dbf6-a58d-4871-961e-36d5016a0f49)"
3334
- />
3335
- </svg>
3336
- <svg
3337
- className="absolute bottom-12 left-full transform translate-x-32"
3338
- width={404}
3339
- height={384}
3340
- fill="none"
3341
- viewBox="0 0 404 384"
3342
- >
3343
- <defs>
3344
- <pattern
3345
- id="d3eb07ae-5182-43e6-857d-35c643af9034"
3346
- x={0}
3347
- y={0}
3348
- width={20}
3349
- height={20}
3350
- patternUnits="userSpaceOnUse"
3351
- >
3352
- <rect
3353
- x={0}
3354
- y={0}
3355
- width={4}
3356
- height={4}
3357
- className="text-gray-200"
3358
- fill="currentColor"
3359
- />
3360
- </pattern>
3361
- </defs>
3362
- <rect
3363
- width={404}
3364
- height={384}
3365
- fill="url(#d3eb07ae-5182-43e6-857d-35c643af9034)"
3366
- />
3367
- </svg>
3368
- </div>
3369
- </div>
3370
- <div className="relative px-4 sm:px-6 lg:px-8">
3371
- <div className="text-lg max-w-prose mx-auto">
3372
- <TinaMarkdown components={components} content={content} />
3373
- </div>
3374
- </div>
3375
- </div>
3376
- )
3377
- }`;
3378
-
3379
- // src/utils/script-helpers.ts
3380
- function generateGqlScript(scriptValue) {
3381
- return `tinacms dev -c "${scriptValue}"`;
3382
- }
3383
- function extendNextScripts(scripts) {
3384
- return {
3385
- ...scripts,
3386
- dev: generateGqlScript((scripts == null ? void 0 : scripts.dev) || "next dev"),
3387
- build: `tinacms build && ${(scripts == null ? void 0 : scripts.build) || "next build"}`,
3388
- start: `tinacms build && ${(scripts == null ? void 0 : scripts.start) || "next start"}`
3428
+ const env = {
3429
+ forestryConfigExists: hasForestryConfig,
3430
+ frontMatterFormat,
3431
+ gitIgnoreExists: hasGitIgnore,
3432
+ gitIgnoreNodeModulesExists: hasGitIgnoreNodeModules,
3433
+ gitIgnoreEnvExists: hasGitIgnoreEnv,
3434
+ gitIgnoreTinaEnvExists: hasEnvTina,
3435
+ packageJSONExists: hasPackageJSON,
3436
+ sampleContentExists: hasSampleContent,
3437
+ sampleContentPath,
3438
+ generatedFiles,
3439
+ usingSrc,
3440
+ tinaConfigExists,
3441
+ hasTinaDeps
3389
3442
  };
3390
- }
3391
-
3392
- // src/cmds/init/setup-files/config.ts
3393
- var clientConfig = (isForestryMigration) => {
3394
- if (isForestryMigration) {
3395
- return "client: {skip: true},";
3443
+ if (debug) {
3444
+ console.log("Environment:");
3445
+ console.log(JSON.stringify(env, null, 2));
3396
3446
  }
3397
- return "";
3447
+ return env;
3398
3448
  };
3399
- var other = (args) => {
3400
- return `
3401
- import { defineConfig } from "tinacms";
3402
- ${args.extraText || ""}
3449
+ var detectEnvironment_default = detectEnvironment;
3403
3450
 
3404
- // Your hosting provider likely exposes this as an environment variable
3405
- const branch = process.env.HEAD || process.env.VERCEL_GIT_COMMIT_REF || "main";
3451
+ // src/cmds/init/prompts/index.ts
3452
+ var import_prompts6 = __toESM(require("prompts"));
3406
3453
 
3407
- export default defineConfig({
3408
- branch,
3409
- clientId: ${args.clientId ? `'${args.clientId}'` : "null"}, // Get this from tina.io
3410
- token: ${args.token ? `'${args.token}'` : "null"}, // Get this from tina.io
3411
- ${clientConfig(args.isForestryMigration)}
3412
- build: {
3413
- outputFolder: "admin",
3414
- publicFolder: "${args.publicFolder}",
3454
+ // src/cmds/init/prompts/askTinaCloudSetup.ts
3455
+ var import_prompts2 = __toESM(require("prompts"));
3456
+ var tinaCloudSetupQuestions = [
3457
+ {
3458
+ name: "clientId",
3459
+ type: "text",
3460
+ message: `What is your Tina Cloud Client ID? (Hit enter to skip and set up yourself later)
3461
+ ${logText(
3462
+ "Don't have a Client ID? Create one here: "
3463
+ )}${linkText("https://app.tina.io/projects/new")}`,
3464
+ initial: process.env.NEXT_PUBLIC_TINA_CLIENT_ID
3415
3465
  },
3416
- media: {
3417
- tina: {
3418
- mediaRoot: "",
3419
- publicFolder: "${args.publicFolder}",
3466
+ {
3467
+ name: "token",
3468
+ type: "text",
3469
+ message: (prev) => `What is your Tina Cloud Read Only Token?
3470
+ ${logText(
3471
+ "Don't have a Read Only Token? Create one here: "
3472
+ )}${linkText(`https://app.tina.io/projects/${prev || "[XXX]"}/tokens`)}`,
3473
+ initial: process.env.TINA_TOKEN
3474
+ }
3475
+ ];
3476
+ var askTinaCloudSetup = async ({ config: config2 }) => {
3477
+ const { clientId, token } = await (0, import_prompts2.default)(tinaCloudSetupQuestions);
3478
+ config2.envVars.push(
3479
+ {
3480
+ key: "NEXT_PUBLIC_TINA_CLIENT_ID",
3481
+ value: clientId
3420
3482
  },
3421
- },
3422
- schema: {
3423
- collections: ${args.collections || `[
3483
+ {
3484
+ key: "NEXT_PUBLIC_TINA_CLIENT_SECRET",
3485
+ value: token
3486
+ }
3487
+ );
3488
+ };
3489
+
3490
+ // src/cmds/init/prompts/gitProvider.ts
3491
+ var import_prompts3 = __toESM(require("prompts"));
3492
+ var supportedGitProviders = {
3493
+ github: {
3494
+ imports: [
3424
3495
  {
3425
- name: "post",
3426
- label: "Posts",
3427
- path: "content/posts",
3428
- fields: [
3429
- {
3430
- type: "string",
3431
- name: "title",
3432
- label: "Title",
3433
- isTitle: true,
3434
- required: true,
3435
- },
3436
- {
3437
- type: "rich-text",
3438
- name: "body",
3439
- label: "Body",
3440
- isBody: true,
3441
- },
3442
- ],
3443
- },
3444
- ]`},
3496
+ from: "tinacms-gitprovider-github",
3497
+ imported: ["GitHubProvider"],
3498
+ packageName: "tinacms-gitprovider-github"
3499
+ }
3500
+ ],
3501
+ gitProviderClassText: `new GitHubProvider({
3502
+ branch,
3503
+ owner: process.env.GITHUB_OWNER,
3504
+ repo: process.env.GITHUB_REPO,
3505
+ token: process.env.GITHUB_PERSONAL_ACCESS_TOKEN,
3506
+ })`
3445
3507
  },
3446
- });
3447
- `;
3508
+ other: {
3509
+ gitProviderClassText: ""
3510
+ }
3448
3511
  };
3449
- var configExamples = {
3450
- next: (args) => `import { defineConfig } from 'tinacms'
3451
-
3452
- // Your hosting provider likely exposes this as an environment variable
3453
- const branch = process.env.HEAD || process.env.VERCEL_GIT_COMMIT_REF || 'main'
3454
-
3455
- export default defineConfig({
3456
- branch,
3457
- clientId: ${args.clientId ? `'${args.clientId}'` : "null"}, // Get this from tina.io
3458
- token: ${args.token ? `'${args.token}'` : "null"}, // Get this from tina.io
3459
- ${clientConfig(args.isForestryMigration)}
3460
- build: {
3461
- outputFolder: "admin",
3462
- publicFolder: "${args.publicFolder}",
3512
+ var chooseGitProvider = async ({ config: config2 }) => {
3513
+ const result = await (0, import_prompts3.default)([
3514
+ {
3515
+ name: "githubToken",
3516
+ type: "text",
3517
+ message: `What is your GitHub Personal Access Token? (Hit enter to skip and set up later)
3518
+ ${logText(
3519
+ "Learn more here: "
3520
+ )}${linkText(
3521
+ "https://tina.io/docs/self-hosted/existing-site/#github-personal-access-token"
3522
+ )}`,
3523
+ initial: process.env.GITHUB_PERSONAL_ACCESS_TOKEN
3463
3524
  },
3464
- media: {
3465
- tina: {
3466
- mediaRoot: "",
3467
- publicFolder: "${args.publicFolder}",
3468
- },
3525
+ {
3526
+ name: "githubOwner",
3527
+ type: "text",
3528
+ message: `What is your GitHub Owner (Your Github Username)?
3529
+ (Hit enter to skip and set up later)
3530
+ `
3469
3531
  },
3470
- schema: {
3471
- collections:${args.collections || `[
3472
- {
3473
- name: 'post',
3474
- label: 'Posts',
3475
- path: 'content/posts',
3476
- fields: [
3477
- {
3478
- type: 'string',
3479
- name: 'title',
3480
- label: 'Title',
3481
- isTitle: true,
3482
- required: true,
3483
- },
3484
- {
3485
- type: 'rich-text',
3486
- name: 'body',
3487
- label: 'Body',
3488
- isBody: true,
3489
- },
3490
- ],
3491
- ui: {
3492
- // This is an DEMO router. You can remove this to fit your site
3493
- router: ({ document }) => \`/demo/blog/\${document._sys.filename}\`,
3494
- },
3495
- },
3496
- ]`},
3532
+ {
3533
+ name: "githubRepo",
3534
+ type: "text",
3535
+ message: `What is your GitHub Repo name? Ex: my-nextjs-app
3536
+ (Hit enter to skip and set up later)
3537
+ `
3538
+ }
3539
+ ]);
3540
+ config2.envVars.push(
3541
+ {
3542
+ key: "GITHUB_PERSONAL_ACCESS_TOKEN",
3543
+ value: result.githubToken
3497
3544
  },
3498
- })
3499
- `,
3500
- other,
3501
- hugo: other,
3502
- jekyll: other
3545
+ {
3546
+ key: "GITHUB_OWNER",
3547
+ value: result.githubOwner
3548
+ },
3549
+ {
3550
+ key: "GITHUB_REPO",
3551
+ value: result.githubRepo
3552
+ }
3553
+ );
3554
+ return supportedGitProviders.github;
3503
3555
  };
3504
3556
 
3505
- // src/cmds/forestry-migrate/index.ts
3506
- var import_fs_extra9 = __toESM(require("fs-extra"));
3507
- var import_path9 = __toESM(require("path"));
3508
- var import_js_yaml2 = __toESM(require("js-yaml"));
3509
- var import_minimatch = __toESM(require("minimatch"));
3510
- var import_graphql15 = require("@tinacms/graphql");
3511
-
3512
- // src/cmds/forestry-migrate/util/index.ts
3513
- var import_fs_extra8 = __toESM(require("fs-extra"));
3514
- var import_path8 = __toESM(require("path"));
3515
- var import_js_yaml = __toESM(require("js-yaml"));
3516
- var import_zod = __toESM(require("zod"));
3517
-
3518
- // src/cmds/forestry-migrate/util/errorSingleton.ts
3519
- var ErrorSingleton = class {
3520
- constructor() {
3557
+ // src/cmds/init/prompts/databaseAdapter.ts
3558
+ var import_prompts4 = __toESM(require("prompts"));
3559
+ var supportedDatabaseAdapters = {
3560
+ ["upstash-redis"]: {
3561
+ databaseAdapterClassText: `new RedisLevel({
3562
+ redis: {
3563
+ url: process.env.KV_REST_API_URL || 'http://localhost:8079',
3564
+ token: process.env.KV_REST_API_TOKEN || 'example_token',
3565
+ },
3566
+ debug: process.env.DEBUG === 'true' || false,
3567
+ })`,
3568
+ imports: [
3569
+ {
3570
+ imported: ["RedisLevel"],
3571
+ from: "upstash-redis-level",
3572
+ packageName: "upstash-redis-level"
3573
+ }
3574
+ ]
3575
+ },
3576
+ mongodb: {
3577
+ databaseAdapterClassText: `new MongodbLevel({
3578
+ collectionName: 'tinacms',
3579
+ dbName: 'tinacms',
3580
+ mongoUri: process.env.MONGODB_URI,
3581
+ })`,
3582
+ imports: [
3583
+ {
3584
+ from: "mongodb-level",
3585
+ imported: ["MongodbLevel"],
3586
+ packageName: "mongodb-level"
3587
+ }
3588
+ ]
3589
+ },
3590
+ other: {
3591
+ databaseAdapterClassText: ""
3521
3592
  }
3522
- static getInstance() {
3523
- if (!ErrorSingleton.instance) {
3524
- ErrorSingleton.instance = new ErrorSingleton();
3525
- ErrorSingleton.instance.collectionNameErrors = [];
3593
+ };
3594
+ var databaseAdapterUpdateConfig = {
3595
+ other: async (_args) => {
3596
+ },
3597
+ mongodb: async ({ config: config2 }) => {
3598
+ const result = await (0, import_prompts4.default)([
3599
+ {
3600
+ name: "mongoDBUri",
3601
+ type: "text",
3602
+ message: `What is the MongoDB URI, Ex: mongodb+srv://<username>:<password>@cluster0.yoeujeh.mongodb.net/?retryWrites=true&w=majority
3603
+ (Hit enter to skip and set up yourself later)`,
3604
+ initial: process.env.MONGODB_URI
3605
+ }
3606
+ ]);
3607
+ config2.envVars.push({
3608
+ key: "MONGODB_URI",
3609
+ value: result.mongoDBUri
3610
+ });
3611
+ },
3612
+ "upstash-redis": async ({ config: config2 }) => {
3613
+ const result = await (0, import_prompts4.default)([
3614
+ {
3615
+ name: "kvRestApiUrl",
3616
+ type: "text",
3617
+ message: `What is the KV (Redis) Rest API URL? Ex: https://***.upstash.io
3618
+ (Hit enter to skip and set up yourself later)`,
3619
+ initial: process.env.KV_REST_API_URL
3620
+ },
3621
+ {
3622
+ name: "kvRestApiToken",
3623
+ type: "text",
3624
+ message: `What is the KV (Redis) Rest API Token? (Hit enter to skip and set up yourself later)`,
3625
+ initial: process.env.KV_REST_API_TOKEN
3626
+ }
3627
+ ]);
3628
+ config2.envVars.push(
3629
+ {
3630
+ key: "KV_REST_API_URL",
3631
+ value: result.kvRestApiUrl
3632
+ },
3633
+ {
3634
+ key: "KV_REST_API_TOKEN",
3635
+ value: result.kvRestApiToken
3636
+ }
3637
+ );
3638
+ }
3639
+ };
3640
+ var chooseDatabaseAdapter = async ({
3641
+ framework,
3642
+ config: config2
3643
+ }) => {
3644
+ const answers = await (0, import_prompts4.default)([
3645
+ {
3646
+ name: "dataLayerAdapter",
3647
+ message: "Select a self-hosted Database Adapter",
3648
+ type: "select",
3649
+ choices: [
3650
+ {
3651
+ title: "Vercel KV/Upstash Redis",
3652
+ value: "upstash-redis"
3653
+ },
3654
+ {
3655
+ title: "MongoDB",
3656
+ value: "mongodb"
3657
+ }
3658
+ ]
3659
+ }
3660
+ ]);
3661
+ if (typeof answers.dataLayerAdapter === "undefined") {
3662
+ throw new Error("Database adapter is required");
3663
+ }
3664
+ const chosen = answers.dataLayerAdapter;
3665
+ await databaseAdapterUpdateConfig[chosen]({ config: config2 });
3666
+ return supportedDatabaseAdapters[chosen];
3667
+ };
3668
+
3669
+ // src/cmds/init/prompts/authProvider.ts
3670
+ var import_prompts5 = __toESM(require("prompts"));
3671
+ var import_crypto_js = __toESM(require("crypto-js"));
3672
+ var supportedAuthProviders = {
3673
+ other: {
3674
+ name: "other"
3675
+ },
3676
+ "tina-cloud": {
3677
+ configAuthProviderClass: "",
3678
+ backendAuthProvider: "TinaCloudBackendAuthProvider()",
3679
+ name: "tina-cloud",
3680
+ backendAuthProviderImports: [
3681
+ {
3682
+ imported: ["TinaCloudBackendAuthProvider"],
3683
+ from: "@tinacms/auth",
3684
+ packageName: "@tinacms/auth"
3685
+ }
3686
+ ]
3687
+ },
3688
+ "next-auth": {
3689
+ name: "next-auth",
3690
+ configAuthProviderClass: `new UsernamePasswordAuthJSProvider()`,
3691
+ configImports: [
3692
+ {
3693
+ imported: ["UsernamePasswordAuthJSProvider", "TinaUserCollection"],
3694
+ from: "tinacms-authjs/dist/tinacms",
3695
+ packageName: "tinacms-authjs"
3696
+ }
3697
+ ],
3698
+ extraTinaCollections: ["TinaUserCollection"],
3699
+ backendAuthProvider: `AuthJsBackendAuthProvider({
3700
+ authOptions: TinaAuthJSOptions({
3701
+ databaseClient: databaseClient,
3702
+ secret: process.env.NEXTAUTH_SECRET,
3703
+ }),
3704
+ })`,
3705
+ backendAuthProviderImports: [
3706
+ {
3707
+ from: "tinacms-authjs",
3708
+ packageName: "tinacms-authjs",
3709
+ imported: ["AuthJsBackendAuthProvider", "TinaAuthJSOptions"]
3710
+ }
3711
+ ],
3712
+ peerDependencies: ["next-auth"]
3713
+ }
3714
+ };
3715
+ var authProviderUpdateConfig = {
3716
+ other: async () => {
3717
+ },
3718
+ "tina-cloud": askTinaCloudSetup,
3719
+ "next-auth": async ({ config: config2 }) => {
3720
+ const result = await (0, import_prompts5.default)([
3721
+ {
3722
+ name: "nextAuthSecret",
3723
+ type: "text",
3724
+ message: `What is the NextAuth.js Secret? (Hit enter to use a randomly generated secret)`,
3725
+ initial: process.env.NEXTAUTH_SECRET || import_crypto_js.default.lib.WordArray.random(16).toString()
3726
+ }
3727
+ ]);
3728
+ config2.envVars.push({
3729
+ key: "NEXTAUTH_SECRET",
3730
+ value: result.nextAuthSecret
3731
+ });
3732
+ }
3733
+ };
3734
+ var chooseAuthProvider = async ({
3735
+ framework,
3736
+ config: config2
3737
+ }) => {
3738
+ const authProvider = supportedAuthProviders["next-auth"];
3739
+ await authProviderUpdateConfig["next-auth"]({
3740
+ config: config2
3741
+ });
3742
+ return authProvider;
3743
+ };
3744
+
3745
+ // src/cmds/init/prompts/index.ts
3746
+ var forestryDisclaimer = logText(
3747
+ `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)`
3748
+ );
3749
+ var askCommonSetUp = async () => {
3750
+ const answers = await (0, import_prompts6.default)([
3751
+ {
3752
+ name: "framework",
3753
+ type: "select",
3754
+ message: "What framework are you using?",
3755
+ choices: [
3756
+ { title: "Next.js", value: { name: "next", reactive: true } },
3757
+ { title: "Hugo", value: { name: "hugo", reactive: false } },
3758
+ { title: "Jekyll", value: { name: "jekyll", reactive: false } },
3759
+ {
3760
+ title: "Other (SSG frameworks like gatsby, etc.)",
3761
+ value: { name: "other", reactive: false }
3762
+ }
3763
+ ]
3764
+ },
3765
+ {
3766
+ name: "packageManager",
3767
+ type: "select",
3768
+ message: "Choose your package manager",
3769
+ choices: [
3770
+ { title: "PNPM", value: "pnpm" },
3771
+ { title: "Yarn", value: "yarn" },
3772
+ { title: "NPM", value: "npm" }
3773
+ ]
3774
+ }
3775
+ ]);
3776
+ if (typeof answers.framework === "undefined" || typeof answers.packageManager === "undefined") {
3777
+ throw new Error("Framework and package manager are required");
3778
+ }
3779
+ return answers;
3780
+ };
3781
+ var askForestryMigrate = async ({
3782
+ framework,
3783
+ env
3784
+ }) => {
3785
+ const questions = [
3786
+ {
3787
+ name: "forestryMigrate",
3788
+ type: "confirm",
3789
+ initial: true,
3790
+ message: `Would you like to migrate your Forestry templates?
3791
+ ${forestryDisclaimer}`
3792
+ }
3793
+ ];
3794
+ if (framework.name === "hugo") {
3795
+ questions.push({
3796
+ name: "frontMatterFormat",
3797
+ type: (_, answers2) => {
3798
+ if (answers2.forestryMigrate) {
3799
+ if (env.frontMatterFormat && env.frontMatterFormat[1]) {
3800
+ return null;
3801
+ }
3802
+ return "select";
3803
+ }
3804
+ },
3805
+ choices: [
3806
+ { title: "yaml", value: "yaml" },
3807
+ { title: "toml", value: "toml" },
3808
+ { title: "json", value: "json" }
3809
+ ],
3810
+ message: `What format are you using in your frontmatter?`
3811
+ });
3812
+ }
3813
+ const answers = await (0, import_prompts6.default)(questions);
3814
+ return answers;
3815
+ };
3816
+ var askTinaSetupPrompts = async (params) => {
3817
+ const questions = [
3818
+ {
3819
+ name: "typescript",
3820
+ type: "confirm",
3821
+ initial: true,
3822
+ message: "Would you like to use Typescript for your Tina Configuration (Recommended)?"
3823
+ }
3824
+ ];
3825
+ if (!params.config.publicFolder) {
3826
+ questions.push({
3827
+ name: "publicFolder",
3828
+ type: "text",
3829
+ initial: "public",
3830
+ message: `Where are public assets stored? (default: "public")
3831
+ ` + logText(
3832
+ `Not sure what value to use? Refer to our "Frameworks" doc: ${linkText(
3833
+ "https://tina.io/docs/integration/frameworks/#configuring-tina-with-each-framework"
3834
+ )}`
3835
+ )
3836
+ });
3837
+ }
3838
+ const answers = await (0, import_prompts6.default)(questions);
3839
+ return answers;
3840
+ };
3841
+ var askIfUsingSelfHosted = async () => {
3842
+ const answers = await (0, import_prompts6.default)([
3843
+ {
3844
+ name: "hosting",
3845
+ type: "select",
3846
+ choices: [
3847
+ {
3848
+ title: "Tina Cloud",
3849
+ value: "tina-cloud"
3850
+ },
3851
+ {
3852
+ title: "Self-Hosted",
3853
+ value: "self-host"
3854
+ }
3855
+ ],
3856
+ message: "Do you want to host your project on Tina Cloud or self-host? (With self-hosting, the graphql api, auth and database will be hosted on your own server.)"
3857
+ }
3858
+ ]);
3859
+ return answers;
3860
+ };
3861
+ var makeImportString = (imports) => {
3862
+ if (!imports) {
3863
+ return "";
3864
+ }
3865
+ return imports.map((x) => {
3866
+ return `import { ${x.imported.join(",")} } from '${x.from}'`;
3867
+ }).join("\n");
3868
+ };
3869
+
3870
+ // src/cmds/init/prompts/generatedFiles.ts
3871
+ var import_prompts7 = __toESM(require("prompts"));
3872
+ var askIfOverride = async ({
3873
+ generatedFile,
3874
+ usingTypescript
3875
+ }) => {
3876
+ if (usingTypescript) {
3877
+ const result = await (0, import_prompts7.default)({
3878
+ name: `override`,
3879
+ type: "confirm",
3880
+ message: `Found existing file at ${generatedFile.fullPathTS}. Would you like to overwrite?`
3881
+ });
3882
+ return Boolean(result.override);
3883
+ } else {
3884
+ const result = await (0, import_prompts7.default)({
3885
+ name: `override`,
3886
+ type: "confirm",
3887
+ message: `Found existing file at ${generatedFile.fullPathJS}. Would you like to overwrite?`
3888
+ });
3889
+ return Boolean(result.override);
3890
+ }
3891
+ };
3892
+ var askOverwriteGenerateFiles = async ({
3893
+ config: config2,
3894
+ generatedFiles
3895
+ }) => {
3896
+ const overwriteList = [];
3897
+ for (let i = 0; i < generatedFiles.length; i++) {
3898
+ const generatedFile = generatedFiles[i];
3899
+ if (generatedFile.resolve(config2.typescript).exists) {
3900
+ const overwrite = await askIfOverride({
3901
+ generatedFile,
3902
+ usingTypescript: config2.typescript
3903
+ });
3904
+ if (overwrite) {
3905
+ overwriteList.push(generatedFile.generatedFileType);
3906
+ }
3907
+ }
3908
+ }
3909
+ return overwriteList;
3910
+ };
3911
+
3912
+ // src/cmds/init/configure.ts
3913
+ async function configure(env, opts) {
3914
+ if (opts.isBackend && !env.tinaConfigExists) {
3915
+ logger.info("Looks like Tina has not been setup, setting up now...");
3916
+ }
3917
+ if (env.tinaConfigExists && !opts.isBackend) {
3918
+ logger.info(
3919
+ `Tina config already exists, skipping setup. (If you want to init tina from scratch, delete your tina config file and run this command again)`
3920
+ );
3921
+ process.exit(0);
3922
+ }
3923
+ const skipTinaSetupCommands = env.tinaConfigExists;
3924
+ const { framework, packageManager } = await askCommonSetUp();
3925
+ const config2 = {
3926
+ envVars: [],
3927
+ framework,
3928
+ packageManager,
3929
+ forestryMigrate: false,
3930
+ isLocalEnvVarName: "TINA_PUBLIC_IS_LOCAL",
3931
+ typescript: false
3932
+ };
3933
+ if (config2.framework.name === "next") {
3934
+ config2.publicFolder = "public";
3935
+ } else if (config2.framework.name === "hugo") {
3936
+ config2.publicFolder = "static";
3937
+ }
3938
+ if (skipTinaSetupCommands) {
3939
+ config2.typescript = env.generatedFiles.config.typescriptExists;
3940
+ } else {
3941
+ const { typescript, publicFolder } = await askTinaSetupPrompts({
3942
+ frameworkName: framework.name,
3943
+ config: config2
3944
+ });
3945
+ config2.typescript = typescript;
3946
+ if (publicFolder) {
3947
+ config2.publicFolder = publicFolder;
3948
+ }
3949
+ }
3950
+ if (env.forestryConfigExists) {
3951
+ const { forestryMigrate: forestryMigrate2, frontMatterFormat } = await askForestryMigrate({
3952
+ env,
3953
+ framework
3954
+ });
3955
+ config2.forestryMigrate = forestryMigrate2;
3956
+ config2.frontMatterFormat = frontMatterFormat;
3957
+ }
3958
+ if (opts.isBackend) {
3959
+ const result = await askIfUsingSelfHosted();
3960
+ config2.hosting = result.hosting;
3961
+ if (result.hosting === "tina-cloud") {
3962
+ await askTinaCloudSetup({ config: config2 });
3963
+ } else if (result.hosting === "self-host") {
3964
+ config2.gitProvider = await chooseGitProvider({ config: config2 });
3965
+ config2.databaseAdapter = await chooseDatabaseAdapter({
3966
+ framework,
3967
+ config: config2
3968
+ });
3969
+ config2.authProvider = await chooseAuthProvider({
3970
+ framework,
3971
+ config: config2
3972
+ });
3973
+ }
3974
+ }
3975
+ config2.nextAuthCredentialsProviderName = "VercelKVCredentialsProvider";
3976
+ if (opts.debug) {
3977
+ console.log("Configuration:");
3978
+ console.log(JSON.stringify(config2, null, 2));
3979
+ }
3980
+ const firstTimeSetup = !env.tinaConfigExists;
3981
+ const generatedFilesInUse = [];
3982
+ if (env.tinaConfigExists && !opts.isBackend) {
3983
+ generatedFilesInUse.push(env.generatedFiles.config);
3984
+ }
3985
+ if (config2.hosting === "self-host") {
3986
+ generatedFilesInUse.push(env.generatedFiles.database);
3987
+ generatedFilesInUse.push(env.generatedFiles["next-api-handler"]);
3988
+ generatedFilesInUse.push(env.generatedFiles["users-json"]);
3989
+ }
3990
+ if (config2.framework.reactive && firstTimeSetup) {
3991
+ generatedFilesInUse.push(env.generatedFiles["reactive-example"]);
3992
+ }
3993
+ if (env.sampleContentExists && firstTimeSetup) {
3994
+ generatedFilesInUse.push(env.generatedFiles["sample-content"]);
3995
+ }
3996
+ config2.overwriteList = await askOverwriteGenerateFiles({
3997
+ generatedFiles: generatedFilesInUse,
3998
+ config: config2
3999
+ });
4000
+ return config2;
4001
+ }
4002
+ var configure_default = configure;
4003
+
4004
+ // src/cmds/index.ts
4005
+ var CLICommand = class {
4006
+ constructor(handler) {
4007
+ this.handler = handler;
4008
+ }
4009
+ async execute(params) {
4010
+ await this.handler.setup(params);
4011
+ const environment = await this.handler.detectEnvironment(params);
4012
+ const config2 = await this.handler.configure(environment, params);
4013
+ await this.handler.apply(config2, environment, params);
4014
+ }
4015
+ };
4016
+
4017
+ // src/cmds/init/apply.ts
4018
+ var import_path12 = __toESM(require("path"));
4019
+
4020
+ // src/cmds/forestry-migrate/index.ts
4021
+ var import_fs_extra10 = __toESM(require("fs-extra"));
4022
+ var import_path10 = __toESM(require("path"));
4023
+ var import_js_yaml2 = __toESM(require("js-yaml"));
4024
+ var import_minimatch = __toESM(require("minimatch"));
4025
+ var import_graphql16 = require("@tinacms/graphql");
4026
+
4027
+ // src/cmds/forestry-migrate/util/index.ts
4028
+ var import_fs_extra9 = __toESM(require("fs-extra"));
4029
+ var import_path9 = __toESM(require("path"));
4030
+ var import_js_yaml = __toESM(require("js-yaml"));
4031
+ var import_zod = __toESM(require("zod"));
4032
+
4033
+ // src/cmds/forestry-migrate/util/errorSingleton.ts
4034
+ var ErrorSingleton = class {
4035
+ constructor() {
4036
+ }
4037
+ static getInstance() {
4038
+ if (!ErrorSingleton.instance) {
4039
+ ErrorSingleton.instance = new ErrorSingleton();
4040
+ ErrorSingleton.instance.collectionNameErrors = [];
3526
4041
  }
3527
4042
  return ErrorSingleton.instance;
3528
4043
  }
@@ -3855,7 +4370,7 @@ var transformForestryFieldsToTinaFields = ({
3855
4370
  if (skipBlocks) {
3856
4371
  break;
3857
4372
  }
3858
- const templates = [];
4373
+ const templates2 = [];
3859
4374
  forestryField2 == null ? void 0 : forestryField2.template_types.forEach((tem) => {
3860
4375
  const { template: template2 } = getFieldsFromTemplates({
3861
4376
  tem,
@@ -3875,7 +4390,7 @@ var transformForestryFieldsToTinaFields = ({
3875
4390
  ;
3876
4391
  t.nameOverride = tem;
3877
4392
  }
3878
- templates.push(t);
4393
+ templates2.push(t);
3879
4394
  });
3880
4395
  field = {
3881
4396
  type: "object",
@@ -3883,7 +4398,7 @@ var transformForestryFieldsToTinaFields = ({
3883
4398
  templateKey: "template",
3884
4399
  label: forestryField2.label,
3885
4400
  ...getTinaFieldsFromName(forestryField2.name),
3886
- templates
4401
+ templates: templates2
3887
4402
  };
3888
4403
  break;
3889
4404
  }
@@ -3922,7 +4437,7 @@ var transformForestryFieldsToTinaFields = ({
3922
4437
  return tinaFields;
3923
4438
  };
3924
4439
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
3925
- const templatePath = import_path8.default.join(
4440
+ const templatePath = import_path9.default.join(
3926
4441
  pathToForestryConfig,
3927
4442
  ".forestry",
3928
4443
  "front_matter",
@@ -3931,7 +4446,7 @@ var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false })
3931
4446
  );
3932
4447
  let templateString = "";
3933
4448
  try {
3934
- templateString = import_fs_extra8.default.readFileSync(templatePath).toString();
4449
+ templateString = import_fs_extra9.default.readFileSync(templatePath).toString();
3935
4450
  } catch {
3936
4451
  throw new Error(
3937
4452
  `Could not find template ${tem} at ${templatePath}
@@ -3996,9 +4511,9 @@ function checkExt(ext) {
3996
4511
  var generateAllTemplates = async ({
3997
4512
  pathToForestryConfig
3998
4513
  }) => {
3999
- const allTemplates = (await import_fs_extra9.default.readdir(
4000
- import_path9.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4001
- )).map((tem) => import_path9.default.basename(tem, ".yml"));
4514
+ const allTemplates = (await import_fs_extra10.default.readdir(
4515
+ import_path10.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
4516
+ )).map((tem) => import_path10.default.basename(tem, ".yml"));
4002
4517
  const templateMap = /* @__PURE__ */ new Map();
4003
4518
  const proms = allTemplates.map(async (tem) => {
4004
4519
  try {
@@ -4140,9 +4655,9 @@ var generateCollectionFromForestrySection = (args) => {
4140
4655
  return c;
4141
4656
  } else if (section.type === "document") {
4142
4657
  const filePath = section.path;
4143
- const extname = import_path9.default.extname(filePath);
4144
- const fileName = import_path9.default.basename(filePath, extname);
4145
- const dir = import_path9.default.dirname(filePath);
4658
+ const extname = import_path10.default.extname(filePath);
4659
+ const fileName = import_path10.default.basename(filePath, extname);
4660
+ const dir = import_path10.default.dirname(filePath);
4146
4661
  const ext = checkExt(extname);
4147
4662
  if (ext) {
4148
4663
  const fields = [];
@@ -4204,8 +4719,8 @@ var generateCollections = async ({
4204
4719
  templateMap,
4205
4720
  usingTypescript
4206
4721
  });
4207
- const forestryConfig = await import_fs_extra9.default.readFile(
4208
- import_path9.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4722
+ const forestryConfig = await import_fs_extra10.default.readFile(
4723
+ import_path10.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4209
4724
  );
4210
4725
  rewriteTemplateKeysInDocs({
4211
4726
  templateMap,
@@ -4236,13 +4751,13 @@ var rewriteTemplateKeysInDocs = (args) => {
4236
4751
  const { templateObj } = templateMap.get(templateKey);
4237
4752
  (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
4238
4753
  try {
4239
- const filePath = import_path9.default.join(page);
4240
- if (import_fs_extra9.default.lstatSync(filePath).isDirectory()) {
4754
+ const filePath = import_path10.default.join(page);
4755
+ if (import_fs_extra10.default.lstatSync(filePath).isDirectory()) {
4241
4756
  return;
4242
4757
  }
4243
- const extname = import_path9.default.extname(filePath);
4244
- const fileContent = import_fs_extra9.default.readFileSync(filePath).toString();
4245
- const content2 = (0, import_graphql15.parseFile)(
4758
+ const extname = import_path10.default.extname(filePath);
4759
+ const fileContent = import_fs_extra10.default.readFileSync(filePath).toString();
4760
+ const content = (0, import_graphql16.parseFile)(
4246
4761
  fileContent,
4247
4762
  extname,
4248
4763
  (yup) => yup.object({}),
@@ -4250,11 +4765,11 @@ var rewriteTemplateKeysInDocs = (args) => {
4250
4765
  );
4251
4766
  const newContent = {
4252
4767
  _template: stringifyLabel(templateKey),
4253
- ...content2
4768
+ ...content
4254
4769
  };
4255
- import_fs_extra9.default.writeFileSync(
4770
+ import_fs_extra10.default.writeFileSync(
4256
4771
  filePath,
4257
- (0, import_graphql15.stringifyFile)(newContent, extname, true, markdownParseConfig)
4772
+ (0, import_graphql16.stringifyFile)(newContent, extname, true, markdownParseConfig)
4258
4773
  );
4259
4774
  } catch (error) {
4260
4775
  console.log(
@@ -4265,10 +4780,14 @@ var rewriteTemplateKeysInDocs = (args) => {
4265
4780
  }
4266
4781
  };
4267
4782
 
4783
+ // src/cmds/init/apply.ts
4784
+ var import_metrics2 = require("@tinacms/metrics");
4785
+ var import_fs_extra13 = __toESM(require("fs-extra"));
4786
+
4268
4787
  // src/next/commands/codemod-command/index.ts
4269
4788
  var import_clipanion5 = require("clipanion");
4270
- var import_fs_extra10 = __toESM(require("fs-extra"));
4271
- var import_path10 = __toESM(require("path"));
4789
+ var import_fs_extra11 = __toESM(require("fs-extra"));
4790
+ var import_path11 = __toESM(require("path"));
4272
4791
  var CodemodCommand = class extends import_clipanion5.Command {
4273
4792
  constructor() {
4274
4793
  super(...arguments);
@@ -4291,12 +4810,12 @@ var CodemodCommand = class extends import_clipanion5.Command {
4291
4810
  process.exit(1);
4292
4811
  }
4293
4812
  const mods = { "move-tina-folder": () => moveTinaFolder(this.rootPath) };
4294
- const command = mods[mod];
4295
- if (!command) {
4813
+ const command2 = mods[mod];
4814
+ if (!command2) {
4296
4815
  logger.error(`Mod not found for ${mod}`);
4297
4816
  process.exit(1);
4298
4817
  }
4299
- await command();
4818
+ await command2();
4300
4819
  }
4301
4820
  };
4302
4821
  CodemodCommand.paths = [["codemod"], ["codemod", "move-tina-folder"]];
@@ -4312,13 +4831,13 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
4312
4831
  logger.error(e.message);
4313
4832
  process.exit(1);
4314
4833
  }
4315
- const tinaDestination = import_path10.default.join(configManager.rootPath, "tina");
4316
- if (await import_fs_extra10.default.existsSync(tinaDestination)) {
4834
+ const tinaDestination = import_path11.default.join(configManager.rootPath, "tina");
4835
+ if (await import_fs_extra11.default.existsSync(tinaDestination)) {
4317
4836
  logger.info(
4318
4837
  `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.`
4319
4838
  );
4320
4839
  } else {
4321
- await import_fs_extra10.default.moveSync(configManager.tinaFolderPath, tinaDestination);
4840
+ await import_fs_extra11.default.moveSync(configManager.tinaFolderPath, tinaDestination);
4322
4841
  await writeGitignore(configManager.rootPath);
4323
4842
  logger.info(
4324
4843
  "Move to 'tina' folder complete. Be sure to update any imports of the autogenerated client!"
@@ -4326,208 +4845,870 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
4326
4845
  }
4327
4846
  };
4328
4847
  var writeGitignore = async (rootPath) => {
4329
- await import_fs_extra10.default.outputFileSync(
4330
- import_path10.default.join(rootPath, "tina", ".gitignore"),
4848
+ await import_fs_extra11.default.outputFileSync(
4849
+ import_path11.default.join(rootPath, "tina", ".gitignore"),
4331
4850
  "__generated__"
4332
4851
  );
4333
4852
  };
4334
4853
 
4335
- // src/cmds/init/index.ts
4336
- async function initStaticTina({
4337
- rootPath,
4338
- pathToForestryConfig,
4339
- noTelemetry
4340
- }) {
4341
- logger.level = "info";
4342
- process.chdir(rootPath);
4343
- const clientId = await chooseClientId();
4344
- let token = null;
4345
- if (clientId) {
4346
- token = await chooseToken({ clientId });
4347
- }
4348
- const packageManager = await choosePackageManager();
4349
- const framework = await chooseFramework();
4350
- const usingTypescript = await chooseTypescript();
4351
- const publicFolder = await choosePublicFolder({ framework });
4352
- let collections;
4353
- let templateCode;
4354
- let extraText;
4355
- const hasForestryConfig = await import_fs_extra11.default.pathExists(
4356
- import_path11.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4357
- );
4358
- let isForestryMigration = false;
4359
- if (hasForestryConfig) {
4360
- const res = await forestryMigrate({
4361
- usingTypescript,
4362
- pathToForestryConfig,
4363
- rootPath,
4364
- framework
4365
- });
4366
- if (res) {
4367
- templateCode = res.templateCodeString;
4368
- collections = res.collectionString;
4369
- extraText = res.importStatements;
4370
- isForestryMigration = true;
4371
- }
4854
+ // src/cmds/init/templates/next.ts
4855
+ var templates = {
4856
+ ["demo-post-page"]: ({
4857
+ usingSrc,
4858
+ dataLayer
4859
+ }) => {
4860
+ return `// THIS FILE HAS BEEN GENERATED WITH THE TINA CLI.
4861
+ // @ts-nocheck
4862
+ // This is a demo file once you have tina setup feel free to delete this file
4863
+
4864
+ import Head from 'next/head'
4865
+ import { useTina } from 'tinacms/dist/react'
4866
+ import { TinaMarkdown } from 'tinacms/dist/rich-text'
4867
+ import client from '${usingSrc ? "../" : ""}../../../tina/__generated__/${dataLayer ? "databaseClient" : "client"}'
4868
+
4869
+ const BlogPage = (props) => {
4870
+ const { data } = useTina({
4871
+ query: props.query,
4872
+ variables: props.variables,
4873
+ data: props.data,
4874
+ })
4875
+
4876
+ return (
4877
+ <>
4878
+ <Head>
4879
+ {/* Tailwind CDN */}
4880
+ <link
4881
+ rel='stylesheet'
4882
+ href='https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.7/tailwind.min.css'
4883
+ integrity='sha512-y6ZMKFUQrn+UUEVoqYe8ApScqbjuhjqzTuwUMEGMDuhS2niI8KA3vhH2LenreqJXQS+iIXVTRL2iaNfJbDNA1Q=='
4884
+ crossOrigin='anonymous'
4885
+ referrerPolicy='no-referrer'
4886
+ />
4887
+ </Head>
4888
+ <div>
4889
+ <div
4890
+ style={{
4891
+ textAlign: 'center',
4892
+ }}
4893
+ >
4894
+ <h1 className='text-3xl m-8 text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl'>
4895
+ {data.post.title}
4896
+ </h1>
4897
+ <ContentSection content={data.post.body}></ContentSection>
4898
+ </div>
4899
+ <div className='bg-green-100 text-center'>
4900
+ Lost and looking for a place to start?
4901
+ <a
4902
+ href='https://tina.io/guides/tina-cloud/getting-started/overview/'
4903
+ className='text-blue-500 underline'
4904
+ >
4905
+ {' '}
4906
+ Check out this guide
4907
+ </a>{' '}
4908
+ to see how add TinaCMS to an existing Next.js site.
4909
+ </div>
4910
+ </div>
4911
+ </>
4912
+ )
4913
+ }
4914
+
4915
+ export const getStaticProps = async ({ params }) => {
4916
+ let data = {}
4917
+ let query = {}
4918
+ let variables = { relativePath: \`\${params.filename}.md\` }
4919
+ try {
4920
+ const res = await client.queries.post(variables)
4921
+ query = res.query
4922
+ data = res.data
4923
+ variables = res.variables
4924
+ } catch {
4925
+ // swallow errors related to document creation
4372
4926
  }
4373
- await reportTelemetry({
4374
- usingTypescript,
4375
- hasForestryConfig,
4376
- noTelemetry
4377
- });
4378
- const hasPackageJSON = await import_fs_extra11.default.pathExistsSync("package.json");
4379
- if (!hasPackageJSON) {
4380
- await createPackageJSON();
4927
+
4928
+ return {
4929
+ props: {
4930
+ variables: variables,
4931
+ data: data,
4932
+ query: query,
4933
+ //myOtherProp: 'some-other-data',
4934
+ },
4381
4935
  }
4382
- const hasGitignore = await import_fs_extra11.default.pathExistsSync(".gitignore");
4383
- if (!hasGitignore) {
4384
- await createGitignore({ baseDir: "" });
4385
- } else {
4386
- const hasNodeModulesIgnored = await checkGitignoreForNodeModules({
4387
- baseDir: ""
4388
- });
4389
- if (!hasNodeModulesIgnored) {
4390
- await addNodeModulesToGitignore({ baseDir: "" });
4391
- }
4936
+ }
4937
+
4938
+ export const getStaticPaths = async () => {
4939
+ const postsListData = await client.queries.postConnection()
4940
+
4941
+ return {
4942
+ paths: postsListData.data.postConnection.edges.map((post) => ({
4943
+ params: { filename: post.node._sys.filename },
4944
+ })),
4945
+ fallback: false,
4946
+ }
4947
+ }
4948
+
4949
+ export default BlogPage
4950
+
4951
+ const PageSection = (props) => {
4952
+ return (
4953
+ <>
4954
+ <h2>{props.heading}</h2>
4955
+ <p>{props.content}</p>
4956
+ </>
4957
+ )
4958
+ }
4959
+
4960
+ const components = {
4961
+ PageSection: PageSection,
4962
+ }
4963
+
4964
+ const ContentSection = ({ content }) => {
4965
+ return (
4966
+ <div className='relative py-16 bg-white overflow-hidden text-black'>
4967
+ <div className='hidden lg:block lg:absolute lg:inset-y-0 lg:h-full lg:w-full'>
4968
+ <div
4969
+ className='relative h-full text-lg max-w-prose mx-auto'
4970
+ aria-hidden='true'
4971
+ >
4972
+ <svg
4973
+ className='absolute top-12 left-full transform translate-x-32'
4974
+ width={404}
4975
+ height={384}
4976
+ fill='none'
4977
+ viewBox='0 0 404 384'
4978
+ >
4979
+ <defs>
4980
+ <pattern
4981
+ id='74b3fd99-0a6f-4271-bef2-e80eeafdf357'
4982
+ x={0}
4983
+ y={0}
4984
+ width={20}
4985
+ height={20}
4986
+ patternUnits='userSpaceOnUse'
4987
+ >
4988
+ <rect
4989
+ x={0}
4990
+ y={0}
4991
+ width={4}
4992
+ height={4}
4993
+ className='text-gray-200'
4994
+ fill='currentColor'
4995
+ />
4996
+ </pattern>
4997
+ </defs>
4998
+ <rect
4999
+ width={404}
5000
+ height={384}
5001
+ fill='url(#74b3fd99-0a6f-4271-bef2-e80eeafdf357)'
5002
+ />
5003
+ </svg>
5004
+ <svg
5005
+ className='absolute top-1/2 right-full transform -translate-y-1/2 -translate-x-32'
5006
+ width={404}
5007
+ height={384}
5008
+ fill='none'
5009
+ viewBox='0 0 404 384'
5010
+ >
5011
+ <defs>
5012
+ <pattern
5013
+ id='f210dbf6-a58d-4871-961e-36d5016a0f49'
5014
+ x={0}
5015
+ y={0}
5016
+ width={20}
5017
+ height={20}
5018
+ patternUnits='userSpaceOnUse'
5019
+ >
5020
+ <rect
5021
+ x={0}
5022
+ y={0}
5023
+ width={4}
5024
+ height={4}
5025
+ className='text-gray-200'
5026
+ fill='currentColor'
5027
+ />
5028
+ </pattern>
5029
+ </defs>
5030
+ <rect
5031
+ width={404}
5032
+ height={384}
5033
+ fill='url(#f210dbf6-a58d-4871-961e-36d5016a0f49)'
5034
+ />
5035
+ </svg>
5036
+ <svg
5037
+ className='absolute bottom-12 left-full transform translate-x-32'
5038
+ width={404}
5039
+ height={384}
5040
+ fill='none'
5041
+ viewBox='0 0 404 384'
5042
+ >
5043
+ <defs>
5044
+ <pattern
5045
+ id='d3eb07ae-5182-43e6-857d-35c643af9034'
5046
+ x={0}
5047
+ y={0}
5048
+ width={20}
5049
+ height={20}
5050
+ patternUnits='userSpaceOnUse'
5051
+ >
5052
+ <rect
5053
+ x={0}
5054
+ y={0}
5055
+ width={4}
5056
+ height={4}
5057
+ className='text-gray-200'
5058
+ fill='currentColor'
5059
+ />
5060
+ </pattern>
5061
+ </defs>
5062
+ <rect
5063
+ width={404}
5064
+ height={384}
5065
+ fill='url(#d3eb07ae-5182-43e6-857d-35c643af9034)'
5066
+ />
5067
+ </svg>
5068
+ </div>
5069
+ </div>
5070
+ <div className='relative px-4 sm:px-6 lg:px-8'>
5071
+ <div className='text-lg max-w-prose mx-auto'>
5072
+ <TinaMarkdown components={components} content={content} />
5073
+ </div>
5074
+ </div>
5075
+ </div>
5076
+ )
5077
+ }
5078
+ `;
4392
5079
  }
4393
- await addDependencies(packageManager);
5080
+ };
5081
+
5082
+ // src/cmds/init/templates/config.ts
5083
+ var clientConfig = (isForestryMigration) => {
4394
5084
  if (isForestryMigration) {
4395
- await addTemplateFile({ baseDir: "", usingTypescript, templateCode });
5085
+ return "client: {skip: true},";
4396
5086
  }
4397
- await addConfigFile({
4398
- publicFolder: import_path11.default.join(
4399
- import_path11.default.relative(process.cwd(), pathToForestryConfig),
4400
- publicFolder
4401
- ),
4402
- baseDir: "",
4403
- usingTypescript,
4404
- framework,
4405
- collections,
4406
- token,
4407
- clientId,
4408
- isForestryMigration,
4409
- extraText
4410
- });
4411
- if (!hasForestryConfig) {
4412
- await addContentFile({ baseDir: "" });
4413
- }
4414
- if (framework.reactive) {
4415
- await addReactiveFile[framework.name]({
4416
- baseDir: "",
4417
- framework,
4418
- usingTypescript
4419
- });
5087
+ return "";
5088
+ };
5089
+ var baseFields = `[
5090
+ {
5091
+ type: 'string',
5092
+ name: 'title',
5093
+ label: 'Title',
5094
+ isTitle: true,
5095
+ required: true,
5096
+ },
5097
+ {
5098
+ type: 'rich-text',
5099
+ name: 'body',
5100
+ label: 'Body',
5101
+ isBody: true,
5102
+ },
5103
+ ]`;
5104
+ var generateCollectionString = (args) => {
5105
+ var _a, _b, _c, _d;
5106
+ if (args.collections) {
5107
+ return args.collections;
5108
+ }
5109
+ const extraTinaCollections = (_b = (_a = args.config.authProvider) == null ? void 0 : _a.extraTinaCollections) == null ? void 0 : _b.join(",\n");
5110
+ const baseCollections = `[
5111
+ ${extraTinaCollections || ""}
5112
+ {
5113
+ name: 'post',
5114
+ label: 'Posts',
5115
+ path: 'content/posts',
5116
+ fields: ${baseFields},
5117
+ },
5118
+ ]`;
5119
+ const nextExampleCollection = `[
5120
+ ${extraTinaCollections || ""}
5121
+ {
5122
+ ${extraTinaCollections ? `${extraTinaCollections},` : ""}
5123
+ name: 'post',
5124
+ label: 'Posts',
5125
+ path: 'content/posts',
5126
+ fields: ${baseFields},
5127
+ ui: {
5128
+ // This is an DEMO router. You can remove this to fit your site
5129
+ router: ({ document }) => \`/demo/blog/\${document._sys.filename}\`,
5130
+ },
5131
+ },
5132
+ ]`;
5133
+ if (((_d = (_c = args.config) == null ? void 0 : _c.framework) == null ? void 0 : _d.name) === "next") {
5134
+ return nextExampleCollection;
4420
5135
  }
4421
- logNextSteps({ packageManager, framework });
4422
- }
4423
- var chooseClientId = async () => {
4424
- const option = await (0, import_prompts2.default)({
4425
- name: "clientId",
4426
- type: "text",
4427
- message: `What is your Tina Cloud Client ID? (Hit enter to skip and set up yourself later)
4428
- ${logText(
4429
- "Don't have a Client ID? Create one here: "
4430
- )}${linkText("https://app.tina.io/projects/new")}`
4431
- });
4432
- return option["clientId"];
5136
+ return baseCollections;
4433
5137
  };
4434
- var chooseToken = async ({ clientId }) => {
4435
- const option = await (0, import_prompts2.default)({
4436
- name: "token",
4437
- type: "text",
4438
- message: `What is your Tina Cloud Read Only Token?
4439
- ${logText(
4440
- "Don't have a Read Only Token? Create one here: "
4441
- )}${linkText(`https://app.tina.io/projects/${clientId}/tokens`)}`
4442
- });
4443
- return option["token"];
5138
+ var generateConfig = (args) => {
5139
+ var _a, _b, _c;
5140
+ const isUsingTinaCloud = !args.selfHosted || ((_a = args.config.authProvider) == null ? void 0 : _a.name) === "tina-cloud";
5141
+ let extraImports = "";
5142
+ if (args.selfHosted) {
5143
+ if (args.config.authProvider) {
5144
+ extraImports = extraImports + makeImportString((_b = args.config.authProvider) == null ? void 0 : _b.configImports);
5145
+ }
5146
+ if (!isUsingTinaCloud) {
5147
+ extraImports = extraImports + `
5148
+ import { LocalAuthProvider } from "tinacms";`;
5149
+ }
5150
+ }
5151
+ return `
5152
+ import { defineConfig } from "tinacms";
5153
+ ${extraImports}
5154
+ ${args.extraText || ""}
5155
+
5156
+ // Your hosting provider likely exposes this as an environment variable
5157
+ const branch = process.env.GITHUB_BRANCH ||
5158
+ process.env.VERCEL_GIT_COMMIT_REF ||
5159
+ process.env.HEAD ||
5160
+ "main"
5161
+ ${args.isLocalEnvVarName && args.selfHosted && `const isLocal = process.env.${args.isLocalEnvVarName} === 'true'` || ""}
5162
+ export default defineConfig({
5163
+ ${args.selfHosted && !isUsingTinaCloud ? `contentApiUrlOverride: "/api/tina/gql",` : ""}
5164
+ branch,
5165
+ ${args.selfHosted && !isUsingTinaCloud ? `authProvider: isLocal
5166
+ ? new LocalAuthProvider()
5167
+ :${(_c = args.config) == null ? void 0 : _c.authProvider.configAuthProviderClass},` : ""}
5168
+ ${isUsingTinaCloud ? `// Get this from tina.io
5169
+ clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,` : ""}
5170
+ ${isUsingTinaCloud ? `// Get this from tina.io
5171
+ token: process.env.TINA_TOKEN,` : ""}
5172
+
5173
+ ${clientConfig(args.isForestryMigration)}
5174
+ build: {
5175
+ outputFolder: "admin",
5176
+ publicFolder: "${args.publicFolder}",
5177
+ },
5178
+ media: {
5179
+ tina: {
5180
+ mediaRoot: "",
5181
+ publicFolder: "${args.publicFolder}",
5182
+ },
5183
+ },
5184
+ // See docs on content modeling for more info on how to setup new content models: https://tina.io/docs/schema/
5185
+ schema: {
5186
+ collections: ${generateCollectionString(args)},
5187
+ },
5188
+ });
5189
+ `;
4444
5190
  };
4445
- var choosePackageManager = async () => {
4446
- const option = await (0, import_prompts2.default)({
4447
- name: "selection",
4448
- type: "select",
4449
- message: "Choose your package manager",
4450
- choices: [
4451
- { title: "PNPM", value: "pnpm" },
4452
- { title: "Yarn", value: "yarn" },
4453
- { title: "NPM", value: "npm" }
4454
- ]
4455
- });
4456
- return option["selection"];
5191
+
5192
+ // src/cmds/init/templates/database.ts
5193
+ var databaseTemplate = ({ config: config2 }) => {
5194
+ var _a, _b, _c, _d;
5195
+ return `
5196
+ import { createDatabase, createLocalDatabase } from '@tinacms/datalayer'
5197
+ ${makeImportString((_a = config2.gitProvider) == null ? void 0 : _a.imports)}
5198
+ ${makeImportString((_b = config2.databaseAdapter) == null ? void 0 : _b.imports)}
5199
+
5200
+ const branch = (process.env.GITHUB_BRANCH ||
5201
+ process.env.VERCEL_GIT_COMMIT_REF ||
5202
+ process.env.HEAD ||
5203
+ "main")
5204
+
5205
+ const isLocal = process.env.${config2.isLocalEnvVarName} === 'true'
5206
+
5207
+ export default isLocal
5208
+ ? createLocalDatabase()
5209
+ : createDatabase({
5210
+ gitProvider: ${(_c = config2.gitProvider) == null ? void 0 : _c.gitProviderClassText},
5211
+ databaseAdapter: ${(_d = config2.databaseAdapter) == null ? void 0 : _d.databaseAdapterClassText},
5212
+ namespace: branch,
5213
+ })
5214
+ `;
4457
5215
  };
4458
- var chooseTypescript = async () => {
4459
- const option = await (0, import_prompts2.default)({
4460
- name: "selection",
4461
- type: "confirm",
4462
- initial: true,
4463
- message: "Would you like to use Typescript for your Tina Configuration (Recommended)?"
4464
- });
4465
- return option["selection"];
5216
+
5217
+ // src/cmds/init/templates/tinaNextRoute.tsx
5218
+ var nextApiRouteTemplate = ({
5219
+ config: config2,
5220
+ env
5221
+ }) => {
5222
+ var _a, _b;
5223
+ const extraPath = env.usingSrc ? "../" : "";
5224
+ return `import { TinaNodeBackend, LocalBackendAuthProvider } from '@tinacms/datalayer'
5225
+ ${makeImportString((_a = config2.authProvider) == null ? void 0 : _a.backendAuthProviderImports)}
5226
+
5227
+
5228
+
5229
+ import databaseClient from '${extraPath}../../../tina/__generated__/databaseClient'
5230
+
5231
+ const isLocal = process.env.TINA_PUBLIC_IS_LOCAL === 'true'
5232
+
5233
+ const handler = TinaNodeBackend({
5234
+ authProvider: isLocal
5235
+ ? LocalBackendAuthProvider()
5236
+ : ${((_b = config2.authProvider) == null ? void 0 : _b.backendAuthProvider) || ""},
5237
+ databaseClient,
5238
+ })
5239
+
5240
+ export default (req, res) => {
5241
+ // Modify the request here if you need to
5242
+ return handler(req, res)
5243
+ }`;
4466
5244
  };
4467
- var choosePublicFolder = async ({ framework }) => {
4468
- let suggestion = "public";
4469
- switch (framework.name) {
4470
- case "next":
4471
- return "public";
4472
- case "hugo":
4473
- return "static";
4474
- case "jekyll":
4475
- suggestion = "public";
4476
- break;
4477
- }
4478
- const option = await (0, import_prompts2.default)({
4479
- name: "selection",
4480
- type: "text",
4481
- message: `Where are public assets stored? (default: "${suggestion}")
4482
- ` + logText(
4483
- `Not sure what value to use? Refer to our "Frameworks" doc: ${linkText(
4484
- "https://tina.io/docs/integration/frameworks/#configuring-tina-with-each-framework"
4485
- )}`
4486
- )
4487
- });
4488
- return option["selection"] || suggestion;
5245
+
5246
+ // src/cmds/init/templates/content.ts
5247
+ var helloWorldPost = `---
5248
+ title: Hello, World!
5249
+ ---
5250
+
5251
+ ## Hello World!
5252
+
5253
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut non lorem diam. Quisque vulputate nibh sodales eros pretium tincidunt. Aenean porttitor efficitur convallis. Nulla sagittis finibus convallis. Phasellus in fermentum quam, eu egestas tortor. Maecenas ac mollis leo. Integer maximus eu nisl vel sagittis.
5254
+
5255
+ Suspendisse facilisis, mi ac scelerisque interdum, ligula ex imperdiet felis, a posuere eros justo nec sem. Nullam laoreet accumsan metus, sit amet tincidunt orci egestas nec. Pellentesque ut aliquet ante, at tristique nunc. Donec non massa nibh. Ut posuere lacus non aliquam laoreet. Fusce pharetra ligula a felis porttitor, at mollis ipsum maximus. Donec quam tortor, vehicula a magna sit amet, tincidunt dictum enim. In hac habitasse platea dictumst. Mauris sit amet ornare ligula, blandit consequat risus. Duis malesuada pellentesque lectus, non feugiat turpis eleifend a. Nullam tempus ante et diam pretium, ac faucibus ligula interdum.
5256
+ `;
5257
+
5258
+ // src/cmds/init/apply.ts
5259
+ var import_prettier2 = require("prettier");
5260
+
5261
+ // src/utils/script-helpers.ts
5262
+ function generateGqlScript(scriptValue, opts) {
5263
+ const cmd = `tinacms dev -c "${scriptValue}"`;
5264
+ if (opts == null ? void 0 : opts.isLocalEnvVarName) {
5265
+ return `${opts.isLocalEnvVarName}=true ${cmd}`;
5266
+ }
5267
+ return cmd;
5268
+ }
5269
+ function extendNextScripts(scripts, opts) {
5270
+ var _a, _b;
5271
+ const result = {
5272
+ ...scripts,
5273
+ dev: !(scripts == null ? void 0 : scripts.dev) || ((_a = scripts == null ? void 0 : scripts.dev) == null ? void 0 : _a.indexOf("tinacms dev -c")) === -1 ? generateGqlScript((scripts == null ? void 0 : scripts.dev) || "next dev", opts) : scripts == null ? void 0 : scripts.dev,
5274
+ build: !(scripts == null ? void 0 : scripts.build) || !((_b = scripts == null ? void 0 : scripts.build) == null ? void 0 : _b.startsWith("tinacms build &&")) ? `tinacms build && ${(scripts == null ? void 0 : scripts.build) || "next build"}` : scripts == null ? void 0 : scripts.build
5275
+ };
5276
+ if ((opts == null ? void 0 : opts.addSetupUsers) && !scripts["setup:users"]) {
5277
+ result["setup:users"] = "tinacms-next-auth setup";
5278
+ }
5279
+ return result;
5280
+ }
5281
+
5282
+ // src/cmds/init/codegen/index.ts
5283
+ var import_typescript3 = __toESM(require("typescript"));
5284
+ var import_fs_extra12 = __toESM(require("fs-extra"));
5285
+
5286
+ // src/cmds/init/codegen/util.ts
5287
+ var import_typescript2 = __toESM(require("typescript"));
5288
+ var makeTransformer = (makeVisitor) => (ctx) => (node) => import_typescript2.default.visitNode(node, makeVisitor(ctx));
5289
+ function parseExpression(expression) {
5290
+ const sourceFile = import_typescript2.default.createSourceFile(
5291
+ "temp.ts",
5292
+ expression,
5293
+ import_typescript2.default.ScriptTarget.Latest
5294
+ );
5295
+ if (sourceFile.statements.length !== 1) {
5296
+ throw new Error("Expected one statement");
5297
+ }
5298
+ const statement = sourceFile.statements[0];
5299
+ if (!import_typescript2.default.isExpressionStatement(statement)) {
5300
+ throw new Error("Expected an expression statement");
5301
+ }
5302
+ return [sourceFile, statement.expression];
5303
+ }
5304
+ function parseVariableStatement(stmt) {
5305
+ const sourceFile = import_typescript2.default.createSourceFile(
5306
+ "temp.ts",
5307
+ stmt,
5308
+ import_typescript2.default.ScriptTarget.Latest
5309
+ );
5310
+ if (sourceFile.statements.length !== 1) {
5311
+ throw new Error("Expected one statement");
5312
+ }
5313
+ const statement = sourceFile.statements[0];
5314
+ if (!import_typescript2.default.isVariableStatement(statement)) {
5315
+ throw new Error("Expected a variable statement");
5316
+ }
5317
+ return [sourceFile, statement];
5318
+ }
5319
+
5320
+ // src/cmds/init/codegen/index.ts
5321
+ var makeVariableStatementVisitor = (sourceFile, variableStmtSourceFile, variableStmt) => (ctx) => (node) => {
5322
+ if (import_typescript3.default.isSourceFile(node)) {
5323
+ const newStatements = [...node.statements];
5324
+ let encounteredImports = false;
5325
+ let firstNonImportStatementIdx = -1;
5326
+ let existingStatementIdx = -1;
5327
+ const [newVarDec] = variableStmt.declarationList.declarations;
5328
+ const newVarDecName = newVarDec.name.getText(variableStmtSourceFile);
5329
+ for (let i = 0; i < newStatements.length; i++) {
5330
+ const isImport = import_typescript3.default.isImportDeclaration(newStatements[i]);
5331
+ if (isImport && !encounteredImports) {
5332
+ encounteredImports = true;
5333
+ }
5334
+ if (!isImport && encounteredImports && firstNonImportStatementIdx === -1) {
5335
+ firstNonImportStatementIdx = i;
5336
+ }
5337
+ const stmt = newStatements[i];
5338
+ if (import_typescript3.default.isVariableStatement(stmt)) {
5339
+ const [dec] = stmt.declarationList.declarations;
5340
+ if (dec.name && import_typescript3.default.isIdentifier(dec.name) && dec.name.getText(sourceFile) === newVarDecName) {
5341
+ existingStatementIdx = i;
5342
+ }
5343
+ }
5344
+ if (existingStatementIdx !== -1 && firstNonImportStatementIdx !== -1) {
5345
+ break;
5346
+ }
5347
+ }
5348
+ if (firstNonImportStatementIdx === -1) {
5349
+ firstNonImportStatementIdx = 0;
5350
+ }
5351
+ if (existingStatementIdx === -1) {
5352
+ newStatements.splice(firstNonImportStatementIdx, 0, variableStmt);
5353
+ }
5354
+ return import_typescript3.default.factory.updateSourceFile(node, newStatements);
5355
+ }
4489
5356
  };
4490
- var chooseFramework = async () => {
4491
- const option = await (0, import_prompts2.default)({
4492
- name: "selection",
4493
- type: "select",
4494
- message: "What framework are you using?",
4495
- choices: [
4496
- { title: "Next.js", value: { name: "next", reactive: true } },
4497
- { title: "Hugo", value: { name: "hugo", reactive: false } },
4498
- { title: "Jekyll", value: { name: "jekyll", reactive: false } },
4499
- {
4500
- title: "Other (SSG frameworks like gatsby, etc.)",
4501
- value: { name: "other", reactive: false }
5357
+ var makeImportsVisitor = (sourceFile, importMap) => (ctx) => (node) => {
5358
+ var _a;
5359
+ if (import_typescript3.default.isSourceFile(node)) {
5360
+ let newStatements = [...node.statements];
5361
+ let changed = false;
5362
+ for (const [moduleName, imports] of Object.entries(importMap)) {
5363
+ let foundImportStatement = false;
5364
+ for (const statement of newStatements) {
5365
+ if (import_typescript3.default.isImportDeclaration(statement) && import_typescript3.default.isStringLiteral(statement.moduleSpecifier) && statement.moduleSpecifier.text === moduleName) {
5366
+ foundImportStatement = true;
5367
+ const existingImports = ((_a = statement.importClause) == null ? void 0 : _a.namedBindings) && import_typescript3.default.isNamedImports(statement.importClause.namedBindings) ? statement.importClause.namedBindings.elements.map(
5368
+ (e) => e.name.text
5369
+ ) : [];
5370
+ const newImports = [
5371
+ .../* @__PURE__ */ new Set([
5372
+ ...existingImports,
5373
+ ...imports
5374
+ ])
5375
+ ];
5376
+ const importSpecifiers = newImports.map(
5377
+ (i) => import_typescript3.default.factory.createImportSpecifier(
5378
+ void 0,
5379
+ import_typescript3.default.factory.createIdentifier(i)
5380
+ )
5381
+ );
5382
+ const namedImports = import_typescript3.default.factory.createNamedImports(importSpecifiers);
5383
+ const importClause = import_typescript3.default.factory.createImportClause(
5384
+ false,
5385
+ void 0,
5386
+ namedImports
5387
+ );
5388
+ const importDec = import_typescript3.default.factory.createImportDeclaration(
5389
+ void 0,
5390
+ void 0,
5391
+ importClause,
5392
+ import_typescript3.default.factory.createStringLiteral(moduleName)
5393
+ );
5394
+ newStatements[newStatements.indexOf(statement)] = importDec;
5395
+ changed = true;
5396
+ }
4502
5397
  }
4503
- ]
4504
- });
4505
- return option["selection"];
5398
+ if (!foundImportStatement) {
5399
+ const importSpecifiers = imports.map(
5400
+ (i) => import_typescript3.default.factory.createImportSpecifier(
5401
+ void 0,
5402
+ import_typescript3.default.factory.createIdentifier(i)
5403
+ )
5404
+ );
5405
+ const namedImports = import_typescript3.default.factory.createNamedImports(importSpecifiers);
5406
+ const importClause = import_typescript3.default.factory.createImportClause(
5407
+ false,
5408
+ void 0,
5409
+ namedImports
5410
+ );
5411
+ const importDec = import_typescript3.default.factory.createImportDeclaration(
5412
+ void 0,
5413
+ void 0,
5414
+ importClause,
5415
+ import_typescript3.default.factory.createStringLiteral(moduleName)
5416
+ );
5417
+ newStatements.unshift(importDec);
5418
+ changed = true;
5419
+ }
5420
+ }
5421
+ if (changed) {
5422
+ return import_typescript3.default.factory.updateSourceFile(node, newStatements);
5423
+ }
5424
+ }
4506
5425
  };
4507
- var forestryMigrate = async ({
4508
- pathToForestryConfig,
4509
- usingTypescript,
4510
- rootPath,
4511
- framework
4512
- }) => {
4513
- logger.info(`Forestry.io configuration found.`);
4514
- const disclaimer = logText(
4515
- `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)`
5426
+ var makeAddExpressionToSchemaCollectionVisitor = (sourceFile, functionName, newExpressionSourceFile, newExpression) => (ctx) => {
5427
+ const visit2 = (node) => {
5428
+ if (import_typescript3.default.isCallExpression(node) && import_typescript3.default.isIdentifier(node.expression) && node.expression.text === functionName && node.arguments.length > 0 && import_typescript3.default.isObjectLiteralExpression(node.arguments[0])) {
5429
+ const configObject = node.arguments[0];
5430
+ const updateProperties = configObject.properties.map((property) => {
5431
+ if (import_typescript3.default.isPropertyAssignment(property)) {
5432
+ const thisPropertyName = property.name.getText(sourceFile);
5433
+ if (thisPropertyName === "schema" && import_typescript3.default.isPropertyAssignment(property) && import_typescript3.default.isObjectLiteralExpression(property.initializer)) {
5434
+ const schemaObject = property.initializer;
5435
+ const collectionsProperty = schemaObject.properties.find(
5436
+ (p) => import_typescript3.default.isPropertyAssignment(p) && p.name.getText(sourceFile) === "collections"
5437
+ );
5438
+ if (collectionsProperty && import_typescript3.default.isPropertyAssignment(collectionsProperty) && import_typescript3.default.isArrayLiteralExpression(collectionsProperty.initializer)) {
5439
+ const collectionsArray = collectionsProperty.initializer;
5440
+ const collectionItems = collectionsArray.elements.map(
5441
+ (e) => e.getText(sourceFile)
5442
+ );
5443
+ if (collectionItems.includes(
5444
+ newExpression.getText(newExpressionSourceFile)
5445
+ )) {
5446
+ return property;
5447
+ }
5448
+ return import_typescript3.default.factory.updatePropertyAssignment(
5449
+ property,
5450
+ property.name,
5451
+ import_typescript3.default.factory.createObjectLiteralExpression(
5452
+ schemaObject.properties.map((subProp) => {
5453
+ if (import_typescript3.default.isPropertyAssignment(subProp) && subProp.name.getText(sourceFile) === "collections" && import_typescript3.default.isArrayLiteralExpression(subProp.initializer)) {
5454
+ return import_typescript3.default.factory.updatePropertyAssignment(
5455
+ subProp,
5456
+ subProp.name,
5457
+ import_typescript3.default.factory.createArrayLiteralExpression(
5458
+ [newExpression, ...subProp.initializer.elements],
5459
+ true
5460
+ )
5461
+ );
5462
+ }
5463
+ return subProp;
5464
+ }),
5465
+ true
5466
+ )
5467
+ );
5468
+ }
5469
+ }
5470
+ }
5471
+ return property;
5472
+ });
5473
+ return import_typescript3.default.factory.createCallExpression(
5474
+ node.expression,
5475
+ node.typeArguments,
5476
+ [import_typescript3.default.factory.createObjectLiteralExpression(updateProperties, true)]
5477
+ );
5478
+ }
5479
+ return import_typescript3.default.visitEachChild(node, visit2, ctx);
5480
+ };
5481
+ return visit2;
5482
+ };
5483
+ var makeUpdateObjectLiteralPropertyVisitor = (sourceFile, functionName, propertyName, propertyValueExpressionSourceFile, propertyValue) => (ctx) => {
5484
+ const visitor = (node) => {
5485
+ if (import_typescript3.default.isCallExpression(node) && import_typescript3.default.isIdentifier(node.expression) && node.expression.text === functionName && node.arguments.length > 0 && import_typescript3.default.isObjectLiteralExpression(node.arguments[0])) {
5486
+ let foundProperty = false;
5487
+ const configObject = node.arguments[0];
5488
+ const updateProperties = configObject.properties.map((property) => {
5489
+ if (import_typescript3.default.isPropertyAssignment(property) || import_typescript3.default.isShorthandPropertyAssignment(property)) {
5490
+ const name2 = property.name.getText(sourceFile);
5491
+ if (name2 === propertyName) {
5492
+ foundProperty = true;
5493
+ return import_typescript3.default.factory.createPropertyAssignment(name2, propertyValue);
5494
+ }
5495
+ }
5496
+ return property;
5497
+ });
5498
+ if (!foundProperty) {
5499
+ updateProperties.unshift(
5500
+ import_typescript3.default.factory.createPropertyAssignment(propertyName, propertyValue)
5501
+ );
5502
+ }
5503
+ return import_typescript3.default.factory.createCallExpression(
5504
+ node.expression,
5505
+ node.typeArguments,
5506
+ [import_typescript3.default.factory.createObjectLiteralExpression(updateProperties, true)]
5507
+ );
5508
+ }
5509
+ return import_typescript3.default.visitEachChild(node, visitor, ctx);
5510
+ };
5511
+ return visitor;
5512
+ };
5513
+ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5514
+ const pathToConfig = configFile.resolve(config2.typescript).path;
5515
+ const sourceFile = import_typescript3.default.createSourceFile(
5516
+ pathToConfig,
5517
+ import_fs_extra12.default.readFileSync(pathToConfig, "utf8"),
5518
+ config2.typescript ? import_typescript3.default.ScriptTarget.Latest : import_typescript3.default.ScriptTarget.ESNext
4516
5519
  );
4517
- const option = await (0, import_prompts2.default)({
4518
- name: "selection",
4519
- type: "confirm",
4520
- initial: true,
4521
- message: `Would you like to migrate your Forestry templates?
4522
- ${disclaimer}`
5520
+ const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5521
+ const importMap = {
5522
+ ...configImports.reduce((acc, { from, imported }) => {
5523
+ acc[from] = imported;
5524
+ return acc;
5525
+ }, {})
5526
+ };
5527
+ const transformedSourceFileResult = import_typescript3.default.transform(
5528
+ sourceFile,
5529
+ [
5530
+ makeImportsVisitor(sourceFile, {
5531
+ ...importMap,
5532
+ tinacms: ["LocalAuthProvider"]
5533
+ }),
5534
+ makeVariableStatementVisitor(
5535
+ sourceFile,
5536
+ ...parseVariableStatement(
5537
+ "const isLocal = process.env.TINA_PUBLIC_IS_LOCAL === 'true'"
5538
+ )
5539
+ ),
5540
+ makeUpdateObjectLiteralPropertyVisitor(
5541
+ sourceFile,
5542
+ "defineConfig",
5543
+ "authProvider",
5544
+ ...parseExpression(
5545
+ `isLocal ? new LocalAuthProvider() : ${configAuthProviderClass}`
5546
+ )
5547
+ ),
5548
+ makeUpdateObjectLiteralPropertyVisitor(
5549
+ sourceFile,
5550
+ "defineConfig",
5551
+ "contentApiUrlOverride",
5552
+ ...parseExpression("'/api/tina/gql'")
5553
+ ),
5554
+ ...extraTinaCollections.map(
5555
+ (collectionName) => makeAddExpressionToSchemaCollectionVisitor(
5556
+ sourceFile,
5557
+ "defineConfig",
5558
+ ...parseExpression(collectionName)
5559
+ )
5560
+ )
5561
+ ].map((visitor) => makeTransformer(visitor))
5562
+ );
5563
+ return import_fs_extra12.default.writeFile(
5564
+ pathToConfig,
5565
+ import_typescript3.default.createPrinter({ omitTrailingSemicolon: true }).printFile(transformedSourceFileResult.transformed[0])
5566
+ );
5567
+ };
5568
+
5569
+ // src/cmds/init/apply.ts
5570
+ async function apply({
5571
+ env,
5572
+ params,
5573
+ config: config2
5574
+ }) {
5575
+ var _a;
5576
+ if (config2.framework.name === "other" && config2.hosting === "self-host") {
5577
+ logger.error(
5578
+ logText(
5579
+ "Self-hosted Tina requires init setup only works with next.js right now. Please check out the docs for info on how to setup Tina on another framework: https://tina.io/docs/self-hosted/existing-site/"
5580
+ )
5581
+ );
5582
+ return;
5583
+ }
5584
+ const { pathToForestryConfig, noTelemetry, baseDir = "" } = params;
5585
+ let collections;
5586
+ let templateCode;
5587
+ let extraText;
5588
+ let isForestryMigration = false;
5589
+ if (env.forestryConfigExists) {
5590
+ const res = await forestryMigrate({
5591
+ frontMatterFormat: env.frontMatterFormat || config2.frontMatterFormat,
5592
+ pathToForestryConfig,
5593
+ usingTypescript: config2.typescript
5594
+ });
5595
+ if (res) {
5596
+ templateCode = res.templateCodeString;
5597
+ collections = res.collectionString;
5598
+ extraText = res.importStatements;
5599
+ isForestryMigration = true;
5600
+ }
5601
+ }
5602
+ await reportTelemetry({
5603
+ usingTypescript: config2.typescript,
5604
+ hasForestryConfig: env.forestryConfigExists,
5605
+ noTelemetry
4523
5606
  });
4524
- if (!option["selection"]) {
4525
- return null;
5607
+ if (!env.packageJSONExists) {
5608
+ await createPackageJSON();
4526
5609
  }
4527
- let frontMatterFormat = null;
4528
- if (framework.name === "hugo") {
4529
- frontMatterFormat = await getFrontmatterFormat(rootPath);
5610
+ if (!env.gitIgnoreExists) {
5611
+ await createGitignore({ baseDir });
5612
+ } else {
5613
+ const itemsToAdd = [];
5614
+ if (!env.gitIgnoreNodeModulesExists) {
5615
+ itemsToAdd.push("node_modules");
5616
+ }
5617
+ if (!env.gitIgnoreEnvExists) {
5618
+ itemsToAdd.push(".env");
5619
+ }
5620
+ if (itemsToAdd.length > 0) {
5621
+ await updateGitIgnore({ baseDir, items: itemsToAdd });
5622
+ }
5623
+ }
5624
+ if (isForestryMigration && !env.tinaConfigExists) {
5625
+ await addTemplateFile({
5626
+ generatedFile: env.generatedFiles["templates"],
5627
+ content: templateCode,
5628
+ config: config2
5629
+ });
4530
5630
  }
5631
+ const usingDataLayer = config2.hosting === "self-host";
5632
+ if (usingDataLayer) {
5633
+ await addDatabaseFile({
5634
+ config: config2,
5635
+ generatedFile: env.generatedFiles["database"]
5636
+ });
5637
+ await addNextApiRoute({
5638
+ env,
5639
+ config: config2,
5640
+ generatedFile: env.generatedFiles["next-api-handler"]
5641
+ });
5642
+ await addTemplateFile({
5643
+ config: config2,
5644
+ generatedFile: env.generatedFiles["users-json"],
5645
+ content: JSON.stringify(
5646
+ {
5647
+ users: [
5648
+ {
5649
+ name: "Tina User",
5650
+ email: "user@tina.io",
5651
+ username: "tinauser",
5652
+ password: {
5653
+ value: "tinarocks",
5654
+ passwordChangeRequired: true
5655
+ }
5656
+ }
5657
+ ]
5658
+ },
5659
+ null,
5660
+ 2
5661
+ )
5662
+ });
5663
+ }
5664
+ if (!env.forestryConfigExists && !env.tinaConfigExists) {
5665
+ await addContentFile({ config: config2, env });
5666
+ }
5667
+ if (config2.framework.reactive && addReactiveFile[config2.framework.name] && !env.tinaConfigExists) {
5668
+ await addReactiveFile[config2.framework.name]({
5669
+ baseDir,
5670
+ config: config2,
5671
+ env,
5672
+ dataLayer: usingDataLayer,
5673
+ generatedFile: env.generatedFiles["reactive-example"]
5674
+ });
5675
+ }
5676
+ await addDependencies(config2, env, params);
5677
+ if (!env.tinaConfigExists) {
5678
+ await addConfigFile({
5679
+ configArgs: {
5680
+ config: config2,
5681
+ publicFolder: import_path12.default.join(
5682
+ import_path12.default.relative(process.cwd(), pathToForestryConfig),
5683
+ config2.publicFolder
5684
+ ),
5685
+ collections,
5686
+ extraText,
5687
+ isLocalEnvVarName: config2.isLocalEnvVarName,
5688
+ isForestryMigration,
5689
+ selfHosted: usingDataLayer
5690
+ },
5691
+ baseDir,
5692
+ generatedFile: env.generatedFiles["config"],
5693
+ config: config2
5694
+ });
5695
+ }
5696
+ if (env.tinaConfigExists && params.isBackendInit && config2.hosting === "self-host" && (((_a = config2.authProvider) == null ? void 0 : _a.name) || "") !== "tina-cloud") {
5697
+ await addSelfHostedTinaAuthToConfig(config2, env.generatedFiles["config"]);
5698
+ }
5699
+ logNextSteps({
5700
+ config: config2,
5701
+ isBackend: params.isBackendInit,
5702
+ dataLayer: usingDataLayer,
5703
+ packageManager: config2.packageManager,
5704
+ framework: config2.framework
5705
+ });
5706
+ }
5707
+ var forestryMigrate = async ({
5708
+ pathToForestryConfig,
5709
+ usingTypescript,
5710
+ frontMatterFormat
5711
+ }) => {
4531
5712
  const { collections, importStatements, templateCode } = await generateCollections({
4532
5713
  pathToForestryConfig,
4533
5714
  usingTypescript,
@@ -4541,32 +5722,6 @@ ${disclaimer}`
4541
5722
  templateCodeString: templateCode
4542
5723
  };
4543
5724
  };
4544
- var getFrontmatterFormat = async (rootPath) => {
4545
- try {
4546
- const hugoConfigPath = import_path11.default.join(rootPath, "config.toml");
4547
- const hugoConfig = await import_fs_extra11.default.readFile(hugoConfigPath, "utf8");
4548
- const frontMatterFormat = hugoConfig.match(/metaDataFormat = "(.*)"/);
4549
- console.log({ frontMatterFormat });
4550
- if (frontMatterFormat && frontMatterFormat[1]) {
4551
- return frontMatterFormat[1];
4552
- }
4553
- } catch (e) {
4554
- }
4555
- const option = await (0, import_prompts2.default)({
4556
- name: "selection",
4557
- type: "select",
4558
- choices: [
4559
- { title: "yaml", value: "yaml" },
4560
- { title: "toml", value: "toml" },
4561
- { title: "json", value: "json" }
4562
- ],
4563
- message: `What format are you using in your frontmatter?`
4564
- });
4565
- if (!option["selection"]) {
4566
- return null;
4567
- }
4568
- return option["selection"];
4569
- };
4570
5725
  var reportTelemetry = async ({
4571
5726
  hasForestryConfig,
4572
5727
  noTelemetry,
@@ -4591,188 +5746,299 @@ var createPackageJSON = async () => {
4591
5746
  };
4592
5747
  var createGitignore = async ({ baseDir }) => {
4593
5748
  logger.info(logText("No .gitignore found, creating one"));
4594
- await import_fs_extra11.default.outputFileSync(import_path11.default.join(baseDir, ".gitignore"), "node_modules");
5749
+ import_fs_extra13.default.outputFileSync(import_path12.default.join(baseDir, ".gitignore"), "node_modules");
4595
5750
  };
4596
- var checkGitignoreForNodeModules = async ({
4597
- baseDir
5751
+ var updateGitIgnore = async ({
5752
+ baseDir,
5753
+ items
4598
5754
  }) => {
4599
- const gitignoreContent = await import_fs_extra11.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
4600
- return gitignoreContent.split("\n").some((item) => item === "node_modules");
4601
- };
4602
- var addNodeModulesToGitignore = async ({ baseDir }) => {
4603
- logger.info(logText("Adding node_modules to .gitignore"));
4604
- const gitignoreContent = await import_fs_extra11.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
4605
- const newGitignoreContent = [
4606
- ...gitignoreContent.split("\n"),
4607
- "node_modules"
4608
- ].join("\n");
4609
- await import_fs_extra11.default.writeFileSync(import_path11.default.join(baseDir, ".gitignore"), newGitignoreContent);
5755
+ logger.info(logText(`Adding ${items.join(",")} to .gitignore`));
5756
+ const gitignoreContent = import_fs_extra13.default.readFileSync(import_path12.default.join(baseDir, ".gitignore")).toString();
5757
+ const newGitignoreContent = [...gitignoreContent.split("\n"), ...items].join(
5758
+ "\n"
5759
+ );
5760
+ await import_fs_extra13.default.writeFile(import_path12.default.join(baseDir, ".gitignore"), newGitignoreContent);
4610
5761
  };
4611
- var addDependencies = async (packageManager) => {
4612
- logger.info(logText("Adding dependencies, this might take a moment..."));
4613
- const deps = ["tinacms", "@tinacms/cli"];
4614
- const packageManagers = {
5762
+ var addDependencies = async (config2, env, params) => {
5763
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
5764
+ const { packageManager } = config2;
5765
+ const tagVersion = params.tinaVersion ? `@${params.tinaVersion}` : "";
5766
+ let deps = [];
5767
+ let devDeps = [];
5768
+ if (!env.hasTinaDeps) {
5769
+ deps.push("tinacms");
5770
+ devDeps.push("@tinacms/cli");
5771
+ }
5772
+ if (config2.typescript) {
5773
+ devDeps.push("@types/node");
5774
+ }
5775
+ if (config2.hosting === "self-host") {
5776
+ deps.push("@tinacms/datalayer");
5777
+ }
5778
+ deps.push(
5779
+ ...((_b = (_a = config2.databaseAdapter) == null ? void 0 : _a.imports) == null ? void 0 : _b.map((x) => x.packageName)) || []
5780
+ );
5781
+ deps.push(...((_c = config2.authProvider) == null ? void 0 : _c.peerDependencies) || []);
5782
+ deps.push(
5783
+ ...((_e = (_d = config2.authProvider) == null ? void 0 : _d.backendAuthProviderImports) == null ? void 0 : _e.map(
5784
+ (x) => x.packageName
5785
+ )) || []
5786
+ );
5787
+ deps.push(
5788
+ ...((_g = (_f = config2.authProvider) == null ? void 0 : _f.configImports) == null ? void 0 : _g.map((x) => x.packageName)) || []
5789
+ );
5790
+ deps.push(...((_i = (_h = config2.gitProvider) == null ? void 0 : _h.imports) == null ? void 0 : _i.map((x) => x.packageName)) || []);
5791
+ if (tagVersion) {
5792
+ deps = deps.map(
5793
+ (dep) => dep.indexOf("tina") >= 0 ? `${dep}${tagVersion}` : dep
5794
+ );
5795
+ devDeps = devDeps.map(
5796
+ (dep) => dep.indexOf("tina") >= 0 ? `${dep}${tagVersion}` : dep
5797
+ );
5798
+ }
5799
+ let packageManagers = {
4615
5800
  pnpm: process.env.USE_WORKSPACE ? `pnpm add ${deps.join(" ")} --workspace` : `pnpm add ${deps.join(" ")}`,
4616
5801
  npm: `npm install ${deps.join(" ")}`,
4617
5802
  yarn: `yarn add ${deps.join(" ")}`
4618
5803
  };
4619
- logger.info(indentedCmd(`${logText(packageManagers[packageManager])}`));
4620
- await execShellCommand(packageManagers[packageManager]);
4621
- };
4622
- var addConfigFile = async (args) => {
4623
- const { baseDir, usingTypescript } = args;
4624
- const configPath = import_path11.default.join(
4625
- "tina",
4626
- `config.${usingTypescript ? "ts" : "js"}`
4627
- );
4628
- const fullConfigPath = import_path11.default.join(baseDir, configPath);
4629
- if (import_fs_extra11.default.pathExistsSync(fullConfigPath)) {
4630
- const override = await (0, import_prompts2.default)({
4631
- name: "selection",
4632
- type: "confirm",
4633
- message: `Found existing file at ${configPath}. Would you like to override?`
4634
- });
4635
- if (override["selection"]) {
4636
- logger.info(logText(`Overriding file at ${configPath}.`));
4637
- await import_fs_extra11.default.outputFileSync(fullConfigPath, config2(args));
4638
- } else {
4639
- logger.info(logText(`Not overriding file at ${configPath}.`));
5804
+ if (packageManagers[packageManager] && deps.length > 0) {
5805
+ logger.info(logText("Adding dependencies, this might take a moment..."));
5806
+ logger.info(indentedCmd(`${logText(packageManagers[packageManager])}`));
5807
+ await execShellCommand(packageManagers[packageManager]);
5808
+ }
5809
+ if (devDeps.length > 0) {
5810
+ packageManagers = {
5811
+ pnpm: process.env.USE_WORKSPACE ? `pnpm add -D ${devDeps.join(" ")} --workspace` : `pnpm add -D ${devDeps.join(" ")}`,
5812
+ npm: `npm install -D ${devDeps.join(" ")}`,
5813
+ yarn: `yarn add -D ${devDeps.join(" ")}`
5814
+ };
5815
+ if (packageManagers[packageManager]) {
5816
+ logger.info(
5817
+ logText("Adding dev dependencies, this might take a moment...")
5818
+ );
5819
+ logger.info(indentedCmd(`${logText(packageManagers[packageManager])}`));
5820
+ await execShellCommand(packageManagers[packageManager]);
4640
5821
  }
4641
- } else {
4642
- logger.info(
4643
- logText(
4644
- `Adding config file at tina/config.${usingTypescript ? "ts" : "js"}`
4645
- )
4646
- );
4647
- await import_fs_extra11.default.outputFileSync(fullConfigPath, config2(args));
4648
- await writeGitignore(baseDir);
4649
5822
  }
4650
5823
  };
4651
- var addTemplateFile = async (args) => {
4652
- const { baseDir, usingTypescript, templateCode } = args;
4653
- const templatesPath = import_path11.default.join(
4654
- "tina",
4655
- `templates.${usingTypescript ? "ts" : "js"}`
4656
- );
4657
- const fullTemplatesPath = import_path11.default.join(baseDir, templatesPath);
4658
- if (import_fs_extra11.default.pathExistsSync(fullTemplatesPath)) {
4659
- const override = await (0, import_prompts2.default)({
4660
- name: "selection",
4661
- type: "confirm",
4662
- message: `Found existing file at ${templatesPath}. Would you like to override?`
4663
- });
4664
- if (override["selection"]) {
4665
- logger.info(logText(`Overriding file at ${templatesPath}.`));
4666
- await import_fs_extra11.default.outputFileSync(fullTemplatesPath, templateCode);
5824
+ var writeGeneratedFile = async ({
5825
+ generatedFile,
5826
+ overwrite,
5827
+ content,
5828
+ typescript
5829
+ }) => {
5830
+ const { exists, path: path13, parentPath } = generatedFile.resolve(typescript);
5831
+ if (exists) {
5832
+ if (overwrite) {
5833
+ logger.info(`Overwriting file at ${path13}... \u2705`);
5834
+ import_fs_extra13.default.outputFileSync(path13, content);
4667
5835
  } else {
4668
- logger.info(logText(`Not overriding file at ${templatesPath}.`));
5836
+ logger.info(`Not overwriting file at ${path13}.`);
5837
+ logger.info(
5838
+ logText(`Please add the following to ${path13}:
5839
+ ${indentText(content)}}`)
5840
+ );
4669
5841
  }
4670
5842
  } else {
4671
- logger.info(logText(`Adding template file at ${templatesPath}`));
4672
- await import_fs_extra11.default.outputFileSync(fullTemplatesPath, templateCode);
5843
+ logger.info(`Adding file at ${path13}... \u2705`);
5844
+ await import_fs_extra13.default.ensureDir(parentPath);
5845
+ import_fs_extra13.default.outputFileSync(path13, content);
4673
5846
  }
4674
5847
  };
4675
- var addContentFile = async ({ baseDir }) => {
4676
- const contentPath = import_path11.default.join("content", "posts", "hello-world.md");
4677
- const fullContentPath = import_path11.default.join(baseDir, contentPath);
4678
- if (import_fs_extra11.default.pathExistsSync(fullContentPath)) {
4679
- const override = await (0, import_prompts2.default)({
4680
- name: "selection",
4681
- type: "confirm",
4682
- message: `Found existing file at ${contentPath}. Would you like to override?`
4683
- });
4684
- if (override["selection"]) {
4685
- logger.info(logText(`Overriding file at ${contentPath}.`));
4686
- await import_fs_extra11.default.outputFileSync(fullContentPath, content);
4687
- } else {
4688
- logger.info(logText(`Not overriding file at ${contentPath}.`));
4689
- }
4690
- } else {
4691
- logger.info(logText(`Adding content file at ${contentPath}`));
4692
- await import_fs_extra11.default.outputFileSync(fullContentPath, content);
5848
+ var addConfigFile = async ({
5849
+ baseDir,
5850
+ configArgs,
5851
+ generatedFile,
5852
+ config: config2
5853
+ }) => {
5854
+ var _a;
5855
+ const content = (0, import_prettier2.format)(generateConfig(configArgs), {
5856
+ parser: "babel"
5857
+ });
5858
+ await writeGeneratedFile({
5859
+ overwrite: (_a = config2.overwriteList) == null ? void 0 : _a.includes("config"),
5860
+ generatedFile,
5861
+ content,
5862
+ typescript: config2.typescript
5863
+ });
5864
+ const { exists } = generatedFile.resolve(config2.typescript);
5865
+ if (!exists) {
5866
+ await writeGitignore(baseDir);
4693
5867
  }
4694
5868
  };
5869
+ var addDatabaseFile = async ({
5870
+ config: config2,
5871
+ generatedFile
5872
+ }) => {
5873
+ var _a;
5874
+ await writeGeneratedFile({
5875
+ generatedFile,
5876
+ overwrite: (_a = config2.overwriteList) == null ? void 0 : _a.includes("database"),
5877
+ content: databaseTemplate({ config: config2 }),
5878
+ typescript: config2.typescript
5879
+ });
5880
+ };
5881
+ var addNextApiRoute = async ({
5882
+ config: config2,
5883
+ generatedFile,
5884
+ env
5885
+ }) => {
5886
+ var _a;
5887
+ const content = (0, import_prettier2.format)(nextApiRouteTemplate({ config: config2, env }), {
5888
+ parser: "babel"
5889
+ });
5890
+ await writeGeneratedFile({
5891
+ generatedFile,
5892
+ overwrite: (_a = config2.overwriteList) == null ? void 0 : _a.includes("next-api-handler"),
5893
+ content,
5894
+ typescript: config2.typescript
5895
+ });
5896
+ };
5897
+ var addTemplateFile = async ({
5898
+ content,
5899
+ generatedFile,
5900
+ config: config2
5901
+ }) => {
5902
+ var _a;
5903
+ await writeGeneratedFile({
5904
+ generatedFile,
5905
+ overwrite: (_a = config2.overwriteList) == null ? void 0 : _a.includes(generatedFile.generatedFileType),
5906
+ content,
5907
+ typescript: config2.typescript
5908
+ });
5909
+ };
5910
+ var addContentFile = async ({
5911
+ config: config2,
5912
+ env
5913
+ }) => {
5914
+ var _a;
5915
+ await writeGeneratedFile({
5916
+ generatedFile: {
5917
+ javascriptExists: false,
5918
+ typescriptExists: false,
5919
+ fullPathJS: "",
5920
+ fullPathTS: "",
5921
+ generatedFileType: "sample-content",
5922
+ name: "",
5923
+ parentPath: "",
5924
+ get resolve() {
5925
+ return () => ({
5926
+ exists: env.sampleContentExists,
5927
+ path: env.sampleContentPath,
5928
+ parentPath: import_path12.default.dirname(env.sampleContentPath)
5929
+ });
5930
+ }
5931
+ },
5932
+ overwrite: (_a = config2.overwriteList) == null ? void 0 : _a.includes("sample-content"),
5933
+ content: helloWorldPost,
5934
+ typescript: false
5935
+ });
5936
+ };
4695
5937
  var logNextSteps = ({
5938
+ config: config2,
5939
+ dataLayer: _datalayer,
4696
5940
  framework,
4697
- packageManager
5941
+ packageManager,
5942
+ isBackend
4698
5943
  }) => {
4699
- logger.info(focusText(`
5944
+ if (isBackend) {
5945
+ logger.info(focusText(`
5946
+ ${titleText(" TinaCMS ")} backend initialized!`));
5947
+ const envFileText = config2.envVars.map((x) => {
5948
+ return `${x.key}=${x.value || "***"}`;
5949
+ }).join("\n") + `
5950
+ TINA_PUBLIC_IS_LOCAL=true`;
5951
+ const envFile = import_path12.default.join(process.cwd(), ".env");
5952
+ if (!import_fs_extra13.default.existsSync(envFile)) {
5953
+ logger.info(`Adding .env file to your project... \u2705`);
5954
+ import_fs_extra13.default.writeFileSync(envFile, envFileText);
5955
+ } else {
5956
+ logger.info(
5957
+ "Please add the following environment variables to your .env file"
5958
+ );
5959
+ logger.info(indentText(envFileText));
5960
+ }
5961
+ logger.info(
5962
+ "Before you can run your site you will need to update it to use the backend client.\nSee docs for more info: https://tina.io/docs/self-hosted/querying-data/"
5963
+ );
5964
+ logger.info(
5965
+ "If you are deploying to vercel make sure to add the environment variables to your project."
5966
+ );
5967
+ logger.info("Make sure to push tina-lock.json to your GitHub repo");
5968
+ } else {
5969
+ logger.info(focusText(`
4700
5970
  ${titleText(" TinaCMS ")} has been initialized!`));
4701
- logger.info(
4702
- "To get started run: " + cmdText(frameworkDevCmds[framework.name]({ packageManager }))
4703
- );
4704
- logger.info(
4705
- `
5971
+ logger.info(
5972
+ "To get started run: " + cmdText(frameworkDevCmds[framework.name]({ packageManager }))
5973
+ );
5974
+ logger.info(
5975
+ "To get your site production ready, run: " + cmdText(`tinacms init backend`)
5976
+ );
5977
+ logger.info(
5978
+ `
4706
5979
  Once your site is running, access the CMS at ${linkText(
4707
- "<YourDevURL>/admin/index.html"
4708
- )}`
4709
- );
5980
+ "<YourDevURL>/admin/index.html"
5981
+ )}`
5982
+ );
5983
+ }
4710
5984
  };
4711
- var other2 = ({ packageManager }) => {
5985
+ var other = ({ packageManager }) => {
4712
5986
  const packageManagers = {
4713
5987
  pnpm: `pnpm`,
4714
5988
  npm: `npx`,
4715
5989
  yarn: `yarn`
4716
5990
  };
4717
- const installText = `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
4718
- return installText;
5991
+ return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
4719
5992
  };
4720
5993
  var frameworkDevCmds = {
4721
- other: other2,
4722
- hugo: other2,
4723
- jekyll: other2,
5994
+ other,
5995
+ hugo: other,
5996
+ jekyll: other,
4724
5997
  next: ({ packageManager }) => {
4725
5998
  const packageManagers = {
4726
5999
  pnpm: `pnpm`,
4727
6000
  npm: `npm run`,
4728
6001
  yarn: `yarn`
4729
6002
  };
4730
- const installText = `${packageManagers[packageManager]} dev`;
4731
- return installText;
6003
+ return `${packageManagers[packageManager]} dev`;
4732
6004
  }
4733
6005
  };
4734
- var config2 = (args) => {
4735
- return (0, import_prettier2.format)(configExamples[args.framework.name](args), { parser: "babel" });
4736
- };
4737
- var content = `---
4738
- title: Hello, World!
4739
- ---
4740
-
4741
- ## Hello World!
4742
-
4743
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut non lorem diam. Quisque vulputate nibh sodales eros pretium tincidunt. Aenean porttitor efficitur convallis. Nulla sagittis finibus convallis. Phasellus in fermentum quam, eu egestas tortor. Maecenas ac mollis leo. Integer maximus eu nisl vel sagittis.
4744
-
4745
- Suspendisse facilisis, mi ac scelerisque interdum, ligula ex imperdiet felis, a posuere eros justo nec sem. Nullam laoreet accumsan metus, sit amet tincidunt orci egestas nec. Pellentesque ut aliquet ante, at tristique nunc. Donec non massa nibh. Ut posuere lacus non aliquam laoreet. Fusce pharetra ligula a felis porttitor, at mollis ipsum maximus. Donec quam tortor, vehicula a magna sit amet, tincidunt dictum enim. In hac habitasse platea dictumst. Mauris sit amet ornare ligula, blandit consequat risus. Duis malesuada pellentesque lectus, non feugiat turpis eleifend a. Nullam tempus ante et diam pretium, ac faucibus ligula interdum.
4746
- `;
4747
6006
  var addReactiveFile = {
4748
- next: ({
6007
+ next: async ({
6008
+ generatedFile,
6009
+ config: config2,
6010
+ env,
4749
6011
  baseDir,
4750
- usingTypescript
6012
+ dataLayer
4751
6013
  }) => {
4752
- const usingSrc = !import_fs_extra11.default.pathExistsSync(import_path11.default.join(baseDir, "pages"));
4753
- const pagesPath = import_path11.default.join(baseDir, usingSrc ? "src" : "", "pages");
4754
- const packageJSONPath = import_path11.default.join(baseDir, "package.json");
4755
- const tinaBlogPagePath = import_path11.default.join(pagesPath, "demo", "blog");
4756
- const tinaBlogPagePathFile = import_path11.default.join(
4757
- tinaBlogPagePath,
4758
- `[filename].${usingTypescript ? "tsx" : "js"}`
4759
- );
4760
- if (!import_fs_extra11.default.pathExistsSync(tinaBlogPagePathFile)) {
4761
- import_fs_extra11.default.mkdirpSync(tinaBlogPagePath);
4762
- import_fs_extra11.default.writeFileSync(tinaBlogPagePathFile, nextPostPage({ usingSrc }));
4763
- }
6014
+ var _a, _b;
6015
+ const packageJsonPath = import_path12.default.join(baseDir, "package.json");
6016
+ await writeGeneratedFile({
6017
+ generatedFile,
6018
+ typescript: config2.typescript,
6019
+ overwrite: (_a = config2.overwriteList) == null ? void 0 : _a.includes(
6020
+ generatedFile.generatedFileType
6021
+ ),
6022
+ content: templates["demo-post-page"]({
6023
+ usingSrc: env.usingSrc,
6024
+ dataLayer
6025
+ })
6026
+ });
4764
6027
  logger.info("Adding a nextjs example... \u2705");
4765
- const pack = JSON.parse(import_fs_extra11.default.readFileSync(packageJSONPath).toString());
4766
- const oldScripts = pack.scripts || {};
4767
- const newPack = JSON.stringify(
6028
+ const packageJson = JSON.parse(import_fs_extra13.default.readFileSync(packageJsonPath).toString());
6029
+ const scripts = packageJson.scripts || {};
6030
+ const updatedPackageJson = JSON.stringify(
4768
6031
  {
4769
- ...pack,
4770
- scripts: extendNextScripts(oldScripts)
6032
+ ...packageJson,
6033
+ scripts: extendNextScripts(scripts, {
6034
+ isLocalEnvVarName: config2.isLocalEnvVarName,
6035
+ addSetupUsers: ((_b = config2.authProvider) == null ? void 0 : _b.name) === "next-auth"
6036
+ })
4771
6037
  },
4772
6038
  null,
4773
6039
  2
4774
6040
  );
4775
- import_fs_extra11.default.writeFileSync(packageJSONPath, newPack);
6041
+ import_fs_extra13.default.writeFileSync(packageJsonPath, updatedPackageJson);
4776
6042
  }
4777
6043
  };
4778
6044
  function execShellCommand(cmd) {
@@ -4786,6 +6052,40 @@ function execShellCommand(cmd) {
4786
6052
  });
4787
6053
  });
4788
6054
  }
6055
+ var apply_default = apply;
6056
+
6057
+ // src/cmds/init/index.ts
6058
+ var command = new CLICommand({
6059
+ async setup(params) {
6060
+ logger.level = "info";
6061
+ process.chdir(params.rootPath);
6062
+ },
6063
+ detectEnvironment({
6064
+ rootPath,
6065
+ pathToForestryConfig,
6066
+ baseDir = "",
6067
+ debug = false,
6068
+ tinaVersion
6069
+ }) {
6070
+ return detectEnvironment_default({
6071
+ baseDir,
6072
+ pathToForestryConfig,
6073
+ rootPath,
6074
+ debug,
6075
+ tinaVersion
6076
+ });
6077
+ },
6078
+ configure(env, { debug = false, isBackendInit = false }) {
6079
+ return configure_default(env, { debug, isBackend: isBackendInit });
6080
+ },
6081
+ apply(config2, env, params) {
6082
+ return apply_default({
6083
+ env,
6084
+ params,
6085
+ config: config2
6086
+ });
6087
+ }
6088
+ });
4789
6089
 
4790
6090
  // src/next/commands/init-command/index.ts
4791
6091
  var InitCommand = class extends import_clipanion6.Command {
@@ -4797,9 +6097,15 @@ var InitCommand = class extends import_clipanion6.Command {
4797
6097
  this.rootPath = import_clipanion6.Option.String("--rootPath", {
4798
6098
  description: "Specify the root directory to run the CLI from (defaults to current working directory)"
4799
6099
  });
6100
+ this.debug = import_clipanion6.Option.Boolean("--debug", false, {
6101
+ description: "Enable debug logging"
6102
+ });
4800
6103
  this.noTelemetry = import_clipanion6.Option.Boolean("--noTelemetry", false, {
4801
6104
  description: "Disable anonymous telemetry that is collected"
4802
6105
  });
6106
+ this.tinaVersion = import_clipanion6.Option.String("--tinaVersion", {
6107
+ description: "Specify a version for tina dependencies"
6108
+ });
4803
6109
  }
4804
6110
  async catch(error) {
4805
6111
  logger.error("Error occured during tinacms init");
@@ -4807,16 +6113,20 @@ var InitCommand = class extends import_clipanion6.Command {
4807
6113
  process.exit(1);
4808
6114
  }
4809
6115
  async execute() {
6116
+ const isBackend = Boolean(this.path.find((x) => x === "backend"));
4810
6117
  const rootPath = this.rootPath || process.cwd();
4811
- await initStaticTina({
6118
+ await command.execute({
6119
+ isBackendInit: isBackend,
4812
6120
  rootPath,
4813
6121
  pathToForestryConfig: this.pathToForestryConfig || rootPath,
4814
- noTelemetry: this.noTelemetry
6122
+ noTelemetry: this.noTelemetry,
6123
+ debug: this.debug,
6124
+ tinaVersion: this.tinaVersion
4815
6125
  });
4816
6126
  process.exit();
4817
6127
  }
4818
6128
  };
4819
- InitCommand.paths = [["init"]];
6129
+ InitCommand.paths = [["init"], ["init", "backend"]];
4820
6130
  InitCommand.usage = import_clipanion6.Command.Usage({
4821
6131
  category: `Commands`,
4822
6132
  description: `Add Tina to an existing project`
@@ -4824,7 +6134,7 @@ InitCommand.usage = import_clipanion6.Command.Usage({
4824
6134
 
4825
6135
  // src/next/commands/searchindex-command/index.ts
4826
6136
  var import_clipanion7 = require("clipanion");
4827
- var import_graphql16 = require("@tinacms/graphql");
6137
+ var import_graphql17 = require("@tinacms/graphql");
4828
6138
  var import_search3 = require("@tinacms/search");
4829
6139
  var SearchIndexCommand = class extends import_clipanion7.Command {
4830
6140
  constructor() {
@@ -4858,7 +6168,7 @@ var SearchIndexCommand = class extends import_clipanion7.Command {
4858
6168
  process.exit(1);
4859
6169
  }
4860
6170
  const { schema } = configManager.config;
4861
- const tinaSchema = await (0, import_graphql16.createSchema)({
6171
+ const tinaSchema = await (0, import_graphql17.createSchema)({
4862
6172
  schema: { ...schema, config: configManager.config }
4863
6173
  });
4864
6174
  let client;
@@ -4897,7 +6207,7 @@ var SearchIndexCommand = class extends import_clipanion7.Command {
4897
6207
  }
4898
6208
  const searchIndexer = new import_search3.SearchIndexer({
4899
6209
  batchSize: ((_t = configManager.config.search) == null ? void 0 : _t.indexBatchSize) || 100,
4900
- bridge: new import_graphql16.FilesystemBridge(
6210
+ bridge: new import_graphql17.FilesystemBridge(
4901
6211
  configManager.rootPath,
4902
6212
  configManager.contentRootPath
4903
6213
  ),