create-tina-app 2.1.5 → 2.1.7
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 +115 -62
- package/dist/util/install.d.ts +2 -0
- package/dist/util/posthog.d.ts +1 -0
- package/dist/util/textstyles.d.ts +5 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,6 +9,19 @@ import path from "path";
|
|
|
9
9
|
|
|
10
10
|
// src/util/textstyles.ts
|
|
11
11
|
import chalk from "chalk";
|
|
12
|
+
var stripAnsi = (str) => str.replace(/\]8;;[^]*/g, "").replace(/\[[0-9;]*m/g, "");
|
|
13
|
+
var box = (lines, color = chalk.hex("#EC4816")) => {
|
|
14
|
+
const pad = 1;
|
|
15
|
+
const width = Math.max(...lines.map((l) => stripAnsi(l).length));
|
|
16
|
+
const rule = color("\u2500".repeat(width + pad * 2));
|
|
17
|
+
const top = `${color("\u250C")}${rule}${color("\u2510")}`;
|
|
18
|
+
const bottom = `${color("\u2514")}${rule}${color("\u2518")}`;
|
|
19
|
+
const body = lines.map((line) => {
|
|
20
|
+
const trailing = " ".repeat(width - stripAnsi(line).length);
|
|
21
|
+
return `${color("\u2502")}${" ".repeat(pad)}${line}${trailing}${" ".repeat(pad)}${color("\u2502")}`;
|
|
22
|
+
});
|
|
23
|
+
return [top, ...body, bottom].join("\n");
|
|
24
|
+
};
|
|
12
25
|
var TextStyles = {
|
|
13
26
|
tinaOrange: chalk.hex("#EC4816"),
|
|
14
27
|
link: (url) => `\x1B]8;;${url}\x07${chalk.cyan.underline(url)}\x1B]8;;\x07`,
|
|
@@ -143,18 +156,36 @@ async function updateTelemetryConfig(dir, mode) {
|
|
|
143
156
|
|
|
144
157
|
// src/util/install.ts
|
|
145
158
|
import spawn from "cross-spawn";
|
|
159
|
+
var MAX_OUTPUT_CHARS = 4e3;
|
|
146
160
|
function install(packageManager, verboseOutput) {
|
|
161
|
+
const command = `${packageManager} install`;
|
|
147
162
|
return new Promise((resolve, reject) => {
|
|
148
163
|
const child = spawn(packageManager, ["install"], {
|
|
149
|
-
stdio: verboseOutput ? "inherit" : "ignore",
|
|
164
|
+
stdio: verboseOutput ? "inherit" : ["ignore", "ignore", "pipe"],
|
|
150
165
|
env: { ...process.env, ADBLOCK: "1", DISABLE_OPENCOLLECTIVE: "1" }
|
|
151
166
|
});
|
|
167
|
+
let captured = "";
|
|
168
|
+
child.stderr?.on("data", (chunk) => {
|
|
169
|
+
captured = (captured + chunk.toString()).slice(-MAX_OUTPUT_CHARS);
|
|
170
|
+
});
|
|
171
|
+
child.on("error", (err) => {
|
|
172
|
+
reject(
|
|
173
|
+
new Error(`Failed to run "${command}": ${err.message}`)
|
|
174
|
+
);
|
|
175
|
+
});
|
|
152
176
|
child.on("close", (code) => {
|
|
153
|
-
if (code
|
|
154
|
-
|
|
177
|
+
if (code === 0) {
|
|
178
|
+
resolve();
|
|
155
179
|
return;
|
|
156
180
|
}
|
|
157
|
-
|
|
181
|
+
const details = captured.trim();
|
|
182
|
+
let message = `"${command}" exited with code ${code ?? "unknown"}.`;
|
|
183
|
+
if (details) {
|
|
184
|
+
message += `
|
|
185
|
+
|
|
186
|
+
${details}`;
|
|
187
|
+
}
|
|
188
|
+
reject(new Error(message));
|
|
158
189
|
});
|
|
159
190
|
});
|
|
160
191
|
}
|
|
@@ -422,18 +453,31 @@ async function downloadTemplate(template, root, spinner) {
|
|
|
422
453
|
}
|
|
423
454
|
|
|
424
455
|
// src/util/preRunChecks.ts
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
456
|
+
import { readFileSync } from "node:fs";
|
|
457
|
+
import { dirname, join } from "node:path";
|
|
458
|
+
import { fileURLToPath } from "node:url";
|
|
459
|
+
function getSupportedMajors() {
|
|
460
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
461
|
+
try {
|
|
462
|
+
const { engines } = JSON.parse(
|
|
463
|
+
readFileSync(join(here, "../package.json"), "utf8")
|
|
464
|
+
);
|
|
465
|
+
return [...String(engines?.node ?? "").matchAll(/(\d+)\.x/g)].map(
|
|
466
|
+
(m) => Number(m[1])
|
|
467
|
+
);
|
|
468
|
+
} catch {
|
|
469
|
+
return [];
|
|
470
|
+
}
|
|
471
|
+
}
|
|
432
472
|
function preRunChecks(spinner) {
|
|
433
473
|
spinner.start("Running pre-run checks...");
|
|
474
|
+
const supported = getSupportedMajors();
|
|
475
|
+
const currentMajor = Number(process.versions.node.split(".")[0]);
|
|
476
|
+
const isSupported = supported.includes(currentMajor);
|
|
434
477
|
if (!isSupported) {
|
|
478
|
+
const range = supported.length ? supported.map((v) => `v${v}`).join(" or ") : "a supported LTS version";
|
|
435
479
|
spinner.warn(
|
|
436
|
-
`Node ${process.version} is not supported by create-tina-app. Please
|
|
480
|
+
`Node ${process.version} is not supported by create-tina-app. Please use ${range}. See https://nodejs.org/en/download/ for more details.`
|
|
437
481
|
);
|
|
438
482
|
} else {
|
|
439
483
|
spinner.succeed(`Node ${process.version} is supported.`);
|
|
@@ -466,7 +510,7 @@ import { Command } from "commander";
|
|
|
466
510
|
|
|
467
511
|
// package.json
|
|
468
512
|
var name = "create-tina-app";
|
|
469
|
-
var version = "2.1.
|
|
513
|
+
var version = "2.1.7";
|
|
470
514
|
|
|
471
515
|
// src/util/packageManagers.ts
|
|
472
516
|
var PKG_MANAGERS = ["npm", "yarn", "pnpm", "bun"];
|
|
@@ -689,6 +733,7 @@ var ERROR_CODES = {
|
|
|
689
733
|
ERR_VAL_INVALID_TEMPLATE: "ERR_VAL_INVALID_TEMPLATE",
|
|
690
734
|
ERR_VAL_INVALID_PKG_MANAGER: "ERR_VAL_INVALID_PKG_MANAGER",
|
|
691
735
|
ERR_VAL_INVALID_PROJECT_NAME: "ERR_VAL_INVALID_PROJECT_NAME",
|
|
736
|
+
ERR_VAL_INVALID_THEME: "ERR_VAL_INVALID_THEME",
|
|
692
737
|
ERR_VAL_UNSUPPORTED_NODE: "ERR_VAL_UNSUPPORTED_NODE",
|
|
693
738
|
ERR_VAL_NO_PKG_MANAGERS: "ERR_VAL_NO_PKG_MANAGERS",
|
|
694
739
|
// File System Errors (FS_*)
|
|
@@ -879,6 +924,8 @@ async function fetchPostHogConfig(endpointUrl) {
|
|
|
879
924
|
|
|
880
925
|
// src/index.ts
|
|
881
926
|
import { osInfo as getOsSystemInfo } from "systeminformation";
|
|
927
|
+
var DISCORD_SUPPORT_URL = "https://discord.com/invite/zumN63Ybpf";
|
|
928
|
+
var FAQ_URL = "https://tina.io/docs/faq";
|
|
882
929
|
var posthogClient = null;
|
|
883
930
|
async function initializePostHog(configEndpoint, disableGeoip) {
|
|
884
931
|
let apiKey;
|
|
@@ -963,6 +1010,18 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
963
1010
|
}
|
|
964
1011
|
const spinner = ora();
|
|
965
1012
|
preRunChecks(spinner);
|
|
1013
|
+
const fatalExit = async (message, error, context) => {
|
|
1014
|
+
spinner.fail(
|
|
1015
|
+
`${message}
|
|
1016
|
+
|
|
1017
|
+
Need more help? Reach out to the TinaCMS community at ${TextStyles.link(
|
|
1018
|
+
DISCORD_SUPPORT_URL
|
|
1019
|
+
)}`
|
|
1020
|
+
);
|
|
1021
|
+
postHogCaptureError(posthogClient, userId, sessionId, error, context);
|
|
1022
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
1023
|
+
exit(1);
|
|
1024
|
+
};
|
|
966
1025
|
postHogCapture(
|
|
967
1026
|
posthogClient,
|
|
968
1027
|
userId,
|
|
@@ -974,15 +1033,10 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
974
1033
|
if (opts.template) {
|
|
975
1034
|
template = TEMPLATES.find((_template) => _template.value === opts.template);
|
|
976
1035
|
if (!template) {
|
|
977
|
-
|
|
1036
|
+
await fatalExit(
|
|
978
1037
|
`The provided template '${opts.template}' is invalid. Please provide one of the following: ${TEMPLATES.map(
|
|
979
1038
|
(x2) => x2.value
|
|
980
|
-
)}
|
|
981
|
-
);
|
|
982
|
-
postHogCaptureError(
|
|
983
|
-
posthogClient,
|
|
984
|
-
userId,
|
|
985
|
-
sessionId,
|
|
1039
|
+
)}`,
|
|
986
1040
|
new Error(`Invalid template: ${opts.template}`),
|
|
987
1041
|
{
|
|
988
1042
|
errorCode: ERROR_CODES.ERR_VAL_INVALID_TEMPLATE,
|
|
@@ -992,17 +1046,13 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
992
1046
|
additionalProperties: { ...telemetryData }
|
|
993
1047
|
}
|
|
994
1048
|
);
|
|
995
|
-
if (posthogClient) await posthogClient.shutdown();
|
|
996
|
-
exit(1);
|
|
997
1049
|
}
|
|
998
1050
|
}
|
|
999
1051
|
let pkgManager = opts.pkgManager;
|
|
1000
1052
|
if (pkgManager) {
|
|
1001
1053
|
if (!PKG_MANAGERS.find((_pkgManager) => _pkgManager === pkgManager)) {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
userId,
|
|
1005
|
-
sessionId,
|
|
1054
|
+
await fatalExit(
|
|
1055
|
+
`The provided package manager '${opts.pkgManager}' is not supported. Please provide one of the following: ${PKG_MANAGERS}`,
|
|
1006
1056
|
new Error(`Invalid package manager: ${opts.pkgManager}`),
|
|
1007
1057
|
{
|
|
1008
1058
|
errorCode: ERROR_CODES.ERR_VAL_INVALID_PKG_MANAGER,
|
|
@@ -1012,22 +1062,12 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1012
1062
|
additionalProperties: { ...telemetryData }
|
|
1013
1063
|
}
|
|
1014
1064
|
);
|
|
1015
|
-
if (posthogClient) await posthogClient.shutdown();
|
|
1016
|
-
spinner.fail(
|
|
1017
|
-
`The provided package manager '${opts.pkgManager}' is not supported. Please provide one of the following: ${PKG_MANAGERS}`
|
|
1018
|
-
);
|
|
1019
|
-
exit(1);
|
|
1020
1065
|
}
|
|
1021
1066
|
}
|
|
1022
1067
|
if (!pkgManager) {
|
|
1023
1068
|
if (installedPkgManagers.length === 0) {
|
|
1024
|
-
|
|
1025
|
-
`You have no supported package managers installed. Please install one of the following: ${PKG_MANAGERS}
|
|
1026
|
-
);
|
|
1027
|
-
postHogCaptureError(
|
|
1028
|
-
posthogClient,
|
|
1029
|
-
userId,
|
|
1030
|
-
sessionId,
|
|
1069
|
+
await fatalExit(
|
|
1070
|
+
`You have no supported package managers installed. Please install one of the following: ${PKG_MANAGERS}`,
|
|
1031
1071
|
new Error("No supported package managers installed"),
|
|
1032
1072
|
{
|
|
1033
1073
|
errorCode: ERROR_CODES.ERR_VAL_NO_PKG_MANAGERS,
|
|
@@ -1037,8 +1077,6 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1037
1077
|
additionalProperties: telemetryData
|
|
1038
1078
|
}
|
|
1039
1079
|
);
|
|
1040
|
-
if (posthogClient) await posthogClient.shutdown();
|
|
1041
|
-
exit(1);
|
|
1042
1080
|
}
|
|
1043
1081
|
const res = await prompts({
|
|
1044
1082
|
message: "Which package manager would you like to use?",
|
|
@@ -1134,10 +1172,20 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1134
1172
|
if (opts.theme) {
|
|
1135
1173
|
const validThemes = THEMES.map((t) => t.value);
|
|
1136
1174
|
if (!validThemes.includes(opts.theme)) {
|
|
1137
|
-
|
|
1138
|
-
`Invalid theme "${opts.theme}". Valid options are: ${validThemes.join(", ")}
|
|
1175
|
+
await fatalExit(
|
|
1176
|
+
`Invalid theme "${opts.theme}". Valid options are: ${validThemes.join(", ")}`,
|
|
1177
|
+
new Error(`Invalid theme: ${opts.theme}`),
|
|
1178
|
+
{
|
|
1179
|
+
errorCode: ERROR_CODES.ERR_VAL_INVALID_THEME,
|
|
1180
|
+
errorCategory: "validation",
|
|
1181
|
+
step: TRACKING_STEPS.THEME_SELECT,
|
|
1182
|
+
fatal: true,
|
|
1183
|
+
additionalProperties: {
|
|
1184
|
+
...telemetryData,
|
|
1185
|
+
template: template.value
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1139
1188
|
);
|
|
1140
|
-
exit(1);
|
|
1141
1189
|
}
|
|
1142
1190
|
themeChoice = opts.theme;
|
|
1143
1191
|
} else {
|
|
@@ -1172,13 +1220,8 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1172
1220
|
}
|
|
1173
1221
|
const rootDir = path3.join(process.cwd(), projectName);
|
|
1174
1222
|
if (!await isWriteable(path3.dirname(rootDir))) {
|
|
1175
|
-
|
|
1176
|
-
"The application path is not writable, please check folder permissions and try again. It is likely you do not have write permissions for this folder."
|
|
1177
|
-
);
|
|
1178
|
-
postHogCaptureError(
|
|
1179
|
-
posthogClient,
|
|
1180
|
-
userId,
|
|
1181
|
-
sessionId,
|
|
1223
|
+
await fatalExit(
|
|
1224
|
+
"The application path is not writable, please check folder permissions and try again. It is likely you do not have write permissions for this folder.",
|
|
1182
1225
|
new Error("Directory not writable"),
|
|
1183
1226
|
{
|
|
1184
1227
|
errorCode: ERROR_CODES.ERR_FS_NOT_WRITABLE,
|
|
@@ -1188,8 +1231,6 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1188
1231
|
additionalProperties: { ...telemetryData }
|
|
1189
1232
|
}
|
|
1190
1233
|
);
|
|
1191
|
-
if (posthogClient) await posthogClient.shutdown();
|
|
1192
|
-
process.exit(1);
|
|
1193
1234
|
}
|
|
1194
1235
|
let appName;
|
|
1195
1236
|
try {
|
|
@@ -1197,16 +1238,13 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1197
1238
|
telemetryData["app-name"] = appName;
|
|
1198
1239
|
} catch (err) {
|
|
1199
1240
|
const error = err;
|
|
1200
|
-
|
|
1201
|
-
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1241
|
+
await fatalExit(error.message, error, {
|
|
1202
1242
|
errorCode: ERROR_CODES.ERR_FS_MKDIR_FAILED,
|
|
1203
1243
|
errorCategory: "filesystem",
|
|
1204
1244
|
step: TRACKING_STEPS.DIRECTORY_SETUP,
|
|
1205
1245
|
fatal: true,
|
|
1206
1246
|
additionalProperties: { ...telemetryData }
|
|
1207
1247
|
});
|
|
1208
|
-
if (posthogClient) await posthogClient.shutdown();
|
|
1209
|
-
exit(1);
|
|
1210
1248
|
}
|
|
1211
1249
|
try {
|
|
1212
1250
|
if (themeChoice) {
|
|
@@ -1225,24 +1263,30 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1225
1263
|
spinner.succeed();
|
|
1226
1264
|
} catch (err) {
|
|
1227
1265
|
const error = err;
|
|
1228
|
-
|
|
1229
|
-
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1266
|
+
await fatalExit(`Failed to download template: ${error.message}`, error, {
|
|
1230
1267
|
errorCode: ERROR_CODES.ERR_TPL_DOWNLOAD_FAILED,
|
|
1231
1268
|
errorCategory: "template",
|
|
1232
1269
|
step: TRACKING_STEPS.DOWNLOADING_TEMPLATE,
|
|
1233
1270
|
fatal: true,
|
|
1234
1271
|
additionalProperties: { ...telemetryData }
|
|
1235
1272
|
});
|
|
1236
|
-
if (posthogClient) await posthogClient.shutdown();
|
|
1237
|
-
exit(1);
|
|
1238
1273
|
}
|
|
1239
1274
|
spinner.start("Installing packages.");
|
|
1240
1275
|
try {
|
|
1241
1276
|
await install(pkgManager, opts.verbose);
|
|
1242
1277
|
spinner.succeed();
|
|
1243
1278
|
} catch (err) {
|
|
1244
|
-
const error = err;
|
|
1245
|
-
|
|
1279
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1280
|
+
const reason = error.message || String(err);
|
|
1281
|
+
spinner.fail(`Failed to install packages: ${reason}`);
|
|
1282
|
+
console.log(
|
|
1283
|
+
`
|
|
1284
|
+
${box([
|
|
1285
|
+
`${TextStyles.bold("Stuck?")} Check the TinaCMS FAQ for common install issues:`,
|
|
1286
|
+
TextStyles.link(FAQ_URL)
|
|
1287
|
+
])}
|
|
1288
|
+
`
|
|
1289
|
+
);
|
|
1246
1290
|
packageManagerInstallationHadError = true;
|
|
1247
1291
|
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1248
1292
|
errorCode: ERROR_CODES.ERR_INSTALL_PKG_MANAGER_FAILED,
|
|
@@ -1317,12 +1361,21 @@ ${TextStylesBold.bold("Telemetry Notice")}`);
|
|
|
1317
1361
|
"https://tina.io/docs/r/what-is-tinacloud"
|
|
1318
1362
|
)}`
|
|
1319
1363
|
);
|
|
1364
|
+
console.log(
|
|
1365
|
+
` \u2022 \u{1F4AC} Reach out for support: ${TextStyles.link(DISCORD_SUPPORT_URL)}`
|
|
1366
|
+
);
|
|
1320
1367
|
}
|
|
1321
1368
|
run().catch(async (error) => {
|
|
1322
1369
|
if (process.stdout.columns >= 60) {
|
|
1323
1370
|
console.log(TextStyles.tinaOrange(`${errorArt}`));
|
|
1324
1371
|
}
|
|
1325
1372
|
console.error("Error running create-tina-app:", error);
|
|
1373
|
+
console.error(
|
|
1374
|
+
`
|
|
1375
|
+
\u{1F4AC} Need more help? Reach out to the TinaCMS community at ${TextStyles.link(
|
|
1376
|
+
DISCORD_SUPPORT_URL
|
|
1377
|
+
)}`
|
|
1378
|
+
);
|
|
1326
1379
|
const sessionId = generateSessionId();
|
|
1327
1380
|
const userId = await getAnonymousUserId();
|
|
1328
1381
|
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
package/dist/util/install.d.ts
CHANGED
|
@@ -3,5 +3,7 @@ import { PackageManager } from './packageManagers';
|
|
|
3
3
|
* Spawn a package manager installation.
|
|
4
4
|
*
|
|
5
5
|
* @returns A Promise that resolves once the installation is finished.
|
|
6
|
+
* On failure it rejects with an `Error` whose message includes the command,
|
|
7
|
+
* the exit code, and the tail of the captured output.
|
|
6
8
|
*/
|
|
7
9
|
export declare function install(packageManager: PackageManager, verboseOutput: boolean): Promise<void>;
|
package/dist/util/posthog.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare const ERROR_CODES: {
|
|
|
35
35
|
readonly ERR_VAL_INVALID_TEMPLATE: "ERR_VAL_INVALID_TEMPLATE";
|
|
36
36
|
readonly ERR_VAL_INVALID_PKG_MANAGER: "ERR_VAL_INVALID_PKG_MANAGER";
|
|
37
37
|
readonly ERR_VAL_INVALID_PROJECT_NAME: "ERR_VAL_INVALID_PROJECT_NAME";
|
|
38
|
+
readonly ERR_VAL_INVALID_THEME: "ERR_VAL_INVALID_THEME";
|
|
38
39
|
readonly ERR_VAL_UNSUPPORTED_NODE: "ERR_VAL_UNSUPPORTED_NODE";
|
|
39
40
|
readonly ERR_VAL_NO_PKG_MANAGERS: "ERR_VAL_NO_PKG_MANAGERS";
|
|
40
41
|
readonly ERR_FS_NOT_WRITABLE: "ERR_FS_NOT_WRITABLE";
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draw a bordered box around one or more lines so a message stands out from the
|
|
3
|
+
* surrounding log output.
|
|
4
|
+
*/
|
|
5
|
+
export declare const box: (lines: string[], color?: (s: string) => string) => string;
|
|
1
6
|
export declare const TextStyles: {
|
|
2
7
|
tinaOrange: import("chalk").ChalkInstance;
|
|
3
8
|
link: (url: string) => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-tina-app",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
]
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": "
|
|
23
|
+
"node": "22.x || 24.x"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"registry": "https://registry.npmjs.org"
|