create-tina-app 0.0.0-e6ffde4-20251216055147 → 0.0.0-e9ba228-20251219004107
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 +511 -44
- package/dist/util/fetchPosthogConfig.d.ts +5 -0
- package/dist/util/posthog.d.ts +147 -0
- package/dist/util/textstyles.d.ts +10 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { Telemetry } from "@tinacms/metrics";
|
|
3
2
|
import prompts from "prompts";
|
|
4
|
-
import
|
|
3
|
+
import path3 from "node:path";
|
|
5
4
|
import { createRequire } from "node:module";
|
|
6
5
|
|
|
7
6
|
// src/util/fileUtil.ts
|
|
@@ -20,6 +19,16 @@ var TextStyles = {
|
|
|
20
19
|
err: chalk.red,
|
|
21
20
|
bold: chalk.bold
|
|
22
21
|
};
|
|
22
|
+
var TextStylesBold = {
|
|
23
|
+
tinaOrange: chalk.hex("#EC4816").bold,
|
|
24
|
+
link: (url) => `\x1B]8;;${url}\x07${chalk.cyan.underline(url)}\x1B]8;;\x07`,
|
|
25
|
+
cmd: chalk.bgBlackBright.bold.white,
|
|
26
|
+
info: chalk.blue,
|
|
27
|
+
success: chalk.green,
|
|
28
|
+
warn: chalk.yellow,
|
|
29
|
+
err: chalk.red,
|
|
30
|
+
bold: chalk.bold
|
|
31
|
+
};
|
|
23
32
|
|
|
24
33
|
// src/util/fileUtil.ts
|
|
25
34
|
async function isWriteable(directory) {
|
|
@@ -125,7 +134,6 @@ function install(packageManager, verboseOutput) {
|
|
|
125
134
|
|
|
126
135
|
// src/util/git.ts
|
|
127
136
|
import { execSync } from "child_process";
|
|
128
|
-
import path2 from "path";
|
|
129
137
|
import fs2 from "fs-extra";
|
|
130
138
|
function isInGitRepository() {
|
|
131
139
|
try {
|
|
@@ -144,16 +152,11 @@ function isInMercurialRepository() {
|
|
|
144
152
|
return false;
|
|
145
153
|
}
|
|
146
154
|
function makeFirstCommit(root) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
});
|
|
153
|
-
} catch (err) {
|
|
154
|
-
fs2.removeSync(path2.join(root, ".git"));
|
|
155
|
-
throw err;
|
|
156
|
-
}
|
|
155
|
+
execSync("git checkout -b main", { stdio: "ignore" });
|
|
156
|
+
execSync("git add -A", { stdio: "ignore" });
|
|
157
|
+
execSync('git commit -m "Initial commit from Create Tina App"', {
|
|
158
|
+
stdio: "ignore"
|
|
159
|
+
});
|
|
157
160
|
}
|
|
158
161
|
function initializeGit(spinner) {
|
|
159
162
|
execSync("git --version", { stdio: "ignore" });
|
|
@@ -236,7 +239,7 @@ async function downloadAndExtractRepo(root, { username, name: name2, branch, fil
|
|
|
236
239
|
|
|
237
240
|
// src/templates.ts
|
|
238
241
|
import { copy } from "fs-extra";
|
|
239
|
-
import
|
|
242
|
+
import path2 from "path";
|
|
240
243
|
var TEMPLATES = [
|
|
241
244
|
{
|
|
242
245
|
title: "\u2B50 NextJS starter",
|
|
@@ -405,7 +408,7 @@ async function downloadTemplate(template, root, spinner) {
|
|
|
405
408
|
)}`;
|
|
406
409
|
await downloadAndExtractRepo(root, repoInfo);
|
|
407
410
|
} else {
|
|
408
|
-
const templateFile =
|
|
411
|
+
const templateFile = path2.join(__dirname, "..", "examples", template.value);
|
|
409
412
|
await copy(`${templateFile}/`, "./");
|
|
410
413
|
}
|
|
411
414
|
}
|
|
@@ -455,7 +458,7 @@ import { Command } from "commander";
|
|
|
455
458
|
|
|
456
459
|
// package.json
|
|
457
460
|
var name = "create-tina-app";
|
|
458
|
-
var version = "2.
|
|
461
|
+
var version = "2.1.0";
|
|
459
462
|
|
|
460
463
|
// src/util/packageManagers.ts
|
|
461
464
|
var PKG_MANAGERS = ["npm", "yarn", "pnpm", "bun"];
|
|
@@ -631,6 +634,259 @@ var THEMES = [
|
|
|
631
634
|
];
|
|
632
635
|
|
|
633
636
|
// src/index.ts
|
|
637
|
+
import { PostHog } from "posthog-node";
|
|
638
|
+
|
|
639
|
+
// src/util/posthog.ts
|
|
640
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
641
|
+
import { system as getSystemInfo } from "systeminformation";
|
|
642
|
+
var CreateTinaAppStartedEvent = "create-tina-app-started";
|
|
643
|
+
var CreateTinaAppFinishedEvent = "create-tina-app-finished";
|
|
644
|
+
var TRACKING_STEPS = {
|
|
645
|
+
INIT: "initializing",
|
|
646
|
+
PRE_RUN_CHECKS: "pre_run_checks",
|
|
647
|
+
TELEMETRY_SETUP: "telemetry_setup",
|
|
648
|
+
PKG_MANAGER_SELECT: "package_manager_selection",
|
|
649
|
+
PROJECT_NAME_INPUT: "project_name_input",
|
|
650
|
+
TEMPLATE_SELECT: "template_selection",
|
|
651
|
+
THEME_SELECT: "theme_selection",
|
|
652
|
+
DIRECTORY_SETUP: "directory_setup",
|
|
653
|
+
DOWNLOADING_TEMPLATE: "downloading_template",
|
|
654
|
+
UPDATING_METADATA: "updating_metadata",
|
|
655
|
+
INSTALLING_PACKAGES: "installing_packages",
|
|
656
|
+
GIT_INIT: "git_initialization",
|
|
657
|
+
COMPLETE: "complete"
|
|
658
|
+
};
|
|
659
|
+
function generateSessionId() {
|
|
660
|
+
return randomUUID();
|
|
661
|
+
}
|
|
662
|
+
async function getAnonymousUserId() {
|
|
663
|
+
try {
|
|
664
|
+
const sysInfo = await getSystemInfo();
|
|
665
|
+
const systemUuid = sysInfo.uuid || "unknown";
|
|
666
|
+
if (systemUuid === "unknown" || !systemUuid) {
|
|
667
|
+
return `fallback-${randomUUID()}`;
|
|
668
|
+
}
|
|
669
|
+
const hash = createHash("sha256");
|
|
670
|
+
hash.update(systemUuid);
|
|
671
|
+
return hash.digest("hex").substring(0, 32);
|
|
672
|
+
} catch (error) {
|
|
673
|
+
return `fallback-${randomUUID()}`;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
var ERROR_CODES = {
|
|
677
|
+
// Validation Errors (VAL_*)
|
|
678
|
+
ERR_VAL_INVALID_TEMPLATE: "ERR_VAL_INVALID_TEMPLATE",
|
|
679
|
+
ERR_VAL_INVALID_PKG_MANAGER: "ERR_VAL_INVALID_PKG_MANAGER",
|
|
680
|
+
ERR_VAL_INVALID_PROJECT_NAME: "ERR_VAL_INVALID_PROJECT_NAME",
|
|
681
|
+
ERR_VAL_UNSUPPORTED_NODE: "ERR_VAL_UNSUPPORTED_NODE",
|
|
682
|
+
ERR_VAL_NO_PKG_MANAGERS: "ERR_VAL_NO_PKG_MANAGERS",
|
|
683
|
+
// File System Errors (FS_*)
|
|
684
|
+
ERR_FS_NOT_WRITABLE: "ERR_FS_NOT_WRITABLE",
|
|
685
|
+
ERR_FS_HAS_CONFLICTS: "ERR_FS_HAS_CONFLICTS",
|
|
686
|
+
ERR_FS_MKDIR_FAILED: "ERR_FS_MKDIR_FAILED",
|
|
687
|
+
ERR_FS_CHDIR_FAILED: "ERR_FS_CHDIR_FAILED",
|
|
688
|
+
ERR_FS_READ_PACKAGE_JSON: "ERR_FS_READ_PACKAGE_JSON",
|
|
689
|
+
ERR_FS_WRITE_PACKAGE_JSON: "ERR_FS_WRITE_PACKAGE_JSON",
|
|
690
|
+
ERR_FS_UPDATE_THEME_FAILED: "ERR_FS_UPDATE_THEME_FAILED",
|
|
691
|
+
ERR_FS_COPY_TEMPLATE_FAILED: "ERR_FS_COPY_TEMPLATE_FAILED",
|
|
692
|
+
// Network Errors (NET_*)
|
|
693
|
+
ERR_NET_POSTHOG_CONFIG_FETCH: "ERR_NET_POSTHOG_CONFIG_FETCH",
|
|
694
|
+
ERR_NET_TARBALL_DOWNLOAD: "ERR_NET_TARBALL_DOWNLOAD",
|
|
695
|
+
ERR_NET_GITHUB_API_FAILED: "ERR_NET_GITHUB_API_FAILED",
|
|
696
|
+
ERR_NET_REPO_INFO_NOT_FOUND: "ERR_NET_REPO_INFO_NOT_FOUND",
|
|
697
|
+
ERR_NET_REPO_INVALID_URL: "ERR_NET_REPO_INVALID_URL",
|
|
698
|
+
ERR_NET_TARBALL_EXTRACT: "ERR_NET_TARBALL_EXTRACT",
|
|
699
|
+
// Installation Errors (INSTALL_*)
|
|
700
|
+
ERR_INSTALL_PKG_MANAGER_FAILED: "ERR_INSTALL_PKG_MANAGER_FAILED",
|
|
701
|
+
ERR_INSTALL_PKG_MANAGER_NOT_FOUND: "ERR_INSTALL_PKG_MANAGER_NOT_FOUND",
|
|
702
|
+
ERR_INSTALL_SPAWN_ERROR: "ERR_INSTALL_SPAWN_ERROR",
|
|
703
|
+
ERR_INSTALL_TIMEOUT: "ERR_INSTALL_TIMEOUT",
|
|
704
|
+
// Git Errors (GIT_*)
|
|
705
|
+
ERR_GIT_NOT_INSTALLED: "ERR_GIT_NOT_INSTALLED",
|
|
706
|
+
ERR_GIT_INIT_FAILED: "ERR_GIT_INIT_FAILED",
|
|
707
|
+
ERR_GIT_ADD_FAILED: "ERR_GIT_ADD_FAILED",
|
|
708
|
+
ERR_GIT_COMMIT_FAILED: "ERR_GIT_COMMIT_FAILED",
|
|
709
|
+
ERR_GIT_CHECKOUT_FAILED: "ERR_GIT_CHECKOUT_FAILED",
|
|
710
|
+
ERR_GIT_ALREADY_INITIALIZED: "ERR_GIT_ALREADY_INITIALIZED",
|
|
711
|
+
// User Cancellation (CANCEL_*)
|
|
712
|
+
ERR_CANCEL_PKG_MANAGER_PROMPT: "ERR_CANCEL_PKG_MANAGER_PROMPT",
|
|
713
|
+
ERR_CANCEL_PROJECT_NAME_PROMPT: "ERR_CANCEL_PROJECT_NAME_PROMPT",
|
|
714
|
+
ERR_CANCEL_TEMPLATE_PROMPT: "ERR_CANCEL_TEMPLATE_PROMPT",
|
|
715
|
+
ERR_CANCEL_THEME_PROMPT: "ERR_CANCEL_THEME_PROMPT",
|
|
716
|
+
ERR_CANCEL_SIGINT: "ERR_CANCEL_SIGINT",
|
|
717
|
+
// Configuration Errors (CFG_*)
|
|
718
|
+
ERR_CFG_POSTHOG_INIT_FAILED: "ERR_CFG_POSTHOG_INIT_FAILED",
|
|
719
|
+
ERR_CFG_OSINFO_FETCH_FAILED: "ERR_CFG_OSINFO_FETCH_FAILED",
|
|
720
|
+
ERR_CFG_TELEMETRY_SETUP_FAILED: "ERR_CFG_TELEMETRY_SETUP_FAILED",
|
|
721
|
+
// Template Errors (TPL_*)
|
|
722
|
+
ERR_TPL_DOWNLOAD_FAILED: "ERR_TPL_DOWNLOAD_FAILED",
|
|
723
|
+
ERR_TPL_EXTRACT_FAILED: "ERR_TPL_EXTRACT_FAILED",
|
|
724
|
+
ERR_TPL_METADATA_UPDATE_FAILED: "ERR_TPL_METADATA_UPDATE_FAILED",
|
|
725
|
+
ERR_TPL_INTERNAL_COPY_FAILED: "ERR_TPL_INTERNAL_COPY_FAILED",
|
|
726
|
+
ERR_TPL_THEME_UPDATE_FAILED: "ERR_TPL_THEME_UPDATE_FAILED",
|
|
727
|
+
// Uncategorized
|
|
728
|
+
ERR_UNCAUGHT: "ERR_UNCAUGHT"
|
|
729
|
+
};
|
|
730
|
+
function sanitizeStackTrace(stack) {
|
|
731
|
+
if (!stack) return "";
|
|
732
|
+
let sanitized = stack;
|
|
733
|
+
sanitized = sanitized.replace(/\/Users\/[^\/]+/g, "<user-home>");
|
|
734
|
+
sanitized = sanitized.replace(/[A-Z]:\\Users\\[^\\]+/gi, "<user-home>");
|
|
735
|
+
sanitized = sanitized.replace(
|
|
736
|
+
/.*\/(packages\/create-tina-app)\//g,
|
|
737
|
+
"<workspace>/$1/"
|
|
738
|
+
);
|
|
739
|
+
sanitized = sanitized.replace(
|
|
740
|
+
/(\/|\\)node_modules(\/|\\)/g,
|
|
741
|
+
"<node_modules>/"
|
|
742
|
+
);
|
|
743
|
+
sanitized = sanitized.replace(/\.npm\/_cacache/g, "<pkg-cache>");
|
|
744
|
+
sanitized = sanitized.replace(/\.yarn\/cache/g, "<pkg-cache>");
|
|
745
|
+
sanitized = sanitized.replace(/\.pnpm-store/g, "<pkg-cache>");
|
|
746
|
+
sanitized = sanitized.replace(/[A-Z]:\\/gi, "<drive>/");
|
|
747
|
+
return sanitized;
|
|
748
|
+
}
|
|
749
|
+
function truncateStackTrace(stack, maxFrames = 5) {
|
|
750
|
+
const lines = stack.split("\n");
|
|
751
|
+
const filtered = lines.filter((line) => {
|
|
752
|
+
if (!line.trim().startsWith("at ")) return true;
|
|
753
|
+
return !line.includes("node:internal") && !line.includes("node_modules/prompts") && !line.includes("node_modules/ora");
|
|
754
|
+
}).slice(0, maxFrames + 1);
|
|
755
|
+
return filtered.join("\n");
|
|
756
|
+
}
|
|
757
|
+
function createSimpleHash(str) {
|
|
758
|
+
let hash = 0;
|
|
759
|
+
for (let i = 0; i < str.length; i++) {
|
|
760
|
+
const char = str.charCodeAt(i);
|
|
761
|
+
hash = (hash << 5) - hash + char;
|
|
762
|
+
hash = hash & hash;
|
|
763
|
+
}
|
|
764
|
+
return Math.abs(hash).toString(36);
|
|
765
|
+
}
|
|
766
|
+
function sanitizeError(error) {
|
|
767
|
+
const message = error.message || "Unknown error";
|
|
768
|
+
const rawStack = error.stack || "";
|
|
769
|
+
const truncated = truncateStackTrace(rawStack);
|
|
770
|
+
const sanitizedStack = sanitizeStackTrace(truncated);
|
|
771
|
+
const stackForHash = rawStack.replace(/:\d+:\d+/g, "").replace(/\/Users\/[^\/]+/g, "").replace(/[A-Z]:\\Users\\[^\\]+/gi, "");
|
|
772
|
+
const originalStackHash = createSimpleHash(stackForHash);
|
|
773
|
+
return {
|
|
774
|
+
message,
|
|
775
|
+
sanitizedStack,
|
|
776
|
+
originalStackHash
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
function postHogCapture(client, distinctId, sessionId, event, properties) {
|
|
780
|
+
if (process.env.TINA_DEV === "true") return;
|
|
781
|
+
if (!client) {
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
try {
|
|
785
|
+
client.capture({
|
|
786
|
+
distinctId,
|
|
787
|
+
event,
|
|
788
|
+
properties: {
|
|
789
|
+
...properties,
|
|
790
|
+
sessionId,
|
|
791
|
+
system: "tinacms/create-tina-app"
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
} catch (error) {
|
|
795
|
+
console.error("Error capturing event:", error);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
function postHogCaptureError(client, distinctId, sessionId, error, context) {
|
|
799
|
+
if (process.env.TINA_DEV === "true") return;
|
|
800
|
+
if (!client) return;
|
|
801
|
+
const { message, sanitizedStack, originalStackHash } = sanitizeError(error);
|
|
802
|
+
const {
|
|
803
|
+
errorCode,
|
|
804
|
+
errorCategory,
|
|
805
|
+
step,
|
|
806
|
+
fatal = true,
|
|
807
|
+
additionalProperties = {}
|
|
808
|
+
} = context;
|
|
809
|
+
let eventName;
|
|
810
|
+
if (errorCategory === "user-cancellation") {
|
|
811
|
+
eventName = "create-tina-app-user-cancelled";
|
|
812
|
+
} else if (errorCategory === "validation") {
|
|
813
|
+
eventName = "create-tina-app-validation-error";
|
|
814
|
+
} else {
|
|
815
|
+
eventName = "create-tina-app-error";
|
|
816
|
+
}
|
|
817
|
+
const properties = {
|
|
818
|
+
error_code: errorCode,
|
|
819
|
+
error_category: errorCategory,
|
|
820
|
+
error_message: message.substring(0, 500),
|
|
821
|
+
// Limit message length
|
|
822
|
+
sanitized_stack: sanitizedStack,
|
|
823
|
+
stack_hash: originalStackHash,
|
|
824
|
+
step,
|
|
825
|
+
fatal,
|
|
826
|
+
user_cancelled: errorCategory === "user-cancellation",
|
|
827
|
+
sessionId,
|
|
828
|
+
...additionalProperties
|
|
829
|
+
};
|
|
830
|
+
try {
|
|
831
|
+
client.capture({
|
|
832
|
+
distinctId,
|
|
833
|
+
event: eventName,
|
|
834
|
+
properties: {
|
|
835
|
+
...properties,
|
|
836
|
+
system: "tinacms/create-tina-app"
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
} catch (captureError) {
|
|
840
|
+
console.error("Error capturing error event:", captureError);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/util/fetchPosthogConfig.tsx
|
|
845
|
+
async function fetchPostHogConfig(endpointUrl) {
|
|
846
|
+
try {
|
|
847
|
+
const response = await fetch(endpointUrl, {
|
|
848
|
+
method: "GET",
|
|
849
|
+
headers: {
|
|
850
|
+
"Content-Type": "application/json"
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
if (!response.ok) {
|
|
854
|
+
throw new Error(`Failed to fetch PostHog config: ${response.statusText}`);
|
|
855
|
+
}
|
|
856
|
+
const config = await response.json();
|
|
857
|
+
return {
|
|
858
|
+
POSTHOG_API_KEY: config.api_key,
|
|
859
|
+
POSTHOG_ENDPOINT: config.host
|
|
860
|
+
};
|
|
861
|
+
} catch (error) {
|
|
862
|
+
console.warn(
|
|
863
|
+
`Failed to fetch PostHog config from endpoint: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
864
|
+
);
|
|
865
|
+
return {};
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// src/index.ts
|
|
870
|
+
import { osInfo as getOsSystemInfo } from "systeminformation";
|
|
871
|
+
var posthogClient = null;
|
|
872
|
+
async function initializePostHog(configEndpoint) {
|
|
873
|
+
let apiKey;
|
|
874
|
+
let endpoint;
|
|
875
|
+
if (configEndpoint) {
|
|
876
|
+
const config = await fetchPostHogConfig(configEndpoint);
|
|
877
|
+
apiKey = config.POSTHOG_API_KEY;
|
|
878
|
+
endpoint = config.POSTHOG_ENDPOINT;
|
|
879
|
+
}
|
|
880
|
+
if (!apiKey) {
|
|
881
|
+
console.warn(
|
|
882
|
+
"PostHog API key not found. PostHog tracking will be disabled."
|
|
883
|
+
);
|
|
884
|
+
return null;
|
|
885
|
+
}
|
|
886
|
+
return new PostHog(apiKey, {
|
|
887
|
+
host: endpoint
|
|
888
|
+
});
|
|
889
|
+
}
|
|
634
890
|
function formatTemplateChoice(template) {
|
|
635
891
|
let description = template.description || "";
|
|
636
892
|
if (template.features && template.features.length > 0) {
|
|
@@ -649,6 +905,8 @@ ${featuresText}`;
|
|
|
649
905
|
async function run() {
|
|
650
906
|
const ora = (await import("ora")).default;
|
|
651
907
|
let packageManagerInstallationHadError = false;
|
|
908
|
+
const sessionId = generateSessionId();
|
|
909
|
+
const userId = await getAnonymousUserId();
|
|
652
910
|
if (process.stdout.columns >= 60) {
|
|
653
911
|
console.log(TextStyles.tinaOrange(`${llama}`));
|
|
654
912
|
console.log(TextStyles.tinaOrange(`${tinaCms}`));
|
|
@@ -658,10 +916,43 @@ async function run() {
|
|
|
658
916
|
const require2 = createRequire(import.meta.url);
|
|
659
917
|
const version2 = require2("../package.json").version;
|
|
660
918
|
console.log(`Create Tina App v${version2}`);
|
|
919
|
+
const opts = extractOptions(process.argv);
|
|
920
|
+
const installedPkgManagers = [];
|
|
921
|
+
for (const pkg_manager of PKG_MANAGERS) {
|
|
922
|
+
if (await checkPackageExists(pkg_manager)) {
|
|
923
|
+
installedPkgManagers.push(pkg_manager);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
const telemetryData = {};
|
|
927
|
+
if (!opts.noTelemetry) {
|
|
928
|
+
console.log(`
|
|
929
|
+
${TextStylesBold.bold("Telemetry Notice")}`);
|
|
930
|
+
console.log(
|
|
931
|
+
`To help the TinaCMS team improve the developer experience, create-tina-app collects anonymous usage statistics. This data helps us understand which environments and features are most important to support. Usage analytics may include: Operating system and version, package manager name and version (local only), Node.js version (local only), and the selected TinaCMS starter template.
|
|
932
|
+
No personal or project-specific code is ever collected. You can opt out at any time by passing the --noTelemetry flag.
|
|
933
|
+
`
|
|
934
|
+
);
|
|
935
|
+
posthogClient = await initializePostHog(
|
|
936
|
+
"https://identity-v2.tinajs.io/v2/posthog-token"
|
|
937
|
+
);
|
|
938
|
+
const osInfo = await getOsSystemInfo();
|
|
939
|
+
telemetryData["os-platform"] = osInfo.platform;
|
|
940
|
+
telemetryData["os-distro"] = osInfo.distro;
|
|
941
|
+
telemetryData["os-release"] = osInfo.release;
|
|
942
|
+
telemetryData["node-version"] = process.version;
|
|
943
|
+
for (const pkgManager2 of PKG_MANAGERS) {
|
|
944
|
+
telemetryData[`${pkgManager2}-installed`] = installedPkgManagers.includes(pkgManager2);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
661
947
|
const spinner = ora();
|
|
662
948
|
preRunChecks(spinner);
|
|
663
|
-
|
|
664
|
-
|
|
949
|
+
postHogCapture(
|
|
950
|
+
posthogClient,
|
|
951
|
+
userId,
|
|
952
|
+
sessionId,
|
|
953
|
+
CreateTinaAppStartedEvent,
|
|
954
|
+
telemetryData
|
|
955
|
+
);
|
|
665
956
|
let template = null;
|
|
666
957
|
if (opts.template) {
|
|
667
958
|
template = TEMPLATES.find((_template) => _template.value === opts.template);
|
|
@@ -671,6 +962,23 @@ async function run() {
|
|
|
671
962
|
(x2) => x2.value
|
|
672
963
|
)}`
|
|
673
964
|
);
|
|
965
|
+
postHogCaptureError(
|
|
966
|
+
posthogClient,
|
|
967
|
+
userId,
|
|
968
|
+
sessionId,
|
|
969
|
+
new Error(`Invalid template: ${opts.template}`),
|
|
970
|
+
{
|
|
971
|
+
errorCode: ERROR_CODES.ERR_VAL_INVALID_TEMPLATE,
|
|
972
|
+
errorCategory: "validation",
|
|
973
|
+
step: TRACKING_STEPS.TEMPLATE_SELECT,
|
|
974
|
+
fatal: true,
|
|
975
|
+
additionalProperties: {
|
|
976
|
+
...telemetryData,
|
|
977
|
+
"package-manager": opts.template
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
);
|
|
981
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
674
982
|
exit(1);
|
|
675
983
|
}
|
|
676
984
|
}
|
|
@@ -680,20 +988,45 @@ async function run() {
|
|
|
680
988
|
spinner.fail(
|
|
681
989
|
`The provided package manager '${opts.pkgManager}' is not supported. Please provide one of the following: ${PKG_MANAGERS}`
|
|
682
990
|
);
|
|
991
|
+
postHogCaptureError(
|
|
992
|
+
posthogClient,
|
|
993
|
+
userId,
|
|
994
|
+
sessionId,
|
|
995
|
+
new Error(`Invalid package manager: ${opts.pkgManager}`),
|
|
996
|
+
{
|
|
997
|
+
errorCode: ERROR_CODES.ERR_VAL_INVALID_PKG_MANAGER,
|
|
998
|
+
errorCategory: "validation",
|
|
999
|
+
step: TRACKING_STEPS.PKG_MANAGER_SELECT,
|
|
1000
|
+
fatal: true,
|
|
1001
|
+
additionalProperties: {
|
|
1002
|
+
...telemetryData,
|
|
1003
|
+
provided_pkg_manager: opts.pkgManager
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
);
|
|
1007
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
683
1008
|
exit(1);
|
|
684
1009
|
}
|
|
685
1010
|
}
|
|
686
1011
|
if (!pkgManager) {
|
|
687
|
-
const installedPkgManagers = [];
|
|
688
|
-
for (const pkg_manager of PKG_MANAGERS) {
|
|
689
|
-
if (await checkPackageExists(pkg_manager)) {
|
|
690
|
-
installedPkgManagers.push(pkg_manager);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
1012
|
if (installedPkgManagers.length === 0) {
|
|
694
1013
|
spinner.fail(
|
|
695
1014
|
`You have no supported package managers installed. Please install one of the following: ${PKG_MANAGERS}`
|
|
696
1015
|
);
|
|
1016
|
+
postHogCaptureError(
|
|
1017
|
+
posthogClient,
|
|
1018
|
+
userId,
|
|
1019
|
+
sessionId,
|
|
1020
|
+
new Error("No supported package managers installed"),
|
|
1021
|
+
{
|
|
1022
|
+
errorCode: ERROR_CODES.ERR_VAL_NO_PKG_MANAGERS,
|
|
1023
|
+
errorCategory: "validation",
|
|
1024
|
+
step: TRACKING_STEPS.PRE_RUN_CHECKS,
|
|
1025
|
+
fatal: true,
|
|
1026
|
+
additionalProperties: telemetryData
|
|
1027
|
+
}
|
|
1028
|
+
);
|
|
1029
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
697
1030
|
exit(1);
|
|
698
1031
|
}
|
|
699
1032
|
const res = await prompts({
|
|
@@ -704,9 +1037,26 @@ async function run() {
|
|
|
704
1037
|
return { title: manager, value: manager };
|
|
705
1038
|
})
|
|
706
1039
|
});
|
|
707
|
-
if (!Object.hasOwn(res, "packageManager"))
|
|
1040
|
+
if (!Object.hasOwn(res, "packageManager")) {
|
|
1041
|
+
postHogCaptureError(
|
|
1042
|
+
posthogClient,
|
|
1043
|
+
userId,
|
|
1044
|
+
sessionId,
|
|
1045
|
+
new Error("User cancelled package manager selection"),
|
|
1046
|
+
{
|
|
1047
|
+
errorCode: ERROR_CODES.ERR_CANCEL_PKG_MANAGER_PROMPT,
|
|
1048
|
+
errorCategory: "user-cancellation",
|
|
1049
|
+
step: TRACKING_STEPS.PKG_MANAGER_SELECT,
|
|
1050
|
+
fatal: true,
|
|
1051
|
+
additionalProperties: telemetryData
|
|
1052
|
+
}
|
|
1053
|
+
);
|
|
1054
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
1055
|
+
exit(1);
|
|
1056
|
+
}
|
|
708
1057
|
pkgManager = res.packageManager;
|
|
709
1058
|
}
|
|
1059
|
+
telemetryData["package-manager"] = pkgManager;
|
|
710
1060
|
let projectName = opts.projectName;
|
|
711
1061
|
if (!projectName) {
|
|
712
1062
|
const res = await prompts({
|
|
@@ -716,13 +1066,29 @@ async function run() {
|
|
|
716
1066
|
initial: "my-tina-app",
|
|
717
1067
|
validate: (name2) => {
|
|
718
1068
|
const { message, isError } = validate(
|
|
719
|
-
|
|
1069
|
+
path3.basename(path3.resolve(name2))
|
|
720
1070
|
);
|
|
721
1071
|
if (isError) return `Invalid project name: ${message}`;
|
|
722
1072
|
return true;
|
|
723
1073
|
}
|
|
724
1074
|
});
|
|
725
|
-
if (!Object.hasOwn(res, "name"))
|
|
1075
|
+
if (!Object.hasOwn(res, "name")) {
|
|
1076
|
+
postHogCaptureError(
|
|
1077
|
+
posthogClient,
|
|
1078
|
+
userId,
|
|
1079
|
+
sessionId,
|
|
1080
|
+
new Error("User cancelled project name input"),
|
|
1081
|
+
{
|
|
1082
|
+
errorCode: ERROR_CODES.ERR_CANCEL_PROJECT_NAME_PROMPT,
|
|
1083
|
+
errorCategory: "user-cancellation",
|
|
1084
|
+
step: TRACKING_STEPS.PROJECT_NAME_INPUT,
|
|
1085
|
+
fatal: true,
|
|
1086
|
+
additionalProperties: telemetryData
|
|
1087
|
+
}
|
|
1088
|
+
);
|
|
1089
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
1090
|
+
exit(1);
|
|
1091
|
+
}
|
|
726
1092
|
projectName = res.name;
|
|
727
1093
|
}
|
|
728
1094
|
if (!template) {
|
|
@@ -732,9 +1098,26 @@ async function run() {
|
|
|
732
1098
|
message: "What starter code would you like to use?",
|
|
733
1099
|
choices: TEMPLATES.map(formatTemplateChoice)
|
|
734
1100
|
});
|
|
735
|
-
if (!Object.hasOwn(res, "template"))
|
|
1101
|
+
if (!Object.hasOwn(res, "template")) {
|
|
1102
|
+
postHogCaptureError(
|
|
1103
|
+
posthogClient,
|
|
1104
|
+
userId,
|
|
1105
|
+
sessionId,
|
|
1106
|
+
new Error("User cancelled template selection"),
|
|
1107
|
+
{
|
|
1108
|
+
errorCode: ERROR_CODES.ERR_CANCEL_TEMPLATE_PROMPT,
|
|
1109
|
+
errorCategory: "user-cancellation",
|
|
1110
|
+
step: TRACKING_STEPS.TEMPLATE_SELECT,
|
|
1111
|
+
fatal: true,
|
|
1112
|
+
additionalProperties: telemetryData
|
|
1113
|
+
}
|
|
1114
|
+
);
|
|
1115
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
1116
|
+
exit(1);
|
|
1117
|
+
}
|
|
736
1118
|
template = TEMPLATES.find((_template) => _template.value === res.template);
|
|
737
1119
|
}
|
|
1120
|
+
telemetryData["template"] = template.value;
|
|
738
1121
|
let themeChoice;
|
|
739
1122
|
if (template.value === "tina-docs") {
|
|
740
1123
|
const res = await prompts({
|
|
@@ -743,33 +1126,69 @@ async function run() {
|
|
|
743
1126
|
message: "What theme would you like to use?",
|
|
744
1127
|
choices: THEMES
|
|
745
1128
|
});
|
|
746
|
-
if (!Object.hasOwn(res, "theme"))
|
|
1129
|
+
if (!Object.hasOwn(res, "theme")) {
|
|
1130
|
+
postHogCaptureError(
|
|
1131
|
+
posthogClient,
|
|
1132
|
+
userId,
|
|
1133
|
+
sessionId,
|
|
1134
|
+
new Error("User cancelled theme selection"),
|
|
1135
|
+
{
|
|
1136
|
+
errorCode: ERROR_CODES.ERR_CANCEL_THEME_PROMPT,
|
|
1137
|
+
errorCategory: "user-cancellation",
|
|
1138
|
+
step: TRACKING_STEPS.THEME_SELECT,
|
|
1139
|
+
fatal: true,
|
|
1140
|
+
additionalProperties: {
|
|
1141
|
+
...telemetryData,
|
|
1142
|
+
template: template.value
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
);
|
|
1146
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
1147
|
+
exit(1);
|
|
1148
|
+
}
|
|
747
1149
|
themeChoice = res.theme;
|
|
748
1150
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
name: "create-tina-app:invoke",
|
|
752
|
-
template: template.value,
|
|
753
|
-
pkgManager
|
|
754
|
-
}
|
|
755
|
-
});
|
|
756
|
-
const rootDir = path4.join(process.cwd(), projectName);
|
|
757
|
-
if (!await isWriteable(path4.dirname(rootDir))) {
|
|
1151
|
+
const rootDir = path3.join(process.cwd(), projectName);
|
|
1152
|
+
if (!await isWriteable(path3.dirname(rootDir))) {
|
|
758
1153
|
spinner.fail(
|
|
759
1154
|
"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."
|
|
760
1155
|
);
|
|
1156
|
+
postHogCaptureError(
|
|
1157
|
+
posthogClient,
|
|
1158
|
+
userId,
|
|
1159
|
+
sessionId,
|
|
1160
|
+
new Error("Directory not writable"),
|
|
1161
|
+
{
|
|
1162
|
+
errorCode: ERROR_CODES.ERR_FS_NOT_WRITABLE,
|
|
1163
|
+
errorCategory: "filesystem",
|
|
1164
|
+
step: TRACKING_STEPS.DIRECTORY_SETUP,
|
|
1165
|
+
fatal: true,
|
|
1166
|
+
additionalProperties: { ...telemetryData }
|
|
1167
|
+
}
|
|
1168
|
+
);
|
|
1169
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
761
1170
|
process.exit(1);
|
|
762
1171
|
}
|
|
763
1172
|
let appName;
|
|
764
1173
|
try {
|
|
765
1174
|
appName = await setupProjectDirectory(rootDir);
|
|
1175
|
+
telemetryData["app-name"] = appName;
|
|
766
1176
|
} catch (err) {
|
|
767
|
-
|
|
1177
|
+
const error = err;
|
|
1178
|
+
spinner.fail(error.message);
|
|
1179
|
+
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1180
|
+
errorCode: ERROR_CODES.ERR_FS_MKDIR_FAILED,
|
|
1181
|
+
errorCategory: "filesystem",
|
|
1182
|
+
step: TRACKING_STEPS.DIRECTORY_SETUP,
|
|
1183
|
+
fatal: true,
|
|
1184
|
+
additionalProperties: { ...telemetryData }
|
|
1185
|
+
});
|
|
1186
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
768
1187
|
exit(1);
|
|
769
1188
|
}
|
|
770
1189
|
try {
|
|
771
|
-
await downloadTemplate(template, rootDir, spinner);
|
|
772
1190
|
if (themeChoice) {
|
|
1191
|
+
telemetryData["theme"] = themeChoice;
|
|
773
1192
|
await updateThemeSettings(rootDir, themeChoice);
|
|
774
1193
|
}
|
|
775
1194
|
spinner.start("Downloading template...");
|
|
@@ -780,7 +1199,16 @@ async function run() {
|
|
|
780
1199
|
updateProjectPackageVersion(rootDir, "0.0.1");
|
|
781
1200
|
spinner.succeed();
|
|
782
1201
|
} catch (err) {
|
|
783
|
-
|
|
1202
|
+
const error = err;
|
|
1203
|
+
spinner.fail(`Failed to download template: ${error.message}`);
|
|
1204
|
+
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1205
|
+
errorCode: ERROR_CODES.ERR_TPL_DOWNLOAD_FAILED,
|
|
1206
|
+
errorCategory: "template",
|
|
1207
|
+
step: TRACKING_STEPS.DOWNLOADING_TEMPLATE,
|
|
1208
|
+
fatal: true,
|
|
1209
|
+
additionalProperties: { ...telemetryData }
|
|
1210
|
+
});
|
|
1211
|
+
if (posthogClient) await posthogClient.shutdown();
|
|
784
1212
|
exit(1);
|
|
785
1213
|
}
|
|
786
1214
|
spinner.start("Installing packages.");
|
|
@@ -788,8 +1216,16 @@ async function run() {
|
|
|
788
1216
|
await install(pkgManager, opts.verbose);
|
|
789
1217
|
spinner.succeed();
|
|
790
1218
|
} catch (err) {
|
|
791
|
-
|
|
1219
|
+
const error = err;
|
|
1220
|
+
spinner.fail(`Failed to install packages: ${error.message}`);
|
|
792
1221
|
packageManagerInstallationHadError = true;
|
|
1222
|
+
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1223
|
+
errorCode: ERROR_CODES.ERR_INSTALL_PKG_MANAGER_FAILED,
|
|
1224
|
+
errorCategory: "installation",
|
|
1225
|
+
step: TRACKING_STEPS.INSTALLING_PACKAGES,
|
|
1226
|
+
fatal: false,
|
|
1227
|
+
additionalProperties: { ...telemetryData }
|
|
1228
|
+
});
|
|
793
1229
|
}
|
|
794
1230
|
spinner.start("Initializing git repository.");
|
|
795
1231
|
try {
|
|
@@ -798,8 +1234,23 @@ async function run() {
|
|
|
798
1234
|
spinner.succeed();
|
|
799
1235
|
}
|
|
800
1236
|
} catch (err) {
|
|
1237
|
+
const error = err;
|
|
801
1238
|
spinner.fail("Failed to initialize Git repository, skipping.");
|
|
1239
|
+
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1240
|
+
errorCode: ERROR_CODES.ERR_GIT_INIT_FAILED,
|
|
1241
|
+
errorCategory: "git",
|
|
1242
|
+
step: TRACKING_STEPS.GIT_INIT,
|
|
1243
|
+
fatal: false,
|
|
1244
|
+
additionalProperties: { ...telemetryData }
|
|
1245
|
+
});
|
|
802
1246
|
}
|
|
1247
|
+
postHogCapture(
|
|
1248
|
+
posthogClient,
|
|
1249
|
+
userId,
|
|
1250
|
+
sessionId,
|
|
1251
|
+
CreateTinaAppFinishedEvent,
|
|
1252
|
+
telemetryData
|
|
1253
|
+
);
|
|
803
1254
|
spinner.succeed(`Created ${TextStyles.tinaOrange(appName)}
|
|
804
1255
|
`);
|
|
805
1256
|
if (template.value === "tina-hugo-starter") {
|
|
@@ -842,12 +1293,28 @@ async function run() {
|
|
|
842
1293
|
)}`
|
|
843
1294
|
);
|
|
844
1295
|
}
|
|
845
|
-
run().catch((error) => {
|
|
1296
|
+
run().catch(async (error) => {
|
|
846
1297
|
if (process.stdout.columns >= 60) {
|
|
847
1298
|
console.log(TextStyles.tinaOrange(`${errorArt}`));
|
|
848
1299
|
}
|
|
849
|
-
console.error("Error running create-tina-app:
|
|
1300
|
+
console.error("Error running create-tina-app:", error);
|
|
1301
|
+
const sessionId = generateSessionId();
|
|
1302
|
+
const userId = await getAnonymousUserId();
|
|
1303
|
+
postHogCaptureError(posthogClient, userId, sessionId, error, {
|
|
1304
|
+
errorCode: ERROR_CODES.ERR_UNCAUGHT,
|
|
1305
|
+
errorCategory: "uncategorized",
|
|
1306
|
+
step: "unknown",
|
|
1307
|
+
fatal: true,
|
|
1308
|
+
additionalProperties: {}
|
|
1309
|
+
});
|
|
1310
|
+
if (posthogClient) {
|
|
1311
|
+
await posthogClient.shutdown();
|
|
1312
|
+
}
|
|
850
1313
|
process.exit(1);
|
|
1314
|
+
}).then(async () => {
|
|
1315
|
+
if (posthogClient) {
|
|
1316
|
+
await posthogClient.shutdown();
|
|
1317
|
+
}
|
|
851
1318
|
});
|
|
852
1319
|
export {
|
|
853
1320
|
run
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { PostHog } from 'posthog-node';
|
|
2
|
+
export declare const CreateTinaAppStartedEvent: string;
|
|
3
|
+
export declare const CreateTinaAppFinishedEvent: string;
|
|
4
|
+
/**
|
|
5
|
+
* Step names for tracking progress through the create-tina-app process
|
|
6
|
+
*/
|
|
7
|
+
export declare const TRACKING_STEPS: {
|
|
8
|
+
readonly INIT: "initializing";
|
|
9
|
+
readonly PRE_RUN_CHECKS: "pre_run_checks";
|
|
10
|
+
readonly TELEMETRY_SETUP: "telemetry_setup";
|
|
11
|
+
readonly PKG_MANAGER_SELECT: "package_manager_selection";
|
|
12
|
+
readonly PROJECT_NAME_INPUT: "project_name_input";
|
|
13
|
+
readonly TEMPLATE_SELECT: "template_selection";
|
|
14
|
+
readonly THEME_SELECT: "theme_selection";
|
|
15
|
+
readonly DIRECTORY_SETUP: "directory_setup";
|
|
16
|
+
readonly DOWNLOADING_TEMPLATE: "downloading_template";
|
|
17
|
+
readonly UPDATING_METADATA: "updating_metadata";
|
|
18
|
+
readonly INSTALLING_PACKAGES: "installing_packages";
|
|
19
|
+
readonly GIT_INIT: "git_initialization";
|
|
20
|
+
readonly COMPLETE: "complete";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Generate a unique session ID for this run
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateSessionId(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Get a hashed user ID based on system UUID
|
|
28
|
+
* Returns a consistent anonymous identifier for the machine
|
|
29
|
+
*/
|
|
30
|
+
export declare function getAnonymousUserId(): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Structured error codes for categorizing failures
|
|
33
|
+
*/
|
|
34
|
+
export declare const ERROR_CODES: {
|
|
35
|
+
readonly ERR_VAL_INVALID_TEMPLATE: "ERR_VAL_INVALID_TEMPLATE";
|
|
36
|
+
readonly ERR_VAL_INVALID_PKG_MANAGER: "ERR_VAL_INVALID_PKG_MANAGER";
|
|
37
|
+
readonly ERR_VAL_INVALID_PROJECT_NAME: "ERR_VAL_INVALID_PROJECT_NAME";
|
|
38
|
+
readonly ERR_VAL_UNSUPPORTED_NODE: "ERR_VAL_UNSUPPORTED_NODE";
|
|
39
|
+
readonly ERR_VAL_NO_PKG_MANAGERS: "ERR_VAL_NO_PKG_MANAGERS";
|
|
40
|
+
readonly ERR_FS_NOT_WRITABLE: "ERR_FS_NOT_WRITABLE";
|
|
41
|
+
readonly ERR_FS_HAS_CONFLICTS: "ERR_FS_HAS_CONFLICTS";
|
|
42
|
+
readonly ERR_FS_MKDIR_FAILED: "ERR_FS_MKDIR_FAILED";
|
|
43
|
+
readonly ERR_FS_CHDIR_FAILED: "ERR_FS_CHDIR_FAILED";
|
|
44
|
+
readonly ERR_FS_READ_PACKAGE_JSON: "ERR_FS_READ_PACKAGE_JSON";
|
|
45
|
+
readonly ERR_FS_WRITE_PACKAGE_JSON: "ERR_FS_WRITE_PACKAGE_JSON";
|
|
46
|
+
readonly ERR_FS_UPDATE_THEME_FAILED: "ERR_FS_UPDATE_THEME_FAILED";
|
|
47
|
+
readonly ERR_FS_COPY_TEMPLATE_FAILED: "ERR_FS_COPY_TEMPLATE_FAILED";
|
|
48
|
+
readonly ERR_NET_POSTHOG_CONFIG_FETCH: "ERR_NET_POSTHOG_CONFIG_FETCH";
|
|
49
|
+
readonly ERR_NET_TARBALL_DOWNLOAD: "ERR_NET_TARBALL_DOWNLOAD";
|
|
50
|
+
readonly ERR_NET_GITHUB_API_FAILED: "ERR_NET_GITHUB_API_FAILED";
|
|
51
|
+
readonly ERR_NET_REPO_INFO_NOT_FOUND: "ERR_NET_REPO_INFO_NOT_FOUND";
|
|
52
|
+
readonly ERR_NET_REPO_INVALID_URL: "ERR_NET_REPO_INVALID_URL";
|
|
53
|
+
readonly ERR_NET_TARBALL_EXTRACT: "ERR_NET_TARBALL_EXTRACT";
|
|
54
|
+
readonly ERR_INSTALL_PKG_MANAGER_FAILED: "ERR_INSTALL_PKG_MANAGER_FAILED";
|
|
55
|
+
readonly ERR_INSTALL_PKG_MANAGER_NOT_FOUND: "ERR_INSTALL_PKG_MANAGER_NOT_FOUND";
|
|
56
|
+
readonly ERR_INSTALL_SPAWN_ERROR: "ERR_INSTALL_SPAWN_ERROR";
|
|
57
|
+
readonly ERR_INSTALL_TIMEOUT: "ERR_INSTALL_TIMEOUT";
|
|
58
|
+
readonly ERR_GIT_NOT_INSTALLED: "ERR_GIT_NOT_INSTALLED";
|
|
59
|
+
readonly ERR_GIT_INIT_FAILED: "ERR_GIT_INIT_FAILED";
|
|
60
|
+
readonly ERR_GIT_ADD_FAILED: "ERR_GIT_ADD_FAILED";
|
|
61
|
+
readonly ERR_GIT_COMMIT_FAILED: "ERR_GIT_COMMIT_FAILED";
|
|
62
|
+
readonly ERR_GIT_CHECKOUT_FAILED: "ERR_GIT_CHECKOUT_FAILED";
|
|
63
|
+
readonly ERR_GIT_ALREADY_INITIALIZED: "ERR_GIT_ALREADY_INITIALIZED";
|
|
64
|
+
readonly ERR_CANCEL_PKG_MANAGER_PROMPT: "ERR_CANCEL_PKG_MANAGER_PROMPT";
|
|
65
|
+
readonly ERR_CANCEL_PROJECT_NAME_PROMPT: "ERR_CANCEL_PROJECT_NAME_PROMPT";
|
|
66
|
+
readonly ERR_CANCEL_TEMPLATE_PROMPT: "ERR_CANCEL_TEMPLATE_PROMPT";
|
|
67
|
+
readonly ERR_CANCEL_THEME_PROMPT: "ERR_CANCEL_THEME_PROMPT";
|
|
68
|
+
readonly ERR_CANCEL_SIGINT: "ERR_CANCEL_SIGINT";
|
|
69
|
+
readonly ERR_CFG_POSTHOG_INIT_FAILED: "ERR_CFG_POSTHOG_INIT_FAILED";
|
|
70
|
+
readonly ERR_CFG_OSINFO_FETCH_FAILED: "ERR_CFG_OSINFO_FETCH_FAILED";
|
|
71
|
+
readonly ERR_CFG_TELEMETRY_SETUP_FAILED: "ERR_CFG_TELEMETRY_SETUP_FAILED";
|
|
72
|
+
readonly ERR_TPL_DOWNLOAD_FAILED: "ERR_TPL_DOWNLOAD_FAILED";
|
|
73
|
+
readonly ERR_TPL_EXTRACT_FAILED: "ERR_TPL_EXTRACT_FAILED";
|
|
74
|
+
readonly ERR_TPL_METADATA_UPDATE_FAILED: "ERR_TPL_METADATA_UPDATE_FAILED";
|
|
75
|
+
readonly ERR_TPL_INTERNAL_COPY_FAILED: "ERR_TPL_INTERNAL_COPY_FAILED";
|
|
76
|
+
readonly ERR_TPL_THEME_UPDATE_FAILED: "ERR_TPL_THEME_UPDATE_FAILED";
|
|
77
|
+
readonly ERR_UNCAUGHT: "ERR_UNCAUGHT";
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Sends an event to PostHog for analytics tracking.
|
|
81
|
+
*
|
|
82
|
+
* @param client - The PostHog client instance used to send the event
|
|
83
|
+
* @param distinctId - A unique identifier for the user (hashed system UUID)
|
|
84
|
+
* @param sessionId - A unique identifier for this run/session
|
|
85
|
+
* @param event - The name of the event to track (e.g., 'create-tina-app-started')
|
|
86
|
+
* @param properties - Additional properties to include with the event
|
|
87
|
+
*
|
|
88
|
+
* @remarks
|
|
89
|
+
* - Returns early if the PostHog client is not provided
|
|
90
|
+
* - Skips sending data when `TINA_DEV` environment variable is set to 'true'
|
|
91
|
+
* - Automatically adds a 'system' property with value 'tinacms/create-tina-app'
|
|
92
|
+
* - Includes sessionId in properties to track individual runs
|
|
93
|
+
* - Uses hashed system UUID as distinctId to track unique users anonymously
|
|
94
|
+
* - Logs errors to console if event capture fails
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const client = new PostHog('api-key');
|
|
99
|
+
* const userId = await getAnonymousUserId();
|
|
100
|
+
* const sessionId = generateSessionId();
|
|
101
|
+
* postHogCapture(client, userId, sessionId, 'create-tina-app-started', {
|
|
102
|
+
* template: 'basic',
|
|
103
|
+
* typescript: true
|
|
104
|
+
* });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare function postHogCapture(client: PostHog, distinctId: string, sessionId: string, event: string, properties: Record<string, any>): void;
|
|
108
|
+
/**
|
|
109
|
+
* Capture an error event in PostHog with categorized tracking and sanitized stack traces
|
|
110
|
+
*
|
|
111
|
+
* @param client - The PostHog client instance
|
|
112
|
+
* @param distinctId - A unique identifier for the user (hashed system UUID)
|
|
113
|
+
* @param sessionId - A unique identifier for this run/session
|
|
114
|
+
* @param error - The error object that was thrown
|
|
115
|
+
* @param context - Context about the error including code, category, step, and additional properties
|
|
116
|
+
*
|
|
117
|
+
* @remarks
|
|
118
|
+
* - Sanitizes stack traces to remove local file paths
|
|
119
|
+
* - Maps error categories to three event types:
|
|
120
|
+
* - 'create-tina-app-error' for technical failures (filesystem, network, installation, git, etc.)
|
|
121
|
+
* - 'create-tina-app-validation-error' for user input validation issues
|
|
122
|
+
* - 'create-tina-app-user-cancelled' for user cancellations (Ctrl+C)
|
|
123
|
+
* - Includes error code, sanitized stack, step name, and telemetry data in properties
|
|
124
|
+
* - Non-fatal errors are tracked but allow the process to continue
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* try {
|
|
129
|
+
* await downloadTemplate();
|
|
130
|
+
* } catch (err) {
|
|
131
|
+
* postHogCaptureError(client, userId, sessionId, err as Error, {
|
|
132
|
+
* errorCode: ERROR_CODES.ERR_TPL_DOWNLOAD_FAILED,
|
|
133
|
+
* errorCategory: 'template',
|
|
134
|
+
* step: TRACKING_STEPS.DOWNLOADING_TEMPLATE,
|
|
135
|
+
* fatal: true,
|
|
136
|
+
* additionalProperties: { template: 'basic' }
|
|
137
|
+
* });
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export declare function postHogCaptureError(client: PostHog | null, distinctId: string, sessionId: string, error: Error, context: {
|
|
142
|
+
errorCode: string;
|
|
143
|
+
errorCategory: string;
|
|
144
|
+
step: string;
|
|
145
|
+
fatal?: boolean;
|
|
146
|
+
additionalProperties?: Record<string, any>;
|
|
147
|
+
}): void;
|
|
@@ -8,3 +8,13 @@ export declare const TextStyles: {
|
|
|
8
8
|
err: import("chalk").ChalkInstance;
|
|
9
9
|
bold: import("chalk").ChalkInstance;
|
|
10
10
|
};
|
|
11
|
+
export declare const TextStylesBold: {
|
|
12
|
+
tinaOrange: import("chalk").ChalkInstance;
|
|
13
|
+
link: (url: string) => string;
|
|
14
|
+
cmd: import("chalk").ChalkInstance;
|
|
15
|
+
info: import("chalk").ChalkInstance;
|
|
16
|
+
success: import("chalk").ChalkInstance;
|
|
17
|
+
warn: import("chalk").ChalkInstance;
|
|
18
|
+
err: import("chalk").ChalkInstance;
|
|
19
|
+
bold: import("chalk").ChalkInstance;
|
|
20
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-tina-app",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-e9ba228-20251219004107",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -44,9 +44,10 @@
|
|
|
44
44
|
"cross-spawn": "^7.0.6",
|
|
45
45
|
"fs-extra": "^11.3.0",
|
|
46
46
|
"ora": "^8.2.0",
|
|
47
|
+
"posthog-node": "^5.17.2",
|
|
47
48
|
"prompts": "^2.4.2",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
49
|
+
"systeminformation": "^5.27.13",
|
|
50
|
+
"tar": "7.4.0"
|
|
50
51
|
},
|
|
51
52
|
"scripts": {
|
|
52
53
|
"types": "pnpm tsc",
|