@tinacms/cli 1.5.31 → 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.31";
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
  }
@@ -890,7 +916,7 @@ var createConfig = async ({
890
916
  noWatch,
891
917
  rollupOptions
892
918
  }) => {
893
- var _a, _b, _c, _d, _e, _f;
919
+ var _a, _b, _c, _d, _e, _f, _g, _h;
894
920
  const publicEnv = {};
895
921
  Object.keys(process.env).forEach((key) => {
896
922
  if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
@@ -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
@@ -954,7 +980,7 @@ var createConfig = async ({
954
980
  "process.env": `new Object(${JSON.stringify(publicEnv)})`,
955
981
  "process.platform": `"${process.platform}"`,
956
982
  __API_URL__: `"${apiURL}"`,
957
- __TOKEN__: `"${configManager.config.token}"`,
983
+ __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
958
984
  __TINA_GRAPHQL_VERSION__: `"${configManager.getTinaGraphQLVersion()}"`
959
985
  },
960
986
  logLevel: "error",
@@ -963,7 +989,7 @@ var createConfig = async ({
963
989
  include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
964
990
  },
965
991
  server: {
966
- host: (_f = (_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.host) != null ? _f : false,
992
+ host: (_h = (_g = (_f = configManager.config) == null ? void 0 : _f.build) == null ? void 0 : _g.host) != null ? _h : false,
967
993
  watch: noWatch ? {
968
994
  ignored: ["**/*"]
969
995
  } : {
@@ -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
  ),
@@ -2654,22 +2798,26 @@ ${dangerText(e.message)}
2654
2798
  }
2655
2799
  }
2656
2800
  const summaryItems = [];
2801
+ const autogeneratedFiles = [];
2657
2802
  if (!configManager.shouldSkipSDK()) {
2658
- summaryItems.push({
2659
- emoji: "\u{1F916}",
2660
- heading: "Auto-generated files",
2661
- subItems: [
2662
- {
2663
- key: "GraphQL Client",
2664
- value: configManager.printGeneratedClientFilePath()
2665
- },
2666
- {
2667
- key: "Typescript Types",
2668
- value: configManager.printGeneratedTypesFilePath()
2669
- }
2670
- ]
2803
+ autogeneratedFiles.push({
2804
+ key: "GraphQL Client",
2805
+ value: configManager.printGeneratedClientFilePath()
2806
+ });
2807
+ autogeneratedFiles.push({
2808
+ key: "Typescript Types",
2809
+ value: configManager.printGeneratedTypesFilePath()
2671
2810
  });
2672
2811
  }
2812
+ autogeneratedFiles.push({
2813
+ key: "Static HTML file",
2814
+ value: configManager.printRelativePath(configManager.outputHTMLFilePath)
2815
+ });
2816
+ summaryItems.push({
2817
+ emoji: "\u{1F916}",
2818
+ heading: "Auto-generated files",
2819
+ subItems: autogeneratedFiles
2820
+ });
2673
2821
  summary({
2674
2822
  heading: "Tina build complete",
2675
2823
  items: [
@@ -2693,8 +2841,8 @@ ${dangerText(e.message)}
2693
2841
  }
2694
2842
  }
2695
2843
  async checkClientInfo(configManager, apiURL) {
2696
- const { config: config3 } = configManager;
2697
- const token = config3.token;
2844
+ const { config: config2 } = configManager;
2845
+ const token = config2.token;
2698
2846
  const { clientId, branch, host } = (0, import_schema_tools2.parseURL)(apiURL);
2699
2847
  const url = `https://${host}/db/${clientId}/status/${branch}`;
2700
2848
  const bar2 = new import_progress2.default("Checking clientId and token. :prog", 1);
@@ -2720,11 +2868,11 @@ ${dangerText(e.message)}
2720
2868
  subItems: [
2721
2869
  {
2722
2870
  key: "clientId",
2723
- value: config3.clientId
2871
+ value: config2.clientId
2724
2872
  },
2725
2873
  {
2726
2874
  key: "token",
2727
- value: config3.token
2875
+ value: config2.token
2728
2876
  }
2729
2877
  ]
2730
2878
  }
@@ -2778,8 +2926,8 @@ ${dangerText(e.message)}
2778
2926
  "Checking local GraphQL Schema matches server. :prog",
2779
2927
  1
2780
2928
  );
2781
- const { config: config3 } = configManager;
2782
- const token = config3.token;
2929
+ const { config: config2 } = configManager;
2930
+ const token = config2.token;
2783
2931
  const remoteSchema = await fetchRemoteGraphqlSchema({
2784
2932
  url: apiURL,
2785
2933
  token
@@ -2789,16 +2937,16 @@ ${dangerText(e.message)}
2789
2937
  prog: "\u274C"
2790
2938
  });
2791
2939
  let errorMessage = `The remote GraphQL schema does not exist. Check indexing for this branch.`;
2792
- if (config3 == null ? void 0 : config3.branch) {
2940
+ if (config2 == null ? void 0 : config2.branch) {
2793
2941
  errorMessage += `
2794
2942
 
2795
- Additional info: Branch: ${config3.branch}, Client ID: ${config3.clientId} `;
2943
+ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
2796
2944
  }
2797
2945
  throw new Error(errorMessage);
2798
2946
  }
2799
- const remoteGqlSchema = (0, import_graphql11.buildClientSchema)(remoteSchema);
2947
+ const remoteGqlSchema = (0, import_graphql12.buildClientSchema)(remoteSchema);
2800
2948
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
2801
- const localGraphqlSchema = (0, import_graphql11.buildASTSchema)(localSchemaDocument);
2949
+ const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
2802
2950
  try {
2803
2951
  const diffResult = await (0, import_core2.diff)(localGraphqlSchema, remoteGqlSchema);
2804
2952
  if (diffResult.length === 0) {
@@ -2809,11 +2957,11 @@ Additional info: Branch: ${config3.branch}, Client ID: ${config3.clientId} `;
2809
2957
  bar2.tick({
2810
2958
  prog: "\u274C"
2811
2959
  });
2812
- 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.`;
2813
- if (config3 == null ? void 0 : config3.branch) {
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.`;
2961
+ if (config2 == null ? void 0 : config2.branch) {
2814
2962
  errorMessage += `
2815
2963
 
2816
- Additional info: Branch: ${config3.branch}, Client ID: ${config3.clientId} `;
2964
+ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
2817
2965
  }
2818
2966
  throw new Error(errorMessage);
2819
2967
  }
@@ -2883,7 +3031,7 @@ var fetchRemoteGraphqlSchema = async ({
2883
3031
  if (token) {
2884
3032
  headers.append("X-API-KEY", token);
2885
3033
  }
2886
- const body = JSON.stringify({ query: (0, import_graphql11.getIntrospectionQuery)(), variables: {} });
3034
+ const body = JSON.stringify({ query: (0, import_graphql12.getIntrospectionQuery)(), variables: {} });
2887
3035
  headers.append("Content-Type", "application/json");
2888
3036
  const res = await (0, import_node_fetch2.default)(url, {
2889
3037
  method: "POST",
@@ -2896,12 +3044,12 @@ var fetchRemoteGraphqlSchema = async ({
2896
3044
 
2897
3045
  // src/next/commands/audit-command/index.ts
2898
3046
  var import_clipanion4 = require("clipanion");
2899
- var import_graphql13 = require("@tinacms/graphql");
3047
+ var import_graphql14 = require("@tinacms/graphql");
2900
3048
 
2901
3049
  // src/next/commands/audit-command/audit.ts
2902
3050
  var import_prompts = __toESM(require("prompts"));
2903
3051
  var import_metrics = require("@tinacms/metrics");
2904
- var import_graphql12 = require("@tinacms/graphql");
3052
+ var import_graphql13 = require("@tinacms/graphql");
2905
3053
  var import_chalk5 = __toESM(require("chalk"));
2906
3054
  var audit = async ({
2907
3055
  database,
@@ -2986,7 +3134,7 @@ var auditDocuments = async (args) => {
2986
3134
  }
2987
3135
  }
2988
3136
  }`;
2989
- const docResult = await (0, import_graphql12.resolve)({
3137
+ const docResult = await (0, import_graphql13.resolve)({
2990
3138
  database,
2991
3139
  query: documentQuery,
2992
3140
  variables: {},
@@ -3027,7 +3175,7 @@ var auditDocuments = async (args) => {
3027
3175
  params: $params
3028
3176
  ){__typename}
3029
3177
  }`;
3030
- const mutationRes = await (0, import_graphql12.resolve)({
3178
+ const mutationRes = await (0, import_graphql13.resolve)({
3031
3179
  database,
3032
3180
  query: mutation,
3033
3181
  variables: {
@@ -3059,7 +3207,7 @@ function filterObject(obj) {
3059
3207
  }
3060
3208
 
3061
3209
  // src/next/commands/audit-command/index.ts
3062
- var import_graphql14 = require("@tinacms/graphql");
3210
+ var import_graphql15 = require("@tinacms/graphql");
3063
3211
  var AuditCommand = class extends import_clipanion4.Command {
3064
3212
  constructor() {
3065
3213
  super(...arguments);
@@ -3102,9 +3250,9 @@ var AuditCommand = class extends import_clipanion4.Command {
3102
3250
  const database = await createAndInitializeDatabase(
3103
3251
  configManager,
3104
3252
  Number(this.datalayerPort),
3105
- this.clean ? void 0 : new import_graphql14.AuditFileSystemBridge(configManager.rootPath)
3253
+ this.clean ? void 0 : new import_graphql15.AuditFileSystemBridge(configManager.rootPath)
3106
3254
  );
3107
- const { tinaSchema, graphQLSchema, lookup } = await (0, import_graphql13.buildSchema)(
3255
+ const { tinaSchema, graphQLSchema, lookup } = await (0, import_graphql14.buildSchema)(
3108
3256
  configManager.config
3109
3257
  );
3110
3258
  const warnings = [];
@@ -3144,373 +3292,744 @@ AuditCommand.usage = import_clipanion4.Command.Usage({
3144
3292
  // src/next/commands/init-command/index.ts
3145
3293
  var import_clipanion6 = require("clipanion");
3146
3294
 
3147
- // src/cmds/init/index.ts
3148
- var import_path11 = __toESM(require("path"));
3149
- var import_prettier2 = require("prettier");
3150
- var import_fs_extra11 = __toESM(require("fs-extra"));
3151
- var import_prompts2 = __toESM(require("prompts"));
3152
- var import_metrics2 = require("@tinacms/metrics");
3153
-
3154
- // src/cmds/init/setup-files/index.ts
3155
- var nextPostPage = ({
3156
- usingSrc
3157
- }) => `// THIS FILE HAS BEEN GENERATED WITH THE TINA CLI.
3158
- // This is a demo file once you have tina setup feel free to delete this file
3159
-
3160
- import Head from 'next/head'
3161
- import { useTina } from 'tinacms/dist/react'
3162
- import { TinaMarkdown } from 'tinacms/dist/rich-text'
3163
- import client from '${usingSrc ? "../" : ""}../../../tina/__generated__/client'
3164
-
3165
- const BlogPage = (props) => {
3166
- const { data } = useTina({
3167
- query: props.query,
3168
- variables: props.variables,
3169
- data: props.data,
3170
- })
3171
-
3172
- return (
3173
- <>
3174
- <Head>
3175
- {/* Tailwind CDN */}
3176
- <link
3177
- rel="stylesheet"
3178
- href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.7/tailwind.min.css"
3179
- integrity="sha512-y6ZMKFUQrn+UUEVoqYe8ApScqbjuhjqzTuwUMEGMDuhS2niI8KA3vhH2LenreqJXQS+iIXVTRL2iaNfJbDNA1Q=="
3180
- crossOrigin="anonymous"
3181
- referrerPolicy="no-referrer"
3182
- />
3183
- </Head>
3184
- <div>
3185
- <div
3186
- style={{
3187
- textAlign: 'center',
3188
- }}
3189
- >
3190
- <h1 className="text-3xl m-8 text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
3191
- {data.post.title}
3192
- </h1>
3193
- <ContentSection content={data.post.body}></ContentSection>
3194
- </div>
3195
- <div className="bg-green-100 text-center">
3196
- Lost and looking for a place to start?
3197
- <a
3198
- href="https://tina.io/guides/tina-cloud/getting-started/overview/"
3199
- className="text-blue-500 underline"
3200
- >
3201
- {' '}
3202
- Check out this guide
3203
- </a>{' '}
3204
- to see how add TinaCMS to an existing Next.js site.
3205
- </div>
3206
- </div>
3207
- </>
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" }
3208
3389
  )
3209
- }
3210
-
3211
- export const getStaticProps = async ({ params }) => {
3212
- let data = {}
3213
- let query = {}
3214
- 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) {
3215
3395
  try {
3216
- const res = await client.queries.post(variables)
3217
- query = res.query
3218
- data = res.data
3219
- variables = res.variables
3220
- } catch {
3221
- // swallow errors related to document creation
3222
- }
3223
-
3224
- return {
3225
- props: {
3226
- variables: variables,
3227
- data: data,
3228
- query: query,
3229
- //myOtherProp: 'some-other-data',
3230
- },
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
+ );
3231
3411
  }
3232
3412
  }
3233
-
3234
- export const getStaticPaths = async () => {
3235
- const postsListData = await client.queries.postConnection()
3236
-
3237
- return {
3238
- paths: postsListData.data.postConnection.edges.map((post) => ({
3239
- params: { filename: post.node._sys.filename },
3240
- })),
3241
- 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
+ }
3242
3426
  }
3243
3427
  }
3244
-
3245
- export default BlogPage
3246
-
3247
- const PageSection = (props) => {
3248
- return (
3249
- <>
3250
- <h2>{props.heading}</h2>
3251
- <p>{props.content}</p>
3252
- </>
3253
- )
3254
- }
3255
-
3256
- const components = {
3257
- PageSection: PageSection,
3258
- }
3259
-
3260
- const ContentSection = ({ content }) => {
3261
- return (
3262
- <div className="relative py-16 bg-white overflow-hidden">
3263
- <div className="hidden lg:block lg:absolute lg:inset-y-0 lg:h-full lg:w-full">
3264
- <div
3265
- className="relative h-full text-lg max-w-prose mx-auto"
3266
- aria-hidden="true"
3267
- >
3268
- <svg
3269
- className="absolute top-12 left-full transform translate-x-32"
3270
- width={404}
3271
- height={384}
3272
- fill="none"
3273
- viewBox="0 0 404 384"
3274
- >
3275
- <defs>
3276
- <pattern
3277
- id="74b3fd99-0a6f-4271-bef2-e80eeafdf357"
3278
- x={0}
3279
- y={0}
3280
- width={20}
3281
- height={20}
3282
- patternUnits="userSpaceOnUse"
3283
- >
3284
- <rect
3285
- x={0}
3286
- y={0}
3287
- width={4}
3288
- height={4}
3289
- className="text-gray-200"
3290
- fill="currentColor"
3291
- />
3292
- </pattern>
3293
- </defs>
3294
- <rect
3295
- width={404}
3296
- height={384}
3297
- fill="url(#74b3fd99-0a6f-4271-bef2-e80eeafdf357)"
3298
- />
3299
- </svg>
3300
- <svg
3301
- className="absolute top-1/2 right-full transform -translate-y-1/2 -translate-x-32"
3302
- width={404}
3303
- height={384}
3304
- fill="none"
3305
- viewBox="0 0 404 384"
3306
- >
3307
- <defs>
3308
- <pattern
3309
- id="f210dbf6-a58d-4871-961e-36d5016a0f49"
3310
- x={0}
3311
- y={0}
3312
- width={20}
3313
- height={20}
3314
- patternUnits="userSpaceOnUse"
3315
- >
3316
- <rect
3317
- x={0}
3318
- y={0}
3319
- width={4}
3320
- height={4}
3321
- className="text-gray-200"
3322
- fill="currentColor"
3323
- />
3324
- </pattern>
3325
- </defs>
3326
- <rect
3327
- width={404}
3328
- height={384}
3329
- fill="url(#f210dbf6-a58d-4871-961e-36d5016a0f49)"
3330
- />
3331
- </svg>
3332
- <svg
3333
- className="absolute bottom-12 left-full transform translate-x-32"
3334
- width={404}
3335
- height={384}
3336
- fill="none"
3337
- viewBox="0 0 404 384"
3338
- >
3339
- <defs>
3340
- <pattern
3341
- id="d3eb07ae-5182-43e6-857d-35c643af9034"
3342
- x={0}
3343
- y={0}
3344
- width={20}
3345
- height={20}
3346
- patternUnits="userSpaceOnUse"
3347
- >
3348
- <rect
3349
- x={0}
3350
- y={0}
3351
- width={4}
3352
- height={4}
3353
- className="text-gray-200"
3354
- fill="currentColor"
3355
- />
3356
- </pattern>
3357
- </defs>
3358
- <rect
3359
- width={404}
3360
- height={384}
3361
- fill="url(#d3eb07ae-5182-43e6-857d-35c643af9034)"
3362
- />
3363
- </svg>
3364
- </div>
3365
- </div>
3366
- <div className="relative px-4 sm:px-6 lg:px-8">
3367
- <div className="text-lg max-w-prose mx-auto">
3368
- <TinaMarkdown components={components} content={content} />
3369
- </div>
3370
- </div>
3371
- </div>
3372
- )
3373
- }`;
3374
-
3375
- // src/utils/script-helpers.ts
3376
- function generateGqlScript(scriptValue) {
3377
- return `tinacms dev -c "${scriptValue}"`;
3378
- }
3379
- function extendNextScripts(scripts) {
3380
- return {
3381
- ...scripts,
3382
- dev: generateGqlScript((scripts == null ? void 0 : scripts.dev) || "next dev"),
3383
- build: `tinacms build && ${(scripts == null ? void 0 : scripts.build) || "next build"}`,
3384
- 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
3385
3442
  };
3386
- }
3387
-
3388
- // src/cmds/init/setup-files/config.ts
3389
- var clientConfig = (isForestryMigration) => {
3390
- if (isForestryMigration) {
3391
- return "client: {skip: true},";
3443
+ if (debug) {
3444
+ console.log("Environment:");
3445
+ console.log(JSON.stringify(env, null, 2));
3392
3446
  }
3393
- return "";
3447
+ return env;
3394
3448
  };
3395
- var other = (args) => {
3396
- return `
3397
- import { defineConfig } from "tinacms";
3398
- ${args.extraText || ""}
3449
+ var detectEnvironment_default = detectEnvironment;
3399
3450
 
3400
- // Your hosting provider likely exposes this as an environment variable
3401
- 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"));
3402
3453
 
3403
- export default defineConfig({
3404
- branch,
3405
- clientId: ${args.clientId ? `'${args.clientId}'` : "null"}, // Get this from tina.io
3406
- token: ${args.token ? `'${args.token}'` : "null"}, // Get this from tina.io
3407
- ${clientConfig(args.isForestryMigration)}
3408
- build: {
3409
- outputFolder: "admin",
3410
- 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
3411
3465
  },
3412
- media: {
3413
- tina: {
3414
- mediaRoot: "",
3415
- 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
3416
3482
  },
3417
- },
3418
- schema: {
3419
- 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: [
3420
3495
  {
3421
- name: "post",
3422
- label: "Posts",
3423
- path: "content/posts",
3424
- fields: [
3425
- {
3426
- type: "string",
3427
- name: "title",
3428
- label: "Title",
3429
- isTitle: true,
3430
- required: true,
3431
- },
3432
- {
3433
- type: "rich-text",
3434
- name: "body",
3435
- label: "Body",
3436
- isBody: true,
3437
- },
3438
- ],
3439
- },
3440
- ]`},
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
+ })`
3441
3507
  },
3442
- });
3443
- `;
3508
+ other: {
3509
+ gitProviderClassText: ""
3510
+ }
3444
3511
  };
3445
- var configExamples = {
3446
- next: (args) => `import { defineConfig } from 'tinacms'
3447
-
3448
- // Your hosting provider likely exposes this as an environment variable
3449
- const branch = process.env.HEAD || process.env.VERCEL_GIT_COMMIT_REF || 'main'
3450
-
3451
- export default defineConfig({
3452
- branch,
3453
- clientId: ${args.clientId ? `'${args.clientId}'` : "null"}, // Get this from tina.io
3454
- token: ${args.token ? `'${args.token}'` : "null"}, // Get this from tina.io
3455
- ${clientConfig(args.isForestryMigration)}
3456
- build: {
3457
- outputFolder: "admin",
3458
- 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
3459
3524
  },
3460
- media: {
3461
- tina: {
3462
- mediaRoot: "",
3463
- publicFolder: "${args.publicFolder}",
3464
- },
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
+ `
3465
3531
  },
3466
- schema: {
3467
- collections:${args.collections || `[
3468
- {
3469
- name: 'post',
3470
- label: 'Posts',
3471
- path: 'content/posts',
3472
- fields: [
3473
- {
3474
- type: 'string',
3475
- name: 'title',
3476
- label: 'Title',
3477
- isTitle: true,
3478
- required: true,
3479
- },
3480
- {
3481
- type: 'rich-text',
3482
- name: 'body',
3483
- label: 'Body',
3484
- isBody: true,
3485
- },
3486
- ],
3487
- ui: {
3488
- // This is an DEMO router. You can remove this to fit your site
3489
- router: ({ document }) => \`/demo/blog/\${document._sys.filename}\`,
3490
- },
3491
- },
3492
- ]`},
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
3493
3544
  },
3494
- })
3495
- `,
3496
- other,
3497
- hugo: other,
3498
- 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;
3499
3555
  };
3500
3556
 
3501
- // src/cmds/forestry-migrate/index.ts
3502
- var import_fs_extra9 = __toESM(require("fs-extra"));
3503
- var import_path9 = __toESM(require("path"));
3504
- var import_js_yaml2 = __toESM(require("js-yaml"));
3505
- var import_minimatch = __toESM(require("minimatch"));
3506
- var import_graphql15 = require("@tinacms/graphql");
3507
-
3508
- // src/cmds/forestry-migrate/util/index.ts
3509
- var import_fs_extra8 = __toESM(require("fs-extra"));
3510
- var import_path8 = __toESM(require("path"));
3511
- var import_js_yaml = __toESM(require("js-yaml"));
3512
- var import_zod = __toESM(require("zod"));
3513
-
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: ""
3592
+ }
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
+
3514
4033
  // src/cmds/forestry-migrate/util/errorSingleton.ts
3515
4034
  var ErrorSingleton = class {
3516
4035
  constructor() {
@@ -3851,7 +4370,7 @@ var transformForestryFieldsToTinaFields = ({
3851
4370
  if (skipBlocks) {
3852
4371
  break;
3853
4372
  }
3854
- const templates = [];
4373
+ const templates2 = [];
3855
4374
  forestryField2 == null ? void 0 : forestryField2.template_types.forEach((tem) => {
3856
4375
  const { template: template2 } = getFieldsFromTemplates({
3857
4376
  tem,
@@ -3871,7 +4390,7 @@ var transformForestryFieldsToTinaFields = ({
3871
4390
  ;
3872
4391
  t.nameOverride = tem;
3873
4392
  }
3874
- templates.push(t);
4393
+ templates2.push(t);
3875
4394
  });
3876
4395
  field = {
3877
4396
  type: "object",
@@ -3879,7 +4398,7 @@ var transformForestryFieldsToTinaFields = ({
3879
4398
  templateKey: "template",
3880
4399
  label: forestryField2.label,
3881
4400
  ...getTinaFieldsFromName(forestryField2.name),
3882
- templates
4401
+ templates: templates2
3883
4402
  };
3884
4403
  break;
3885
4404
  }
@@ -3918,7 +4437,7 @@ var transformForestryFieldsToTinaFields = ({
3918
4437
  return tinaFields;
3919
4438
  };
3920
4439
  var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false }) => {
3921
- const templatePath = import_path8.default.join(
4440
+ const templatePath = import_path9.default.join(
3922
4441
  pathToForestryConfig,
3923
4442
  ".forestry",
3924
4443
  "front_matter",
@@ -3927,7 +4446,7 @@ var getFieldsFromTemplates = ({ tem, pathToForestryConfig, skipBlocks = false })
3927
4446
  );
3928
4447
  let templateString = "";
3929
4448
  try {
3930
- templateString = import_fs_extra8.default.readFileSync(templatePath).toString();
4449
+ templateString = import_fs_extra9.default.readFileSync(templatePath).toString();
3931
4450
  } catch {
3932
4451
  throw new Error(
3933
4452
  `Could not find template ${tem} at ${templatePath}
@@ -3992,9 +4511,9 @@ function checkExt(ext) {
3992
4511
  var generateAllTemplates = async ({
3993
4512
  pathToForestryConfig
3994
4513
  }) => {
3995
- const allTemplates = (await import_fs_extra9.default.readdir(
3996
- import_path9.default.join(pathToForestryConfig, ".forestry", "front_matter", "templates")
3997
- )).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"));
3998
4517
  const templateMap = /* @__PURE__ */ new Map();
3999
4518
  const proms = allTemplates.map(async (tem) => {
4000
4519
  try {
@@ -4136,9 +4655,9 @@ var generateCollectionFromForestrySection = (args) => {
4136
4655
  return c;
4137
4656
  } else if (section.type === "document") {
4138
4657
  const filePath = section.path;
4139
- const extname = import_path9.default.extname(filePath);
4140
- const fileName = import_path9.default.basename(filePath, extname);
4141
- 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);
4142
4661
  const ext = checkExt(extname);
4143
4662
  if (ext) {
4144
4663
  const fields = [];
@@ -4200,8 +4719,8 @@ var generateCollections = async ({
4200
4719
  templateMap,
4201
4720
  usingTypescript
4202
4721
  });
4203
- const forestryConfig = await import_fs_extra9.default.readFile(
4204
- 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")
4205
4724
  );
4206
4725
  rewriteTemplateKeysInDocs({
4207
4726
  templateMap,
@@ -4232,13 +4751,13 @@ var rewriteTemplateKeysInDocs = (args) => {
4232
4751
  const { templateObj } = templateMap.get(templateKey);
4233
4752
  (_a = templateObj == null ? void 0 : templateObj.pages) == null ? void 0 : _a.forEach((page) => {
4234
4753
  try {
4235
- const filePath = import_path9.default.join(page);
4236
- 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()) {
4237
4756
  return;
4238
4757
  }
4239
- const extname = import_path9.default.extname(filePath);
4240
- const fileContent = import_fs_extra9.default.readFileSync(filePath).toString();
4241
- 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)(
4242
4761
  fileContent,
4243
4762
  extname,
4244
4763
  (yup) => yup.object({}),
@@ -4246,11 +4765,11 @@ var rewriteTemplateKeysInDocs = (args) => {
4246
4765
  );
4247
4766
  const newContent = {
4248
4767
  _template: stringifyLabel(templateKey),
4249
- ...content2
4768
+ ...content
4250
4769
  };
4251
- import_fs_extra9.default.writeFileSync(
4770
+ import_fs_extra10.default.writeFileSync(
4252
4771
  filePath,
4253
- (0, import_graphql15.stringifyFile)(newContent, extname, true, markdownParseConfig)
4772
+ (0, import_graphql16.stringifyFile)(newContent, extname, true, markdownParseConfig)
4254
4773
  );
4255
4774
  } catch (error) {
4256
4775
  console.log(
@@ -4261,10 +4780,14 @@ var rewriteTemplateKeysInDocs = (args) => {
4261
4780
  }
4262
4781
  };
4263
4782
 
4783
+ // src/cmds/init/apply.ts
4784
+ var import_metrics2 = require("@tinacms/metrics");
4785
+ var import_fs_extra13 = __toESM(require("fs-extra"));
4786
+
4264
4787
  // src/next/commands/codemod-command/index.ts
4265
4788
  var import_clipanion5 = require("clipanion");
4266
- var import_fs_extra10 = __toESM(require("fs-extra"));
4267
- var import_path10 = __toESM(require("path"));
4789
+ var import_fs_extra11 = __toESM(require("fs-extra"));
4790
+ var import_path11 = __toESM(require("path"));
4268
4791
  var CodemodCommand = class extends import_clipanion5.Command {
4269
4792
  constructor() {
4270
4793
  super(...arguments);
@@ -4287,12 +4810,12 @@ var CodemodCommand = class extends import_clipanion5.Command {
4287
4810
  process.exit(1);
4288
4811
  }
4289
4812
  const mods = { "move-tina-folder": () => moveTinaFolder(this.rootPath) };
4290
- const command = mods[mod];
4291
- if (!command) {
4813
+ const command2 = mods[mod];
4814
+ if (!command2) {
4292
4815
  logger.error(`Mod not found for ${mod}`);
4293
4816
  process.exit(1);
4294
4817
  }
4295
- await command();
4818
+ await command2();
4296
4819
  }
4297
4820
  };
4298
4821
  CodemodCommand.paths = [["codemod"], ["codemod", "move-tina-folder"]];
@@ -4308,13 +4831,13 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
4308
4831
  logger.error(e.message);
4309
4832
  process.exit(1);
4310
4833
  }
4311
- const tinaDestination = import_path10.default.join(configManager.rootPath, "tina");
4312
- 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)) {
4313
4836
  logger.info(
4314
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.`
4315
4838
  );
4316
4839
  } else {
4317
- await import_fs_extra10.default.moveSync(configManager.tinaFolderPath, tinaDestination);
4840
+ await import_fs_extra11.default.moveSync(configManager.tinaFolderPath, tinaDestination);
4318
4841
  await writeGitignore(configManager.rootPath);
4319
4842
  logger.info(
4320
4843
  "Move to 'tina' folder complete. Be sure to update any imports of the autogenerated client!"
@@ -4322,208 +4845,870 @@ var moveTinaFolder = async (rootPath = process.cwd()) => {
4322
4845
  }
4323
4846
  };
4324
4847
  var writeGitignore = async (rootPath) => {
4325
- await import_fs_extra10.default.outputFileSync(
4326
- import_path10.default.join(rootPath, "tina", ".gitignore"),
4848
+ await import_fs_extra11.default.outputFileSync(
4849
+ import_path11.default.join(rootPath, "tina", ".gitignore"),
4327
4850
  "__generated__"
4328
4851
  );
4329
4852
  };
4330
4853
 
4331
- // src/cmds/init/index.ts
4332
- async function initStaticTina({
4333
- rootPath,
4334
- pathToForestryConfig,
4335
- noTelemetry
4336
- }) {
4337
- logger.level = "info";
4338
- process.chdir(rootPath);
4339
- const clientId = await chooseClientId();
4340
- let token = null;
4341
- if (clientId) {
4342
- token = await chooseToken({ clientId });
4343
- }
4344
- const packageManager = await choosePackageManager();
4345
- const framework = await chooseFramework();
4346
- const usingTypescript = await chooseTypescript();
4347
- const publicFolder = await choosePublicFolder({ framework });
4348
- let collections;
4349
- let templateCode;
4350
- let extraText;
4351
- const hasForestryConfig = await import_fs_extra11.default.pathExists(
4352
- import_path11.default.join(pathToForestryConfig, ".forestry", "settings.yml")
4353
- );
4354
- let isForestryMigration = false;
4355
- if (hasForestryConfig) {
4356
- const res = await forestryMigrate({
4357
- usingTypescript,
4358
- pathToForestryConfig,
4359
- rootPath,
4360
- framework
4361
- });
4362
- if (res) {
4363
- templateCode = res.templateCodeString;
4364
- collections = res.collectionString;
4365
- extraText = res.importStatements;
4366
- isForestryMigration = true;
4367
- }
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
4368
4926
  }
4369
- await reportTelemetry({
4370
- usingTypescript,
4371
- hasForestryConfig,
4372
- noTelemetry
4373
- });
4374
- const hasPackageJSON = await import_fs_extra11.default.pathExistsSync("package.json");
4375
- if (!hasPackageJSON) {
4376
- await createPackageJSON();
4927
+
4928
+ return {
4929
+ props: {
4930
+ variables: variables,
4931
+ data: data,
4932
+ query: query,
4933
+ //myOtherProp: 'some-other-data',
4934
+ },
4377
4935
  }
4378
- const hasGitignore = await import_fs_extra11.default.pathExistsSync(".gitignore");
4379
- if (!hasGitignore) {
4380
- await createGitignore({ baseDir: "" });
4381
- } else {
4382
- const hasNodeModulesIgnored = await checkGitignoreForNodeModules({
4383
- baseDir: ""
4384
- });
4385
- if (!hasNodeModulesIgnored) {
4386
- await addNodeModulesToGitignore({ baseDir: "" });
4387
- }
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
+ `;
4388
5079
  }
4389
- await addDependencies(packageManager);
5080
+ };
5081
+
5082
+ // src/cmds/init/templates/config.ts
5083
+ var clientConfig = (isForestryMigration) => {
4390
5084
  if (isForestryMigration) {
4391
- await addTemplateFile({ baseDir: "", usingTypescript, templateCode });
5085
+ return "client: {skip: true},";
4392
5086
  }
4393
- await addConfigFile({
4394
- publicFolder: import_path11.default.join(
4395
- import_path11.default.relative(process.cwd(), pathToForestryConfig),
4396
- publicFolder
4397
- ),
4398
- baseDir: "",
4399
- usingTypescript,
4400
- framework,
4401
- collections,
4402
- token,
4403
- clientId,
4404
- isForestryMigration,
4405
- extraText
4406
- });
4407
- if (!hasForestryConfig) {
4408
- await addContentFile({ baseDir: "" });
4409
- }
4410
- if (framework.reactive) {
4411
- await addReactiveFile[framework.name]({
4412
- baseDir: "",
4413
- framework,
4414
- usingTypescript
4415
- });
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;
4416
5135
  }
4417
- logNextSteps({ packageManager, framework });
4418
- }
4419
- var chooseClientId = async () => {
4420
- const option = await (0, import_prompts2.default)({
4421
- name: "clientId",
4422
- type: "text",
4423
- message: `What is your Tina Cloud Client ID? (Hit enter to skip and set up yourself later)
4424
- ${logText(
4425
- "Don't have a Client ID? Create one here: "
4426
- )}${linkText("https://app.tina.io/projects/new")}`
4427
- });
4428
- return option["clientId"];
5136
+ return baseCollections;
4429
5137
  };
4430
- var chooseToken = async ({ clientId }) => {
4431
- const option = await (0, import_prompts2.default)({
4432
- name: "token",
4433
- type: "text",
4434
- message: `What is your Tina Cloud Read Only Token?
4435
- ${logText(
4436
- "Don't have a Read Only Token? Create one here: "
4437
- )}${linkText(`https://app.tina.io/projects/${clientId}/tokens`)}`
4438
- });
4439
- 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
+ `;
4440
5190
  };
4441
- var choosePackageManager = async () => {
4442
- const option = await (0, import_prompts2.default)({
4443
- name: "selection",
4444
- type: "select",
4445
- message: "Choose your package manager",
4446
- choices: [
4447
- { title: "PNPM", value: "pnpm" },
4448
- { title: "Yarn", value: "yarn" },
4449
- { title: "NPM", value: "npm" }
4450
- ]
4451
- });
4452
- 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
+ `;
4453
5215
  };
4454
- var chooseTypescript = async () => {
4455
- const option = await (0, import_prompts2.default)({
4456
- name: "selection",
4457
- type: "confirm",
4458
- initial: true,
4459
- message: "Would you like to use Typescript for your Tina Configuration (Recommended)?"
4460
- });
4461
- 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
+ }`;
4462
5244
  };
4463
- var choosePublicFolder = async ({ framework }) => {
4464
- let suggestion = "public";
4465
- switch (framework.name) {
4466
- case "next":
4467
- return "public";
4468
- case "hugo":
4469
- return "static";
4470
- case "jekyll":
4471
- suggestion = "public";
4472
- break;
4473
- }
4474
- const option = await (0, import_prompts2.default)({
4475
- name: "selection",
4476
- type: "text",
4477
- message: `Where are public assets stored? (default: "${suggestion}")
4478
- ` + logText(
4479
- `Not sure what value to use? Refer to our "Frameworks" doc: ${linkText(
4480
- "https://tina.io/docs/integration/frameworks/#configuring-tina-with-each-framework"
4481
- )}`
4482
- )
4483
- });
4484
- 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
+ }
4485
5356
  };
4486
- var chooseFramework = async () => {
4487
- const option = await (0, import_prompts2.default)({
4488
- name: "selection",
4489
- type: "select",
4490
- message: "What framework are you using?",
4491
- choices: [
4492
- { title: "Next.js", value: { name: "next", reactive: true } },
4493
- { title: "Hugo", value: { name: "hugo", reactive: false } },
4494
- { title: "Jekyll", value: { name: "jekyll", reactive: false } },
4495
- {
4496
- title: "Other (SSG frameworks like gatsby, etc.)",
4497
- 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
+ }
4498
5397
  }
4499
- ]
4500
- });
4501
- 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
+ }
4502
5425
  };
4503
- var forestryMigrate = async ({
4504
- pathToForestryConfig,
4505
- usingTypescript,
4506
- rootPath,
4507
- framework
4508
- }) => {
4509
- logger.info(`Forestry.io configuration found.`);
4510
- const disclaimer = logText(
4511
- `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
4512
5519
  );
4513
- const option = await (0, import_prompts2.default)({
4514
- name: "selection",
4515
- type: "confirm",
4516
- initial: true,
4517
- message: `Would you like to migrate your Forestry templates?
4518
- ${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
4519
5606
  });
4520
- if (!option["selection"]) {
4521
- return null;
5607
+ if (!env.packageJSONExists) {
5608
+ await createPackageJSON();
4522
5609
  }
4523
- let frontMatterFormat = null;
4524
- if (framework.name === "hugo") {
4525
- 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
+ });
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
+ });
4526
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
+ }) => {
4527
5712
  const { collections, importStatements, templateCode } = await generateCollections({
4528
5713
  pathToForestryConfig,
4529
5714
  usingTypescript,
@@ -4537,32 +5722,6 @@ ${disclaimer}`
4537
5722
  templateCodeString: templateCode
4538
5723
  };
4539
5724
  };
4540
- var getFrontmatterFormat = async (rootPath) => {
4541
- try {
4542
- const hugoConfigPath = import_path11.default.join(rootPath, "config.toml");
4543
- const hugoConfig = await import_fs_extra11.default.readFile(hugoConfigPath, "utf8");
4544
- const frontMatterFormat = hugoConfig.match(/metaDataFormat = "(.*)"/);
4545
- console.log({ frontMatterFormat });
4546
- if (frontMatterFormat && frontMatterFormat[1]) {
4547
- return frontMatterFormat[1];
4548
- }
4549
- } catch (e) {
4550
- }
4551
- const option = await (0, import_prompts2.default)({
4552
- name: "selection",
4553
- type: "select",
4554
- choices: [
4555
- { title: "yaml", value: "yaml" },
4556
- { title: "toml", value: "toml" },
4557
- { title: "json", value: "json" }
4558
- ],
4559
- message: `What format are you using in your frontmatter?`
4560
- });
4561
- if (!option["selection"]) {
4562
- return null;
4563
- }
4564
- return option["selection"];
4565
- };
4566
5725
  var reportTelemetry = async ({
4567
5726
  hasForestryConfig,
4568
5727
  noTelemetry,
@@ -4587,188 +5746,299 @@ var createPackageJSON = async () => {
4587
5746
  };
4588
5747
  var createGitignore = async ({ baseDir }) => {
4589
5748
  logger.info(logText("No .gitignore found, creating one"));
4590
- 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");
4591
5750
  };
4592
- var checkGitignoreForNodeModules = async ({
4593
- baseDir
5751
+ var updateGitIgnore = async ({
5752
+ baseDir,
5753
+ items
4594
5754
  }) => {
4595
- const gitignoreContent = await import_fs_extra11.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
4596
- return gitignoreContent.split("\n").some((item) => item === "node_modules");
4597
- };
4598
- var addNodeModulesToGitignore = async ({ baseDir }) => {
4599
- logger.info(logText("Adding node_modules to .gitignore"));
4600
- const gitignoreContent = await import_fs_extra11.default.readFileSync(import_path11.default.join(baseDir, ".gitignore")).toString();
4601
- const newGitignoreContent = [
4602
- ...gitignoreContent.split("\n"),
4603
- "node_modules"
4604
- ].join("\n");
4605
- 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);
4606
5761
  };
4607
- var addDependencies = async (packageManager) => {
4608
- logger.info(logText("Adding dependencies, this might take a moment..."));
4609
- const deps = ["tinacms", "@tinacms/cli"];
4610
- 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 = {
4611
5800
  pnpm: process.env.USE_WORKSPACE ? `pnpm add ${deps.join(" ")} --workspace` : `pnpm add ${deps.join(" ")}`,
4612
5801
  npm: `npm install ${deps.join(" ")}`,
4613
5802
  yarn: `yarn add ${deps.join(" ")}`
4614
5803
  };
4615
- logger.info(indentedCmd(`${logText(packageManagers[packageManager])}`));
4616
- await execShellCommand(packageManagers[packageManager]);
4617
- };
4618
- var addConfigFile = async (args) => {
4619
- const { baseDir, usingTypescript } = args;
4620
- const configPath = import_path11.default.join(
4621
- "tina",
4622
- `config.${usingTypescript ? "ts" : "js"}`
4623
- );
4624
- const fullConfigPath = import_path11.default.join(baseDir, configPath);
4625
- if (import_fs_extra11.default.pathExistsSync(fullConfigPath)) {
4626
- const override = await (0, import_prompts2.default)({
4627
- name: "selection",
4628
- type: "confirm",
4629
- message: `Found existing file at ${configPath}. Would you like to override?`
4630
- });
4631
- if (override["selection"]) {
4632
- logger.info(logText(`Overriding file at ${configPath}.`));
4633
- await import_fs_extra11.default.outputFileSync(fullConfigPath, config2(args));
4634
- } else {
4635
- 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]);
4636
5821
  }
4637
- } else {
4638
- logger.info(
4639
- logText(
4640
- `Adding config file at tina/config.${usingTypescript ? "ts" : "js"}`
4641
- )
4642
- );
4643
- await import_fs_extra11.default.outputFileSync(fullConfigPath, config2(args));
4644
- await writeGitignore(baseDir);
4645
5822
  }
4646
5823
  };
4647
- var addTemplateFile = async (args) => {
4648
- const { baseDir, usingTypescript, templateCode } = args;
4649
- const templatesPath = import_path11.default.join(
4650
- "tina",
4651
- `templates.${usingTypescript ? "ts" : "js"}`
4652
- );
4653
- const fullTemplatesPath = import_path11.default.join(baseDir, templatesPath);
4654
- if (import_fs_extra11.default.pathExistsSync(fullTemplatesPath)) {
4655
- const override = await (0, import_prompts2.default)({
4656
- name: "selection",
4657
- type: "confirm",
4658
- message: `Found existing file at ${templatesPath}. Would you like to override?`
4659
- });
4660
- if (override["selection"]) {
4661
- logger.info(logText(`Overriding file at ${templatesPath}.`));
4662
- 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);
4663
5835
  } else {
4664
- 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
+ );
4665
5841
  }
4666
5842
  } else {
4667
- logger.info(logText(`Adding template file at ${templatesPath}`));
4668
- 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);
4669
5846
  }
4670
5847
  };
4671
- var addContentFile = async ({ baseDir }) => {
4672
- const contentPath = import_path11.default.join("content", "posts", "hello-world.md");
4673
- const fullContentPath = import_path11.default.join(baseDir, contentPath);
4674
- if (import_fs_extra11.default.pathExistsSync(fullContentPath)) {
4675
- const override = await (0, import_prompts2.default)({
4676
- name: "selection",
4677
- type: "confirm",
4678
- message: `Found existing file at ${contentPath}. Would you like to override?`
4679
- });
4680
- if (override["selection"]) {
4681
- logger.info(logText(`Overriding file at ${contentPath}.`));
4682
- await import_fs_extra11.default.outputFileSync(fullContentPath, content);
4683
- } else {
4684
- logger.info(logText(`Not overriding file at ${contentPath}.`));
4685
- }
4686
- } else {
4687
- logger.info(logText(`Adding content file at ${contentPath}`));
4688
- 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);
4689
5867
  }
4690
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
+ };
4691
5937
  var logNextSteps = ({
5938
+ config: config2,
5939
+ dataLayer: _datalayer,
4692
5940
  framework,
4693
- packageManager
5941
+ packageManager,
5942
+ isBackend
4694
5943
  }) => {
4695
- 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(`
4696
5970
  ${titleText(" TinaCMS ")} has been initialized!`));
4697
- logger.info(
4698
- "To get started run: " + cmdText(frameworkDevCmds[framework.name]({ packageManager }))
4699
- );
4700
- logger.info(
4701
- `
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
+ `
4702
5979
  Once your site is running, access the CMS at ${linkText(
4703
- "<YourDevURL>/admin/index.html"
4704
- )}`
4705
- );
5980
+ "<YourDevURL>/admin/index.html"
5981
+ )}`
5982
+ );
5983
+ }
4706
5984
  };
4707
- var other2 = ({ packageManager }) => {
5985
+ var other = ({ packageManager }) => {
4708
5986
  const packageManagers = {
4709
5987
  pnpm: `pnpm`,
4710
5988
  npm: `npx`,
4711
5989
  yarn: `yarn`
4712
5990
  };
4713
- const installText = `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
4714
- return installText;
5991
+ return `${packageManagers[packageManager]} tinacms dev -c "<your dev command>"`;
4715
5992
  };
4716
5993
  var frameworkDevCmds = {
4717
- other: other2,
4718
- hugo: other2,
4719
- jekyll: other2,
5994
+ other,
5995
+ hugo: other,
5996
+ jekyll: other,
4720
5997
  next: ({ packageManager }) => {
4721
5998
  const packageManagers = {
4722
5999
  pnpm: `pnpm`,
4723
6000
  npm: `npm run`,
4724
6001
  yarn: `yarn`
4725
6002
  };
4726
- const installText = `${packageManagers[packageManager]} dev`;
4727
- return installText;
6003
+ return `${packageManagers[packageManager]} dev`;
4728
6004
  }
4729
6005
  };
4730
- var config2 = (args) => {
4731
- return (0, import_prettier2.format)(configExamples[args.framework.name](args), { parser: "babel" });
4732
- };
4733
- var content = `---
4734
- title: Hello, World!
4735
- ---
4736
-
4737
- ## Hello World!
4738
-
4739
- 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.
4740
-
4741
- 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.
4742
- `;
4743
6006
  var addReactiveFile = {
4744
- next: ({
6007
+ next: async ({
6008
+ generatedFile,
6009
+ config: config2,
6010
+ env,
4745
6011
  baseDir,
4746
- usingTypescript
6012
+ dataLayer
4747
6013
  }) => {
4748
- const usingSrc = !import_fs_extra11.default.pathExistsSync(import_path11.default.join(baseDir, "pages"));
4749
- const pagesPath = import_path11.default.join(baseDir, usingSrc ? "src" : "", "pages");
4750
- const packageJSONPath = import_path11.default.join(baseDir, "package.json");
4751
- const tinaBlogPagePath = import_path11.default.join(pagesPath, "demo", "blog");
4752
- const tinaBlogPagePathFile = import_path11.default.join(
4753
- tinaBlogPagePath,
4754
- `[filename].${usingTypescript ? "tsx" : "js"}`
4755
- );
4756
- if (!import_fs_extra11.default.pathExistsSync(tinaBlogPagePathFile)) {
4757
- import_fs_extra11.default.mkdirpSync(tinaBlogPagePath);
4758
- import_fs_extra11.default.writeFileSync(tinaBlogPagePathFile, nextPostPage({ usingSrc }));
4759
- }
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
+ });
4760
6027
  logger.info("Adding a nextjs example... \u2705");
4761
- const pack = JSON.parse(import_fs_extra11.default.readFileSync(packageJSONPath).toString());
4762
- const oldScripts = pack.scripts || {};
4763
- 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(
4764
6031
  {
4765
- ...pack,
4766
- 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
+ })
4767
6037
  },
4768
6038
  null,
4769
6039
  2
4770
6040
  );
4771
- import_fs_extra11.default.writeFileSync(packageJSONPath, newPack);
6041
+ import_fs_extra13.default.writeFileSync(packageJsonPath, updatedPackageJson);
4772
6042
  }
4773
6043
  };
4774
6044
  function execShellCommand(cmd) {
@@ -4782,6 +6052,40 @@ function execShellCommand(cmd) {
4782
6052
  });
4783
6053
  });
4784
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
+ });
4785
6089
 
4786
6090
  // src/next/commands/init-command/index.ts
4787
6091
  var InitCommand = class extends import_clipanion6.Command {
@@ -4793,9 +6097,15 @@ var InitCommand = class extends import_clipanion6.Command {
4793
6097
  this.rootPath = import_clipanion6.Option.String("--rootPath", {
4794
6098
  description: "Specify the root directory to run the CLI from (defaults to current working directory)"
4795
6099
  });
6100
+ this.debug = import_clipanion6.Option.Boolean("--debug", false, {
6101
+ description: "Enable debug logging"
6102
+ });
4796
6103
  this.noTelemetry = import_clipanion6.Option.Boolean("--noTelemetry", false, {
4797
6104
  description: "Disable anonymous telemetry that is collected"
4798
6105
  });
6106
+ this.tinaVersion = import_clipanion6.Option.String("--tinaVersion", {
6107
+ description: "Specify a version for tina dependencies"
6108
+ });
4799
6109
  }
4800
6110
  async catch(error) {
4801
6111
  logger.error("Error occured during tinacms init");
@@ -4803,16 +6113,20 @@ var InitCommand = class extends import_clipanion6.Command {
4803
6113
  process.exit(1);
4804
6114
  }
4805
6115
  async execute() {
6116
+ const isBackend = Boolean(this.path.find((x) => x === "backend"));
4806
6117
  const rootPath = this.rootPath || process.cwd();
4807
- await initStaticTina({
6118
+ await command.execute({
6119
+ isBackendInit: isBackend,
4808
6120
  rootPath,
4809
6121
  pathToForestryConfig: this.pathToForestryConfig || rootPath,
4810
- noTelemetry: this.noTelemetry
6122
+ noTelemetry: this.noTelemetry,
6123
+ debug: this.debug,
6124
+ tinaVersion: this.tinaVersion
4811
6125
  });
4812
6126
  process.exit();
4813
6127
  }
4814
6128
  };
4815
- InitCommand.paths = [["init"]];
6129
+ InitCommand.paths = [["init"], ["init", "backend"]];
4816
6130
  InitCommand.usage = import_clipanion6.Command.Usage({
4817
6131
  category: `Commands`,
4818
6132
  description: `Add Tina to an existing project`
@@ -4820,7 +6134,7 @@ InitCommand.usage = import_clipanion6.Command.Usage({
4820
6134
 
4821
6135
  // src/next/commands/searchindex-command/index.ts
4822
6136
  var import_clipanion7 = require("clipanion");
4823
- var import_graphql16 = require("@tinacms/graphql");
6137
+ var import_graphql17 = require("@tinacms/graphql");
4824
6138
  var import_search3 = require("@tinacms/search");
4825
6139
  var SearchIndexCommand = class extends import_clipanion7.Command {
4826
6140
  constructor() {
@@ -4854,7 +6168,7 @@ var SearchIndexCommand = class extends import_clipanion7.Command {
4854
6168
  process.exit(1);
4855
6169
  }
4856
6170
  const { schema } = configManager.config;
4857
- const tinaSchema = await (0, import_graphql16.createSchema)({
6171
+ const tinaSchema = await (0, import_graphql17.createSchema)({
4858
6172
  schema: { ...schema, config: configManager.config }
4859
6173
  });
4860
6174
  let client;
@@ -4893,7 +6207,7 @@ var SearchIndexCommand = class extends import_clipanion7.Command {
4893
6207
  }
4894
6208
  const searchIndexer = new import_search3.SearchIndexer({
4895
6209
  batchSize: ((_t = configManager.config.search) == null ? void 0 : _t.indexBatchSize) || 100,
4896
- bridge: new import_graphql16.FilesystemBridge(
6210
+ bridge: new import_graphql17.FilesystemBridge(
4897
6211
  configManager.rootPath,
4898
6212
  configManager.contentRootPath
4899
6213
  ),