@tinacms/cli 0.0.0-bd0c18e-20250217004931 → 0.0.0-bdc07c1-20250506013835

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