@tinacms/cli 0.0.0-c852462-20250131014229 → 0.0.0-c965b5f-20250426163441

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
@@ -27,31 +27,24 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/index.ts
30
- var src_exports = {};
31
- __export(src_exports, {
32
- default: () => src_default
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ default: () => index_default
33
33
  });
34
- module.exports = __toCommonJS(src_exports);
34
+ module.exports = __toCommonJS(index_exports);
35
35
  var import_clipanion8 = require("clipanion");
36
36
 
37
37
  // package.json
38
- var version = "1.8.2";
38
+ var version = "1.9.5";
39
39
 
40
40
  // src/next/commands/dev-command/index.ts
41
- var import_clipanion2 = require("clipanion");
42
- var import_fs_extra6 = __toESM(require("fs-extra"));
43
41
  var import_path5 = __toESM(require("path"));
44
- var import_chokidar = __toESM(require("chokidar"));
45
42
  var import_graphql10 = require("@tinacms/graphql");
46
-
47
- // src/next/config-manager.ts
48
- var import_fs_extra = __toESM(require("fs-extra"));
49
- var import_path = __toESM(require("path"));
50
- var import_os = __toESM(require("os"));
51
- var esbuild = __toESM(require("esbuild"));
52
- var dotenv = __toESM(require("dotenv"));
53
- var import_normalize_path = __toESM(require("normalize-path"));
54
- var import_chalk2 = __toESM(require("chalk"));
43
+ var import_search = require("@tinacms/search");
44
+ var import_async_lock = __toESM(require("async-lock"));
45
+ var import_chokidar = __toESM(require("chokidar"));
46
+ var import_clipanion2 = require("clipanion");
47
+ var import_fs_extra6 = __toESM(require("fs-extra"));
55
48
 
56
49
  // src/logger/index.ts
57
50
  var import_chalk = __toESM(require("chalk"));
@@ -164,2155 +157,2176 @@ var S_SUCCESS = s("\u25C6", "*");
164
157
  var S_WARN = s("\u25B2", "!");
165
158
  var S_ERROR = s("\u25A0", "x");
166
159
 
167
- // src/next/config-manager.ts
168
- var TINA_FOLDER = "tina";
169
- var LEGACY_TINA_FOLDER = ".tina";
170
- var GENERATED_FOLDER = "__generated__";
171
- var GRAPHQL_JSON_FILE = "_graphql.json";
172
- var GRAPHQL_GQL_FILE = "schema.gql";
173
- var SCHEMA_JSON_FILE = "_schema.json";
174
- var LOOKUP_JSON_FILE = "_lookup.json";
175
- var ConfigManager = class {
176
- constructor({
177
- rootPath = process.cwd(),
178
- tinaGraphQLVersion,
179
- legacyNoSDK
180
- }) {
181
- this.rootPath = (0, import_normalize_path.default)(rootPath);
182
- this.tinaGraphQLVersionFromCLI = tinaGraphQLVersion;
183
- this.legacyNoSDK = legacyNoSDK;
184
- }
185
- isUsingTs() {
186
- return [".ts", ".tsx"].includes(import_path.default.extname(this.tinaConfigFilePath));
187
- }
188
- hasSelfHostedConfig() {
189
- return !!this.selfHostedDatabaseFilePath;
160
+ // src/utils/spinner.ts
161
+ var import_cli_spinner = require("cli-spinner");
162
+ async function localSpin({
163
+ waitFor,
164
+ text
165
+ }) {
166
+ const spinner = new import_cli_spinner.Spinner({
167
+ text: `${text} %s`,
168
+ stream: process.stderr,
169
+ onTick: function(msg) {
170
+ this.clearLine(this.stream);
171
+ this.stream.write(msg);
172
+ }
173
+ });
174
+ spinner.setSpinnerString("\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F");
175
+ spinner.start();
176
+ const res = await waitFor();
177
+ spinner.stop();
178
+ console.log("");
179
+ return res;
180
+ }
181
+ function spin({
182
+ waitFor,
183
+ text
184
+ }) {
185
+ if (process.env.CI) {
186
+ console.log(text);
187
+ return waitFor();
188
+ } else {
189
+ return localSpin({
190
+ text,
191
+ waitFor
192
+ });
190
193
  }
191
- hasSeparateContentRoot() {
192
- return this.rootPath !== this.contentRootPath;
194
+ }
195
+
196
+ // src/utils/theme.ts
197
+ var import_chalk2 = __toESM(require("chalk"));
198
+ var successText = import_chalk2.default.bold.green;
199
+ var focusText = import_chalk2.default.bold;
200
+ var dangerText = import_chalk2.default.bold.red;
201
+ var neutralText = import_chalk2.default.bold.cyan;
202
+ var linkText = import_chalk2.default.bold.cyan;
203
+ var labelText = import_chalk2.default.bold;
204
+ var cmdText = import_chalk2.default.inverse;
205
+ var indentedCmd = (str) => {
206
+ return ` \u2503 ` + str;
207
+ };
208
+ var indentText = (str) => {
209
+ return String(str).split("\n").map((line) => ` ${line}`).join("\n");
210
+ };
211
+ var logText = import_chalk2.default.italic.gray;
212
+ var warnText = import_chalk2.default.yellowBright.bgBlack;
213
+ var titleText = import_chalk2.default.bgHex("d2f1f8").hex("ec4816");
214
+ var CONFIRMATION_TEXT = import_chalk2.default.dim("enter to confirm");
215
+
216
+ // src/next/codegen/index.ts
217
+ var import_fs_extra = __toESM(require("fs-extra"));
218
+ var import_path = __toESM(require("path"));
219
+ var import_graphql5 = require("graphql");
220
+
221
+ // src/next/codegen/codegen/index.ts
222
+ var import_graphql4 = require("graphql");
223
+
224
+ // src/next/codegen/codegen/plugin.ts
225
+ var AddGeneratedClientFunc = (apiURL) => {
226
+ return (_schema, _documents, _config, _info) => {
227
+ return `
228
+ // TinaSDK generated code
229
+ import { createClient, TinaClient } from "tinacms/dist/client";
230
+
231
+ const generateRequester = (
232
+ client: TinaClient,
233
+ ) => {
234
+ const requester: (
235
+ doc: any,
236
+ vars?: any,
237
+ options?: {
238
+ branch?: string,
239
+ /**
240
+ * Aside from \`method\` and \`body\`, all fetch options are passed
241
+ * through to underlying fetch request
242
+ */
243
+ fetchOptions?: Omit<Parameters<typeof fetch>[1], 'body' | 'method'>,
244
+ },
245
+ client
246
+ ) => Promise<any> = async (doc, vars, options) => {
247
+ let url = client.apiUrl
248
+ if (options?.branch) {
249
+ const index = client.apiUrl.lastIndexOf('/')
250
+ url = client.apiUrl.substring(0, index + 1) + options.branch
251
+ }
252
+ const data = await client.request({
253
+ query: doc,
254
+ variables: vars,
255
+ url,
256
+ }, options)
257
+
258
+ return { data: data?.data, errors: data?.errors, query: doc, variables: vars || {} }
193
259
  }
194
- shouldSkipSDK() {
195
- var _a;
196
- if (this.legacyNoSDK) {
197
- return this.legacyNoSDK;
260
+
261
+ return requester
262
+ }
263
+
264
+ /**
265
+ * @experimental this class can be used but may change in the future
266
+ **/
267
+ export const ExperimentalGetTinaClient = () =>
268
+ getSdk(
269
+ generateRequester(
270
+ createClient({
271
+ url: "${apiURL}",
272
+ queries,
273
+ })
274
+ )
275
+ )
276
+
277
+ export const queries = (
278
+ client: TinaClient,
279
+ ) => {
280
+ const requester = generateRequester(client)
281
+ return getSdk(requester)
282
+ }
283
+ `;
284
+ };
285
+ };
286
+ var AddGeneratedClient = (apiURL) => ({
287
+ plugin: AddGeneratedClientFunc(apiURL)
288
+ });
289
+
290
+ // src/next/codegen/codegen/index.ts
291
+ var import_graphql_file_loader = require("@graphql-tools/graphql-file-loader");
292
+ var import_core = require("@graphql-codegen/core");
293
+ var import_load = require("@graphql-tools/load");
294
+ var import_typescript_operations = require("@graphql-codegen/typescript-operations");
295
+ var import_typescript = require("@graphql-codegen/typescript");
296
+
297
+ // src/next/codegen/codegen/sdkPlugin/index.ts
298
+ var import_graphql2 = require("graphql");
299
+ var import_graphql3 = require("graphql");
300
+
301
+ // src/next/codegen/codegen/sdkPlugin/visitor.ts
302
+ var import_visitor_plugin_common = require("@graphql-codegen/visitor-plugin-common");
303
+ var import_auto_bind = __toESM(require("auto-bind"));
304
+ var import_graphql = require("graphql");
305
+ var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBaseVisitor {
306
+ constructor(schema, fragments, rawConfig) {
307
+ super(schema, fragments, rawConfig, {
308
+ usingObservableFrom: rawConfig.usingObservableFrom
309
+ });
310
+ this._operationsToInclude = [];
311
+ (0, import_auto_bind.default)(this);
312
+ if (this.config.usingObservableFrom) {
313
+ this._additionalImports.push(this.config.usingObservableFrom);
314
+ }
315
+ if (this.config.documentMode !== import_visitor_plugin_common.DocumentMode.string) {
198
316
  }
199
- return ((_a = this.config.client) == null ? void 0 : _a.skip) || false;
200
317
  }
201
- async processConfig() {
202
- this.tinaFolderPath = await this.getTinaFolderPath(this.rootPath);
203
- this.envFilePath = import_path.default.resolve(
204
- import_path.default.join(this.tinaFolderPath, "..", ".env")
205
- );
206
- dotenv.config({ path: this.envFilePath });
207
- this.tinaConfigFilePath = await this.getPathWithExtension(
208
- import_path.default.join(this.tinaFolderPath, "config")
209
- );
210
- if (!this.tinaConfigFilePath) {
318
+ buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) {
319
+ if (node.name == null) {
211
320
  throw new Error(
212
- `Unable to find config file in ${this.tinaFolderPath}. Looking for a file named "config.{ts,tsx,js,jsx}"`
321
+ "Plugin 'generic-sdk' cannot generate SDK for unnamed operation.\n\n" + (0, import_graphql.print)(node)
213
322
  );
323
+ } else {
324
+ this._operationsToInclude.push({
325
+ node,
326
+ documentVariableName,
327
+ operationType,
328
+ // This is the only line that is different
329
+ operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
330
+ operationVariablesTypes
331
+ });
214
332
  }
215
- this.selfHostedDatabaseFilePath = await this.getPathWithExtension(
216
- import_path.default.join(this.tinaFolderPath, "database")
217
- );
218
- this.generatedFolderPath = import_path.default.join(this.tinaFolderPath, GENERATED_FOLDER);
219
- this.generatedCachePath = import_path.default.join(
220
- this.generatedFolderPath,
221
- ".cache",
222
- String((/* @__PURE__ */ new Date()).getTime())
223
- );
224
- this.generatedGraphQLGQLPath = import_path.default.join(
225
- this.generatedFolderPath,
226
- GRAPHQL_GQL_FILE
227
- );
228
- this.generatedGraphQLJSONPath = import_path.default.join(
229
- this.generatedFolderPath,
230
- GRAPHQL_JSON_FILE
231
- );
232
- this.generatedSchemaJSONPath = import_path.default.join(
233
- this.generatedFolderPath,
234
- SCHEMA_JSON_FILE
235
- );
236
- this.generatedLookupJSONPath = import_path.default.join(
237
- this.generatedFolderPath,
238
- LOOKUP_JSON_FILE
239
- );
240
- this.generatedQueriesFilePath = import_path.default.join(
241
- this.generatedFolderPath,
242
- "queries.gql"
243
- );
244
- this.generatedFragmentsFilePath = import_path.default.join(
245
- this.generatedFolderPath,
246
- "frags.gql"
247
- );
248
- this.generatedTypesTSFilePath = import_path.default.join(
249
- this.generatedFolderPath,
250
- "types.ts"
251
- );
252
- this.generatedTypesJSFilePath = import_path.default.join(
253
- this.generatedFolderPath,
254
- "types.js"
255
- );
256
- this.generatedTypesDFilePath = import_path.default.join(
257
- this.generatedFolderPath,
258
- "types.d.ts"
259
- );
260
- this.userQueriesAndFragmentsGlob = import_path.default.join(
261
- this.tinaFolderPath,
262
- "queries/**/*.{graphql,gql}"
263
- );
264
- this.generatedQueriesAndFragmentsGlob = import_path.default.join(
265
- this.generatedFolderPath,
266
- "*.{graphql,gql}"
267
- );
268
- this.generatedClientTSFilePath = import_path.default.join(
269
- this.generatedFolderPath,
270
- "client.ts"
271
- );
272
- this.generatedClientJSFilePath = import_path.default.join(
273
- this.generatedFolderPath,
274
- "client.js"
275
- );
276
- this.generatedClientDFilePath = import_path.default.join(
277
- this.generatedFolderPath,
278
- "client.d.ts"
279
- );
280
- this.generatedDatabaseClientDFilePath = import_path.default.join(
281
- this.generatedFolderPath,
282
- "databaseClient.d.ts"
283
- );
284
- this.generatedDatabaseClientTSFilePath = import_path.default.join(
285
- this.generatedFolderPath,
286
- "databaseClient.ts"
287
- );
288
- this.generatedDatabaseClientJSFilePath = import_path.default.join(
289
- this.generatedFolderPath,
290
- "databaseClient.js"
291
- );
292
- const clientExists = this.isUsingTs() ? await import_fs_extra.default.pathExists(this.generatedClientTSFilePath) : await import_fs_extra.default.pathExists(this.generatedClientJSFilePath);
293
- if (!clientExists) {
294
- const file = "export default ()=>({})\nexport const client = ()=>({})";
295
- if (this.isUsingTs()) {
296
- await import_fs_extra.default.outputFile(this.generatedClientTSFilePath, file);
297
- } else {
298
- await import_fs_extra.default.outputFile(this.generatedClientJSFilePath, file);
299
- }
300
- }
301
- const { config: config2, prebuildPath, watchList } = await this.loadConfigFile(
302
- this.generatedFolderPath,
303
- this.tinaConfigFilePath
304
- );
305
- this.watchList = watchList;
306
- this.config = config2;
307
- this.prebuildFilePath = prebuildPath;
308
- this.publicFolderPath = import_path.default.join(
309
- this.rootPath,
310
- this.config.build.publicFolder
311
- );
312
- this.outputFolderPath = import_path.default.join(
313
- this.publicFolderPath,
314
- this.config.build.outputFolder
315
- );
316
- this.outputHTMLFilePath = import_path.default.join(this.outputFolderPath, "index.html");
317
- this.outputGitignorePath = import_path.default.join(this.outputFolderPath, ".gitignore");
318
- const fullLocalContentPath = import_path.default.join(
319
- this.tinaFolderPath,
320
- this.config.localContentPath || ""
321
- );
322
- if (this.config.localContentPath) {
323
- const localContentPathExists = await import_fs_extra.default.pathExists(fullLocalContentPath);
324
- if (localContentPathExists) {
325
- logger.info(`Using separate content repo at ${fullLocalContentPath}`);
326
- this.contentRootPath = fullLocalContentPath;
327
- } else {
328
- logger.warn(
329
- `${import_chalk2.default.yellow("Warning:")} The localContentPath ${import_chalk2.default.cyan(
330
- fullLocalContentPath
331
- )} does not exist. Please create it or remove the localContentPath from your config file at ${import_chalk2.default.cyan(
332
- this.tinaConfigFilePath
333
- )}`
334
- );
335
- }
336
- }
337
- if (!this.contentRootPath) {
338
- this.contentRootPath = this.rootPath;
339
- }
340
- this.generatedFolderPathContentRepo = import_path.default.join(
341
- await this.getTinaFolderPath(this.contentRootPath),
342
- GENERATED_FOLDER
343
- );
344
- this.spaMainPath = require.resolve("@tinacms/app");
345
- this.spaRootPath = import_path.default.join(this.spaMainPath, "..", "..");
346
- }
347
- async getTinaFolderPath(rootPath) {
348
- const tinaFolderPath = import_path.default.join(rootPath, TINA_FOLDER);
349
- const tinaFolderExists = await import_fs_extra.default.pathExists(tinaFolderPath);
350
- if (tinaFolderExists) {
351
- this.isUsingLegacyFolder = false;
352
- return tinaFolderPath;
353
- }
354
- const legacyFolderPath = import_path.default.join(rootPath, LEGACY_TINA_FOLDER);
355
- const legacyFolderExists = await import_fs_extra.default.pathExists(legacyFolderPath);
356
- if (legacyFolderExists) {
357
- this.isUsingLegacyFolder = true;
358
- return legacyFolderPath;
359
- }
360
- throw new Error(
361
- `Unable to find Tina folder, if you're working in folder outside of the Tina config be sure to specify --rootPath`
362
- );
333
+ return null;
363
334
  }
364
- getTinaGraphQLVersion() {
365
- if (this.tinaGraphQLVersionFromCLI) {
366
- const version2 = this.tinaGraphQLVersionFromCLI.split(".");
367
- return {
368
- fullVersion: this.tinaGraphQLVersionFromCLI,
369
- major: version2[0] || "x",
370
- minor: version2[1] || "x",
371
- patch: version2[2] || "x"
372
- };
373
- }
374
- const generatedSchema = import_fs_extra.default.readJSONSync(this.generatedSchemaJSONPath);
375
- if (!generatedSchema || !(typeof (generatedSchema == null ? void 0 : generatedSchema.version) !== "undefined")) {
376
- throw new Error(
377
- `Can not find Tina GraphQL version in ${this.generatedSchemaJSONPath}`
335
+ get sdkContent() {
336
+ const usingObservable = !!this.config.usingObservableFrom;
337
+ const allPossibleActions = this._operationsToInclude.map((o) => {
338
+ const optionalVariables = !o.node.variableDefinitions || o.node.variableDefinitions.length === 0 || o.node.variableDefinitions.every(
339
+ (v) => v.type.kind !== import_graphql.Kind.NON_NULL_TYPE || v.defaultValue
378
340
  );
379
- }
380
- return generatedSchema.version;
381
- }
382
- printGeneratedClientFilePath() {
383
- if (this.isUsingTs()) {
384
- return this.generatedClientTSFilePath.replace(`${this.rootPath}/`, "");
385
- }
386
- return this.generatedClientJSFilePath.replace(`${this.rootPath}/`, "");
387
- }
388
- printGeneratedTypesFilePath() {
389
- return this.generatedTypesTSFilePath.replace(`${this.rootPath}/`, "");
341
+ const returnType = usingObservable && o.operationType === "Subscription" ? "Observable" : "Promise";
342
+ return `${o.node.name.value}(variables${optionalVariables ? "?" : ""}: ${o.operationVariablesTypes}, options?: C): ${returnType}<${o.operationResultType}> {
343
+ return requester<${o.operationResultType}, ${o.operationVariablesTypes}>(${o.documentVariableName}, variables, options);
344
+ }`;
345
+ }).map((s2) => (0, import_visitor_plugin_common.indentMultiline)(s2, 2));
346
+ return `export type Requester<C= {}> = <R, V>(doc: ${this.config.documentMode === import_visitor_plugin_common.DocumentMode.string ? "string" : "DocumentNode"}, vars?: V, options?: C) => ${usingObservable ? "Promise<R> & Observable<R>" : "Promise<R>"}
347
+ export function getSdk<C>(requester: Requester<C>) {
348
+ return {
349
+ ${allPossibleActions.join(",\n")}
350
+ };
390
351
  }
391
- printoutputHTMLFilePath() {
392
- return this.outputHTMLFilePath.replace(`${this.publicFolderPath}/`, "");
352
+ export type Sdk = ReturnType<typeof getSdk>;`;
393
353
  }
394
- printRelativePath(filename) {
395
- if (filename) {
396
- return filename.replace(/\\/g, "/").replace(`${this.rootPath}/`, "");
354
+ };
355
+
356
+ // src/next/codegen/codegen/sdkPlugin/index.ts
357
+ var plugin = (schema, documents, config2) => {
358
+ const allAst = (0, import_graphql3.concatAST)(
359
+ documents.reduce((prev, v) => {
360
+ return [...prev, v.document];
361
+ }, [])
362
+ );
363
+ const allFragments = [
364
+ ...allAst.definitions.filter(
365
+ (d) => d.kind === import_graphql3.Kind.FRAGMENT_DEFINITION
366
+ ).map((fragmentDef) => ({
367
+ node: fragmentDef,
368
+ name: fragmentDef.name.value,
369
+ onType: fragmentDef.typeCondition.name.value,
370
+ isExternal: false
371
+ })),
372
+ ...config2.externalFragments || []
373
+ ];
374
+ const visitor = new GenericSdkVisitor(schema, allFragments, config2);
375
+ const visitorResult = (0, import_graphql2.visit)(allAst, { leave: visitor });
376
+ return {
377
+ // We will take care of imports
378
+ // prepend: visitor.getImports(),
379
+ content: [
380
+ visitor.fragments,
381
+ ...visitorResult.definitions.filter((t) => typeof t === "string"),
382
+ visitor.sdkContent
383
+ ].join("\n")
384
+ };
385
+ };
386
+
387
+ // src/next/codegen/codegen/index.ts
388
+ var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath = process.cwd(), apiURL) => {
389
+ let docs = [];
390
+ let fragDocs = [];
391
+ docs = await loadGraphQLDocuments(queryPathGlob);
392
+ fragDocs = await loadGraphQLDocuments(fragDocPath);
393
+ const res = await (0, import_core.codegen)({
394
+ // Filename is not used. This is because the typescript plugin returns a string instead of writing to a file.
395
+ filename: process.cwd(),
396
+ schema: (0, import_graphql4.parse)((0, import_graphql4.printSchema)(schema)),
397
+ documents: [...docs, ...fragDocs],
398
+ config: {},
399
+ plugins: [
400
+ { typescript: {} },
401
+ { typescriptOperations: {} },
402
+ {
403
+ typescriptSdk: {}
404
+ },
405
+ { AddGeneratedClient: {} }
406
+ ],
407
+ pluginMap: {
408
+ typescript: {
409
+ plugin: import_typescript.plugin
410
+ },
411
+ typescriptOperations: {
412
+ plugin: import_typescript_operations.plugin
413
+ },
414
+ typescriptSdk: {
415
+ plugin
416
+ },
417
+ AddGeneratedClient: AddGeneratedClient(apiURL)
418
+ }
419
+ });
420
+ return res;
421
+ };
422
+ var loadGraphQLDocuments = async (globPath) => {
423
+ let result = [];
424
+ try {
425
+ result = await (0, import_load.loadDocuments)(globPath, {
426
+ loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
427
+ });
428
+ } catch (e) {
429
+ if (
430
+ // https://www.graphql-tools.com/docs/documents-loading#no-files-found
431
+ (e.message || "").includes(
432
+ "Unable to find any GraphQL type definitions for the following pointers:"
433
+ )
434
+ ) {
435
+ } else {
436
+ throw e;
397
437
  }
398
- throw `No path provided to print`;
399
438
  }
400
- printPrebuildFilePath() {
401
- return this.prebuildFilePath.replace(/\\/g, "/").replace(`${this.rootPath}/${this.tinaFolderPath}/`, "");
439
+ return result;
440
+ };
441
+
442
+ // src/next/codegen/index.ts
443
+ var import_esbuild = require("esbuild");
444
+ var import_graphql6 = require("@tinacms/graphql");
445
+ var import_normalize_path = __toESM(require("normalize-path"));
446
+ var TINA_HOST = "content.tinajs.io";
447
+ var Codegen = class {
448
+ constructor({
449
+ configManager,
450
+ port,
451
+ queryDoc,
452
+ fragDoc,
453
+ isLocal,
454
+ graphqlSchemaDoc,
455
+ tinaSchema,
456
+ lookup,
457
+ noClientBuildCache
458
+ }) {
459
+ this.isLocal = isLocal;
460
+ this.graphqlSchemaDoc = graphqlSchemaDoc;
461
+ this.configManager = configManager;
462
+ this.port = port;
463
+ this.schema = (0, import_graphql5.buildASTSchema)(graphqlSchemaDoc);
464
+ this.tinaSchema = tinaSchema;
465
+ this.queryDoc = queryDoc;
466
+ this.fragDoc = fragDoc;
467
+ this.lookup = lookup;
468
+ this.noClientBuildCache = noClientBuildCache;
402
469
  }
403
- printContentRelativePath(filename) {
404
- if (filename) {
405
- return filename.replace(/\\/g, "/").replace(`${this.contentRootPath}/`, "");
470
+ async writeConfigFile(fileName, data) {
471
+ const filePath = import_path.default.join(
472
+ this.configManager.generatedFolderPath,
473
+ fileName
474
+ );
475
+ await import_fs_extra.default.ensureFile(filePath);
476
+ await import_fs_extra.default.outputFile(filePath, data);
477
+ if (this.configManager.hasSeparateContentRoot()) {
478
+ const filePath2 = import_path.default.join(
479
+ this.configManager.generatedFolderPathContentRepo,
480
+ fileName
481
+ );
482
+ await import_fs_extra.default.ensureFile(filePath2);
483
+ await import_fs_extra.default.outputFile(filePath2, data);
406
484
  }
407
- throw `No path provided to print`;
408
485
  }
409
- /**
410
- * Given a filepath without an extension, find the first match (eg. tsx, ts, jsx, js)
411
- */
412
- async getPathWithExtension(filepath) {
413
- const extensions = ["tsx", "ts", "jsx", "js"];
414
- let result;
415
- await Promise.all(
416
- extensions.map(async (ext) => {
417
- if (result) {
418
- return;
419
- }
420
- const filepathWithExtension = `${filepath}.${ext}`;
421
- const exists = import_fs_extra.default.existsSync(filepathWithExtension);
422
- if (exists) {
423
- result = filepathWithExtension;
424
- }
425
- })
426
- );
427
- return result;
486
+ async removeGeneratedFilesIfExists() {
487
+ await unlinkIfExists(this.configManager.generatedClientJSFilePath);
488
+ await unlinkIfExists(this.configManager.generatedTypesDFilePath);
489
+ await unlinkIfExists(this.configManager.generatedTypesJSFilePath);
490
+ await unlinkIfExists(this.configManager.generatedTypesTSFilePath);
491
+ await unlinkIfExists(this.configManager.generatedClientTSFilePath);
492
+ await unlinkIfExists(this.configManager.generatedQueriesFilePath);
493
+ await unlinkIfExists(this.configManager.generatedFragmentsFilePath);
428
494
  }
429
- async loadDatabaseFile() {
430
- const tmpdir = import_path.default.join(import_os.default.tmpdir(), Date.now().toString());
431
- const outfile = import_path.default.join(tmpdir, "database.build.js");
432
- await esbuild.build({
433
- entryPoints: [this.selfHostedDatabaseFilePath],
434
- bundle: true,
435
- platform: "node",
436
- outfile,
437
- loader: loaders
438
- });
439
- const result = require(outfile);
440
- import_fs_extra.default.removeSync(outfile);
441
- return result.default;
442
- }
443
- async loadConfigFile(generatedFolderPath, configFilePath) {
444
- const tmpdir = import_path.default.join(import_os.default.tmpdir(), Date.now().toString());
445
- const preBuildConfigPath = import_path.default.join(
446
- this.generatedFolderPath,
447
- "config.prebuild.jsx"
495
+ async execute() {
496
+ await this.writeConfigFile(
497
+ "_graphql.json",
498
+ JSON.stringify(this.graphqlSchemaDoc)
448
499
  );
449
- const outfile = import_path.default.join(tmpdir, "config.build.jsx");
450
- const outfile2 = import_path.default.join(tmpdir, "config.build.js");
451
- const tempTSConfigFile = import_path.default.join(tmpdir, "tsconfig.json");
452
- import_fs_extra.default.outputFileSync(tempTSConfigFile, "{}");
453
- const result2 = await esbuild.build({
454
- entryPoints: [configFilePath],
455
- bundle: true,
456
- target: ["es2020"],
457
- platform: "browser",
458
- format: "esm",
459
- logLevel: "silent",
460
- packages: "external",
461
- ignoreAnnotations: true,
462
- outfile: preBuildConfigPath,
463
- loader: loaders,
464
- metafile: true
465
- });
466
- const flattenedList = [];
467
- Object.keys(result2.metafile.inputs).forEach((key) => {
468
- if (key.includes("node_modules") || key.includes("__generated__")) {
469
- return;
500
+ const { search, ...rest } = this.tinaSchema.schema.config;
501
+ this.tinaSchema.schema.config = rest;
502
+ await this.writeConfigFile(
503
+ "_schema.json",
504
+ JSON.stringify(this.tinaSchema.schema)
505
+ );
506
+ await this.writeConfigFile("_lookup.json", JSON.stringify(this.lookup));
507
+ const { apiURL, localUrl, tinaCloudUrl } = this._createApiUrl();
508
+ this.apiURL = apiURL;
509
+ this.localUrl = localUrl;
510
+ this.productionUrl = tinaCloudUrl;
511
+ if (this.configManager.shouldSkipSDK()) {
512
+ await this.removeGeneratedFilesIfExists();
513
+ return apiURL;
514
+ }
515
+ await import_fs_extra.default.outputFile(
516
+ this.configManager.generatedQueriesFilePath,
517
+ this.queryDoc
518
+ );
519
+ await import_fs_extra.default.outputFile(
520
+ this.configManager.generatedFragmentsFilePath,
521
+ this.fragDoc
522
+ );
523
+ await maybeWarnFragmentSize(this.configManager.generatedFragmentsFilePath);
524
+ const { clientString } = await this.genClient();
525
+ const databaseClientString = this.configManager.hasSelfHostedConfig() ? await this.genDatabaseClient() : "";
526
+ const { codeString, schemaString } = await this.genTypes();
527
+ await import_fs_extra.default.outputFile(
528
+ this.configManager.generatedGraphQLGQLPath,
529
+ schemaString
530
+ );
531
+ if (this.configManager.isUsingTs()) {
532
+ await import_fs_extra.default.outputFile(
533
+ this.configManager.generatedTypesTSFilePath,
534
+ codeString
535
+ );
536
+ await import_fs_extra.default.outputFile(
537
+ this.configManager.generatedClientTSFilePath,
538
+ clientString
539
+ );
540
+ if (this.configManager.hasSelfHostedConfig()) {
541
+ await import_fs_extra.default.outputFile(
542
+ this.configManager.generatedDatabaseClientTSFilePath,
543
+ databaseClientString
544
+ );
545
+ }
546
+ await unlinkIfExists(this.configManager.generatedClientJSFilePath);
547
+ await unlinkIfExists(this.configManager.generatedTypesDFilePath);
548
+ await unlinkIfExists(this.configManager.generatedTypesJSFilePath);
549
+ } else {
550
+ await import_fs_extra.default.outputFile(
551
+ this.configManager.generatedTypesDFilePath,
552
+ codeString
553
+ );
554
+ const jsTypes = await (0, import_esbuild.transform)(codeString, { loader: "ts" });
555
+ await import_fs_extra.default.outputFile(
556
+ this.configManager.generatedTypesJSFilePath,
557
+ jsTypes.code
558
+ );
559
+ await import_fs_extra.default.outputFile(
560
+ this.configManager.generatedClientDFilePath,
561
+ clientString
562
+ );
563
+ const jsClient = await (0, import_esbuild.transform)(clientString, { loader: "ts" });
564
+ await import_fs_extra.default.outputFile(
565
+ this.configManager.generatedClientJSFilePath,
566
+ jsClient.code
567
+ );
568
+ await unlinkIfExists(this.configManager.generatedTypesTSFilePath);
569
+ await unlinkIfExists(this.configManager.generatedClientTSFilePath);
570
+ if (this.configManager.hasSelfHostedConfig()) {
571
+ const jsDatabaseClient = await (0, import_esbuild.transform)(databaseClientString, {
572
+ loader: "ts"
573
+ });
574
+ await import_fs_extra.default.outputFile(
575
+ this.configManager.generatedDatabaseClientJSFilePath,
576
+ jsDatabaseClient.code
577
+ );
578
+ await import_fs_extra.default.outputFile(
579
+ this.configManager.generatedDatabaseClientDFilePath,
580
+ databaseClientString
581
+ );
582
+ await unlinkIfExists(
583
+ this.configManager.generatedDatabaseClientTSFilePath
584
+ );
470
585
  }
471
- flattenedList.push(key);
472
- });
473
- await esbuild.build({
474
- entryPoints: [configFilePath],
475
- bundle: true,
476
- target: ["es2020"],
477
- logLevel: "silent",
478
- platform: "node",
479
- outfile,
480
- loader: loaders
481
- });
482
- await esbuild.build({
483
- entryPoints: [outfile],
484
- bundle: true,
485
- // Suppress warning about comparison with -0 from client module
486
- logLevel: "silent",
487
- platform: "node",
488
- outfile: outfile2,
489
- loader: loaders
490
- });
491
- let result;
492
- try {
493
- result = require(outfile2);
494
- } catch (e) {
495
- console.error("Unexpected error loading config");
496
- console.error(e);
497
- throw e;
498
586
  }
499
- import_fs_extra.default.removeSync(outfile);
500
- import_fs_extra.default.removeSync(outfile2);
501
- return {
502
- config: result.default,
503
- prebuildPath: preBuildConfigPath,
504
- watchList: flattenedList
505
- };
587
+ return apiURL;
506
588
  }
507
- };
508
- var loaders = {
509
- ".aac": "file",
510
- ".css": "file",
511
- ".eot": "file",
512
- ".flac": "file",
513
- ".gif": "file",
514
- ".jpeg": "file",
515
- ".jpg": "file",
516
- ".json": "json",
517
- ".mp3": "file",
518
- ".mp4": "file",
519
- ".ogg": "file",
520
- ".otf": "file",
521
- ".png": "file",
522
- ".svg": "file",
523
- ".ttf": "file",
524
- ".wav": "file",
525
- ".webm": "file",
526
- ".webp": "file",
527
- ".woff": "file",
528
- ".woff2": "file",
529
- ".js": "jsx",
530
- ".jsx": "jsx",
531
- ".tsx": "tsx"
532
- };
589
+ _createApiUrl() {
590
+ var _a, _b, _c, _d;
591
+ const branch = (_a = this.configManager.config) == null ? void 0 : _a.branch;
592
+ const clientId = (_b = this.configManager.config) == null ? void 0 : _b.clientId;
593
+ const token = (_c = this.configManager.config) == null ? void 0 : _c.token;
594
+ const fullVersion = this.configManager.getTinaGraphQLVersion();
595
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
596
+ const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
597
+ if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
598
+ const missing = [];
599
+ if (!branch) missing.push("branch");
600
+ if (!clientId) missing.push("clientId");
601
+ if (!token) missing.push("token");
602
+ throw new Error(
603
+ `Client not configured properly. Missing ${missing.join(
604
+ ", "
605
+ )}. Please visit https://tina.io/docs/tina-cloud/overview for more information`
606
+ );
607
+ }
608
+ let localUrl = `http://localhost:${this.port}/graphql`;
609
+ let tinaCloudUrl = `${baseUrl}/${version2}/content/${clientId}/github/${branch}`;
610
+ let apiURL = this.isLocal ? `http://localhost:${this.port}/graphql` : `${baseUrl}/${version2}/content/${clientId}/github/${branch}`;
611
+ if (this.configManager.config.contentApiUrlOverride) {
612
+ apiURL = this.configManager.config.contentApiUrlOverride;
613
+ localUrl = apiURL;
614
+ tinaCloudUrl = apiURL;
615
+ }
616
+ return { apiURL, localUrl, tinaCloudUrl };
617
+ }
618
+ getApiURL() {
619
+ if (!this.apiURL)
620
+ throw new Error("apiURL not set. Please run execute() first");
621
+ return this.apiURL;
622
+ }
623
+ async genDatabaseClient() {
624
+ var _a, _b;
625
+ const authCollection = this.tinaSchema.getCollections().find((c) => c.isAuthCollection);
626
+ let authFields = [];
627
+ if (authCollection) {
628
+ const usersFields = (0, import_graphql6.mapUserFields)(authCollection, []);
629
+ if (usersFields.length === 0) {
630
+ throw new Error("No user field found");
631
+ }
632
+ if (usersFields.length > 1) {
633
+ throw new Error("Only one user field is allowed");
634
+ }
635
+ authFields = (_b = (_a = usersFields[0]) == null ? void 0 : _a.collectable) == null ? void 0 : _b.fields.map((f) => {
636
+ if (f.type !== "password" && f.type !== "object") {
637
+ if (f.uid) {
638
+ return `id:${f.name}`;
639
+ } else {
640
+ return `${f.name}`;
641
+ }
642
+ } else if (f.type === "password") {
643
+ return `_password: ${f.name} { passwordChangeRequired }`;
644
+ }
645
+ });
646
+ }
647
+ return `// @ts-nocheck
648
+ import { resolve } from "@tinacms/datalayer";
649
+ import type { TinaClient } from "tinacms/dist/client";
533
650
 
534
- // src/next/commands/dev-command/html.ts
535
- var errorHTML = `<style type="text/css">
536
- #no-assets-placeholder body {
537
- font-family: sans-serif;
538
- font-size: 16px;
539
- line-height: 1.4;
540
- color: #333;
541
- background-color: #f5f5f5;
542
- }
543
- #no-assets-placeholder {
544
- max-width: 600px;
545
- margin: 0 auto;
546
- padding: 40px;
547
- text-align: center;
548
- background-color: #fff;
549
- box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
550
- }
551
- #no-assets-placeholder h1 {
552
- font-size: 24px;
553
- margin-bottom: 20px;
651
+ import { queries } from "./types";
652
+ import database from "../database";
653
+
654
+ export async function databaseRequest({ query, variables, user }) {
655
+ const result = await resolve({
656
+ config: {
657
+ useRelativeMedia: true,
658
+ },
659
+ database,
660
+ query,
661
+ variables,
662
+ verbose: true,
663
+ ctxUser: user,
664
+ });
665
+
666
+ return result;
554
667
  }
555
- #no-assets-placeholder p {
556
- margin-bottom: 10px;
668
+
669
+ export async function authenticate({ username, password }) {
670
+ return databaseRequest({
671
+ query: \`query auth($username:String!, $password:String!) {
672
+ authenticate(sub:$username, password:$password) {
673
+ ${authFields.join(" ")}
674
+ }
675
+ }\`,
676
+ variables: { username, password },
677
+ })
557
678
  }
558
- #no-assets-placeholder a {
559
- color: #0077cc;
560
- text-decoration: none;
679
+
680
+ export async function authorize(user: { sub: string }) {
681
+ return databaseRequest({
682
+ query: \`query authz { authorize { ${authFields.join(" ")}} }\`,
683
+ variables: {},
684
+ user
685
+ })
561
686
  }
562
- #no-assets-placeholder a:hover {
563
- text-decoration: underline;
687
+
688
+ function createDatabaseClient<GenQueries = Record<string, unknown>>({
689
+ queries,
690
+ }: {
691
+ queries: (client: {
692
+ request: TinaClient<GenQueries>["request"];
693
+ }) => GenQueries;
694
+ }) {
695
+ const request = async ({ query, variables, user }) => {
696
+ const data = await databaseRequest({ query, variables, user });
697
+ return { data: data.data as any, query, variables, errors: data.errors || null };
698
+ };
699
+ const q = queries({
700
+ request,
701
+ });
702
+ return { queries: q, request, authenticate, authorize };
564
703
  }
565
- </style>
566
- <div id="no-assets-placeholder">
567
- <h1>Failed loading TinaCMS assets</h1>
568
- <p>
569
- Your TinaCMS configuration may be misconfigured, and we could not load
570
- the assets for this page.
571
- </p>
572
- <p>
573
- Please visit <a href="https://tina.io/docs/tina-cloud/faq/#how-do-i-resolve-failed-loading-tinacms-assets-error">this doc</a> for help.
574
- </p>
575
- </div>
576
- </div>`.trim().replace(/[\r\n\s]+/g, " ");
577
- var devHTML = (port) => `<!DOCTYPE html>
578
- <html lang="en">
579
- <head>
580
- <meta charset="UTF-8" />
581
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
582
- <title>TinaCMS</title>
583
- </head>
584
704
 
585
- <!-- if development -->
586
- <script type="module">
587
- import RefreshRuntime from 'http://localhost:${port}/@react-refresh'
588
- RefreshRuntime.injectIntoGlobalHook(window)
589
- window.$RefreshReg$ = () => {}
590
- window.$RefreshSig$ = () => (type) => type
591
- window.__vite_plugin_react_preamble_installed__ = true
592
- </script>
593
- <script type="module" src="http://localhost:${port}/@vite/client"></script>
594
- <script>
595
- function handleLoadError() {
596
- // Assets have failed to load
597
- document.getElementById('root').innerHTML = '${errorHTML}';
598
- }
599
- </script>
600
- <script
601
- type="module"
602
- src="http://localhost:${port}/src/main.tsx"
603
- onerror="handleLoadError()"
604
- ></script>
605
- <body class="tina-tailwind">
606
- <div id="root"></div>
607
- </body>
608
- </html>`;
705
+ export const databaseClient = createDatabaseClient({ queries });
609
706
 
610
- // src/utils/theme.ts
611
- var import_chalk3 = __toESM(require("chalk"));
612
- var successText = import_chalk3.default.bold.green;
613
- var focusText = import_chalk3.default.bold;
614
- var dangerText = import_chalk3.default.bold.red;
615
- var neutralText = import_chalk3.default.bold.cyan;
616
- var linkText = import_chalk3.default.bold.cyan;
617
- var labelText = import_chalk3.default.bold;
618
- var cmdText = import_chalk3.default.inverse;
619
- var indentedCmd = (str) => {
620
- return ` \u2503 ` + str;
707
+ export const client = databaseClient;
708
+
709
+ export default databaseClient;
710
+ `;
711
+ }
712
+ async genClient() {
713
+ var _a, _b, _c;
714
+ const token = (_a = this.configManager.config) == null ? void 0 : _a.token;
715
+ const errorPolicy = (_c = (_b = this.configManager.config) == null ? void 0 : _b.client) == null ? void 0 : _c.errorPolicy;
716
+ const apiURL = this.getApiURL();
717
+ const clientString = `import { createClient } from "tinacms/dist/client";
718
+ import { queries } from "./types";
719
+ export const client = createClient({ ${this.noClientBuildCache === false ? `cacheDir: '${(0, import_normalize_path.default)(
720
+ this.configManager.generatedCachePath
721
+ )}', ` : ""}url: '${apiURL}', token: '${token}', queries, ${errorPolicy ? `errorPolicy: '${errorPolicy}'` : ""} });
722
+ export default client;
723
+ `;
724
+ return { apiURL, clientString };
725
+ }
726
+ async genTypes() {
727
+ const typescriptTypes = await generateTypes(
728
+ this.schema,
729
+ this.configManager.userQueriesAndFragmentsGlob,
730
+ this.configManager.generatedQueriesAndFragmentsGlob,
731
+ this.getApiURL()
732
+ );
733
+ const codeString = `//@ts-nocheck
734
+ // DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
735
+ export function gql(strings: TemplateStringsArray, ...args: string[]): string {
736
+ let str = ''
737
+ strings.forEach((string, i) => {
738
+ str += string + (args[i] || '')
739
+ })
740
+ return str
741
+ }
742
+ ${typescriptTypes}
743
+ `;
744
+ const schemaString = `# DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
745
+ ${(0, import_graphql5.printSchema)(this.schema)}
746
+ schema {
747
+ query: Query
748
+ mutation: Mutation
749
+ }
750
+ `;
751
+ return { codeString, schemaString };
752
+ }
621
753
  };
622
- var indentText = (str) => {
623
- return String(str).split("\n").map((line) => ` ${line}`).join("\n");
754
+ var maybeWarnFragmentSize = async (filepath) => {
755
+ if (
756
+ // is the file bigger than 100kb?
757
+ (await import_fs_extra.default.stat(filepath)).size > // convert to 100 kb to bytes
758
+ 100 * 1024
759
+ ) {
760
+ console.warn(
761
+ "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
762
+ );
763
+ console.log(
764
+ `const schema = defineSchema({
765
+ client: {
766
+ referenceDepth: 1,
767
+ },
768
+ // ...
769
+ })`
770
+ );
771
+ }
772
+ };
773
+ var unlinkIfExists = async (filepath) => {
774
+ if (import_fs_extra.default.existsSync(filepath)) {
775
+ import_fs_extra.default.unlinkSync(filepath);
776
+ }
624
777
  };
625
- var logText = import_chalk3.default.italic.gray;
626
- var warnText = import_chalk3.default.yellowBright.bgBlack;
627
- var titleText = import_chalk3.default.bgHex("d2f1f8").hex("ec4816");
628
- var CONFIRMATION_TEXT = import_chalk3.default.dim("enter to confirm");
629
-
630
- // src/next/commands/dev-command/server/index.ts
631
- var import_vite3 = require("vite");
632
778
 
633
- // src/next/vite/index.ts
634
- var import_node_path2 = __toESM(require("path"));
635
- var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
779
+ // src/next/config-manager.ts
636
780
  var import_fs_extra2 = __toESM(require("fs-extra"));
781
+ var import_path2 = __toESM(require("path"));
782
+ var import_os = __toESM(require("os"));
783
+ var esbuild = __toESM(require("esbuild"));
784
+ var dotenv = __toESM(require("dotenv"));
637
785
  var import_normalize_path2 = __toESM(require("normalize-path"));
638
- var import_vite = require("vite");
639
-
640
- // src/next/vite/tailwind.ts
641
- var import_node_path = __toESM(require("path"));
642
- var import_aspect_ratio = __toESM(require("@tailwindcss/aspect-ratio"));
643
- var import_container_queries = __toESM(require("@tailwindcss/container-queries"));
644
- var import_typography = __toESM(require("@tailwindcss/typography"));
645
- var import_tailwindcss = __toESM(require("tailwindcss"));
646
- var import_defaultTheme = __toESM(require("tailwindcss/defaultTheme.js"));
647
- var tinaTailwind = (spaPath, prebuildFilePath) => {
648
- return {
649
- name: "vite-plugin-tina",
650
- // @ts-ignore
651
- config: (viteConfig) => {
652
- const plugins = [];
653
- const content = [
654
- import_node_path.default.join(spaPath, "src/**/*.{vue,js,ts,jsx,tsx,svelte}"),
655
- prebuildFilePath,
656
- require.resolve("tinacms")
657
- ];
658
- const tw = (0, import_tailwindcss.default)({
659
- theme: {
660
- columns: {
661
- auto: "auto",
662
- 1: "1",
663
- 2: "2",
664
- 3: "3",
665
- 4: "4",
666
- 5: "5",
667
- 6: "6",
668
- 7: "7",
669
- 8: "8",
670
- 9: "9",
671
- 10: "10",
672
- 11: "11",
673
- 12: "12",
674
- "3xs": "256px",
675
- "2xs": "288px",
676
- xs: "320px",
677
- sm: "384px",
678
- md: "448px",
679
- lg: "512px",
680
- xl: "576px",
681
- "2xl": "672px",
682
- "3xl": "768px",
683
- "4xl": "896px",
684
- "5xl": "1024px",
685
- "6xl": "1152px",
686
- "7xl": "1280px"
687
- },
688
- spacing: {
689
- px: "1px",
690
- 0: "0px",
691
- 0.5: "2px",
692
- 1: "4px",
693
- 1.5: "6px",
694
- 2: "8px",
695
- 2.5: "10px",
696
- 3: "12px",
697
- 3.5: "14px",
698
- 4: "16px",
699
- 5: "20px",
700
- 6: "24px",
701
- 7: "28px",
702
- 8: "32px",
703
- 9: "36px",
704
- 10: "40px",
705
- 11: "44px",
706
- 12: "48px",
707
- 14: "56px",
708
- 16: "64px",
709
- 18: "72px",
710
- 20: "80px",
711
- 24: "96px",
712
- 28: "114px",
713
- 32: "128px",
714
- 36: "144px",
715
- 40: "160px",
716
- 44: "176px",
717
- 48: "192px",
718
- 52: "208px",
719
- 56: "224px",
720
- 60: "240px",
721
- 64: "256px",
722
- 72: "288px",
723
- 80: "320px",
724
- 96: "384px"
725
- },
726
- borderRadius: {
727
- none: "0px",
728
- sm: "2px",
729
- DEFAULT: "4px",
730
- md: "6px",
731
- lg: "8px",
732
- xl: "12px",
733
- "2xl": "16px",
734
- "3xl": "24px",
735
- full: "9999px"
736
- },
737
- borderWidth: {
738
- DEFAULT: "1px",
739
- 0: "0",
740
- 2: "2px",
741
- 3: "3px",
742
- 4: "4px",
743
- 6: "6px",
744
- 8: "8px"
745
- },
746
- fontSize: {
747
- xs: ["13px", { lineHeight: "1.33" }],
748
- sm: ["14px", { lineHeight: "1.43" }],
749
- base: ["16px", { lineHeight: "1.5" }],
750
- md: ["16px", { lineHeight: "1.5" }],
751
- lg: ["18px", { lineHeight: "1.55" }],
752
- xl: ["20px", { lineHeight: "1.4" }],
753
- "2xl": ["24px", { lineHeight: "1.33" }],
754
- "3xl": ["30px", { lineHeight: "1.2" }],
755
- "4xl": ["36px", { lineHeight: "1.1" }],
756
- "5xl": ["48px", { lineHeight: "1" }],
757
- "6xl": ["60px", { lineHeight: "1" }],
758
- "7xl": ["72px", { lineHeight: "1" }],
759
- "8xl": ["96px", { lineHeight: "1" }],
760
- "9xl": ["128px", { lineHeight: "1" }]
761
- },
762
- opacity: {
763
- 0: "0",
764
- 5: ".05",
765
- 7: ".07",
766
- 10: ".1",
767
- 15: ".15",
768
- 20: ".2",
769
- 25: ".25",
770
- 30: ".3",
771
- 40: ".4",
772
- 50: ".5",
773
- 60: ".6",
774
- 70: ".7",
775
- 75: ".75",
776
- 80: ".8",
777
- 90: ".9",
778
- 100: "1"
779
- },
780
- zIndex: {
781
- "-1": "-1",
782
- base: "9000",
783
- panel: "9400",
784
- menu: "9800",
785
- chrome: "10200",
786
- overlay: "10600",
787
- modal: "10800",
788
- 0: "0",
789
- 10: "10",
790
- 20: "20",
791
- 30: "30",
792
- 40: "40",
793
- 25: "25",
794
- 50: "50",
795
- 75: "75",
796
- 100: "100",
797
- auto: "auto"
798
- },
799
- extend: {
800
- scale: {
801
- 97: ".97",
802
- 103: "1.03"
803
- },
804
- transitionDuration: {
805
- 0: "0ms",
806
- 2e3: "2000ms"
807
- },
808
- boxShadow: {
809
- xs: "0 0 0 1px rgba(0, 0, 0, 0.05)",
810
- outline: "0 0 0 3px rgba(66, 153, 225, 0.5)"
811
- },
812
- colors: {
813
- blue: {
814
- 50: "#DCEEFF",
815
- 100: "#B4DBFF",
816
- 200: "#85C5FE",
817
- 300: "#4EABFE",
818
- 400: "#2296fe",
819
- 500: "#0084FF",
820
- 600: "#0574e4",
821
- 700: "#0D5DBD",
822
- 800: "#144696",
823
- 900: "#1D2C6C",
824
- 1e3: "#241748"
825
- },
826
- gray: {
827
- 50: "#F6F6F9",
828
- 100: "#EDECF3",
829
- 150: "#E6E3EF",
830
- 200: "#E1DDEC",
831
- 250: "#C9C5D5",
832
- 300: "#b2adbe",
833
- 400: "#918c9e",
834
- 500: "#716c7f",
835
- 600: "#565165",
836
- 700: "#433e52",
837
- 800: "#363145",
838
- 900: "#252336",
839
- 1e3: "#1c1b2e"
840
- },
841
- orange: {
842
- 400: "#EB6337",
843
- 500: "#EC4815",
844
- 600: "#DC4419"
845
- },
846
- background: "#FFFFFF",
847
- foreground: "#0A0A0A",
848
- muted: "#F5F5F5",
849
- "muted-foreground": "#737373",
850
- popover: "#FFFFFF",
851
- "popover-foreground": "#0A0A0A",
852
- card: "#FFFFFF",
853
- "card-foreground": "#0A0A0A",
854
- border: "#E5E5E5",
855
- input: "#E5E5E5",
856
- primary: "#171717",
857
- "primary-foreground": "#FAFAFA",
858
- secondary: "#F5F5F5",
859
- "secondary-foreground": "#171717",
860
- accent: "#F5F5F5",
861
- "accent-foreground": "#171717",
862
- destructive: "#FF3B3B",
863
- "destructive-foreground": "#FAFAFA",
864
- ring: "#0A0A0A"
865
- },
866
- fontFamily: {
867
- sans: ["Inter", ...import_defaultTheme.default.fontFamily.sans]
868
- },
869
- lineHeight: {
870
- 3: "12px",
871
- 4: "16px",
872
- 5: "20px",
873
- 6: "24px",
874
- 7: "28px",
875
- 8: "32px",
876
- 9: "36px",
877
- 10: "40px"
878
- },
879
- maxWidth: {
880
- form: "900px"
881
- },
882
- screens: {
883
- xs: "320px",
884
- sm: "560px",
885
- md: "720px",
886
- lg: "1030px"
887
- }
888
- }
889
- },
890
- content,
891
- plugins: [
892
- (0, import_typography.default)({ className: "tina-prose" }),
893
- import_aspect_ratio.default,
894
- import_container_queries.default
895
- ]
896
- });
897
- plugins.push(tw);
898
- return {
899
- css: {
900
- postcss: {
901
- plugins
902
- }
903
- }
904
- };
905
- }
906
- };
907
- };
908
-
909
- // src/next/vite/index.ts
910
- async function listFilesRecursively({
911
- directoryPath,
912
- config: config2,
913
- roothPath
914
- }) {
915
- const fullDirectoryPath = import_node_path2.default.join(
916
- roothPath,
917
- config2.publicFolder,
918
- directoryPath
919
- );
920
- const exists = await import_fs_extra2.default.pathExists(fullDirectoryPath);
921
- if (!exists) {
922
- return { "0": [] };
786
+ var import_chalk3 = __toESM(require("chalk"));
787
+ var TINA_FOLDER = "tina";
788
+ var LEGACY_TINA_FOLDER = ".tina";
789
+ var GENERATED_FOLDER = "__generated__";
790
+ var GRAPHQL_JSON_FILE = "_graphql.json";
791
+ var GRAPHQL_GQL_FILE = "schema.gql";
792
+ var SCHEMA_JSON_FILE = "_schema.json";
793
+ var LOOKUP_JSON_FILE = "_lookup.json";
794
+ var ConfigManager = class {
795
+ constructor({
796
+ rootPath = process.cwd(),
797
+ tinaGraphQLVersion,
798
+ legacyNoSDK
799
+ }) {
800
+ this.rootPath = (0, import_normalize_path2.default)(rootPath);
801
+ this.tinaGraphQLVersionFromCLI = tinaGraphQLVersion;
802
+ this.legacyNoSDK = legacyNoSDK;
923
803
  }
924
- const items = await import_fs_extra2.default.readdir(fullDirectoryPath);
925
- const staticMediaItems = [];
926
- for (const item of items) {
927
- const itemPath = import_node_path2.default.join(fullDirectoryPath, item);
928
- const stats = await import_fs_extra2.default.promises.lstat(itemPath);
929
- const staticMediaItem = {
930
- id: item,
931
- filename: item,
932
- type: stats.isDirectory() ? "dir" : "file",
933
- directory: `${directoryPath.replace(config2.mediaRoot, "")}`,
934
- src: `/${import_node_path2.default.join(directoryPath, item)}`,
935
- thumbnails: {
936
- "75x75": `/${import_node_path2.default.join(directoryPath, item)}`,
937
- "400x400": `/${import_node_path2.default.join(directoryPath, item)}`,
938
- "1000x1000": `/${import_node_path2.default.join(directoryPath, item)}`
939
- }
940
- };
941
- if (stats.isDirectory()) {
942
- staticMediaItem.children = await listFilesRecursively({
943
- directoryPath: import_node_path2.default.join(directoryPath, item),
944
- config: config2,
945
- roothPath
946
- });
947
- }
948
- staticMediaItems.push(staticMediaItem);
804
+ isUsingTs() {
805
+ return [".ts", ".tsx"].includes(import_path2.default.extname(this.tinaConfigFilePath));
949
806
  }
950
- function chunkArrayIntoObject(array, chunkSize) {
951
- const result = {};
952
- for (let i = 0; i < array.length; i += chunkSize) {
953
- const chunkKey = `${i / chunkSize * 20}`;
954
- result[chunkKey] = array.slice(i, i + chunkSize);
807
+ hasSelfHostedConfig() {
808
+ return !!this.selfHostedDatabaseFilePath;
809
+ }
810
+ hasSeparateContentRoot() {
811
+ return this.rootPath !== this.contentRootPath;
812
+ }
813
+ shouldSkipSDK() {
814
+ var _a;
815
+ if (this.legacyNoSDK) {
816
+ return this.legacyNoSDK;
955
817
  }
956
- return result;
818
+ return ((_a = this.config.client) == null ? void 0 : _a.skip) || false;
957
819
  }
958
- return chunkArrayIntoObject(staticMediaItems, 20);
959
- }
960
- var createConfig = async ({
961
- configManager,
962
- apiURL,
963
- plugins = [],
964
- noWatch,
965
- rollupOptions
966
- }) => {
967
- var _a, _b, _c, _d, _e, _f, _g, _h;
968
- const publicEnv = {};
969
- Object.keys(process.env).forEach((key) => {
970
- if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
971
- try {
972
- if (typeof process.env[key] === "string") {
973
- publicEnv[key] = process.env[key];
974
- } else {
975
- publicEnv[key] = JSON.stringify(process.env[key]);
976
- }
977
- } catch (error) {
978
- console.warn(
979
- `Could not stringify public env process.env.${key} env variable`
820
+ async processConfig() {
821
+ this.tinaFolderPath = await this.getTinaFolderPath(this.rootPath);
822
+ this.envFilePath = import_path2.default.resolve(
823
+ import_path2.default.join(this.tinaFolderPath, "..", ".env")
824
+ );
825
+ dotenv.config({ path: this.envFilePath });
826
+ this.tinaConfigFilePath = await this.getPathWithExtension(
827
+ import_path2.default.join(this.tinaFolderPath, "config")
828
+ );
829
+ if (!this.tinaConfigFilePath) {
830
+ throw new Error(
831
+ `Unable to find config file in ${this.tinaFolderPath}. Looking for a file named "config.{ts,tsx,js,jsx}"`
832
+ );
833
+ }
834
+ this.selfHostedDatabaseFilePath = await this.getPathWithExtension(
835
+ import_path2.default.join(this.tinaFolderPath, "database")
836
+ );
837
+ this.generatedFolderPath = import_path2.default.join(this.tinaFolderPath, GENERATED_FOLDER);
838
+ this.generatedCachePath = import_path2.default.join(
839
+ this.generatedFolderPath,
840
+ ".cache",
841
+ String((/* @__PURE__ */ new Date()).getTime())
842
+ );
843
+ this.generatedGraphQLGQLPath = import_path2.default.join(
844
+ this.generatedFolderPath,
845
+ GRAPHQL_GQL_FILE
846
+ );
847
+ this.generatedGraphQLJSONPath = import_path2.default.join(
848
+ this.generatedFolderPath,
849
+ GRAPHQL_JSON_FILE
850
+ );
851
+ this.generatedSchemaJSONPath = import_path2.default.join(
852
+ this.generatedFolderPath,
853
+ SCHEMA_JSON_FILE
854
+ );
855
+ this.generatedLookupJSONPath = import_path2.default.join(
856
+ this.generatedFolderPath,
857
+ LOOKUP_JSON_FILE
858
+ );
859
+ this.generatedQueriesFilePath = import_path2.default.join(
860
+ this.generatedFolderPath,
861
+ "queries.gql"
862
+ );
863
+ this.generatedFragmentsFilePath = import_path2.default.join(
864
+ this.generatedFolderPath,
865
+ "frags.gql"
866
+ );
867
+ this.generatedTypesTSFilePath = import_path2.default.join(
868
+ this.generatedFolderPath,
869
+ "types.ts"
870
+ );
871
+ this.generatedTypesJSFilePath = import_path2.default.join(
872
+ this.generatedFolderPath,
873
+ "types.js"
874
+ );
875
+ this.generatedTypesDFilePath = import_path2.default.join(
876
+ this.generatedFolderPath,
877
+ "types.d.ts"
878
+ );
879
+ this.userQueriesAndFragmentsGlob = import_path2.default.join(
880
+ this.tinaFolderPath,
881
+ "queries/**/*.{graphql,gql}"
882
+ );
883
+ this.generatedQueriesAndFragmentsGlob = import_path2.default.join(
884
+ this.generatedFolderPath,
885
+ "*.{graphql,gql}"
886
+ );
887
+ this.generatedClientTSFilePath = import_path2.default.join(
888
+ this.generatedFolderPath,
889
+ "client.ts"
890
+ );
891
+ this.generatedClientJSFilePath = import_path2.default.join(
892
+ this.generatedFolderPath,
893
+ "client.js"
894
+ );
895
+ this.generatedClientDFilePath = import_path2.default.join(
896
+ this.generatedFolderPath,
897
+ "client.d.ts"
898
+ );
899
+ this.generatedDatabaseClientDFilePath = import_path2.default.join(
900
+ this.generatedFolderPath,
901
+ "databaseClient.d.ts"
902
+ );
903
+ this.generatedDatabaseClientTSFilePath = import_path2.default.join(
904
+ this.generatedFolderPath,
905
+ "databaseClient.ts"
906
+ );
907
+ this.generatedDatabaseClientJSFilePath = import_path2.default.join(
908
+ this.generatedFolderPath,
909
+ "databaseClient.js"
910
+ );
911
+ const clientExists = this.isUsingTs() ? await import_fs_extra2.default.pathExists(this.generatedClientTSFilePath) : await import_fs_extra2.default.pathExists(this.generatedClientJSFilePath);
912
+ if (!clientExists) {
913
+ const file = "export default ()=>({})\nexport const client = ()=>({})";
914
+ if (this.isUsingTs()) {
915
+ await import_fs_extra2.default.outputFile(this.generatedClientTSFilePath, file);
916
+ } else {
917
+ await import_fs_extra2.default.outputFile(this.generatedClientJSFilePath, file);
918
+ }
919
+ }
920
+ const { config: config2, prebuildPath, watchList } = await this.loadConfigFile(
921
+ this.generatedFolderPath,
922
+ this.tinaConfigFilePath
923
+ );
924
+ this.watchList = watchList;
925
+ this.config = config2;
926
+ this.prebuildFilePath = prebuildPath;
927
+ this.publicFolderPath = import_path2.default.join(
928
+ this.rootPath,
929
+ this.config.build.publicFolder
930
+ );
931
+ this.outputFolderPath = import_path2.default.join(
932
+ this.publicFolderPath,
933
+ this.config.build.outputFolder
934
+ );
935
+ this.outputHTMLFilePath = import_path2.default.join(this.outputFolderPath, "index.html");
936
+ this.outputGitignorePath = import_path2.default.join(this.outputFolderPath, ".gitignore");
937
+ const fullLocalContentPath = import_path2.default.join(
938
+ this.tinaFolderPath,
939
+ this.config.localContentPath || ""
940
+ );
941
+ if (this.config.localContentPath) {
942
+ const localContentPathExists = await import_fs_extra2.default.pathExists(fullLocalContentPath);
943
+ if (localContentPathExists) {
944
+ logger.info(`Using separate content repo at ${fullLocalContentPath}`);
945
+ this.contentRootPath = fullLocalContentPath;
946
+ } else {
947
+ logger.warn(
948
+ `${import_chalk3.default.yellow("Warning:")} The localContentPath ${import_chalk3.default.cyan(
949
+ fullLocalContentPath
950
+ )} does not exist. Please create it or remove the localContentPath from your config file at ${import_chalk3.default.cyan(
951
+ this.tinaConfigFilePath
952
+ )}`
980
953
  );
981
- console.warn(error);
982
954
  }
983
955
  }
984
- });
985
- const staticMediaPath = import_node_path2.default.join(
986
- configManager.generatedFolderPath,
987
- "static-media.json"
988
- );
989
- if ((_b = (_a = configManager.config.media) == null ? void 0 : _a.tina) == null ? void 0 : _b.static) {
990
- const staticMedia = await listFilesRecursively({
991
- directoryPath: ((_c = configManager.config.media.tina) == null ? void 0 : _c.mediaRoot) || "",
992
- config: configManager.config.media.tina,
993
- roothPath: configManager.rootPath
994
- });
995
- await import_fs_extra2.default.outputFile(staticMediaPath, JSON.stringify(staticMedia, null, 2));
996
- } else {
997
- await import_fs_extra2.default.outputFile(staticMediaPath, `[]`);
956
+ if (!this.contentRootPath) {
957
+ this.contentRootPath = this.rootPath;
958
+ }
959
+ this.generatedFolderPathContentRepo = import_path2.default.join(
960
+ await this.getTinaFolderPath(this.contentRootPath),
961
+ GENERATED_FOLDER
962
+ );
963
+ this.spaMainPath = require.resolve("@tinacms/app");
964
+ this.spaRootPath = import_path2.default.join(this.spaMainPath, "..", "..");
998
965
  }
999
- const alias = {
1000
- TINA_IMPORT: configManager.prebuildFilePath,
1001
- SCHEMA_IMPORT: configManager.generatedGraphQLJSONPath,
1002
- STATIC_MEDIA_IMPORT: staticMediaPath,
1003
- crypto: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1004
- fs: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1005
- os: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1006
- path: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts")
1007
- };
1008
- if (configManager.shouldSkipSDK()) {
1009
- alias["CLIENT_IMPORT"] = import_node_path2.default.join(
1010
- configManager.spaRootPath,
1011
- "src",
1012
- "dummy-client.ts"
966
+ async getTinaFolderPath(rootPath) {
967
+ const tinaFolderPath = import_path2.default.join(rootPath, TINA_FOLDER);
968
+ const tinaFolderExists = await import_fs_extra2.default.pathExists(tinaFolderPath);
969
+ if (tinaFolderExists) {
970
+ this.isUsingLegacyFolder = false;
971
+ return tinaFolderPath;
972
+ }
973
+ const legacyFolderPath = import_path2.default.join(rootPath, LEGACY_TINA_FOLDER);
974
+ const legacyFolderExists = await import_fs_extra2.default.pathExists(legacyFolderPath);
975
+ if (legacyFolderExists) {
976
+ this.isUsingLegacyFolder = true;
977
+ return legacyFolderPath;
978
+ }
979
+ throw new Error(
980
+ `Unable to find Tina folder, if you're working in folder outside of the Tina config be sure to specify --rootPath`
1013
981
  );
1014
- } else {
1015
- alias["CLIENT_IMPORT"] = configManager.isUsingTs() ? configManager.generatedTypesTSFilePath : configManager.generatedTypesJSFilePath;
1016
982
  }
1017
- let basePath;
1018
- if (configManager.config.build.basePath) {
1019
- basePath = configManager.config.build.basePath;
983
+ getTinaGraphQLVersion() {
984
+ if (this.tinaGraphQLVersionFromCLI) {
985
+ const version2 = this.tinaGraphQLVersionFromCLI.split(".");
986
+ return {
987
+ fullVersion: this.tinaGraphQLVersionFromCLI,
988
+ major: version2[0] || "x",
989
+ minor: version2[1] || "x",
990
+ patch: version2[2] || "x"
991
+ };
992
+ }
993
+ const generatedSchema = import_fs_extra2.default.readJSONSync(this.generatedSchemaJSONPath);
994
+ if (!generatedSchema || !(typeof (generatedSchema == null ? void 0 : generatedSchema.version) !== "undefined")) {
995
+ throw new Error(
996
+ `Can not find Tina GraphQL version in ${this.generatedSchemaJSONPath}`
997
+ );
998
+ }
999
+ return generatedSchema.version;
1020
1000
  }
1021
- const fullVersion = configManager.getTinaGraphQLVersion();
1022
- const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1023
- const config2 = {
1024
- root: configManager.spaRootPath,
1025
- base: `/${basePath ? `${(0, import_normalize_path2.default)(basePath)}/` : ""}${(0, import_normalize_path2.default)(
1026
- configManager.config.build.outputFolder
1027
- )}/`,
1028
- appType: "spa",
1029
- resolve: {
1030
- alias,
1031
- dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1032
- },
1033
- define: {
1034
- /**
1035
- * Since we prebuild the config.ts, it's possible for modules to be loaded which make
1036
- * use of `process`. The main scenario where this is an issue is when co-locating schema
1037
- * definitions with source files, and specifically source files which impor from NextJS.
1038
- *
1039
- * Some examples of what NextJS uses for `process.env` are:
1040
- * - `process.env.__NEXT_TRAILING_SLASH`
1041
- * - `process.env.__NEXT_CROSS_ORIGIN`
1042
- * - `process.env.__NEXT_I18N_SUPPORT`
1043
- *
1044
- * Also, interestingly some of the advice for handling this doesn't work, references to replacing
1045
- * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
1046
- * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1047
- */
1048
- "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1049
- // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1050
- "process.platform": `"${process.platform}"`,
1051
- __API_URL__: `"${apiURL}"`,
1052
- __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1053
- __TINA_GRAPHQL_VERSION__: version2
1054
- },
1055
- logLevel: "error",
1056
- // Vite import warnings are noisy
1057
- optimizeDeps: {
1058
- force: true,
1059
- // Not 100% sure why this isn't being picked up automatically, this works from within the monorepo
1060
- // but breaks externally
1061
- include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1062
- },
1063
- server: {
1064
- host: (_h = (_g = (_f = configManager.config) == null ? void 0 : _f.build) == null ? void 0 : _g.host) != null ? _h : false,
1065
- watch: noWatch ? {
1066
- ignored: ["**/*"]
1067
- } : {
1068
- // Ignore everything except for the alias fields we specified above
1069
- ignored: [
1070
- `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1071
- ]
1072
- },
1073
- fs: {
1074
- strict: false
1075
- }
1076
- },
1077
- build: {
1078
- sourcemap: false,
1079
- outDir: configManager.outputFolderPath,
1080
- emptyOutDir: true,
1081
- rollupOptions
1082
- },
1083
- plugins: [
1084
- /**
1085
- * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
1086
- * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
1087
- */
1088
- (0, import_plugin_react.default)({
1089
- babel: {
1090
- // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1091
- compact: true
1092
- }
1093
- }),
1094
- (0, import_vite.splitVendorChunkPlugin)(),
1095
- tinaTailwind(configManager.spaRootPath, configManager.prebuildFilePath),
1096
- ...plugins
1097
- ]
1098
- };
1099
- return config2;
1100
- };
1101
-
1102
- // src/next/vite/plugins.ts
1103
- var import_pluginutils = require("@rollup/pluginutils");
1104
- var import_fs = __toESM(require("fs"));
1105
- var import_vite2 = require("vite");
1106
- var import_esbuild = require("esbuild");
1107
- var import_path3 = __toESM(require("path"));
1108
- var import_body_parser = __toESM(require("body-parser"));
1109
- var import_cors = __toESM(require("cors"));
1110
- var import_graphql = require("@tinacms/graphql");
1111
-
1112
- // src/next/commands/dev-command/server/media.ts
1113
- var import_fs_extra3 = __toESM(require("fs-extra"));
1114
- var import_path2 = __toESM(require("path"));
1115
- var import_busboy = __toESM(require("busboy"));
1116
- var createMediaRouter = (config2) => {
1117
- const mediaFolder = import_path2.default.join(
1118
- config2.rootPath,
1119
- config2.publicFolder,
1120
- config2.mediaRoot
1121
- );
1122
- const mediaModel = new MediaModel(config2);
1123
- const handleList = async (req, res) => {
1124
- const requestURL = new URL(req.url, config2.apiURL);
1125
- const folder = requestURL.pathname.replace("/media/list/", "");
1126
- const limit = requestURL.searchParams.get("limit");
1127
- const cursor = requestURL.searchParams.get("cursor");
1128
- const media = await mediaModel.listMedia({
1129
- searchPath: folder,
1130
- cursor,
1131
- limit
1001
+ printGeneratedClientFilePath() {
1002
+ if (this.isUsingTs()) {
1003
+ return this.generatedClientTSFilePath.replace(`${this.rootPath}/`, "");
1004
+ }
1005
+ return this.generatedClientJSFilePath.replace(`${this.rootPath}/`, "");
1006
+ }
1007
+ printGeneratedTypesFilePath() {
1008
+ return this.generatedTypesTSFilePath.replace(`${this.rootPath}/`, "");
1009
+ }
1010
+ printoutputHTMLFilePath() {
1011
+ return this.outputHTMLFilePath.replace(`${this.publicFolderPath}/`, "");
1012
+ }
1013
+ printRelativePath(filename) {
1014
+ if (filename) {
1015
+ return filename.replace(/\\/g, "/").replace(`${this.rootPath}/`, "");
1016
+ }
1017
+ throw `No path provided to print`;
1018
+ }
1019
+ printPrebuildFilePath() {
1020
+ return this.prebuildFilePath.replace(/\\/g, "/").replace(`${this.rootPath}/${this.tinaFolderPath}/`, "");
1021
+ }
1022
+ printContentRelativePath(filename) {
1023
+ if (filename) {
1024
+ return filename.replace(/\\/g, "/").replace(`${this.contentRootPath}/`, "");
1025
+ }
1026
+ throw `No path provided to print`;
1027
+ }
1028
+ /**
1029
+ * Given a filepath without an extension, find the first match (eg. tsx, ts, jsx, js)
1030
+ */
1031
+ async getPathWithExtension(filepath) {
1032
+ const extensions = ["tsx", "ts", "jsx", "js"];
1033
+ let result;
1034
+ await Promise.all(
1035
+ extensions.map(async (ext) => {
1036
+ if (result) {
1037
+ return;
1038
+ }
1039
+ const filepathWithExtension = `${filepath}.${ext}`;
1040
+ const exists = import_fs_extra2.default.existsSync(filepathWithExtension);
1041
+ if (exists) {
1042
+ result = filepathWithExtension;
1043
+ }
1044
+ })
1045
+ );
1046
+ return result;
1047
+ }
1048
+ async loadDatabaseFile() {
1049
+ const tmpdir = import_path2.default.join(import_os.default.tmpdir(), Date.now().toString());
1050
+ const outfile = import_path2.default.join(tmpdir, "database.build.js");
1051
+ await esbuild.build({
1052
+ entryPoints: [this.selfHostedDatabaseFilePath],
1053
+ bundle: true,
1054
+ platform: "node",
1055
+ outfile,
1056
+ loader: loaders
1132
1057
  });
1133
- res.end(JSON.stringify(media));
1134
- };
1135
- const handleDelete = async (req, res) => {
1136
- const file = decodeURIComponent(req.url.slice("/media/".length));
1137
- const didDelete = await mediaModel.deleteMedia({ searchPath: file });
1138
- res.end(JSON.stringify(didDelete));
1139
- };
1140
- const handlePost = async function(req, res) {
1141
- const bb = (0, import_busboy.default)({ headers: req.headers });
1142
- bb.on("file", async (_name, file, _info) => {
1143
- var _a;
1144
- const fullPath = decodeURI((_a = req.url) == null ? void 0 : _a.slice("/media/upload/".length));
1145
- const saveTo = import_path2.default.join(mediaFolder, ...fullPath.split("/"));
1146
- await import_fs_extra3.default.ensureDir(import_path2.default.dirname(saveTo));
1147
- file.pipe(import_fs_extra3.default.createWriteStream(saveTo));
1058
+ const result = require(outfile);
1059
+ import_fs_extra2.default.removeSync(outfile);
1060
+ return result.default;
1061
+ }
1062
+ async loadConfigFile(generatedFolderPath, configFilePath) {
1063
+ const tmpdir = import_path2.default.join(import_os.default.tmpdir(), Date.now().toString());
1064
+ const preBuildConfigPath = import_path2.default.join(
1065
+ this.generatedFolderPath,
1066
+ "config.prebuild.jsx"
1067
+ );
1068
+ const outfile = import_path2.default.join(tmpdir, "config.build.jsx");
1069
+ const outfile2 = import_path2.default.join(tmpdir, "config.build.js");
1070
+ const tempTSConfigFile = import_path2.default.join(tmpdir, "tsconfig.json");
1071
+ import_fs_extra2.default.outputFileSync(tempTSConfigFile, "{}");
1072
+ const result2 = await esbuild.build({
1073
+ entryPoints: [configFilePath],
1074
+ bundle: true,
1075
+ target: ["es2020"],
1076
+ platform: "browser",
1077
+ format: "esm",
1078
+ logLevel: "silent",
1079
+ packages: "external",
1080
+ ignoreAnnotations: true,
1081
+ outfile: preBuildConfigPath,
1082
+ loader: loaders,
1083
+ metafile: true
1148
1084
  });
1149
- bb.on("error", (error) => {
1150
- res.statusCode = 500;
1151
- if (error instanceof Error) {
1152
- res.end(JSON.stringify({ message: error }));
1153
- } else {
1154
- res.end(JSON.stringify({ message: "Unknown error while uploading" }));
1085
+ const flattenedList = [];
1086
+ Object.keys(result2.metafile.inputs).forEach((key) => {
1087
+ if (key.includes("node_modules") || key.includes("__generated__")) {
1088
+ return;
1155
1089
  }
1090
+ flattenedList.push(key);
1156
1091
  });
1157
- bb.on("close", () => {
1158
- res.statusCode = 200;
1159
- res.end(JSON.stringify({ success: true }));
1092
+ await esbuild.build({
1093
+ entryPoints: [configFilePath],
1094
+ bundle: true,
1095
+ target: ["es2020"],
1096
+ logLevel: "silent",
1097
+ platform: "node",
1098
+ outfile,
1099
+ loader: loaders
1160
1100
  });
1161
- req.pipe(bb);
1162
- };
1163
- return { handleList, handleDelete, handlePost };
1164
- };
1165
- var parseMediaFolder = (str) => {
1166
- let returnString = str;
1167
- if (returnString.startsWith("/")) returnString = returnString.substr(1);
1168
- if (returnString.endsWith("/"))
1169
- returnString = returnString.substr(0, returnString.length - 1);
1170
- return returnString;
1171
- };
1172
- var MediaModel = class {
1173
- constructor({ rootPath, publicFolder, mediaRoot }) {
1174
- this.rootPath = rootPath;
1175
- this.mediaRoot = mediaRoot;
1176
- this.publicFolder = publicFolder;
1177
- }
1178
- async listMedia(args) {
1179
- try {
1180
- const folderPath = (0, import_path2.join)(
1181
- this.rootPath,
1182
- this.publicFolder,
1183
- this.mediaRoot,
1184
- args.searchPath
1185
- );
1186
- const searchPath = parseMediaFolder(args.searchPath);
1187
- if (!await import_fs_extra3.default.pathExists(folderPath)) {
1188
- return {
1189
- files: [],
1190
- directories: []
1191
- };
1192
- }
1193
- const filesStr = await import_fs_extra3.default.readdir(folderPath);
1194
- const filesProm = filesStr.map(async (file) => {
1195
- const filePath = (0, import_path2.join)(folderPath, file);
1196
- const stat = await import_fs_extra3.default.stat(filePath);
1197
- let src = `/${file}`;
1198
- const isFile = stat.isFile();
1199
- if (!isFile) {
1200
- return {
1201
- isFile,
1202
- size: stat.size,
1203
- src,
1204
- filename: file
1205
- };
1206
- }
1207
- if (searchPath) {
1208
- src = `/${searchPath}${src}`;
1209
- }
1210
- if (this.mediaRoot) {
1211
- src = `/${this.mediaRoot}${src}`;
1212
- }
1213
- return {
1214
- isFile,
1215
- size: stat.size,
1216
- src,
1217
- filename: file
1218
- };
1219
- });
1220
- const offset = Number(args.cursor) || 0;
1221
- const limit = Number(args.limit) || 20;
1222
- const rawItems = await Promise.all(filesProm);
1223
- const sortedItems = rawItems.sort((a, b) => {
1224
- if (a.isFile && !b.isFile) {
1225
- return 1;
1226
- }
1227
- if (!a.isFile && b.isFile) {
1228
- return -1;
1229
- }
1230
- return 0;
1231
- });
1232
- const limitItems = sortedItems.slice(offset, offset + limit);
1233
- const files = limitItems.filter((x) => x.isFile);
1234
- const directories = limitItems.filter((x) => !x.isFile).map((x) => x.src);
1235
- const cursor = rawItems.length > offset + limit ? String(offset + limit) : null;
1236
- return {
1237
- files,
1238
- directories,
1239
- cursor
1240
- };
1241
- } catch (error) {
1242
- console.error(error);
1243
- return {
1244
- files: [],
1245
- directories: [],
1246
- error: error == null ? void 0 : error.toString()
1247
- };
1248
- }
1249
- }
1250
- async deleteMedia(args) {
1101
+ await esbuild.build({
1102
+ entryPoints: [outfile],
1103
+ bundle: true,
1104
+ // Suppress warning about comparison with -0 from client module
1105
+ logLevel: "silent",
1106
+ platform: "node",
1107
+ outfile: outfile2,
1108
+ loader: loaders
1109
+ });
1110
+ let result;
1251
1111
  try {
1252
- const file = (0, import_path2.join)(
1253
- this.rootPath,
1254
- this.publicFolder,
1255
- this.mediaRoot,
1256
- args.searchPath
1257
- );
1258
- await import_fs_extra3.default.stat(file);
1259
- await import_fs_extra3.default.remove(file);
1260
- return { ok: true };
1261
- } catch (error) {
1262
- console.error(error);
1263
- return { ok: false, message: error == null ? void 0 : error.toString() };
1112
+ result = require(outfile2);
1113
+ } catch (e) {
1114
+ console.error("Unexpected error loading config");
1115
+ console.error(e);
1116
+ throw e;
1264
1117
  }
1118
+ import_fs_extra2.default.removeSync(outfile);
1119
+ import_fs_extra2.default.removeSync(outfile2);
1120
+ return {
1121
+ config: result.default,
1122
+ prebuildPath: preBuildConfigPath,
1123
+ watchList: flattenedList
1124
+ };
1265
1125
  }
1266
1126
  };
1267
-
1268
- // src/next/commands/dev-command/server/searchIndex.ts
1269
- var createSearchIndexRouter = ({
1270
- config: config2,
1271
- searchIndex
1272
- }) => {
1273
- const put = async (req, res) => {
1274
- const { docs } = req.body;
1275
- const result = await searchIndex.PUT(docs);
1276
- res.writeHead(200, { "Content-Type": "application/json" });
1277
- res.end(JSON.stringify({ result }));
1278
- };
1279
- const get = async (req, res) => {
1280
- const requestURL = new URL(req.url, config2.apiURL);
1281
- const query = requestURL.searchParams.get("q");
1282
- const optionsParam = requestURL.searchParams.get("options");
1283
- let options = {
1284
- DOCUMENTS: false
1285
- };
1286
- if (optionsParam) {
1287
- options = {
1288
- ...options,
1289
- ...JSON.parse(optionsParam)
1290
- };
1291
- }
1292
- res.writeHead(200, { "Content-Type": "application/json" });
1293
- if (query) {
1294
- const result = await searchIndex.QUERY(JSON.parse(query), options);
1295
- res.end(JSON.stringify(result));
1296
- } else {
1297
- res.end(JSON.stringify({ RESULT: [] }));
1298
- }
1299
- };
1300
- const del = async (req, res) => {
1301
- const requestURL = new URL(req.url, config2.apiURL);
1302
- const docId = requestURL.pathname.split("/").filter(Boolean).slice(1).join("/");
1303
- const result = await searchIndex.DELETE(docId);
1304
- res.writeHead(200, { "Content-Type": "application/json" });
1305
- res.end(JSON.stringify({ result }));
1306
- };
1307
- return { del, get, put };
1127
+ var loaders = {
1128
+ ".aac": "file",
1129
+ ".css": "file",
1130
+ ".eot": "file",
1131
+ ".flac": "file",
1132
+ ".gif": "file",
1133
+ ".jpeg": "file",
1134
+ ".jpg": "file",
1135
+ ".json": "json",
1136
+ ".mp3": "file",
1137
+ ".mp4": "file",
1138
+ ".ogg": "file",
1139
+ ".otf": "file",
1140
+ ".png": "file",
1141
+ ".svg": "file",
1142
+ ".ttf": "file",
1143
+ ".wav": "file",
1144
+ ".webm": "file",
1145
+ ".webp": "file",
1146
+ ".woff": "file",
1147
+ ".woff2": "file",
1148
+ ".js": "jsx",
1149
+ ".jsx": "jsx",
1150
+ ".tsx": "tsx"
1308
1151
  };
1309
1152
 
1310
- // src/next/vite/plugins.ts
1311
- var transformTsxPlugin = ({
1312
- configManager: _configManager
1313
- }) => {
1314
- const plug = {
1315
- name: "transform-tsx",
1316
- async transform(code, id) {
1317
- const extName = import_path3.default.extname(id);
1318
- if (extName.startsWith(".tsx") || extName.startsWith(".ts")) {
1319
- const result = await (0, import_esbuild.transform)(code, { loader: "tsx" });
1320
- return {
1321
- code: result.code
1322
- };
1323
- }
1324
- }
1325
- };
1326
- return plug;
1327
- };
1328
- var devServerEndPointsPlugin = ({
1329
- configManager,
1330
- apiURL,
1331
- database,
1332
- searchIndex
1333
- }) => {
1334
- const plug = {
1335
- name: "graphql-endpoints",
1336
- configureServer(server) {
1337
- server.middlewares.use((0, import_cors.default)());
1338
- server.middlewares.use(import_body_parser.default.json({ limit: "5mb" }));
1339
- server.middlewares.use(async (req, res, next) => {
1340
- var _a;
1341
- const mediaPaths = (_a = configManager.config.media) == null ? void 0 : _a.tina;
1342
- const mediaRouter = createMediaRouter({
1343
- rootPath: configManager.rootPath,
1344
- apiURL,
1345
- publicFolder: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.publicFolder) || ""),
1346
- mediaRoot: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.mediaRoot) || "")
1347
- });
1348
- const searchIndexRouter = createSearchIndexRouter({
1349
- config: { apiURL, searchPath: "searchIndex" },
1350
- searchIndex
1351
- });
1352
- if (req.url.startsWith("/media/upload")) {
1353
- await mediaRouter.handlePost(req, res);
1354
- return;
1355
- }
1356
- if (req.url.startsWith("/media")) {
1357
- if (req.method === "DELETE") {
1358
- await mediaRouter.handleDelete(req, res);
1359
- return;
1360
- }
1361
- }
1362
- if (req.url.startsWith("/media/list")) {
1363
- await mediaRouter.handleList(req, res);
1364
- return;
1365
- }
1366
- if (req.url === "/altair") {
1367
- res.end(
1368
- JSON.stringify({
1369
- status: "The GraphQL playground has moved to <your-dev-url>/index.html#/graphql"
1370
- })
1371
- );
1372
- return;
1373
- }
1374
- if (req.url === "/graphql") {
1375
- const { query, variables } = req.body;
1376
- const result = await (0, import_graphql.resolve)({
1377
- config: {
1378
- useRelativeMedia: true
1379
- },
1380
- database,
1381
- query,
1382
- variables,
1383
- verbose: false
1384
- });
1385
- res.end(JSON.stringify(result));
1386
- return;
1387
- }
1388
- if (req.url.startsWith("/searchIndex")) {
1389
- if (req.method === "POST") {
1390
- await searchIndexRouter.put(req, res);
1391
- } else if (req.method === "GET") {
1392
- await searchIndexRouter.get(req, res);
1393
- } else if (req.method === "DELETE") {
1394
- await searchIndexRouter.del(req, res);
1395
- }
1396
- return;
1397
- }
1398
- next();
1399
- });
1153
+ // src/next/database.ts
1154
+ var import_graphql7 = require("@tinacms/graphql");
1155
+ var import_readable_stream = require("readable-stream");
1156
+ var import_net = require("net");
1157
+ var import_many_level = require("many-level");
1158
+ var import_memory_level = require("memory-level");
1159
+ var createDBServer = (port) => {
1160
+ const levelHost = new import_many_level.ManyLevelHost(
1161
+ // @ts-ignore
1162
+ new import_memory_level.MemoryLevel({
1163
+ valueEncoding: "json"
1164
+ })
1165
+ );
1166
+ const dbServer = (0, import_net.createServer)(function(socket) {
1167
+ return (0, import_readable_stream.pipeline)(socket, levelHost.createRpcStream(), socket, () => {
1168
+ });
1169
+ });
1170
+ dbServer.once("error", (err) => {
1171
+ if ((err == null ? void 0 : err.code) === "EADDRINUSE") {
1172
+ throw new Error(
1173
+ `Tina Dev server is already in use. Datalayer server is busy on port ${port}`
1174
+ );
1400
1175
  }
1401
- };
1402
- return plug;
1176
+ });
1177
+ dbServer.listen(port);
1403
1178
  };
1404
- function viteTransformExtension({
1405
- exportAsDefault = true,
1406
- svgrOptions,
1407
- esbuildOptions,
1408
- include = "**/*.svg",
1409
- exclude
1410
- } = {}) {
1411
- const filter = (0, import_pluginutils.createFilter)(include, exclude);
1412
- return {
1413
- name: "vite-plugin-svgr",
1414
- async transform(code, id) {
1415
- if (filter(id)) {
1416
- const { transform: transform2 } = await Promise.resolve().then(() => __toESM(require("@svgr/core")));
1417
- const svgCode = await import_fs.default.promises.readFile(
1418
- id.replace(/\?.*$/, ""),
1419
- "utf8"
1420
- );
1421
- const componentCode = await transform2(svgCode, svgrOptions, {
1422
- filePath: id,
1423
- caller: {
1424
- previousExport: exportAsDefault ? null : code
1425
- }
1426
- });
1427
- const res = await (0, import_vite2.transformWithEsbuild)(componentCode, id, {
1428
- loader: "jsx",
1429
- ...esbuildOptions
1430
- });
1431
- return {
1432
- code: res.code,
1433
- map: null
1434
- // TODO:
1435
- };
1436
- }
1179
+ async function createAndInitializeDatabase(configManager, datalayerPort, bridgeOverride) {
1180
+ let database;
1181
+ const bridge = bridgeOverride || new import_graphql7.FilesystemBridge(configManager.rootPath, configManager.contentRootPath);
1182
+ if (configManager.hasSelfHostedConfig() && configManager.config.contentApiUrlOverride) {
1183
+ database = await configManager.loadDatabaseFile();
1184
+ database.bridge = bridge;
1185
+ } else {
1186
+ if (configManager.hasSelfHostedConfig() && !configManager.config.contentApiUrlOverride) {
1187
+ logger.warn(
1188
+ `Found a database config file at ${configManager.printRelativePath(
1189
+ configManager.selfHostedDatabaseFilePath
1190
+ )} but there was no "contentApiUrlOverride" set. Falling back to built-in datalayer`
1191
+ );
1437
1192
  }
1438
- };
1193
+ const level = new import_graphql7.TinaLevelClient(datalayerPort);
1194
+ level.openConnection();
1195
+ database = (0, import_graphql7.createDatabaseInternal)({
1196
+ bridge,
1197
+ level,
1198
+ tinaDirectory: configManager.isUsingLegacyFolder ? LEGACY_TINA_FOLDER : TINA_FOLDER
1199
+ });
1200
+ }
1201
+ return database;
1439
1202
  }
1440
1203
 
1441
- // src/next/commands/dev-command/server/index.ts
1442
- var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch) => {
1443
- const plugins = [
1444
- transformTsxPlugin({ configManager }),
1445
- devServerEndPointsPlugin({ apiURL, configManager, database, searchIndex }),
1446
- viteTransformExtension()
1447
- ];
1448
- return (0, import_vite3.createServer)(
1449
- await createConfig({
1450
- configManager,
1451
- database,
1452
- apiURL,
1453
- plugins,
1454
- noWatch,
1455
- /**
1456
- * Ensure Vite's import scan uses the spaMainPath as the input
1457
- * so it properly finds everything. This is for dev only, and when
1458
- * running the server outside of this monorepo vite fails to find
1459
- * and optimize the imports, so you get errors about it not being
1460
- * able to find an export from a module, and it's always a CJS
1461
- * module that Vite would usually transform to an ES module.
1462
- */
1463
- rollupOptions: {
1464
- input: configManager.spaMainPath,
1465
- onwarn(warning, warn) {
1466
- if (warning.code === "MODULE_LEVEL_DIRECTIVE") {
1467
- return;
1468
- }
1469
- warn(warning);
1470
- }
1471
- }
1472
- })
1473
- );
1474
- };
1204
+ // src/next/commands/baseCommands.ts
1205
+ var import_clipanion = require("clipanion");
1206
+ var import_chalk4 = __toESM(require("chalk"));
1475
1207
 
1476
- // src/next/codegen/index.ts
1477
- var import_fs_extra4 = __toESM(require("fs-extra"));
1478
- var import_path4 = __toESM(require("path"));
1479
- var import_graphql6 = require("graphql");
1480
-
1481
- // src/next/codegen/codegen/index.ts
1482
- var import_graphql5 = require("graphql");
1483
-
1484
- // src/next/codegen/codegen/plugin.ts
1485
- var AddGeneratedClientFunc = (apiURL) => {
1486
- return (_schema, _documents, _config, _info) => {
1487
- return `
1488
- // TinaSDK generated code
1489
- import { createClient, TinaClient } from "tinacms/dist/client";
1490
-
1491
- const generateRequester = (
1492
- client: TinaClient,
1493
- ) => {
1494
- const requester: (
1495
- doc: any,
1496
- vars?: any,
1497
- options?: {
1498
- branch?: string,
1499
- /**
1500
- * Aside from \`method\` and \`body\`, all fetch options are passed
1501
- * through to underlying fetch request
1502
- */
1503
- fetchOptions?: Omit<Parameters<typeof fetch>[1], 'body' | 'method'>,
1504
- },
1505
- client
1506
- ) => Promise<any> = async (doc, vars, options) => {
1507
- let url = client.apiUrl
1508
- if (options?.branch) {
1509
- const index = client.apiUrl.lastIndexOf('/')
1510
- url = client.apiUrl.substring(0, index + 1) + options.branch
1511
- }
1512
- const data = await client.request({
1513
- query: doc,
1514
- variables: vars,
1515
- url,
1516
- }, options)
1208
+ // src/utils/start-subprocess.ts
1209
+ var import_child_process = __toESM(require("child_process"));
1210
+ var startSubprocess2 = async ({ command: command2 }) => {
1211
+ if (typeof command2 === "string") {
1212
+ const commands = command2.split(" ");
1213
+ const firstCommand = commands[0];
1214
+ const args = commands.slice(1) || [];
1215
+ const ps = import_child_process.default.spawn(firstCommand, args, {
1216
+ stdio: "inherit",
1217
+ shell: true
1218
+ });
1219
+ ps.on("error", (code) => {
1220
+ logger.error(
1221
+ dangerText(
1222
+ `An error has occurred in the Next.js child process. Error message below`
1223
+ )
1224
+ );
1225
+ logger.error(`name: ${code.name}
1226
+ message: ${code.message}
1517
1227
 
1518
- return { data: data?.data, errors: data?.errors, query: doc, variables: vars || {} }
1228
+ stack: ${code.stack || "No stack was provided"}`);
1229
+ });
1230
+ ps.on("close", (code) => {
1231
+ logger.info(`child process exited with code ${code}`);
1232
+ process.exit(code);
1233
+ });
1234
+ return ps;
1519
1235
  }
1520
-
1521
- return requester
1522
- }
1523
-
1524
- /**
1525
- * @experimental this class can be used but may change in the future
1526
- **/
1527
- export const ExperimentalGetTinaClient = () =>
1528
- getSdk(
1529
- generateRequester(
1530
- createClient({
1531
- url: "${apiURL}",
1532
- queries,
1533
- })
1534
- )
1535
- )
1536
-
1537
- export const queries = (
1538
- client: TinaClient,
1539
- ) => {
1540
- const requester = generateRequester(client)
1541
- return getSdk(requester)
1542
- }
1543
- `;
1544
- };
1545
1236
  };
1546
- var AddGeneratedClient = (apiURL) => ({
1547
- plugin: AddGeneratedClientFunc(apiURL)
1548
- });
1549
-
1550
- // src/next/codegen/codegen/index.ts
1551
- var import_graphql_file_loader = require("@graphql-tools/graphql-file-loader");
1552
- var import_core = require("@graphql-codegen/core");
1553
- var import_load = require("@graphql-tools/load");
1554
- var import_typescript_operations = require("@graphql-codegen/typescript-operations");
1555
- var import_typescript = require("@graphql-codegen/typescript");
1556
-
1557
- // src/next/codegen/codegen/sdkPlugin/index.ts
1558
- var import_graphql3 = require("graphql");
1559
- var import_graphql4 = require("graphql");
1560
1237
 
1561
- // src/next/codegen/codegen/sdkPlugin/visitor.ts
1562
- var import_visitor_plugin_common = require("@graphql-codegen/visitor-plugin-common");
1563
- var import_auto_bind = __toESM(require("auto-bind"));
1564
- var import_graphql2 = require("graphql");
1565
- var GenericSdkVisitor = class extends import_visitor_plugin_common.ClientSideBaseVisitor {
1566
- constructor(schema, fragments, rawConfig) {
1567
- super(schema, fragments, rawConfig, {
1568
- usingObservableFrom: rawConfig.usingObservableFrom
1238
+ // src/next/commands/baseCommands.ts
1239
+ var import_graphql8 = require("@tinacms/graphql");
1240
+ var import_fs_extra3 = __toESM(require("fs-extra"));
1241
+ var BaseCommand = class extends import_clipanion.Command {
1242
+ constructor() {
1243
+ super(...arguments);
1244
+ this.experimentalDataLayer = import_clipanion.Option.Boolean("--experimentalData", {
1245
+ description: "DEPRECATED - Build the server with additional data querying capabilities"
1569
1246
  });
1570
- this._operationsToInclude = [];
1571
- (0, import_auto_bind.default)(this);
1572
- if (this.config.usingObservableFrom) {
1573
- this._additionalImports.push(this.config.usingObservableFrom);
1247
+ this.isomorphicGitBridge = import_clipanion.Option.Boolean("--isomorphicGitBridge", {
1248
+ description: "DEPRECATED - Enable Isomorphic Git Bridge Implementation"
1249
+ });
1250
+ this.port = import_clipanion.Option.String("-p,--port", "4001", {
1251
+ description: "Specify a port to run the server on. (default 4001)"
1252
+ });
1253
+ this.datalayerPort = import_clipanion.Option.String("--datalayer-port", "9000", {
1254
+ description: "Specify a port to run the datalayer server on. (default 9000)"
1255
+ });
1256
+ this.subCommand = import_clipanion.Option.String("-c,--command", {
1257
+ description: "The sub-command to run"
1258
+ });
1259
+ this.rootPath = import_clipanion.Option.String("--rootPath", {
1260
+ description: "Specify the root directory to run the CLI from (defaults to current working directory)"
1261
+ });
1262
+ this.verbose = import_clipanion.Option.Boolean("-v,--verbose", false, {
1263
+ description: "increase verbosity of logged output"
1264
+ });
1265
+ this.noSDK = import_clipanion.Option.Boolean("--noSDK", false, {
1266
+ description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1267
+ });
1268
+ this.noTelemetry = import_clipanion.Option.Boolean("--noTelemetry", false, {
1269
+ description: "Disable anonymous telemetry that is collected"
1270
+ });
1271
+ }
1272
+ async startSubCommand() {
1273
+ let subProc;
1274
+ if (this.subCommand) {
1275
+ subProc = await startSubprocess2({ command: this.subCommand });
1276
+ logger.info(
1277
+ `Running web application with command: ${import_chalk4.default.cyan(this.subCommand)}`
1278
+ );
1574
1279
  }
1575
- if (this.config.documentMode !== import_visitor_plugin_common.DocumentMode.string) {
1280
+ function exitHandler(options, exitCode) {
1281
+ if (subProc) {
1282
+ subProc.kill();
1283
+ }
1284
+ process.exit();
1576
1285
  }
1286
+ process.on("exit", exitHandler);
1287
+ process.on("SIGINT", exitHandler);
1288
+ process.on("SIGUSR1", exitHandler);
1289
+ process.on("SIGUSR2", exitHandler);
1290
+ process.on("uncaughtException", (error) => {
1291
+ logger.error(`Uncaught exception ${error.name}`);
1292
+ console.error(error);
1293
+ });
1577
1294
  }
1578
- buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) {
1579
- if (node.name == null) {
1580
- throw new Error(
1581
- "Plugin 'generic-sdk' cannot generate SDK for unnamed operation.\n\n" + (0, import_graphql2.print)(node)
1295
+ logDeprecationWarnings() {
1296
+ if (this.isomorphicGitBridge) {
1297
+ logger.warn("--isomorphicGitBridge has been deprecated");
1298
+ }
1299
+ if (this.experimentalDataLayer) {
1300
+ logger.warn(
1301
+ "--experimentalDataLayer has been deprecated, the data layer is now built-in automatically"
1582
1302
  );
1583
- } else {
1584
- this._operationsToInclude.push({
1585
- node,
1586
- documentVariableName,
1587
- operationType,
1588
- // This is the only line that is different
1589
- operationResultType: `{data: ${operationResultType}, errors?: { message: string, locations: { line: number, column: number }[], path: string[] }[], variables: ${operationVariablesTypes}, query: string}`,
1590
- operationVariablesTypes
1591
- });
1592
1303
  }
1593
- return null;
1594
- }
1595
- get sdkContent() {
1596
- const usingObservable = !!this.config.usingObservableFrom;
1597
- const allPossibleActions = this._operationsToInclude.map((o) => {
1598
- const optionalVariables = !o.node.variableDefinitions || o.node.variableDefinitions.length === 0 || o.node.variableDefinitions.every(
1599
- (v) => v.type.kind !== import_graphql2.Kind.NON_NULL_TYPE || v.defaultValue
1304
+ if (this.noSDK) {
1305
+ logger.warn(
1306
+ "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
1600
1307
  );
1601
- const returnType = usingObservable && o.operationType === "Subscription" ? "Observable" : "Promise";
1602
- return `${o.node.name.value}(variables${optionalVariables ? "?" : ""}: ${o.operationVariablesTypes}, options?: C): ${returnType}<${o.operationResultType}> {
1603
- return requester<${o.operationResultType}, ${o.operationVariablesTypes}>(${o.documentVariableName}, variables, options);
1604
- }`;
1605
- }).map((s2) => (0, import_visitor_plugin_common.indentMultiline)(s2, 2));
1606
- return `export type Requester<C= {}> = <R, V>(doc: ${this.config.documentMode === import_visitor_plugin_common.DocumentMode.string ? "string" : "DocumentNode"}, vars?: V, options?: C) => ${usingObservable ? "Promise<R> & Observable<R>" : "Promise<R>"}
1607
- export function getSdk<C>(requester: Requester<C>) {
1608
- return {
1609
- ${allPossibleActions.join(",\n")}
1610
- };
1611
- }
1612
- export type Sdk = ReturnType<typeof getSdk>;`;
1308
+ }
1613
1309
  }
1614
- };
1615
-
1616
- // src/next/codegen/codegen/sdkPlugin/index.ts
1617
- var plugin = (schema, documents, config2) => {
1618
- const allAst = (0, import_graphql4.concatAST)(
1619
- documents.reduce((prev, v) => {
1620
- return [...prev, v.document];
1621
- }, [])
1622
- );
1623
- const allFragments = [
1624
- ...allAst.definitions.filter(
1625
- (d) => d.kind === import_graphql4.Kind.FRAGMENT_DEFINITION
1626
- ).map((fragmentDef) => ({
1627
- node: fragmentDef,
1628
- name: fragmentDef.name.value,
1629
- onType: fragmentDef.typeCondition.name.value,
1630
- isExternal: false
1631
- })),
1632
- ...config2.externalFragments || []
1633
- ];
1634
- const visitor = new GenericSdkVisitor(schema, allFragments, config2);
1635
- const visitorResult = (0, import_graphql3.visit)(allAst, { leave: visitor });
1636
- return {
1637
- // We will take care of imports
1638
- // prepend: visitor.getImports(),
1639
- content: [
1640
- visitor.fragments,
1641
- ...visitorResult.definitions.filter((t) => typeof t === "string"),
1642
- visitor.sdkContent
1643
- ].join("\n")
1644
- };
1645
- };
1646
-
1647
- // src/next/codegen/codegen/index.ts
1648
- var generateTypes = async (schema, queryPathGlob = process.cwd(), fragDocPath = process.cwd(), apiURL) => {
1649
- let docs = [];
1650
- let fragDocs = [];
1651
- docs = await loadGraphQLDocuments(queryPathGlob);
1652
- fragDocs = await loadGraphQLDocuments(fragDocPath);
1653
- const res = await (0, import_core.codegen)({
1654
- // Filename is not used. This is because the typescript plugin returns a string instead of writing to a file.
1655
- filename: process.cwd(),
1656
- schema: (0, import_graphql5.parse)((0, import_graphql5.printSchema)(schema)),
1657
- documents: [...docs, ...fragDocs],
1658
- config: {},
1659
- plugins: [
1660
- { typescript: {} },
1661
- { typescriptOperations: {} },
1662
- {
1663
- typescriptSdk: {}
1664
- },
1665
- { AddGeneratedClient: {} }
1666
- ],
1667
- pluginMap: {
1668
- typescript: {
1669
- plugin: import_typescript.plugin
1670
- },
1671
- typescriptOperations: {
1672
- plugin: import_typescript_operations.plugin
1673
- },
1674
- typescriptSdk: {
1675
- plugin
1310
+ async indexContentWithSpinner({
1311
+ database,
1312
+ graphQLSchema,
1313
+ tinaSchema,
1314
+ configManager,
1315
+ partialReindex,
1316
+ text
1317
+ }) {
1318
+ const textToUse = text || "Indexing local files";
1319
+ const warnings = [];
1320
+ await spin({
1321
+ waitFor: async () => {
1322
+ var _a, _b;
1323
+ const rootPath = configManager.rootPath;
1324
+ let sha;
1325
+ try {
1326
+ sha = await (0, import_graphql8.getSha)({ fs: import_fs_extra3.default, dir: rootPath });
1327
+ } catch (e) {
1328
+ if (partialReindex) {
1329
+ console.error(
1330
+ "Failed to get sha. NOTE: `--partial-reindex` only supported for git repositories"
1331
+ );
1332
+ throw e;
1333
+ }
1334
+ }
1335
+ const lastSha = await database.getMetadata("lastSha");
1336
+ const exists = lastSha && await (0, import_graphql8.shaExists)({ fs: import_fs_extra3.default, dir: rootPath, sha: lastSha });
1337
+ let res;
1338
+ if (partialReindex && lastSha && exists && sha) {
1339
+ const pathFilter = {};
1340
+ if (configManager.isUsingLegacyFolder) {
1341
+ pathFilter[".tina/__generated__/_schema.json"] = {};
1342
+ } else {
1343
+ pathFilter["tina/tina-lock.json"] = {};
1344
+ }
1345
+ for (const collection of tinaSchema.getCollections()) {
1346
+ pathFilter[collection.path] = {
1347
+ matches: ((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include) ? tinaSchema.getMatches({ collection }) : void 0
1348
+ };
1349
+ }
1350
+ const { added, modified, deleted } = await (0, import_graphql8.getChangedFiles)({
1351
+ fs: import_fs_extra3.default,
1352
+ dir: rootPath,
1353
+ from: lastSha,
1354
+ to: sha,
1355
+ pathFilter
1356
+ });
1357
+ const tinaPathUpdates = modified.filter(
1358
+ (path14) => path14.startsWith(".tina/__generated__/_schema.json") || path14.startsWith("tina/tina-lock.json")
1359
+ );
1360
+ if (tinaPathUpdates.length > 0) {
1361
+ res = await database.indexContent({
1362
+ graphQLSchema,
1363
+ tinaSchema
1364
+ });
1365
+ } else {
1366
+ if (added.length > 0 || modified.length > 0) {
1367
+ await database.indexContentByPaths([...added, ...modified]);
1368
+ }
1369
+ if (deleted.length > 0) {
1370
+ await database.deleteContentByPaths(deleted);
1371
+ }
1372
+ }
1373
+ } else {
1374
+ res = await database.indexContent({
1375
+ graphQLSchema,
1376
+ tinaSchema
1377
+ });
1378
+ }
1379
+ if (sha) {
1380
+ await database.setMetadata("lastSha", sha);
1381
+ }
1382
+ if (res == null ? void 0 : res.warnings) {
1383
+ warnings.push(...res.warnings);
1384
+ }
1676
1385
  },
1677
- AddGeneratedClient: AddGeneratedClient(apiURL)
1678
- }
1679
- });
1680
- return res;
1681
- };
1682
- var loadGraphQLDocuments = async (globPath) => {
1683
- let result = [];
1684
- try {
1685
- result = await (0, import_load.loadDocuments)(globPath, {
1686
- loaders: [new import_graphql_file_loader.GraphQLFileLoader()]
1386
+ text: textToUse
1687
1387
  });
1688
- } catch (e) {
1689
- if (
1690
- // https://www.graphql-tools.com/docs/documents-loading#no-files-found
1691
- (e.message || "").includes(
1692
- "Unable to find any GraphQL type definitions for the following pointers:"
1693
- )
1694
- ) {
1695
- } else {
1696
- throw e;
1388
+ if (warnings.length > 0) {
1389
+ logger.warn(`Indexing completed with ${warnings.length} warning(s)`);
1390
+ warnings.forEach((warning) => {
1391
+ logger.warn(warnText(`${warning}`));
1392
+ });
1697
1393
  }
1698
1394
  }
1699
- return result;
1700
1395
  };
1701
1396
 
1702
- // src/next/codegen/index.ts
1703
- var import_esbuild2 = require("esbuild");
1704
- var import_graphql7 = require("@tinacms/graphql");
1705
- var import_normalize_path3 = __toESM(require("normalize-path"));
1706
- var TINA_HOST = "content.tinajs.io";
1707
- var Codegen = class {
1708
- constructor({
1709
- configManager,
1710
- port,
1711
- queryDoc,
1712
- fragDoc,
1713
- isLocal,
1714
- graphqlSchemaDoc,
1715
- tinaSchema,
1716
- lookup,
1717
- noClientBuildCache
1718
- }) {
1719
- this.isLocal = isLocal;
1720
- this.graphqlSchemaDoc = graphqlSchemaDoc;
1721
- this.configManager = configManager;
1722
- this.port = port;
1723
- this.schema = (0, import_graphql6.buildASTSchema)(graphqlSchemaDoc);
1724
- this.tinaSchema = tinaSchema;
1725
- this.queryDoc = queryDoc;
1726
- this.fragDoc = fragDoc;
1727
- this.lookup = lookup;
1728
- this.noClientBuildCache = noClientBuildCache;
1729
- }
1730
- async writeConfigFile(fileName, data) {
1731
- const filePath = import_path4.default.join(this.configManager.generatedFolderPath, fileName);
1732
- await import_fs_extra4.default.ensureFile(filePath);
1733
- await import_fs_extra4.default.outputFile(filePath, data);
1734
- if (this.configManager.hasSeparateContentRoot()) {
1735
- const filePath2 = import_path4.default.join(
1736
- this.configManager.generatedFolderPathContentRepo,
1737
- fileName
1738
- );
1739
- await import_fs_extra4.default.ensureFile(filePath2);
1740
- await import_fs_extra4.default.outputFile(filePath2, data);
1741
- }
1742
- }
1743
- async removeGeneratedFilesIfExists() {
1744
- await unlinkIfExists(this.configManager.generatedClientJSFilePath);
1745
- await unlinkIfExists(this.configManager.generatedTypesDFilePath);
1746
- await unlinkIfExists(this.configManager.generatedTypesJSFilePath);
1747
- await unlinkIfExists(this.configManager.generatedTypesTSFilePath);
1748
- await unlinkIfExists(this.configManager.generatedClientTSFilePath);
1749
- await unlinkIfExists(this.configManager.generatedQueriesFilePath);
1750
- await unlinkIfExists(this.configManager.generatedFragmentsFilePath);
1397
+ // src/next/commands/dev-command/html.ts
1398
+ var errorHTML = `<style type="text/css">
1399
+ #no-assets-placeholder body {
1400
+ font-family: sans-serif;
1401
+ font-size: 16px;
1402
+ line-height: 1.4;
1403
+ color: #333;
1404
+ background-color: #f5f5f5;
1405
+ }
1406
+ #no-assets-placeholder {
1407
+ max-width: 600px;
1408
+ margin: 0 auto;
1409
+ padding: 40px;
1410
+ text-align: center;
1411
+ background-color: #fff;
1412
+ box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
1413
+ }
1414
+ #no-assets-placeholder h1 {
1415
+ font-size: 24px;
1416
+ margin-bottom: 20px;
1417
+ }
1418
+ #no-assets-placeholder p {
1419
+ margin-bottom: 10px;
1420
+ }
1421
+ #no-assets-placeholder a {
1422
+ color: #0077cc;
1423
+ text-decoration: none;
1424
+ }
1425
+ #no-assets-placeholder a:hover {
1426
+ text-decoration: underline;
1427
+ }
1428
+ </style>
1429
+ <div id="no-assets-placeholder">
1430
+ <h1>Failed loading TinaCMS assets</h1>
1431
+ <p>
1432
+ Your TinaCMS configuration may be misconfigured, and we could not load
1433
+ the assets for this page.
1434
+ </p>
1435
+ <p>
1436
+ Please visit <a href="https://tina.io/docs/tina-cloud/faq/#how-do-i-resolve-failed-loading-tinacms-assets-error">this doc</a> for help.
1437
+ </p>
1438
+ </div>
1439
+ </div>`.trim().replace(/[\r\n\s]+/g, " ");
1440
+ var devHTML = (port) => `<!DOCTYPE html>
1441
+ <html lang="en">
1442
+ <head>
1443
+ <meta charset="UTF-8" />
1444
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1445
+ <title>TinaCMS</title>
1446
+ </head>
1447
+
1448
+ <!-- if development -->
1449
+ <script type="module">
1450
+ import RefreshRuntime from 'http://localhost:${port}/@react-refresh'
1451
+ RefreshRuntime.injectIntoGlobalHook(window)
1452
+ window.$RefreshReg$ = () => {}
1453
+ window.$RefreshSig$ = () => (type) => type
1454
+ window.__vite_plugin_react_preamble_installed__ = true
1455
+ </script>
1456
+ <script type="module" src="http://localhost:${port}/@vite/client"></script>
1457
+ <script>
1458
+ function handleLoadError() {
1459
+ // Assets have failed to load
1460
+ document.getElementById('root').innerHTML = '${errorHTML}';
1751
1461
  }
1752
- async execute() {
1753
- await this.writeConfigFile(
1754
- "_graphql.json",
1755
- JSON.stringify(this.graphqlSchemaDoc)
1756
- );
1757
- const { search, ...rest } = this.tinaSchema.schema.config;
1758
- this.tinaSchema.schema.config = rest;
1759
- await this.writeConfigFile(
1760
- "_schema.json",
1761
- JSON.stringify(this.tinaSchema.schema)
1762
- );
1763
- await this.writeConfigFile("_lookup.json", JSON.stringify(this.lookup));
1764
- const { apiURL, localUrl, tinaCloudUrl } = this._createApiUrl();
1765
- this.apiURL = apiURL;
1766
- this.localUrl = localUrl;
1767
- this.productionUrl = tinaCloudUrl;
1768
- if (this.configManager.shouldSkipSDK()) {
1769
- await this.removeGeneratedFilesIfExists();
1770
- return apiURL;
1771
- }
1772
- await import_fs_extra4.default.outputFile(
1773
- this.configManager.generatedQueriesFilePath,
1774
- this.queryDoc
1775
- );
1776
- await import_fs_extra4.default.outputFile(
1777
- this.configManager.generatedFragmentsFilePath,
1778
- this.fragDoc
1779
- );
1780
- await maybeWarnFragmentSize(this.configManager.generatedFragmentsFilePath);
1781
- const { clientString } = await this.genClient();
1782
- const databaseClientString = this.configManager.hasSelfHostedConfig() ? await this.genDatabaseClient() : "";
1783
- const { codeString, schemaString } = await this.genTypes();
1784
- await import_fs_extra4.default.outputFile(
1785
- this.configManager.generatedGraphQLGQLPath,
1786
- schemaString
1787
- );
1788
- if (this.configManager.isUsingTs()) {
1789
- await import_fs_extra4.default.outputFile(
1790
- this.configManager.generatedTypesTSFilePath,
1791
- codeString
1792
- );
1793
- await import_fs_extra4.default.outputFile(
1794
- this.configManager.generatedClientTSFilePath,
1795
- clientString
1796
- );
1797
- if (this.configManager.hasSelfHostedConfig()) {
1798
- await import_fs_extra4.default.outputFile(
1799
- this.configManager.generatedDatabaseClientTSFilePath,
1800
- databaseClientString
1801
- );
1802
- }
1803
- await unlinkIfExists(this.configManager.generatedClientJSFilePath);
1804
- await unlinkIfExists(this.configManager.generatedTypesDFilePath);
1805
- await unlinkIfExists(this.configManager.generatedTypesJSFilePath);
1806
- } else {
1807
- await import_fs_extra4.default.outputFile(
1808
- this.configManager.generatedTypesDFilePath,
1809
- codeString
1810
- );
1811
- const jsTypes = await (0, import_esbuild2.transform)(codeString, { loader: "ts" });
1812
- await import_fs_extra4.default.outputFile(
1813
- this.configManager.generatedTypesJSFilePath,
1814
- jsTypes.code
1815
- );
1816
- await import_fs_extra4.default.outputFile(
1817
- this.configManager.generatedClientDFilePath,
1818
- clientString
1819
- );
1820
- const jsClient = await (0, import_esbuild2.transform)(clientString, { loader: "ts" });
1821
- await import_fs_extra4.default.outputFile(
1822
- this.configManager.generatedClientJSFilePath,
1823
- jsClient.code
1824
- );
1825
- await unlinkIfExists(this.configManager.generatedTypesTSFilePath);
1826
- await unlinkIfExists(this.configManager.generatedClientTSFilePath);
1827
- if (this.configManager.hasSelfHostedConfig()) {
1828
- const jsDatabaseClient = await (0, import_esbuild2.transform)(databaseClientString, {
1829
- loader: "ts"
1830
- });
1831
- await import_fs_extra4.default.outputFile(
1832
- this.configManager.generatedDatabaseClientJSFilePath,
1833
- jsDatabaseClient.code
1834
- );
1835
- await import_fs_extra4.default.outputFile(
1836
- this.configManager.generatedDatabaseClientDFilePath,
1837
- databaseClientString
1838
- );
1839
- await unlinkIfExists(
1840
- this.configManager.generatedDatabaseClientTSFilePath
1841
- );
1842
- }
1843
- }
1844
- return apiURL;
1845
- }
1846
- _createApiUrl() {
1847
- var _a, _b, _c, _d;
1848
- const branch = (_a = this.configManager.config) == null ? void 0 : _a.branch;
1849
- const clientId = (_b = this.configManager.config) == null ? void 0 : _b.clientId;
1850
- const token = (_c = this.configManager.config) == null ? void 0 : _c.token;
1851
- const fullVersion = this.configManager.getTinaGraphQLVersion();
1852
- const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1853
- const baseUrl = ((_d = this.configManager.config.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://${TINA_HOST}`;
1854
- if ((!branch || !clientId || !token) && !this.port && !this.configManager.config.contentApiUrlOverride) {
1855
- const missing = [];
1856
- if (!branch) missing.push("branch");
1857
- if (!clientId) missing.push("clientId");
1858
- if (!token) missing.push("token");
1859
- throw new Error(
1860
- `Client not configured properly. Missing ${missing.join(
1861
- ", "
1862
- )}. Please visit https://tina.io/docs/tina-cloud/overview for more information`
1863
- );
1864
- }
1865
- let localUrl = `http://localhost:${this.port}/graphql`;
1866
- let tinaCloudUrl = `${baseUrl}/${version2}/content/${clientId}/github/${branch}`;
1867
- let apiURL = this.isLocal ? `http://localhost:${this.port}/graphql` : `${baseUrl}/${version2}/content/${clientId}/github/${branch}`;
1868
- if (this.configManager.config.contentApiUrlOverride) {
1869
- apiURL = this.configManager.config.contentApiUrlOverride;
1870
- localUrl = apiURL;
1871
- tinaCloudUrl = apiURL;
1872
- }
1873
- return { apiURL, localUrl, tinaCloudUrl };
1874
- }
1875
- getApiURL() {
1876
- if (!this.apiURL)
1877
- throw new Error("apiURL not set. Please run execute() first");
1878
- return this.apiURL;
1879
- }
1880
- async genDatabaseClient() {
1881
- var _a, _b;
1882
- const authCollection = this.tinaSchema.getCollections().find((c) => c.isAuthCollection);
1883
- let authFields = [];
1884
- if (authCollection) {
1885
- const usersFields = (0, import_graphql7.mapUserFields)(authCollection, []);
1886
- if (usersFields.length === 0) {
1887
- throw new Error("No user field found");
1888
- }
1889
- if (usersFields.length > 1) {
1890
- throw new Error("Only one user field is allowed");
1891
- }
1892
- authFields = (_b = (_a = usersFields[0]) == null ? void 0 : _a.collectable) == null ? void 0 : _b.fields.map((f) => {
1893
- if (f.type !== "password" && f.type !== "object") {
1894
- if (f.uid) {
1895
- return `id:${f.name}`;
1896
- } else {
1897
- return `${f.name}`;
1462
+ </script>
1463
+ <script
1464
+ type="module"
1465
+ src="http://localhost:${port}/src/main.tsx"
1466
+ onerror="handleLoadError()"
1467
+ ></script>
1468
+ <body class="tina-tailwind">
1469
+ <div id="root"></div>
1470
+ </body>
1471
+ </html>`;
1472
+
1473
+ // src/next/commands/dev-command/server/index.ts
1474
+ var import_vite3 = require("vite");
1475
+
1476
+ // src/next/vite/index.ts
1477
+ var import_node_path2 = __toESM(require("path"));
1478
+ var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
1479
+ var import_fs_extra4 = __toESM(require("fs-extra"));
1480
+ var import_normalize_path3 = __toESM(require("normalize-path"));
1481
+ var import_vite = require("vite");
1482
+
1483
+ // src/next/vite/tailwind.ts
1484
+ var import_node_path = __toESM(require("path"));
1485
+ var import_aspect_ratio = __toESM(require("@tailwindcss/aspect-ratio"));
1486
+ var import_container_queries = __toESM(require("@tailwindcss/container-queries"));
1487
+ var import_typography = __toESM(require("@tailwindcss/typography"));
1488
+ var import_tailwindcss = __toESM(require("tailwindcss"));
1489
+ var import_defaultTheme = __toESM(require("tailwindcss/defaultTheme.js"));
1490
+ var tinaTailwind = (spaPath, prebuildFilePath) => {
1491
+ return {
1492
+ name: "vite-plugin-tina",
1493
+ // @ts-ignore
1494
+ config: (viteConfig) => {
1495
+ const plugins = [];
1496
+ const content = [
1497
+ import_node_path.default.join(spaPath, "src/**/*.{vue,js,ts,jsx,tsx,svelte}"),
1498
+ prebuildFilePath,
1499
+ require.resolve("tinacms")
1500
+ ];
1501
+ const tw = (0, import_tailwindcss.default)({
1502
+ theme: {
1503
+ columns: {
1504
+ auto: "auto",
1505
+ 1: "1",
1506
+ 2: "2",
1507
+ 3: "3",
1508
+ 4: "4",
1509
+ 5: "5",
1510
+ 6: "6",
1511
+ 7: "7",
1512
+ 8: "8",
1513
+ 9: "9",
1514
+ 10: "10",
1515
+ 11: "11",
1516
+ 12: "12",
1517
+ "3xs": "256px",
1518
+ "2xs": "288px",
1519
+ xs: "320px",
1520
+ sm: "384px",
1521
+ md: "448px",
1522
+ lg: "512px",
1523
+ xl: "576px",
1524
+ "2xl": "672px",
1525
+ "3xl": "768px",
1526
+ "4xl": "896px",
1527
+ "5xl": "1024px",
1528
+ "6xl": "1152px",
1529
+ "7xl": "1280px"
1530
+ },
1531
+ spacing: {
1532
+ px: "1px",
1533
+ 0: "0px",
1534
+ 0.5: "2px",
1535
+ 1: "4px",
1536
+ 1.5: "6px",
1537
+ 2: "8px",
1538
+ 2.5: "10px",
1539
+ 3: "12px",
1540
+ 3.5: "14px",
1541
+ 4: "16px",
1542
+ 5: "20px",
1543
+ 6: "24px",
1544
+ 7: "28px",
1545
+ 8: "32px",
1546
+ 9: "36px",
1547
+ 10: "40px",
1548
+ 11: "44px",
1549
+ 12: "48px",
1550
+ 14: "56px",
1551
+ 16: "64px",
1552
+ 18: "72px",
1553
+ 20: "80px",
1554
+ 24: "96px",
1555
+ 28: "114px",
1556
+ 32: "128px",
1557
+ 36: "144px",
1558
+ 40: "160px",
1559
+ 44: "176px",
1560
+ 48: "192px",
1561
+ 52: "208px",
1562
+ 56: "224px",
1563
+ 60: "240px",
1564
+ 64: "256px",
1565
+ 72: "288px",
1566
+ 80: "320px",
1567
+ 96: "384px"
1568
+ },
1569
+ borderRadius: {
1570
+ none: "0px",
1571
+ sm: "2px",
1572
+ DEFAULT: "4px",
1573
+ md: "6px",
1574
+ lg: "8px",
1575
+ xl: "12px",
1576
+ "2xl": "16px",
1577
+ "3xl": "24px",
1578
+ full: "9999px"
1579
+ },
1580
+ borderWidth: {
1581
+ DEFAULT: "1px",
1582
+ 0: "0",
1583
+ 2: "2px",
1584
+ 3: "3px",
1585
+ 4: "4px",
1586
+ 6: "6px",
1587
+ 8: "8px"
1588
+ },
1589
+ fontSize: {
1590
+ xs: ["13px", { lineHeight: "1.33" }],
1591
+ sm: ["14px", { lineHeight: "1.43" }],
1592
+ base: ["16px", { lineHeight: "1.5" }],
1593
+ md: ["16px", { lineHeight: "1.5" }],
1594
+ lg: ["18px", { lineHeight: "1.55" }],
1595
+ xl: ["20px", { lineHeight: "1.4" }],
1596
+ "2xl": ["24px", { lineHeight: "1.33" }],
1597
+ "3xl": ["30px", { lineHeight: "1.2" }],
1598
+ "4xl": ["36px", { lineHeight: "1.1" }],
1599
+ "5xl": ["48px", { lineHeight: "1" }],
1600
+ "6xl": ["60px", { lineHeight: "1" }],
1601
+ "7xl": ["72px", { lineHeight: "1" }],
1602
+ "8xl": ["96px", { lineHeight: "1" }],
1603
+ "9xl": ["128px", { lineHeight: "1" }]
1604
+ },
1605
+ opacity: {
1606
+ 0: "0",
1607
+ 5: ".05",
1608
+ 7: ".07",
1609
+ 10: ".1",
1610
+ 15: ".15",
1611
+ 20: ".2",
1612
+ 25: ".25",
1613
+ 30: ".3",
1614
+ 40: ".4",
1615
+ 50: ".5",
1616
+ 60: ".6",
1617
+ 70: ".7",
1618
+ 75: ".75",
1619
+ 80: ".8",
1620
+ 90: ".9",
1621
+ 100: "1"
1622
+ },
1623
+ zIndex: {
1624
+ "-1": "-1",
1625
+ base: "9000",
1626
+ panel: "9400",
1627
+ menu: "9800",
1628
+ chrome: "10200",
1629
+ overlay: "10600",
1630
+ modal: "10800",
1631
+ 0: "0",
1632
+ 10: "10",
1633
+ 20: "20",
1634
+ 30: "30",
1635
+ 40: "40",
1636
+ 25: "25",
1637
+ 50: "50",
1638
+ 75: "75",
1639
+ 100: "100",
1640
+ auto: "auto"
1641
+ },
1642
+ extend: {
1643
+ scale: {
1644
+ 97: ".97",
1645
+ 103: "1.03"
1646
+ },
1647
+ transitionDuration: {
1648
+ 0: "0ms",
1649
+ 2e3: "2000ms"
1650
+ },
1651
+ boxShadow: {
1652
+ xs: "0 0 0 1px rgba(0, 0, 0, 0.05)",
1653
+ outline: "0 0 0 3px rgba(66, 153, 225, 0.5)"
1654
+ },
1655
+ colors: {
1656
+ blue: {
1657
+ 50: "#DCEEFF",
1658
+ 100: "#B4DBFF",
1659
+ 200: "#85C5FE",
1660
+ 300: "#4EABFE",
1661
+ 400: "#2296fe",
1662
+ 500: "#0084FF",
1663
+ 600: "#0574e4",
1664
+ 700: "#0D5DBD",
1665
+ 800: "#144696",
1666
+ 900: "#1D2C6C",
1667
+ 1e3: "#241748"
1668
+ },
1669
+ gray: {
1670
+ 50: "#F6F6F9",
1671
+ 100: "#EDECF3",
1672
+ 150: "#E6E3EF",
1673
+ 200: "#E1DDEC",
1674
+ 250: "#C9C5D5",
1675
+ 300: "#b2adbe",
1676
+ 400: "#918c9e",
1677
+ 500: "#716c7f",
1678
+ 600: "#565165",
1679
+ 700: "#433e52",
1680
+ 800: "#363145",
1681
+ 900: "#252336",
1682
+ 1e3: "#1c1b2e"
1683
+ },
1684
+ orange: {
1685
+ 400: "#EB6337",
1686
+ 500: "#EC4815",
1687
+ 600: "#DC4419"
1688
+ },
1689
+ background: "#FFFFFF",
1690
+ foreground: "#0A0A0A",
1691
+ muted: "#F5F5F5",
1692
+ "muted-foreground": "#737373",
1693
+ popover: "#FFFFFF",
1694
+ "popover-foreground": "#0A0A0A",
1695
+ card: "#FFFFFF",
1696
+ "card-foreground": "#0A0A0A",
1697
+ border: "#E5E5E5",
1698
+ input: "#E5E5E5",
1699
+ primary: "#171717",
1700
+ "primary-foreground": "#FAFAFA",
1701
+ secondary: "#F5F5F5",
1702
+ "secondary-foreground": "#171717",
1703
+ accent: "#F5F5F5",
1704
+ "accent-foreground": "#171717",
1705
+ destructive: "#FF3B3B",
1706
+ "destructive-foreground": "#FAFAFA",
1707
+ ring: "#0A0A0A"
1708
+ },
1709
+ fontFamily: {
1710
+ sans: ["Inter", ...import_defaultTheme.default.fontFamily.sans]
1711
+ },
1712
+ lineHeight: {
1713
+ 3: "12px",
1714
+ 4: "16px",
1715
+ 5: "20px",
1716
+ 6: "24px",
1717
+ 7: "28px",
1718
+ 8: "32px",
1719
+ 9: "36px",
1720
+ 10: "40px"
1721
+ },
1722
+ maxWidth: {
1723
+ form: "900px"
1724
+ },
1725
+ screens: {
1726
+ xs: "320px",
1727
+ sm: "560px",
1728
+ md: "720px",
1729
+ lg: "1030px"
1730
+ }
1898
1731
  }
1899
- } else if (f.type === "password") {
1900
- return `_password: ${f.name} { passwordChangeRequired }`;
1901
- }
1732
+ },
1733
+ content,
1734
+ plugins: [
1735
+ (0, import_typography.default)({ className: "tina-prose" }),
1736
+ import_aspect_ratio.default,
1737
+ import_container_queries.default
1738
+ ]
1902
1739
  });
1740
+ plugins.push(tw);
1741
+ return {
1742
+ css: {
1743
+ postcss: {
1744
+ plugins
1745
+ }
1746
+ }
1747
+ };
1903
1748
  }
1904
- return `// @ts-nocheck
1905
- import { resolve } from "@tinacms/datalayer";
1906
- import type { TinaClient } from "tinacms/dist/client";
1907
-
1908
- import { queries } from "./types";
1909
- import database from "../database";
1910
-
1911
- export async function databaseRequest({ query, variables, user }) {
1912
- const result = await resolve({
1913
- config: {
1914
- useRelativeMedia: true,
1915
- },
1916
- database,
1917
- query,
1918
- variables,
1919
- verbose: true,
1920
- ctxUser: user,
1921
- });
1922
-
1923
- return result;
1924
- }
1925
-
1926
- export async function authenticate({ username, password }) {
1927
- return databaseRequest({
1928
- query: \`query auth($username:String!, $password:String!) {
1929
- authenticate(sub:$username, password:$password) {
1930
- ${authFields.join(" ")}
1931
- }
1932
- }\`,
1933
- variables: { username, password },
1934
- })
1935
- }
1936
-
1937
- export async function authorize(user: { sub: string }) {
1938
- return databaseRequest({
1939
- query: \`query authz { authorize { ${authFields.join(" ")}} }\`,
1940
- variables: {},
1941
- user
1942
- })
1943
- }
1944
-
1945
- function createDatabaseClient<GenQueries = Record<string, unknown>>({
1946
- queries,
1947
- }: {
1948
- queries: (client: {
1949
- request: TinaClient<GenQueries>["request"];
1950
- }) => GenQueries;
1951
- }) {
1952
- const request = async ({ query, variables, user }) => {
1953
- const data = await databaseRequest({ query, variables, user });
1954
- return { data: data.data as any, query, variables, errors: data.errors || null };
1955
1749
  };
1956
- const q = queries({
1957
- request,
1958
- });
1959
- return { queries: q, request, authenticate, authorize };
1960
- }
1961
-
1962
- export const databaseClient = createDatabaseClient({ queries });
1963
-
1964
- export const client = databaseClient;
1965
-
1966
- export default databaseClient;
1967
- `;
1968
- }
1969
- async genClient() {
1970
- var _a, _b, _c;
1971
- const token = (_a = this.configManager.config) == null ? void 0 : _a.token;
1972
- const errorPolicy = (_c = (_b = this.configManager.config) == null ? void 0 : _b.client) == null ? void 0 : _c.errorPolicy;
1973
- const apiURL = this.getApiURL();
1974
- const clientString = `import { createClient } from "tinacms/dist/client";
1975
- import { queries } from "./types";
1976
- export const client = createClient({ ${this.noClientBuildCache === false ? `cacheDir: '${(0, import_normalize_path3.default)(
1977
- this.configManager.generatedCachePath
1978
- )}', ` : ""}url: '${apiURL}', token: '${token}', queries, ${errorPolicy ? `errorPolicy: '${errorPolicy}'` : ""} });
1979
- export default client;
1980
- `;
1981
- return { apiURL, clientString };
1982
- }
1983
- async genTypes() {
1984
- const typescriptTypes = await generateTypes(
1985
- this.schema,
1986
- this.configManager.userQueriesAndFragmentsGlob,
1987
- this.configManager.generatedQueriesAndFragmentsGlob,
1988
- this.getApiURL()
1989
- );
1990
- const codeString = `//@ts-nocheck
1991
- // DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
1992
- export function gql(strings: TemplateStringsArray, ...args: string[]): string {
1993
- let str = ''
1994
- strings.forEach((string, i) => {
1995
- str += string + (args[i] || '')
1996
- })
1997
- return str
1998
- }
1999
- ${typescriptTypes}
2000
- `;
2001
- const schemaString = `# DO NOT MODIFY THIS FILE. This file is automatically generated by Tina
2002
- ${(0, import_graphql6.printSchema)(this.schema)}
2003
- schema {
2004
- query: Query
2005
- mutation: Mutation
2006
- }
2007
- `;
2008
- return { codeString, schemaString };
2009
- }
2010
- };
2011
- var maybeWarnFragmentSize = async (filepath) => {
2012
- if (
2013
- // is the file bigger than 100kb?
2014
- (await import_fs_extra4.default.stat(filepath)).size > // convert to 100 kb to bytes
2015
- 100 * 1024
2016
- ) {
2017
- console.warn(
2018
- "Warning: frags.gql is very large (>100kb). Consider setting the reference depth to 1 or 0. See code snippet below."
2019
- );
2020
- console.log(
2021
- `const schema = defineSchema({
2022
- client: {
2023
- referenceDepth: 1,
2024
- },
2025
- // ...
2026
- })`
2027
- );
2028
- }
2029
- };
2030
- var unlinkIfExists = async (filepath) => {
2031
- if (import_fs_extra4.default.existsSync(filepath)) {
2032
- import_fs_extra4.default.unlinkSync(filepath);
2033
- }
2034
1750
  };
2035
1751
 
2036
- // src/next/database.ts
2037
- var import_graphql8 = require("@tinacms/graphql");
2038
- var import_readable_stream = require("readable-stream");
2039
- var import_net = require("net");
2040
- var import_many_level = require("many-level");
2041
- var import_memory_level = require("memory-level");
2042
- var createDBServer = (port) => {
2043
- const levelHost = new import_many_level.ManyLevelHost(
2044
- // @ts-ignore
2045
- new import_memory_level.MemoryLevel({
2046
- valueEncoding: "json"
2047
- })
1752
+ // src/next/vite/index.ts
1753
+ async function listFilesRecursively({
1754
+ directoryPath,
1755
+ config: config2,
1756
+ roothPath
1757
+ }) {
1758
+ const fullDirectoryPath = import_node_path2.default.join(
1759
+ roothPath,
1760
+ config2.publicFolder,
1761
+ directoryPath
2048
1762
  );
2049
- const dbServer = (0, import_net.createServer)(function(socket) {
2050
- return (0, import_readable_stream.pipeline)(socket, levelHost.createRpcStream(), socket, () => {
2051
- });
2052
- });
2053
- dbServer.once("error", (err) => {
2054
- if ((err == null ? void 0 : err.code) === "EADDRINUSE") {
2055
- throw new Error(
2056
- `Tina Dev server is already in use. Datalayer server is busy on port ${port}`
2057
- );
2058
- }
2059
- });
2060
- dbServer.listen(port);
2061
- };
2062
- async function createAndInitializeDatabase(configManager, datalayerPort, bridgeOverride) {
2063
- let database;
2064
- const bridge = bridgeOverride || new import_graphql8.FilesystemBridge(configManager.rootPath, configManager.contentRootPath);
2065
- if (configManager.hasSelfHostedConfig() && configManager.config.contentApiUrlOverride) {
2066
- database = await configManager.loadDatabaseFile();
2067
- database.bridge = bridge;
2068
- } else {
2069
- if (configManager.hasSelfHostedConfig() && !configManager.config.contentApiUrlOverride) {
2070
- logger.warn(
2071
- `Found a database config file at ${configManager.printRelativePath(
2072
- configManager.selfHostedDatabaseFilePath
2073
- )} but there was no "contentApiUrlOverride" set. Falling back to built-in datalayer`
2074
- );
2075
- }
2076
- const level = new import_graphql8.TinaLevelClient(datalayerPort);
2077
- level.openConnection();
2078
- database = (0, import_graphql8.createDatabaseInternal)({
2079
- bridge,
2080
- level,
2081
- tinaDirectory: configManager.isUsingLegacyFolder ? LEGACY_TINA_FOLDER : TINA_FOLDER
2082
- });
1763
+ const exists = await import_fs_extra4.default.pathExists(fullDirectoryPath);
1764
+ if (!exists) {
1765
+ return { "0": [] };
2083
1766
  }
2084
- return database;
2085
- }
2086
-
2087
- // src/next/commands/baseCommands.ts
2088
- var import_clipanion = require("clipanion");
2089
- var import_chalk4 = __toESM(require("chalk"));
2090
-
2091
- // src/utils/start-subprocess.ts
2092
- var import_child_process = __toESM(require("child_process"));
2093
- var startSubprocess2 = async ({ command: command2 }) => {
2094
- if (typeof command2 === "string") {
2095
- const commands = command2.split(" ");
2096
- const firstCommand = commands[0];
2097
- const args = commands.slice(1) || [];
2098
- const ps = import_child_process.default.spawn(firstCommand, args, {
2099
- stdio: "inherit",
2100
- shell: true
2101
- });
2102
- ps.on("error", (code) => {
2103
- logger.error(
2104
- dangerText(
2105
- `An error has occurred in the Next.js child process. Error message below`
2106
- )
2107
- );
2108
- logger.error(`name: ${code.name}
2109
- message: ${code.message}
2110
-
2111
- stack: ${code.stack || "No stack was provided"}`);
2112
- });
2113
- ps.on("close", (code) => {
2114
- logger.info(`child process exited with code ${code}`);
2115
- process.exit(code);
2116
- });
2117
- return ps;
1767
+ const items = await import_fs_extra4.default.readdir(fullDirectoryPath);
1768
+ const staticMediaItems = [];
1769
+ for (const item of items) {
1770
+ const itemPath = import_node_path2.default.join(fullDirectoryPath, item);
1771
+ const stats = await import_fs_extra4.default.promises.lstat(itemPath);
1772
+ const staticMediaItem = {
1773
+ id: item,
1774
+ filename: item,
1775
+ type: stats.isDirectory() ? "dir" : "file",
1776
+ directory: `${directoryPath.replace(config2.mediaRoot, "")}`,
1777
+ src: `/${import_node_path2.default.join(directoryPath, item)}`,
1778
+ thumbnails: {
1779
+ "75x75": `/${import_node_path2.default.join(directoryPath, item)}`,
1780
+ "400x400": `/${import_node_path2.default.join(directoryPath, item)}`,
1781
+ "1000x1000": `/${import_node_path2.default.join(directoryPath, item)}`
1782
+ }
1783
+ };
1784
+ if (stats.isDirectory()) {
1785
+ staticMediaItem.children = await listFilesRecursively({
1786
+ directoryPath: import_node_path2.default.join(directoryPath, item),
1787
+ config: config2,
1788
+ roothPath
1789
+ });
1790
+ }
1791
+ staticMediaItems.push(staticMediaItem);
2118
1792
  }
2119
- };
2120
-
2121
- // src/utils/spinner.ts
2122
- var import_cli_spinner = require("cli-spinner");
2123
- async function localSpin({
2124
- waitFor,
2125
- text
2126
- }) {
2127
- const spinner = new import_cli_spinner.Spinner({
2128
- text: `${text} %s`,
2129
- stream: process.stderr,
2130
- onTick: function(msg) {
2131
- this.clearLine(this.stream);
2132
- this.stream.write(msg);
1793
+ function chunkArrayIntoObject(array, chunkSize) {
1794
+ const result = {};
1795
+ for (let i = 0; i < array.length; i += chunkSize) {
1796
+ const chunkKey = `${i / chunkSize * 20}`;
1797
+ result[chunkKey] = array.slice(i, i + chunkSize);
2133
1798
  }
2134
- });
2135
- spinner.setSpinnerString("\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F");
2136
- spinner.start();
2137
- const res = await waitFor();
2138
- spinner.stop();
2139
- console.log("");
2140
- return res;
1799
+ return result;
1800
+ }
1801
+ return chunkArrayIntoObject(staticMediaItems, 20);
2141
1802
  }
2142
- function spin({
2143
- waitFor,
2144
- text
2145
- }) {
2146
- if (process.env.CI) {
2147
- console.log(text);
2148
- return waitFor();
2149
- } else {
2150
- return localSpin({
2151
- text,
2152
- waitFor
1803
+ var createConfig = async ({
1804
+ configManager,
1805
+ apiURL,
1806
+ plugins = [],
1807
+ noWatch,
1808
+ rollupOptions
1809
+ }) => {
1810
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1811
+ const publicEnv = {};
1812
+ Object.keys(process.env).forEach((key) => {
1813
+ if (key.startsWith("TINA_PUBLIC_") || key.startsWith("NEXT_PUBLIC_") || key === "NODE_ENV" || key === "HEAD") {
1814
+ try {
1815
+ if (typeof process.env[key] === "string") {
1816
+ publicEnv[key] = process.env[key];
1817
+ } else {
1818
+ publicEnv[key] = JSON.stringify(process.env[key]);
1819
+ }
1820
+ } catch (error) {
1821
+ console.warn(
1822
+ `Could not stringify public env process.env.${key} env variable`
1823
+ );
1824
+ console.warn(error);
1825
+ }
1826
+ }
1827
+ });
1828
+ const staticMediaPath = import_node_path2.default.join(
1829
+ configManager.generatedFolderPath,
1830
+ "static-media.json"
1831
+ );
1832
+ if ((_b = (_a = configManager.config.media) == null ? void 0 : _a.tina) == null ? void 0 : _b.static) {
1833
+ const staticMedia = await listFilesRecursively({
1834
+ directoryPath: ((_c = configManager.config.media.tina) == null ? void 0 : _c.mediaRoot) || "",
1835
+ config: configManager.config.media.tina,
1836
+ roothPath: configManager.rootPath
2153
1837
  });
1838
+ await import_fs_extra4.default.outputFile(staticMediaPath, JSON.stringify(staticMedia, null, 2));
1839
+ } else {
1840
+ await import_fs_extra4.default.outputFile(staticMediaPath, `[]`);
2154
1841
  }
2155
- }
1842
+ const alias = {
1843
+ TINA_IMPORT: configManager.prebuildFilePath,
1844
+ SCHEMA_IMPORT: configManager.generatedGraphQLJSONPath,
1845
+ STATIC_MEDIA_IMPORT: staticMediaPath,
1846
+ crypto: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1847
+ fs: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1848
+ os: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts"),
1849
+ path: import_node_path2.default.join(configManager.spaRootPath, "src", "dummy-client.ts")
1850
+ };
1851
+ if (configManager.shouldSkipSDK()) {
1852
+ alias["CLIENT_IMPORT"] = import_node_path2.default.join(
1853
+ configManager.spaRootPath,
1854
+ "src",
1855
+ "dummy-client.ts"
1856
+ );
1857
+ } else {
1858
+ alias["CLIENT_IMPORT"] = configManager.isUsingTs() ? configManager.generatedTypesTSFilePath : configManager.generatedTypesJSFilePath;
1859
+ }
1860
+ let basePath;
1861
+ if (configManager.config.build.basePath) {
1862
+ basePath = configManager.config.build.basePath;
1863
+ }
1864
+ const fullVersion = configManager.getTinaGraphQLVersion();
1865
+ const version2 = `${fullVersion.major}.${fullVersion.minor}`;
1866
+ const config2 = {
1867
+ root: configManager.spaRootPath,
1868
+ base: `/${basePath ? `${(0, import_normalize_path3.default)(basePath)}/` : ""}${(0, import_normalize_path3.default)(
1869
+ configManager.config.build.outputFolder
1870
+ )}/`,
1871
+ appType: "spa",
1872
+ resolve: {
1873
+ alias,
1874
+ dedupe: ["graphql", "tinacms", "react", "react-dom", "react-router-dom"]
1875
+ },
1876
+ define: {
1877
+ /**
1878
+ * Since we prebuild the config.ts, it's possible for modules to be loaded which make
1879
+ * use of `process`. The main scenario where this is an issue is when co-locating schema
1880
+ * definitions with source files, and specifically source files which impor from NextJS.
1881
+ *
1882
+ * Some examples of what NextJS uses for `process.env` are:
1883
+ * - `process.env.__NEXT_TRAILING_SLASH`
1884
+ * - `process.env.__NEXT_CROSS_ORIGIN`
1885
+ * - `process.env.__NEXT_I18N_SUPPORT`
1886
+ *
1887
+ * Also, interestingly some of the advice for handling this doesn't work, references to replacing
1888
+ * `process.env` with `{}` are problematic, because browsers don't understand the `{}.` syntax,
1889
+ * but node does. This was a surprise, but using `new Object()` seems to do the trick.
1890
+ */
1891
+ "process.env": `new Object(${JSON.stringify(publicEnv)})`,
1892
+ // Used by picomatch https://github.com/micromatch/picomatch/blob/master/lib/utils.js#L4
1893
+ "process.platform": `"${process.platform}"`,
1894
+ __API_URL__: `"${apiURL}"`,
1895
+ __BASE_PATH__: `"${((_e = (_d = configManager.config) == null ? void 0 : _d.build) == null ? void 0 : _e.basePath) || ""}"`,
1896
+ __TINA_GRAPHQL_VERSION__: version2
1897
+ },
1898
+ logLevel: "error",
1899
+ // Vite import warnings are noisy
1900
+ optimizeDeps: {
1901
+ force: true,
1902
+ // Not 100% sure why this isn't being picked up automatically, this works from within the monorepo
1903
+ // but breaks externally
1904
+ include: ["react/jsx-runtime", "react/jsx-dev-runtime"]
1905
+ },
1906
+ server: {
1907
+ host: (_h = (_g = (_f = configManager.config) == null ? void 0 : _f.build) == null ? void 0 : _g.host) != null ? _h : false,
1908
+ watch: noWatch ? {
1909
+ ignored: ["**/*"]
1910
+ } : {
1911
+ // Ignore everything except for the alias fields we specified above
1912
+ ignored: [
1913
+ `${configManager.tinaFolderPath}/**/!(config.prebuild.jsx|_graphql.json)`
1914
+ ]
1915
+ },
1916
+ fs: {
1917
+ strict: false
1918
+ }
1919
+ },
1920
+ build: {
1921
+ sourcemap: false,
1922
+ outDir: configManager.outputFolderPath,
1923
+ emptyOutDir: true,
1924
+ rollupOptions
1925
+ },
1926
+ plugins: [
1927
+ /**
1928
+ * `splitVendorChunkPlugin` is needed because `tinacms` is quite large,
1929
+ * Vite's chunking strategy chokes on memory issues for smaller machines (ie. on CI).
1930
+ */
1931
+ (0, import_plugin_react.default)({
1932
+ babel: {
1933
+ // Supresses the warning [NOTE] babel The code generator has deoptimised the styling of
1934
+ compact: true
1935
+ }
1936
+ }),
1937
+ (0, import_vite.splitVendorChunkPlugin)(),
1938
+ tinaTailwind(configManager.spaRootPath, configManager.prebuildFilePath),
1939
+ ...plugins
1940
+ ]
1941
+ };
1942
+ return config2;
1943
+ };
2156
1944
 
2157
- // src/next/commands/baseCommands.ts
1945
+ // src/next/vite/plugins.ts
1946
+ var import_pluginutils = require("@rollup/pluginutils");
1947
+ var import_fs = __toESM(require("fs"));
1948
+ var import_vite2 = require("vite");
1949
+ var import_esbuild2 = require("esbuild");
1950
+ var import_path4 = __toESM(require("path"));
1951
+ var import_body_parser = __toESM(require("body-parser"));
1952
+ var import_cors = __toESM(require("cors"));
2158
1953
  var import_graphql9 = require("@tinacms/graphql");
1954
+
1955
+ // src/next/commands/dev-command/server/media.ts
2159
1956
  var import_fs_extra5 = __toESM(require("fs-extra"));
2160
- var BaseCommand = class extends import_clipanion.Command {
2161
- constructor() {
2162
- super(...arguments);
2163
- this.experimentalDataLayer = import_clipanion.Option.Boolean("--experimentalData", {
2164
- description: "DEPRECATED - Build the server with additional data querying capabilities"
2165
- });
2166
- this.isomorphicGitBridge = import_clipanion.Option.Boolean("--isomorphicGitBridge", {
2167
- description: "DEPRECATED - Enable Isomorphic Git Bridge Implementation"
2168
- });
2169
- this.port = import_clipanion.Option.String("-p,--port", "4001", {
2170
- description: "Specify a port to run the server on. (default 4001)"
2171
- });
2172
- this.datalayerPort = import_clipanion.Option.String("--datalayer-port", "9000", {
2173
- description: "Specify a port to run the datalayer server on. (default 9000)"
2174
- });
2175
- this.subCommand = import_clipanion.Option.String("-c,--command", {
2176
- description: "The sub-command to run"
2177
- });
2178
- this.rootPath = import_clipanion.Option.String("--rootPath", {
2179
- description: "Specify the root directory to run the CLI from (defaults to current working directory)"
1957
+ var import_path3 = __toESM(require("path"));
1958
+ var import_busboy = __toESM(require("busboy"));
1959
+ var createMediaRouter = (config2) => {
1960
+ const mediaFolder = import_path3.default.join(
1961
+ config2.rootPath,
1962
+ config2.publicFolder,
1963
+ config2.mediaRoot
1964
+ );
1965
+ const mediaModel = new MediaModel(config2);
1966
+ const handleList = async (req, res) => {
1967
+ const requestURL = new URL(req.url, config2.apiURL);
1968
+ const folder = requestURL.pathname.replace("/media/list/", "");
1969
+ const limit = requestURL.searchParams.get("limit");
1970
+ const cursor = requestURL.searchParams.get("cursor");
1971
+ const media = await mediaModel.listMedia({
1972
+ searchPath: folder,
1973
+ cursor,
1974
+ limit
2180
1975
  });
2181
- this.verbose = import_clipanion.Option.Boolean("-v,--verbose", false, {
2182
- description: "increase verbosity of logged output"
1976
+ res.end(JSON.stringify(media));
1977
+ };
1978
+ const handleDelete = async (req, res) => {
1979
+ const file = decodeURIComponent(req.url.slice("/media/".length));
1980
+ const didDelete = await mediaModel.deleteMedia({ searchPath: file });
1981
+ res.end(JSON.stringify(didDelete));
1982
+ };
1983
+ const handlePost = async function(req, res) {
1984
+ const bb = (0, import_busboy.default)({ headers: req.headers });
1985
+ bb.on("file", async (_name, file, _info) => {
1986
+ var _a;
1987
+ const fullPath = decodeURI((_a = req.url) == null ? void 0 : _a.slice("/media/upload/".length));
1988
+ const saveTo = import_path3.default.join(mediaFolder, ...fullPath.split("/"));
1989
+ await import_fs_extra5.default.ensureDir(import_path3.default.dirname(saveTo));
1990
+ file.pipe(import_fs_extra5.default.createWriteStream(saveTo));
2183
1991
  });
2184
- this.noSDK = import_clipanion.Option.Boolean("--noSDK", false, {
2185
- description: "DEPRECATED - This should now be set in the config at client.skip = true'. Don't generate the generated client SDK"
1992
+ bb.on("error", (error) => {
1993
+ res.statusCode = 500;
1994
+ if (error instanceof Error) {
1995
+ res.end(JSON.stringify({ message: error }));
1996
+ } else {
1997
+ res.end(JSON.stringify({ message: "Unknown error while uploading" }));
1998
+ }
2186
1999
  });
2187
- this.noTelemetry = import_clipanion.Option.Boolean("--noTelemetry", false, {
2188
- description: "Disable anonymous telemetry that is collected"
2000
+ bb.on("close", () => {
2001
+ res.statusCode = 200;
2002
+ res.end(JSON.stringify({ success: true }));
2189
2003
  });
2004
+ req.pipe(bb);
2005
+ };
2006
+ return { handleList, handleDelete, handlePost };
2007
+ };
2008
+ var parseMediaFolder = (str) => {
2009
+ let returnString = str;
2010
+ if (returnString.startsWith("/")) returnString = returnString.substr(1);
2011
+ if (returnString.endsWith("/"))
2012
+ returnString = returnString.substr(0, returnString.length - 1);
2013
+ return returnString;
2014
+ };
2015
+ var MediaModel = class {
2016
+ constructor({ rootPath, publicFolder, mediaRoot }) {
2017
+ this.rootPath = rootPath;
2018
+ this.mediaRoot = mediaRoot;
2019
+ this.publicFolder = publicFolder;
2190
2020
  }
2191
- async startSubCommand() {
2192
- let subProc;
2193
- if (this.subCommand) {
2194
- subProc = await startSubprocess2({ command: this.subCommand });
2195
- logger.info(`Starting subprocess: ${import_chalk4.default.cyan(this.subCommand)}`);
2196
- }
2197
- function exitHandler(options, exitCode) {
2198
- if (subProc) {
2199
- subProc.kill();
2021
+ async listMedia(args) {
2022
+ try {
2023
+ const folderPath = (0, import_path3.join)(
2024
+ this.rootPath,
2025
+ this.publicFolder,
2026
+ this.mediaRoot,
2027
+ decodeURIComponent(args.searchPath)
2028
+ );
2029
+ const searchPath = parseMediaFolder(args.searchPath);
2030
+ if (!await import_fs_extra5.default.pathExists(folderPath)) {
2031
+ return {
2032
+ files: [],
2033
+ directories: []
2034
+ };
2200
2035
  }
2201
- process.exit();
2036
+ const filesStr = await import_fs_extra5.default.readdir(folderPath);
2037
+ const filesProm = filesStr.map(async (file) => {
2038
+ const filePath = (0, import_path3.join)(folderPath, file);
2039
+ const stat = await import_fs_extra5.default.stat(filePath);
2040
+ let src = `/${file}`;
2041
+ const isFile = stat.isFile();
2042
+ if (!isFile) {
2043
+ return {
2044
+ isFile,
2045
+ size: stat.size,
2046
+ src,
2047
+ filename: file
2048
+ };
2049
+ }
2050
+ if (searchPath) {
2051
+ src = `/${searchPath}${src}`;
2052
+ }
2053
+ if (this.mediaRoot) {
2054
+ src = `/${this.mediaRoot}${src}`;
2055
+ }
2056
+ return {
2057
+ isFile,
2058
+ size: stat.size,
2059
+ src,
2060
+ filename: file
2061
+ };
2062
+ });
2063
+ const offset = Number(args.cursor) || 0;
2064
+ const limit = Number(args.limit) || 20;
2065
+ const rawItems = await Promise.all(filesProm);
2066
+ const sortedItems = rawItems.sort((a, b) => {
2067
+ if (a.isFile && !b.isFile) {
2068
+ return 1;
2069
+ }
2070
+ if (!a.isFile && b.isFile) {
2071
+ return -1;
2072
+ }
2073
+ return 0;
2074
+ });
2075
+ const limitItems = sortedItems.slice(offset, offset + limit);
2076
+ const files = limitItems.filter((x) => x.isFile);
2077
+ const directories = limitItems.filter((x) => !x.isFile).map((x) => x.src);
2078
+ const cursor = rawItems.length > offset + limit ? String(offset + limit) : null;
2079
+ return {
2080
+ files,
2081
+ directories,
2082
+ cursor
2083
+ };
2084
+ } catch (error) {
2085
+ console.error(error);
2086
+ return {
2087
+ files: [],
2088
+ directories: [],
2089
+ error: error == null ? void 0 : error.toString()
2090
+ };
2202
2091
  }
2203
- process.on("exit", exitHandler);
2204
- process.on("SIGINT", exitHandler);
2205
- process.on("SIGUSR1", exitHandler);
2206
- process.on("SIGUSR2", exitHandler);
2207
- process.on("uncaughtException", (error) => {
2208
- logger.error(`Uncaught exception ${error.name}`);
2092
+ }
2093
+ async deleteMedia(args) {
2094
+ try {
2095
+ const file = (0, import_path3.join)(
2096
+ this.rootPath,
2097
+ this.publicFolder,
2098
+ this.mediaRoot,
2099
+ decodeURIComponent(args.searchPath)
2100
+ );
2101
+ await import_fs_extra5.default.stat(file);
2102
+ await import_fs_extra5.default.remove(file);
2103
+ return { ok: true };
2104
+ } catch (error) {
2209
2105
  console.error(error);
2210
- });
2106
+ return { ok: false, message: error == null ? void 0 : error.toString() };
2107
+ }
2211
2108
  }
2212
- logDeprecationWarnings() {
2213
- if (this.isomorphicGitBridge) {
2214
- logger.warn("--isomorphicGitBridge has been deprecated");
2109
+ };
2110
+
2111
+ // src/next/commands/dev-command/server/searchIndex.ts
2112
+ var createSearchIndexRouter = ({
2113
+ config: config2,
2114
+ searchIndex
2115
+ }) => {
2116
+ const put = async (req, res) => {
2117
+ const { docs } = req.body;
2118
+ const result = await searchIndex.PUT(docs);
2119
+ res.writeHead(200, { "Content-Type": "application/json" });
2120
+ res.end(JSON.stringify({ result }));
2121
+ };
2122
+ const get = async (req, res) => {
2123
+ const requestURL = new URL(req.url, config2.apiURL);
2124
+ const query = requestURL.searchParams.get("q");
2125
+ const optionsParam = requestURL.searchParams.get("options");
2126
+ let options = {
2127
+ DOCUMENTS: false
2128
+ };
2129
+ if (optionsParam) {
2130
+ options = {
2131
+ ...options,
2132
+ ...JSON.parse(optionsParam)
2133
+ };
2215
2134
  }
2216
- if (this.experimentalDataLayer) {
2217
- logger.warn(
2218
- "--experimentalDataLayer has been deprecated, the data layer is now built-in automatically"
2219
- );
2135
+ res.writeHead(200, { "Content-Type": "application/json" });
2136
+ if (query) {
2137
+ const result = await searchIndex.QUERY(JSON.parse(query), options);
2138
+ res.end(JSON.stringify(result));
2139
+ } else {
2140
+ res.end(JSON.stringify({ RESULT: [] }));
2220
2141
  }
2221
- if (this.noSDK) {
2222
- logger.warn(
2223
- "--noSDK has been deprecated, and will be unsupported in a future release. This should be set in the config at client.skip = true"
2224
- );
2142
+ };
2143
+ const del = async (req, res) => {
2144
+ const requestURL = new URL(req.url, config2.apiURL);
2145
+ const docId = requestURL.pathname.split("/").filter(Boolean).slice(1).join("/");
2146
+ const result = await searchIndex.DELETE(docId);
2147
+ res.writeHead(200, { "Content-Type": "application/json" });
2148
+ res.end(JSON.stringify({ result }));
2149
+ };
2150
+ return { del, get, put };
2151
+ };
2152
+
2153
+ // src/next/vite/plugins.ts
2154
+ var transformTsxPlugin = ({
2155
+ configManager: _configManager
2156
+ }) => {
2157
+ const plug = {
2158
+ name: "transform-tsx",
2159
+ async transform(code, id) {
2160
+ const extName = import_path4.default.extname(id);
2161
+ if (extName.startsWith(".tsx") || extName.startsWith(".ts")) {
2162
+ const result = await (0, import_esbuild2.transform)(code, { loader: "tsx" });
2163
+ return {
2164
+ code: result.code
2165
+ };
2166
+ }
2225
2167
  }
2226
- }
2227
- async indexContentWithSpinner({
2228
- database,
2229
- graphQLSchema,
2230
- tinaSchema,
2231
- configManager,
2232
- partialReindex,
2233
- text
2234
- }) {
2235
- const textToUse = text || "Indexing local files";
2236
- const warnings = [];
2237
- await spin({
2238
- waitFor: async () => {
2239
- var _a, _b;
2240
- const rootPath = configManager.rootPath;
2241
- let sha;
2242
- try {
2243
- sha = await (0, import_graphql9.getSha)({ fs: import_fs_extra5.default, dir: rootPath });
2244
- } catch (e) {
2245
- if (partialReindex) {
2246
- console.error(
2247
- "Failed to get sha. NOTE: `--partial-reindex` only supported for git repositories"
2248
- );
2249
- throw e;
2250
- }
2168
+ };
2169
+ return plug;
2170
+ };
2171
+ var devServerEndPointsPlugin = ({
2172
+ configManager,
2173
+ apiURL,
2174
+ database,
2175
+ searchIndex,
2176
+ databaseLock
2177
+ }) => {
2178
+ const plug = {
2179
+ name: "graphql-endpoints",
2180
+ configureServer(server) {
2181
+ server.middlewares.use((0, import_cors.default)());
2182
+ server.middlewares.use(import_body_parser.default.json({ limit: "5mb" }));
2183
+ server.middlewares.use(async (req, res, next) => {
2184
+ var _a;
2185
+ const mediaPaths = (_a = configManager.config.media) == null ? void 0 : _a.tina;
2186
+ const mediaRouter = createMediaRouter({
2187
+ rootPath: configManager.rootPath,
2188
+ apiURL,
2189
+ publicFolder: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.publicFolder) || ""),
2190
+ mediaRoot: parseMediaFolder((mediaPaths == null ? void 0 : mediaPaths.mediaRoot) || "")
2191
+ });
2192
+ const searchIndexRouter = createSearchIndexRouter({
2193
+ config: { apiURL, searchPath: "searchIndex" },
2194
+ searchIndex
2195
+ });
2196
+ if (req.url.startsWith("/media/upload")) {
2197
+ await mediaRouter.handlePost(req, res);
2198
+ return;
2251
2199
  }
2252
- const lastSha = await database.getMetadata("lastSha");
2253
- const exists = lastSha && await (0, import_graphql9.shaExists)({ fs: import_fs_extra5.default, dir: rootPath, sha: lastSha });
2254
- let res;
2255
- if (partialReindex && lastSha && exists && sha) {
2256
- const pathFilter = {};
2257
- if (configManager.isUsingLegacyFolder) {
2258
- pathFilter[".tina/__generated__/_schema.json"] = {};
2259
- } else {
2260
- pathFilter["tina/tina-lock.json"] = {};
2261
- }
2262
- for (const collection of tinaSchema.getCollections()) {
2263
- pathFilter[collection.path] = {
2264
- matches: ((_a = collection.match) == null ? void 0 : _a.exclude) || ((_b = collection.match) == null ? void 0 : _b.include) ? tinaSchema.getMatches({ collection }) : void 0
2265
- };
2266
- }
2267
- const { added, modified, deleted } = await (0, import_graphql9.getChangedFiles)({
2268
- fs: import_fs_extra5.default,
2269
- dir: rootPath,
2270
- from: lastSha,
2271
- to: sha,
2272
- pathFilter
2273
- });
2274
- const tinaPathUpdates = modified.filter(
2275
- (path14) => path14.startsWith(".tina/__generated__/_schema.json") || path14.startsWith("tina/tina-lock.json")
2200
+ if (req.url.startsWith("/media")) {
2201
+ if (req.method === "DELETE") {
2202
+ await mediaRouter.handleDelete(req, res);
2203
+ return;
2204
+ }
2205
+ }
2206
+ if (req.url.startsWith("/media/list")) {
2207
+ await mediaRouter.handleList(req, res);
2208
+ return;
2209
+ }
2210
+ if (req.url === "/altair") {
2211
+ res.end(
2212
+ JSON.stringify({
2213
+ status: "The GraphQL playground has moved to <your-dev-url>/index.html#/graphql"
2214
+ })
2276
2215
  );
2277
- if (tinaPathUpdates.length > 0) {
2278
- res = await database.indexContent({
2279
- graphQLSchema,
2280
- tinaSchema
2216
+ return;
2217
+ }
2218
+ if (req.url === "/graphql") {
2219
+ const { query, variables } = req.body;
2220
+ let result;
2221
+ await databaseLock(async () => {
2222
+ result = await (0, import_graphql9.resolve)({
2223
+ config: {
2224
+ useRelativeMedia: true
2225
+ },
2226
+ database,
2227
+ query,
2228
+ variables,
2229
+ verbose: false
2281
2230
  });
2282
- } else {
2283
- if (added.length > 0 || modified.length > 0) {
2284
- await database.indexContentByPaths([...added, ...modified]);
2285
- }
2286
- if (deleted.length > 0) {
2287
- await database.deleteContentByPaths(deleted);
2288
- }
2289
- }
2290
- } else {
2291
- res = await database.indexContent({
2292
- graphQLSchema,
2293
- tinaSchema
2294
2231
  });
2232
+ res.end(JSON.stringify(result));
2233
+ return;
2295
2234
  }
2296
- if (sha) {
2297
- await database.setMetadata("lastSha", sha);
2298
- }
2299
- if (res == null ? void 0 : res.warnings) {
2300
- warnings.push(...res.warnings);
2235
+ if (req.url.startsWith("/searchIndex")) {
2236
+ if (req.method === "POST") {
2237
+ await searchIndexRouter.put(req, res);
2238
+ } else if (req.method === "GET") {
2239
+ await searchIndexRouter.get(req, res);
2240
+ } else if (req.method === "DELETE") {
2241
+ await searchIndexRouter.del(req, res);
2242
+ }
2243
+ return;
2301
2244
  }
2302
- },
2303
- text: textToUse
2304
- });
2305
- if (warnings.length > 0) {
2306
- logger.warn(`Indexing completed with ${warnings.length} warning(s)`);
2307
- warnings.forEach((warning) => {
2308
- logger.warn(warnText(`${warning}`));
2245
+ next();
2309
2246
  });
2310
2247
  }
2311
- }
2248
+ };
2249
+ return plug;
2250
+ };
2251
+ function viteTransformExtension({
2252
+ exportAsDefault = true,
2253
+ svgrOptions,
2254
+ esbuildOptions,
2255
+ include = "**/*.svg",
2256
+ exclude
2257
+ } = {}) {
2258
+ const filter = (0, import_pluginutils.createFilter)(include, exclude);
2259
+ return {
2260
+ name: "vite-plugin-svgr",
2261
+ async transform(code, id) {
2262
+ if (filter(id)) {
2263
+ const { transform: transform2 } = await Promise.resolve().then(() => __toESM(require("@svgr/core")));
2264
+ const svgCode = await import_fs.default.promises.readFile(
2265
+ id.replace(/\?.*$/, ""),
2266
+ "utf8"
2267
+ );
2268
+ const componentCode = await transform2(svgCode, svgrOptions, {
2269
+ filePath: id,
2270
+ caller: {
2271
+ previousExport: exportAsDefault ? null : code
2272
+ }
2273
+ });
2274
+ const res = await (0, import_vite2.transformWithEsbuild)(componentCode, id, {
2275
+ loader: "jsx",
2276
+ ...esbuildOptions
2277
+ });
2278
+ return {
2279
+ code: res.code,
2280
+ map: null
2281
+ // TODO:
2282
+ };
2283
+ }
2284
+ }
2285
+ };
2286
+ }
2287
+
2288
+ // src/next/commands/dev-command/server/index.ts
2289
+ var createDevServer = async (configManager, database, searchIndex, apiURL, noWatch, databaseLock) => {
2290
+ const plugins = [
2291
+ transformTsxPlugin({ configManager }),
2292
+ devServerEndPointsPlugin({
2293
+ apiURL,
2294
+ configManager,
2295
+ database,
2296
+ searchIndex,
2297
+ databaseLock
2298
+ }),
2299
+ viteTransformExtension()
2300
+ ];
2301
+ return (0, import_vite3.createServer)(
2302
+ await createConfig({
2303
+ configManager,
2304
+ database,
2305
+ apiURL,
2306
+ plugins,
2307
+ noWatch,
2308
+ /**
2309
+ * Ensure Vite's import scan uses the spaMainPath as the input
2310
+ * so it properly finds everything. This is for dev only, and when
2311
+ * running the server outside of this monorepo vite fails to find
2312
+ * and optimize the imports, so you get errors about it not being
2313
+ * able to find an export from a module, and it's always a CJS
2314
+ * module that Vite would usually transform to an ES module.
2315
+ */
2316
+ rollupOptions: {
2317
+ input: configManager.spaMainPath,
2318
+ onwarn(warning, warn) {
2319
+ if (warning.code === "MODULE_LEVEL_DIRECTIVE") {
2320
+ return;
2321
+ }
2322
+ warn(warning);
2323
+ }
2324
+ }
2325
+ })
2326
+ );
2312
2327
  };
2313
2328
 
2314
2329
  // src/next/commands/dev-command/index.ts
2315
- var import_search = require("@tinacms/search");
2316
2330
  var DevCommand = class extends BaseCommand {
2317
2331
  constructor() {
2318
2332
  super(...arguments);
@@ -2326,6 +2340,10 @@ var DevCommand = class extends BaseCommand {
2326
2340
  this.outputSearchIndexPath = import_clipanion2.Option.String("--outputSearchIndexPath", {
2327
2341
  description: "Path to write the search index to"
2328
2342
  });
2343
+ this.noServer = import_clipanion2.Option.Boolean("--no-server", false, {
2344
+ description: "Do not start the dev server"
2345
+ });
2346
+ this.indexingLock = new import_async_lock.default();
2329
2347
  }
2330
2348
  async catch(error) {
2331
2349
  logger.error("Error occured during tinacms dev");
@@ -2346,10 +2364,13 @@ var DevCommand = class extends BaseCommand {
2346
2364
  rootPath: this.rootPath,
2347
2365
  legacyNoSDK: this.noSDK
2348
2366
  });
2349
- logger.info("Starting Tina Dev Server");
2367
+ logger.info("\u{1F999} TinaCMS Dev Server is initializing...");
2350
2368
  this.logDeprecationWarnings();
2351
2369
  createDBServer(Number(this.datalayerPort));
2352
2370
  let database = null;
2371
+ const dbLock = async (fn) => {
2372
+ return this.indexingLock.acquire("Key", fn);
2373
+ };
2353
2374
  const setup = async ({ firstTime }) => {
2354
2375
  try {
2355
2376
  await configManager.processConfig();
@@ -2410,7 +2431,11 @@ var DevCommand = class extends BaseCommand {
2410
2431
  logger.error("Re-index complete");
2411
2432
  }
2412
2433
  if (!this.noWatch) {
2413
- this.watchQueries(configManager, async () => await codegen2.execute());
2434
+ this.watchQueries(
2435
+ configManager,
2436
+ dbLock,
2437
+ async () => await codegen2.execute()
2438
+ );
2414
2439
  }
2415
2440
  return { apiURL: apiURL2, database, graphQLSchema: graphQLSchema2, tinaSchema: tinaSchema2 };
2416
2441
  } catch (e) {
@@ -2446,14 +2471,6 @@ ${dangerText(e.message)}
2446
2471
  tokenSplitRegex: (_d = (_c = configManager.config.search) == null ? void 0 : _c.tina) == null ? void 0 : _d.tokenSplitRegex
2447
2472
  });
2448
2473
  await searchIndexClient.onStartIndexing();
2449
- const server = await createDevServer(
2450
- configManager,
2451
- database,
2452
- searchIndexClient.searchIndex,
2453
- apiURL,
2454
- this.noWatch
2455
- );
2456
- await server.listen(Number(this.port));
2457
2474
  const searchIndexer = new import_search.SearchIndexer({
2458
2475
  batchSize: ((_e = configManager.config.search) == null ? void 0 : _e.indexBatchSize) || 100,
2459
2476
  bridge: new import_graphql10.FilesystemBridge(
@@ -2475,16 +2492,34 @@ ${dangerText(e.message)}
2475
2492
  await searchIndexClient.export(this.outputSearchIndexPath);
2476
2493
  }
2477
2494
  }
2495
+ if (this.noServer) {
2496
+ logger.info("--no-server option specified - Dev server not started");
2497
+ process.exit(0);
2498
+ }
2478
2499
  if (!this.noWatch) {
2479
2500
  this.watchContentFiles(
2480
2501
  configManager,
2481
2502
  database,
2503
+ dbLock,
2482
2504
  configManager.config.search && searchIndexer
2483
2505
  );
2506
+ }
2507
+ const server = await createDevServer(
2508
+ configManager,
2509
+ database,
2510
+ searchIndexClient.searchIndex,
2511
+ apiURL,
2512
+ this.noWatch,
2513
+ dbLock
2514
+ );
2515
+ await server.listen(Number(this.port));
2516
+ if (!this.noWatch) {
2484
2517
  import_chokidar.default.watch(configManager.watchList).on("change", async () => {
2485
- logger.info(`Tina config change detected, rebuilding`);
2486
- await setup({ firstTime: false });
2487
- server.ws.send({ type: "full-reload", path: "*" });
2518
+ await dbLock(async () => {
2519
+ logger.info(`Tina config change detected, rebuilding`);
2520
+ await setup({ firstTime: false });
2521
+ server.ws.send({ type: "full-reload", path: "*" });
2522
+ });
2488
2523
  });
2489
2524
  }
2490
2525
  const subItems = [];
@@ -2497,7 +2532,7 @@ ${dangerText(e.message)}
2497
2532
  const summaryItems = [
2498
2533
  {
2499
2534
  emoji: "\u{1F999}",
2500
- heading: "Tina Config",
2535
+ heading: "TinaCMS URLs",
2501
2536
  subItems: [
2502
2537
  {
2503
2538
  key: "CMS",
@@ -2532,7 +2567,7 @@ ${dangerText(e.message)}
2532
2567
  });
2533
2568
  }
2534
2569
  summary({
2535
- heading: "Tina Dev Server is running...",
2570
+ heading: "\u2705 \u{1F999} TinaCMS Dev Server is active:",
2536
2571
  items: [
2537
2572
  ...summaryItems
2538
2573
  // {
@@ -2553,7 +2588,7 @@ ${dangerText(e.message)}
2553
2588
  });
2554
2589
  await this.startSubCommand();
2555
2590
  }
2556
- watchContentFiles(configManager, database, searchIndexer) {
2591
+ watchContentFiles(configManager, database, databaseLock, searchIndexer) {
2557
2592
  const collectionContentFiles = [];
2558
2593
  configManager.config.schema.collections.forEach((collection) => {
2559
2594
  const collectionGlob = `${import_path5.default.join(
@@ -2569,39 +2604,42 @@ ${dangerText(e.message)}
2569
2604
  if (!ready) {
2570
2605
  return;
2571
2606
  }
2572
- const pathFromRoot = configManager.printContentRelativePath(addedFile);
2573
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2574
- if (searchIndexer) {
2575
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2576
- }
2607
+ await databaseLock(async () => {
2608
+ const pathFromRoot = configManager.printContentRelativePath(addedFile);
2609
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2610
+ if (searchIndexer) {
2611
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2612
+ }
2613
+ });
2577
2614
  }).on("change", async (changedFile) => {
2578
2615
  const pathFromRoot = configManager.printContentRelativePath(changedFile);
2579
- await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2580
- if (searchIndexer) {
2581
- await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2582
- }
2616
+ await databaseLock(async () => {
2617
+ await database.indexContentByPaths([pathFromRoot]).catch(console.error);
2618
+ if (searchIndexer) {
2619
+ await searchIndexer.indexContentByPaths([pathFromRoot]).catch(console.error);
2620
+ }
2621
+ });
2583
2622
  }).on("unlink", async (removedFile) => {
2584
2623
  const pathFromRoot = configManager.printContentRelativePath(removedFile);
2585
- await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2586
- if (searchIndexer) {
2587
- await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2588
- }
2624
+ await databaseLock(async () => {
2625
+ await database.deleteContentByPaths([pathFromRoot]).catch(console.error);
2626
+ if (searchIndexer) {
2627
+ await searchIndexer.deleteIndexContent([pathFromRoot]).catch(console.error);
2628
+ }
2629
+ });
2589
2630
  });
2590
2631
  }
2591
- watchQueries(configManager, callback) {
2592
- let ready = false;
2593
- import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("ready", () => {
2594
- ready = true;
2595
- }).on("add", async (addedFile) => {
2596
- await callback();
2597
- }).on("change", async (changedFile) => {
2598
- await callback();
2599
- }).on("unlink", async (removedFile) => {
2600
- await callback();
2601
- });
2632
+ watchQueries(configManager, databaseLock, callback) {
2633
+ const executeCallback = async (_) => {
2634
+ await databaseLock(async () => {
2635
+ await callback();
2636
+ });
2637
+ };
2638
+ import_chokidar.default.watch(configManager.userQueriesAndFragmentsGlob).on("add", executeCallback).on("change", executeCallback).on("unlink", executeCallback);
2602
2639
  }
2603
2640
  };
2604
2641
  DevCommand.paths = [["dev"], ["server:start"]];
2642
+ // Prevent indexes and reads occurring at once
2605
2643
  DevCommand.usage = import_clipanion2.Command.Usage({
2606
2644
  category: `Commands`,
2607
2645
  description: `Builds Tina and starts the dev server`,
@@ -2612,12 +2650,41 @@ DevCommand.usage = import_clipanion2.Command.Usage({
2612
2650
  });
2613
2651
 
2614
2652
  // src/next/commands/build-command/index.ts
2615
- var import_clipanion3 = require("clipanion");
2616
- var import_progress2 = __toESM(require("progress"));
2617
- var import_fs_extra7 = __toESM(require("fs-extra"));
2618
2653
  var import_crypto = __toESM(require("crypto"));
2619
2654
  var import_path6 = __toESM(require("path"));
2655
+ var import_core3 = require("@graphql-inspector/core");
2620
2656
  var import_graphql11 = require("@tinacms/graphql");
2657
+ var import_schema_tools2 = require("@tinacms/schema-tools");
2658
+ var import_search2 = require("@tinacms/search");
2659
+ var import_clipanion3 = require("clipanion");
2660
+ var import_fs_extra7 = __toESM(require("fs-extra"));
2661
+ var import_graphql12 = require("graphql");
2662
+ var import_progress2 = __toESM(require("progress"));
2663
+
2664
+ // src/utils/index.ts
2665
+ var import_core2 = require("@graphql-inspector/core");
2666
+ var getFaqLink = (type) => {
2667
+ switch (type) {
2668
+ case import_core2.ChangeType.FieldRemoved: {
2669
+ return "https://tina.io/docs/introduction/faq#how-do-i-resolve-the-local-graphql-schema-doesnt-match-the-remote-graphql-schema-errors";
2670
+ }
2671
+ default:
2672
+ return null;
2673
+ }
2674
+ };
2675
+
2676
+ // src/utils/sleep.ts
2677
+ function timeout(ms) {
2678
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
2679
+ }
2680
+ async function sleepAndCallFunc({
2681
+ fn,
2682
+ ms
2683
+ }) {
2684
+ await timeout(ms);
2685
+ const res = await fn();
2686
+ return res;
2687
+ }
2621
2688
 
2622
2689
  // src/next/commands/build-command/server.ts
2623
2690
  var import_vite5 = require("vite");
@@ -2657,29 +2724,9 @@ var buildProductionSpa = async (configManager, database, apiURL) => {
2657
2724
  return (0, import_vite5.build)(config2);
2658
2725
  };
2659
2726
 
2660
- // src/next/commands/build-command/index.ts
2661
- var import_schema_tools2 = require("@tinacms/schema-tools");
2662
- var import_graphql12 = require("graphql");
2663
- var import_core3 = require("@graphql-inspector/core");
2664
-
2665
2727
  // src/next/commands/build-command/waitForDB.ts
2666
- var import_progress = __toESM(require("progress"));
2667
2728
  var import_schema_tools = require("@tinacms/schema-tools");
2668
-
2669
- // src/utils/sleep.ts
2670
- function timeout(ms) {
2671
- return new Promise((resolve2) => setTimeout(resolve2, ms));
2672
- }
2673
- async function sleepAndCallFunc({
2674
- fn,
2675
- ms
2676
- }) {
2677
- await timeout(ms);
2678
- const res = await fn();
2679
- return res;
2680
- }
2681
-
2682
- // src/next/commands/build-command/waitForDB.ts
2729
+ var import_progress = __toESM(require("progress"));
2683
2730
  var POLLING_INTERVAL = 5e3;
2684
2731
  var STATUS_INPROGRESS = "inprogress";
2685
2732
  var STATUS_COMPLETE = "complete";
@@ -2695,12 +2742,12 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2695
2742
  const { clientId, branch, isLocalClient, host } = (0, import_schema_tools.parseURL)(apiUrl);
2696
2743
  if (isLocalClient || !host || !clientId || !branch) {
2697
2744
  if (verbose) {
2698
- logger.info(logText("Not using Tina Cloud, skipping DB check"));
2745
+ logger.info(logText("Not using TinaCloud, skipping DB check"));
2699
2746
  }
2700
2747
  return;
2701
2748
  }
2702
2749
  const bar2 = new import_progress.default(
2703
- "Checking indexing process in Tina Cloud... :prog",
2750
+ "Checking indexing process in TinaCloud... :prog",
2704
2751
  1
2705
2752
  );
2706
2753
  const pollForStatus = async () => {
@@ -2734,11 +2781,11 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2734
2781
  await sleepAndCallFunc({ fn: pollForStatus, ms: POLLING_INTERVAL });
2735
2782
  } else if (status === STATUS_FAILED) {
2736
2783
  throw new IndexFailedError(
2737
- `Attempting to index but responded with status 'failed'. To retry the indexing process, click the "Reindex" button for '${previewName || branch}' in the Tina Cloud configuration for this project. ${error}`
2784
+ `Attempting to index but responded with status 'failed'. To retry the indexing process, click the "Reindex" button for '${previewName || branch}' in the TinaCloud configuration for this project. ${error}`
2738
2785
  );
2739
2786
  } else {
2740
2787
  throw new IndexFailedError(
2741
- `Attempting to index but responded with status 'unknown'. To retry the indexing process, click the "Reindex" button for '${previewName || branch}' in the Tina Cloud configuration for this project. ${error}`
2788
+ `Attempting to index but responded with status 'unknown'. To retry the indexing process, click the "Reindex" button for '${previewName || branch}' in the TinaCloud configuration for this project. ${error}`
2742
2789
  );
2743
2790
  }
2744
2791
  } catch (e) {
@@ -2755,26 +2802,11 @@ var waitForDB = async (config2, apiUrl, previewName, verbose) => {
2755
2802
  }
2756
2803
  };
2757
2804
  await spin({
2758
- text: "Checking indexing process in Tina Cloud...",
2805
+ text: "Checking indexing process in TinaCloud...",
2759
2806
  waitFor: pollForStatus
2760
2807
  });
2761
2808
  };
2762
2809
 
2763
- // src/next/commands/build-command/index.ts
2764
- var import_search2 = require("@tinacms/search");
2765
-
2766
- // src/utils/index.ts
2767
- var import_core2 = require("@graphql-inspector/core");
2768
- var getFaqLink = (type) => {
2769
- switch (type) {
2770
- case import_core2.ChangeType.FieldRemoved: {
2771
- return "https://tina.io/docs/introduction/faq#how-do-i-resolve-the-local-graphql-schema-doesnt-match-the-remote-graphql-schema-errors";
2772
- }
2773
- default:
2774
- return null;
2775
- }
2776
- };
2777
-
2778
2810
  // src/next/commands/build-command/index.ts
2779
2811
  var BuildCommand = class extends BaseCommand {
2780
2812
  constructor() {
@@ -2792,7 +2824,7 @@ var BuildCommand = class extends BaseCommand {
2792
2824
  description: "Specify the version of @tinacms/graphql to use (defaults to latest)"
2793
2825
  });
2794
2826
  /**
2795
- * This option allows the user to skip the tina cloud checks if they want to. This could be useful for mismatched GraphQL versions or if they want to build only using the local client and never connect to Tina Cloud
2827
+ * This option allows the user to skip the TinaCloud checks if they want to. This could be useful for mismatched GraphQL versions or if they want to build only using the local client and never connect to TinaCloud
2796
2828
  */
2797
2829
  this.skipCloudChecks = import_clipanion3.Option.Boolean("--skip-cloud-checks", false, {
2798
2830
  description: "Skips checking the provided cloud config."
@@ -2899,7 +2931,8 @@ ${dangerText(e.message)}
2899
2931
  database,
2900
2932
  null,
2901
2933
  apiURL,
2902
- true
2934
+ true,
2935
+ (lockedFn) => lockedFn()
2903
2936
  );
2904
2937
  await server.listen(Number(this.port));
2905
2938
  console.log("server listening on port", this.port);
@@ -2961,7 +2994,9 @@ ${dangerText(e.message)}
2961
2994
  `ERROR: Branch not configured in tina search configuration.`
2962
2995
  )}`
2963
2996
  );
2964
- throw new Error("Branch not configured in tina search configuration.");
2997
+ throw new Error(
2998
+ "Branch not configured in tina search configuration."
2999
+ );
2965
3000
  }
2966
3001
  if (!((_d = configManager.config) == null ? void 0 : _d.clientId)) {
2967
3002
  logger.error(`${dangerText(`ERROR: clientId not configured.`)}`);
@@ -3104,7 +3139,7 @@ ${dangerText(e.message)}
3104
3139
  });
3105
3140
  throw e;
3106
3141
  }
3107
- const branchBar = new import_progress2.default("Checking branch is on Tina Cloud. :prog", 1);
3142
+ const branchBar = new import_progress2.default("Checking branch is on TinaCloud. :prog", 1);
3108
3143
  if (branchKnown) {
3109
3144
  branchBar.tick({
3110
3145
  prog: "\u2705"
@@ -3141,12 +3176,12 @@ ${dangerText(e.message)}
3141
3176
  });
3142
3177
  logger.error(
3143
3178
  `${dangerText(
3144
- `ERROR: Branch '${branch}' is not on Tina Cloud.`
3179
+ `ERROR: Branch '${branch}' is not on TinaCloud.`
3145
3180
  )} Please make sure that branch '${branch}' exists in your repository and that you have pushed your all changes to the remote. View all all branches and there current status here: ${linkText(
3146
3181
  `https://app.tina.io/projects/${clientId}/configuration`
3147
3182
  )}`
3148
3183
  );
3149
- throw new Error("Branch is not on Tina Cloud");
3184
+ throw new Error("Branch is not on TinaCloud");
3150
3185
  }
3151
3186
  async syncProject(configManager, apiURL, options) {
3152
3187
  const { config: config2 } = configManager;
@@ -3228,7 +3263,7 @@ Additional info: Branch: ${config2.branch}, Client ID: ${config2.clientId} `;
3228
3263
  const localSchemaDocument = await database.getGraphQLSchemaFromBridge();
3229
3264
  const localGraphqlSchema = (0, import_graphql12.buildASTSchema)(localSchemaDocument);
3230
3265
  try {
3231
- const diffResult = await (0, import_core3.diff)(localGraphqlSchema, remoteGqlSchema);
3266
+ const diffResult = await (0, import_core3.diff)(remoteGqlSchema, localGraphqlSchema);
3232
3267
  if (diffResult.length === 0) {
3233
3268
  bar2.tick({
3234
3269
  prog: "\u2705"
@@ -3285,7 +3320,7 @@ Additional info:
3285
3320
  const { clientId, branch, isLocalClient, host } = (0, import_schema_tools2.parseURL)(apiURL);
3286
3321
  if (isLocalClient || !host || !clientId || !branch) {
3287
3322
  if (verbose) {
3288
- logger.info(logText("Not using Tina Cloud, skipping Tina Schema check"));
3323
+ logger.info(logText("Not using TinaCloud, skipping Tina Schema check"));
3289
3324
  }
3290
3325
  return;
3291
3326
  }
@@ -3344,7 +3379,7 @@ Additional info:
3344
3379
  BuildCommand.paths = [["build"]];
3345
3380
  BuildCommand.usage = import_clipanion3.Command.Usage({
3346
3381
  category: `Commands`,
3347
- description: `Build the CMS and autogenerated modules for usage with Tina Cloud`
3382
+ description: `Build the CMS and autogenerated modules for usage with TinaCloud`
3348
3383
  });
3349
3384
  async function request(args) {
3350
3385
  const headers = new Headers();
@@ -3846,7 +3881,7 @@ var tinaCloudSetupQuestions = [
3846
3881
  {
3847
3882
  name: "clientId",
3848
3883
  type: "text",
3849
- message: `What is your Tina Cloud Client ID? (Hit enter to skip and set up yourself later)
3884
+ message: `What is your TinaCloud Client ID? (Hit enter to skip and set up yourself later)
3850
3885
  ${logText(
3851
3886
  "Don't have a Client ID? Create one here: "
3852
3887
  )}${linkText("https://app.tina.io/projects/new")}`,
@@ -3855,7 +3890,7 @@ ${logText(
3855
3890
  {
3856
3891
  name: "token",
3857
3892
  type: "text",
3858
- message: (prev) => `What is your Tina Cloud Read Only Token?
3893
+ message: (prev) => `What is your TinaCloud Read Only Token?
3859
3894
  ${logText(
3860
3895
  "Don't have a Read Only Token? Create one here: "
3861
3896
  )}${linkText(`https://app.tina.io/projects/${prev || "[XXX]"}/tokens`)}`,
@@ -4066,8 +4101,8 @@ var chooseDatabaseAdapter = async ({
4066
4101
  };
4067
4102
 
4068
4103
  // src/cmds/init/prompts/authProvider.ts
4069
- var import_prompts5 = __toESM(require("prompts"));
4070
4104
  var import_crypto_js = __toESM(require("crypto-js"));
4105
+ var import_prompts5 = __toESM(require("prompts"));
4071
4106
  var supportedAuthProviders = {
4072
4107
  other: {
4073
4108
  name: "other"
@@ -4244,7 +4279,7 @@ var askIfUsingSelfHosted = async () => {
4244
4279
  type: "select",
4245
4280
  choices: [
4246
4281
  {
4247
- title: "Tina Cloud",
4282
+ title: "TinaCloud",
4248
4283
  value: "tina-cloud"
4249
4284
  },
4250
4285
  {
@@ -4252,7 +4287,7 @@ var askIfUsingSelfHosted = async () => {
4252
4287
  value: "self-host"
4253
4288
  }
4254
4289
  ],
4255
- 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.)"
4290
+ message: "Do you want to host your project on TinaCloud or self-host? (With self-hosting, the graphql api, auth and database will be hosted on your own server.)"
4256
4291
  }
4257
4292
  ]);
4258
4293
  return answers;
@@ -4807,7 +4842,6 @@ var transformForestryFieldsToTinaFields = ({
4807
4842
  name: stringifyTemplateName(tem, tem)
4808
4843
  };
4809
4844
  if (t.name != tem) {
4810
- ;
4811
4845
  t.nameOverride = tem;
4812
4846
  }
4813
4847
  templates2.push(t);
@@ -5952,10 +5986,13 @@ var addSelfHostedTinaAuthToConfig = async (config2, configFile) => {
5952
5986
  const { configImports, configAuthProviderClass, extraTinaCollections } = config2.authProvider;
5953
5987
  const importMap = {
5954
5988
  // iterate over configImports and add them to the import map
5955
- ...configImports.reduce((acc, { from, imported }) => {
5956
- acc[from] = imported;
5957
- return acc;
5958
- }, {})
5989
+ ...configImports.reduce(
5990
+ (acc, { from, imported }) => {
5991
+ acc[from] = imported;
5992
+ return acc;
5993
+ },
5994
+ {}
5995
+ )
5959
5996
  };
5960
5997
  const transformedSourceFileResult = import_typescript3.default.transform(
5961
5998
  sourceFile,
@@ -6410,6 +6447,13 @@ ${titleText(" TinaCMS ")} has been initialized!`));
6410
6447
  logger.info(
6411
6448
  "To get started run: " + cmdText(frameworkDevCmds[framework.name]({ packageManager }))
6412
6449
  );
6450
+ if (framework.name === "hugo") {
6451
+ logger.info(
6452
+ focusText("Hugo is required. "),
6453
+ "Don't have Hugo installed? Follow this guide to set it up: ",
6454
+ linkText("https://gohugo.io/installation/")
6455
+ );
6456
+ }
6413
6457
  logger.info(
6414
6458
  "To get your site production ready, run: " + cmdText(`tinacms init backend`)
6415
6459
  );
@@ -6695,4 +6739,4 @@ cli.register(SearchIndexCommand);
6695
6739
  cli.register(import_clipanion8.Builtins.DefinitionsCommand);
6696
6740
  cli.register(import_clipanion8.Builtins.HelpCommand);
6697
6741
  cli.register(import_clipanion8.Builtins.VersionCommand);
6698
- var src_default = cli;
6742
+ var index_default = cli;