pinme 2.0.4 → 2.0.5-beta.1

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.
Files changed (3) hide show
  1. package/README.md +200 -867
  2. package/dist/index.js +637 -152
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -103,9 +103,9 @@ var require_package = __commonJS({
103
103
  // node_modules/.pnpm/dotenv@16.5.0/node_modules/dotenv/lib/main.js
104
104
  var require_main = __commonJS({
105
105
  "node_modules/.pnpm/dotenv@16.5.0/node_modules/dotenv/lib/main.js"(exports2, module2) {
106
- var fs16 = require("fs");
107
- var path17 = require("path");
108
- var os5 = require("os");
106
+ var fs17 = require("fs");
107
+ var path18 = require("path");
108
+ var os6 = require("os");
109
109
  var crypto3 = require("crypto");
110
110
  var packageJson = require_package();
111
111
  var version2 = packageJson.version;
@@ -207,7 +207,7 @@ var require_main = __commonJS({
207
207
  if (options && options.path && options.path.length > 0) {
208
208
  if (Array.isArray(options.path)) {
209
209
  for (const filepath of options.path) {
210
- if (fs16.existsSync(filepath)) {
210
+ if (fs17.existsSync(filepath)) {
211
211
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
212
212
  }
213
213
  }
@@ -215,15 +215,15 @@ var require_main = __commonJS({
215
215
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
216
216
  }
217
217
  } else {
218
- possibleVaultPath = path17.resolve(process.cwd(), ".env.vault");
218
+ possibleVaultPath = path18.resolve(process.cwd(), ".env.vault");
219
219
  }
220
- if (fs16.existsSync(possibleVaultPath)) {
220
+ if (fs17.existsSync(possibleVaultPath)) {
221
221
  return possibleVaultPath;
222
222
  }
223
223
  return null;
224
224
  }
225
225
  function _resolveHome(envPath) {
226
- return envPath[0] === "~" ? path17.join(os5.homedir(), envPath.slice(1)) : envPath;
226
+ return envPath[0] === "~" ? path18.join(os6.homedir(), envPath.slice(1)) : envPath;
227
227
  }
228
228
  function _configVault(options) {
229
229
  const debug = Boolean(options && options.debug);
@@ -239,7 +239,7 @@ var require_main = __commonJS({
239
239
  return { parsed };
240
240
  }
241
241
  function configDotenv(options) {
242
- const dotenvPath = path17.resolve(process.cwd(), ".env");
242
+ const dotenvPath = path18.resolve(process.cwd(), ".env");
243
243
  let encoding = "utf8";
244
244
  const debug = Boolean(options && options.debug);
245
245
  if (options && options.encoding) {
@@ -262,13 +262,13 @@ var require_main = __commonJS({
262
262
  }
263
263
  let lastError;
264
264
  const parsedAll = {};
265
- for (const path18 of optionPaths) {
265
+ for (const path19 of optionPaths) {
266
266
  try {
267
- const parsed = DotenvModule.parse(fs16.readFileSync(path18, { encoding }));
267
+ const parsed = DotenvModule.parse(fs17.readFileSync(path19, { encoding }));
268
268
  DotenvModule.populate(parsedAll, parsed, options);
269
269
  } catch (e) {
270
270
  if (debug) {
271
- _debug(`Failed to load ${path18} ${e.message}`);
271
+ _debug(`Failed to load ${path19} ${e.message}`);
272
272
  }
273
273
  lastError = e;
274
274
  }
@@ -828,9 +828,9 @@ function isVisitable(thing) {
828
828
  function removeBrackets(key) {
829
829
  return utils_default.endsWith(key, "[]") ? key.slice(0, -2) : key;
830
830
  }
831
- function renderKey(path17, key, dots) {
832
- if (!path17) return key;
833
- return path17.concat(key).map(function each(token, i) {
831
+ function renderKey(path18, key, dots) {
832
+ if (!path18) return key;
833
+ return path18.concat(key).map(function each(token, i) {
834
834
  token = removeBrackets(token);
835
835
  return !dots && i ? "[" + token + "]" : token;
836
836
  }).join(dots ? "." : "");
@@ -872,9 +872,9 @@ function toFormData(obj, formData, options) {
872
872
  }
873
873
  return value;
874
874
  }
875
- function defaultVisitor(value, key, path17) {
875
+ function defaultVisitor(value, key, path18) {
876
876
  let arr = value;
877
- if (value && !path17 && typeof value === "object") {
877
+ if (value && !path18 && typeof value === "object") {
878
878
  if (utils_default.endsWith(key, "{}")) {
879
879
  key = metaTokens ? key : key.slice(0, -2);
880
880
  value = JSON.stringify(value);
@@ -893,7 +893,7 @@ function toFormData(obj, formData, options) {
893
893
  if (isVisitable(value)) {
894
894
  return true;
895
895
  }
896
- formData.append(renderKey(path17, key, dots), convertValue(value));
896
+ formData.append(renderKey(path18, key, dots), convertValue(value));
897
897
  return false;
898
898
  }
899
899
  const stack = [];
@@ -902,10 +902,10 @@ function toFormData(obj, formData, options) {
902
902
  convertValue,
903
903
  isVisitable
904
904
  });
905
- function build(value, path17) {
905
+ function build(value, path18) {
906
906
  if (utils_default.isUndefined(value)) return;
907
907
  if (stack.indexOf(value) !== -1) {
908
- throw Error("Circular reference detected in " + path17.join("."));
908
+ throw Error("Circular reference detected in " + path18.join("."));
909
909
  }
910
910
  stack.push(value);
911
911
  utils_default.forEach(value, function each(el, key) {
@@ -913,11 +913,11 @@ function toFormData(obj, formData, options) {
913
913
  formData,
914
914
  el,
915
915
  utils_default.isString(key) ? key.trim() : key,
916
- path17,
916
+ path18,
917
917
  exposedHelpers
918
918
  );
919
919
  if (result === true) {
920
- build(el, path17 ? path17.concat(key) : [key]);
920
+ build(el, path18 ? path18.concat(key) : [key]);
921
921
  }
922
922
  });
923
923
  stack.pop();
@@ -1137,7 +1137,7 @@ var init_platform = __esm({
1137
1137
  // node_modules/.pnpm/axios@1.3.2/node_modules/axios/lib/helpers/toURLEncodedForm.js
1138
1138
  function toURLEncodedForm(data, options) {
1139
1139
  return toFormData_default(data, new node_default.classes.URLSearchParams(), Object.assign({
1140
- visitor: function(value, key, path17, helpers) {
1140
+ visitor: function(value, key, path18, helpers) {
1141
1141
  if (node_default.isNode && utils_default.isBuffer(value)) {
1142
1142
  this.append(key, value.toString("base64"));
1143
1143
  return false;
@@ -1174,10 +1174,10 @@ function arrayToObject(arr) {
1174
1174
  return obj;
1175
1175
  }
1176
1176
  function formDataToJSON(formData) {
1177
- function buildPath(path17, value, target, index) {
1178
- let name = path17[index++];
1177
+ function buildPath(path18, value, target, index) {
1178
+ let name = path18[index++];
1179
1179
  const isNumericKey = Number.isFinite(+name);
1180
- const isLast = index >= path17.length;
1180
+ const isLast = index >= path18.length;
1181
1181
  name = !name && utils_default.isArray(target) ? target.length : name;
1182
1182
  if (isLast) {
1183
1183
  if (utils_default.hasOwnProp(target, name)) {
@@ -1190,7 +1190,7 @@ function formDataToJSON(formData) {
1190
1190
  if (!target[name] || !utils_default.isObject(target[name])) {
1191
1191
  target[name] = [];
1192
1192
  }
1193
- const result = buildPath(path17, value, target[name], index);
1193
+ const result = buildPath(path18, value, target[name], index);
1194
1194
  if (result && utils_default.isArray(target[name])) {
1195
1195
  target[name] = arrayToObject(target[name]);
1196
1196
  }
@@ -2165,7 +2165,7 @@ var require_has_flag = __commonJS({
2165
2165
  var require_supports_color = __commonJS({
2166
2166
  "node_modules/.pnpm/supports-color@5.5.0/node_modules/supports-color/index.js"(exports2, module2) {
2167
2167
  "use strict";
2168
- var os5 = require("os");
2168
+ var os6 = require("os");
2169
2169
  var hasFlag = require_has_flag();
2170
2170
  var env = process.env;
2171
2171
  var forceColor;
@@ -2203,7 +2203,7 @@ var require_supports_color = __commonJS({
2203
2203
  }
2204
2204
  const min = forceColor ? 1 : 0;
2205
2205
  if (process.platform === "win32") {
2206
- const osRelease = os5.release().split(".");
2206
+ const osRelease = os6.release().split(".");
2207
2207
  if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
2208
2208
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
2209
2209
  }
@@ -3516,9 +3516,9 @@ var init_http = __esm({
3516
3516
  auth = urlUsername + ":" + urlPassword;
3517
3517
  }
3518
3518
  auth && headers.delete("authorization");
3519
- let path17;
3519
+ let path18;
3520
3520
  try {
3521
- path17 = buildURL(
3521
+ path18 = buildURL(
3522
3522
  parsed.pathname + parsed.search,
3523
3523
  config.params,
3524
3524
  config.paramsSerializer
@@ -3536,7 +3536,7 @@ var init_http = __esm({
3536
3536
  false
3537
3537
  );
3538
3538
  const options = {
3539
- path: path17,
3539
+ path: path18,
3540
3540
  method,
3541
3541
  headers: headers.toJSON(),
3542
3542
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -3763,14 +3763,14 @@ var init_cookies = __esm({
3763
3763
  // Standard browser envs support document.cookie
3764
3764
  /* @__PURE__ */ function standardBrowserEnv() {
3765
3765
  return {
3766
- write: function write(name, value, expires, path17, domain, secure) {
3766
+ write: function write(name, value, expires, path18, domain, secure) {
3767
3767
  const cookie = [];
3768
3768
  cookie.push(name + "=" + encodeURIComponent(value));
3769
3769
  if (utils_default.isNumber(expires)) {
3770
3770
  cookie.push("expires=" + new Date(expires).toGMTString());
3771
3771
  }
3772
- if (utils_default.isString(path17)) {
3773
- cookie.push("path=" + path17);
3772
+ if (utils_default.isString(path18)) {
3773
+ cookie.push("path=" + path18);
3774
3774
  }
3775
3775
  if (utils_default.isString(domain)) {
3776
3776
  cookie.push("domain=" + domain);
@@ -5707,10 +5707,11 @@ async function getRootDomain(forceRefresh = false) {
5707
5707
  }
5708
5708
  async function checkDomainAvailable(domainName) {
5709
5709
  var _a2, _b;
5710
- if (isDnsDomain(domainName))
5710
+ if (isDnsDomain(domainName)) {
5711
5711
  return await {
5712
5712
  is_valid: true
5713
5713
  };
5714
+ }
5714
5715
  const client = createPinmeApiClient();
5715
5716
  const configured = APP_CONFIG.pinmeCheckDomainPath;
5716
5717
  const fallbacks = [configured];
@@ -5977,14 +5978,14 @@ var import_chalk26 = __toESM(require("chalk"));
5977
5978
  var import_figlet5 = __toESM(require("figlet"));
5978
5979
 
5979
5980
  // package.json
5980
- var version = "2.0.4";
5981
+ var version = "2.0.5-beta.1";
5981
5982
 
5982
5983
  // bin/upload.ts
5983
- var import_path6 = __toESM(require("path"));
5984
+ var import_path7 = __toESM(require("path"));
5984
5985
  var import_chalk7 = __toESM(require("chalk"));
5985
5986
  var import_inquirer = __toESM(require("inquirer"));
5986
5987
  var import_figlet = __toESM(require("figlet"));
5987
- var import_fs2 = __toESM(require("fs"));
5988
+ var import_fs3 = __toESM(require("fs"));
5988
5989
  init_pinmeApi();
5989
5990
  init_webLogin();
5990
5991
  init_config();
@@ -6221,6 +6222,7 @@ var RETRY_DELAY = APP_CONFIG.upload.retryDelayMs;
6221
6222
  var TIMEOUT = APP_CONFIG.upload.timeoutMs;
6222
6223
  var MAX_POLL_TIME = APP_CONFIG.upload.maxPollTimeMs;
6223
6224
  var POLL_INTERVAL = APP_CONFIG.upload.pollIntervalMs;
6225
+ var COMPLETE_TO_STATUS_DELAY = 5e3;
6224
6226
  var PROGRESS_UPDATE_INTERVAL = 200;
6225
6227
  var EXPECTED_UPLOAD_TIME = 6e4;
6226
6228
  var MAX_PROGRESS = 0.9;
@@ -6262,11 +6264,14 @@ function createUploadBusinessError(stage, endpoint, method, status, data) {
6262
6264
  [`Endpoint: ${endpoint}`]
6263
6265
  );
6264
6266
  }
6265
- function logAxiosErrorDetails(prefix, error) {
6267
+ function logAxiosErrorDetails(prefix, error, traceId) {
6266
6268
  var _a2, _b;
6267
6269
  const status = (_a2 = error == null ? void 0 : error.response) == null ? void 0 : _a2.status;
6268
6270
  const responseData = (_b = error == null ? void 0 : error.response) == null ? void 0 : _b.data;
6269
6271
  console.error(`[pinme upload] ${prefix}`);
6272
+ if (traceId) {
6273
+ console.error(`[pinme upload] trace_id: ${traceId}`);
6274
+ }
6270
6275
  console.error(`[pinme upload] status: ${status ?? "unknown"}`);
6271
6276
  if (responseData === void 0) {
6272
6277
  console.error("[pinme upload] response: <empty>");
@@ -6278,6 +6283,16 @@ function logAxiosErrorDetails(prefix, error) {
6278
6283
  console.error(`[pinme upload] response: ${String(responseData)}`);
6279
6284
  }
6280
6285
  }
6286
+ function delay(ms) {
6287
+ return new Promise((resolve) => setTimeout(resolve, ms));
6288
+ }
6289
+ function appendTraceIdToError(error, traceId) {
6290
+ const message = error instanceof Error ? error.message : String(error);
6291
+ if (message.includes(`trace_id: ${traceId}`)) {
6292
+ return error instanceof Error ? error : new Error(message);
6293
+ }
6294
+ return new Error(`${message} (trace_id: ${traceId})`);
6295
+ }
6281
6296
  function isStorageLimitError(error) {
6282
6297
  const message = extractAxiosErrorMessage(error).toLowerCase();
6283
6298
  return message.includes("storage space limit") || message.includes("space limit reached") || message.includes("storage limit reached") || message.includes("quota exceeded") || message.includes("insufficient storage");
@@ -6533,7 +6548,7 @@ async function uploadChunkWithAbort(sessionId, chunkIndex, chunkData, deviceId,
6533
6548
  );
6534
6549
  }
6535
6550
  }
6536
- async function delayWithAbortCheck(delay, signal) {
6551
+ async function delayWithAbortCheck(delay2, signal) {
6537
6552
  return new Promise((resolve, reject) => {
6538
6553
  const timeoutId = setTimeout(() => {
6539
6554
  if (signal.aborted) {
@@ -6541,7 +6556,7 @@ async function delayWithAbortCheck(delay, signal) {
6541
6556
  } else {
6542
6557
  resolve();
6543
6558
  }
6544
- }, delay);
6559
+ }, delay2);
6545
6560
  if (signal.aborted) {
6546
6561
  clearTimeout(timeoutId);
6547
6562
  reject(new Error("Request cancelled"));
@@ -6685,19 +6700,29 @@ async function getChunkStatus(sessionId, deviceId, options = {}) {
6685
6700
  );
6686
6701
  } catch (error) {
6687
6702
  if (axios_default.isAxiosError(error)) {
6688
- logAxiosErrorDetails("up_status failed", error);
6689
- throw formatAxiosError("Upload status check failed", error);
6703
+ logAxiosErrorDetails("up_status failed", error, sessionId);
6704
+ throw formatAxiosError(
6705
+ `Upload status check failed (trace_id: ${sessionId})`,
6706
+ error
6707
+ );
6690
6708
  }
6691
- throw error;
6709
+ console.error("[pinme upload] up_status failed");
6710
+ console.error(`[pinme upload] trace_id: ${sessionId}`);
6711
+ console.error(
6712
+ `[pinme upload] reason: ${error instanceof Error ? error.message : String(error)}`
6713
+ );
6714
+ throw appendTraceIdToError(error, sessionId);
6692
6715
  }
6693
6716
  }
6694
6717
  async function monitorChunkProgress(traceId, deviceId, options = {}, progressBar) {
6695
6718
  let consecutiveErrors = 0;
6696
- const startTime = Date.now();
6719
+ let startTime = Date.now();
6697
6720
  if (progressBar) {
6698
6721
  progressBar.startSimulatingProgress();
6699
6722
  }
6700
6723
  try {
6724
+ await delay(COMPLETE_TO_STATUS_DELAY);
6725
+ startTime = Date.now();
6701
6726
  while (Date.now() - startTime < MAX_POLL_TIME) {
6702
6727
  try {
6703
6728
  const status = await getChunkStatus(traceId, deviceId, options);
@@ -6725,7 +6750,9 @@ async function monitorChunkProgress(traceId, deviceId, options = {}, progressBar
6725
6750
  await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
6726
6751
  }
6727
6752
  const maxPollTimeMinutes = Math.floor(MAX_POLL_TIME / (60 * 1e3));
6728
- throw new Error(`Polling timeout after ${maxPollTimeMinutes} minutes`);
6753
+ throw new Error(
6754
+ `Polling timeout after ${maxPollTimeMinutes} minutes (trace_id: ${traceId})`
6755
+ );
6729
6756
  } finally {
6730
6757
  if (progressBar) {
6731
6758
  progressBar.stopSimulatingProgress();
@@ -7004,12 +7031,212 @@ function printHighlightedUrl(label, url2, tone = "primary") {
7004
7031
  console.log("");
7005
7032
  }
7006
7033
 
7034
+ // bin/utils/tracker.ts
7035
+ var import_os4 = __toESM(require("os"));
7036
+ var import_fs2 = __toESM(require("fs"));
7037
+ var import_path6 = __toESM(require("path"));
7038
+ var import_child_process2 = require("child_process");
7039
+ var REQUEST_TIMEOUT_MS = 1500;
7040
+ var DEFAULT_GATEWAY = "https://pinme.dev";
7041
+ var DEFAULT_PRODUCT = "pinme-cli";
7042
+ var TRACK_CHILD_SCRIPT = `
7043
+ const rawUrl = process.argv[1];
7044
+ if (!rawUrl) process.exit(0);
7045
+ try {
7046
+ const transport = rawUrl.startsWith('https:') ? require('https') : require('http');
7047
+ const req = transport.get(rawUrl, {
7048
+ headers: {
7049
+ 'User-Agent': 'Pinme-CLI-Tracker'
7050
+ }
7051
+ }, (res) => {
7052
+ res.resume();
7053
+ res.on('end', () => process.exit(0));
7054
+ });
7055
+ req.setTimeout(${REQUEST_TIMEOUT_MS}, () => req.destroy());
7056
+ req.on('error', () => process.exit(0));
7057
+ req.on('close', () => process.exit(0));
7058
+ } catch (_) {
7059
+ process.exit(0);
7060
+ }
7061
+ `;
7062
+ function trimTrailingSlash2(value) {
7063
+ return value.replace(/\/+$/, "");
7064
+ }
7065
+ function shouldDisableTracking() {
7066
+ return process.env.PINME_TRACKING_DISABLED === "1" || process.env.DO_NOT_TRACK === "1";
7067
+ }
7068
+ function sanitizeTrackValue(value) {
7069
+ if (value === void 0 || value === null) {
7070
+ return void 0;
7071
+ }
7072
+ return String(value).trim().slice(0, 200);
7073
+ }
7074
+ function getTrackErrorReason(error) {
7075
+ var _a2, _b, _c, _d, _e;
7076
+ const candidate = ((_b = (_a2 = error == null ? void 0 : error.response) == null ? void 0 : _a2.data) == null ? void 0 : _b.msg) || ((_d = (_c = error == null ? void 0 : error.response) == null ? void 0 : _c.data) == null ? void 0 : _d.message) || (error == null ? void 0 : error.message) || ((_e = error == null ? void 0 : error.toString) == null ? void 0 : _e.call(error)) || "unknown_error";
7077
+ return sanitizeTrackValue(candidate) || "unknown_error";
7078
+ }
7079
+ var cachedProjectContext = null;
7080
+ var cachedProjectContextCwd = null;
7081
+ function resolveProjectContext() {
7082
+ const cwd = process.cwd();
7083
+ if (cachedProjectContext && cachedProjectContextCwd === cwd) {
7084
+ return cachedProjectContext;
7085
+ }
7086
+ const context = {};
7087
+ const configPath = import_path6.default.join(cwd, "pinme.toml");
7088
+ if (import_fs2.default.existsSync(configPath)) {
7089
+ try {
7090
+ const configContent = import_fs2.default.readFileSync(configPath, "utf8");
7091
+ const projectNameMatch = configContent.match(
7092
+ /project_name\s*=\s*"([^"]+)"/
7093
+ );
7094
+ context.projectName = sanitizeTrackValue(projectNameMatch == null ? void 0 : projectNameMatch[1]) || sanitizeTrackValue(process.env.PINME_PROJECT_NAME);
7095
+ context.projectDir = sanitizeTrackValue(import_path6.default.basename(cwd));
7096
+ } catch (_) {
7097
+ context.projectName = sanitizeTrackValue(process.env.PINME_PROJECT_NAME);
7098
+ }
7099
+ } else {
7100
+ context.projectName = sanitizeTrackValue(process.env.PINME_PROJECT_NAME);
7101
+ }
7102
+ cachedProjectContext = context;
7103
+ cachedProjectContextCwd = cwd;
7104
+ return context;
7105
+ }
7106
+ function getPathKind(pathValue) {
7107
+ try {
7108
+ const stat = import_fs2.default.statSync(pathValue);
7109
+ if (stat.isDirectory()) {
7110
+ return "directory";
7111
+ }
7112
+ if (stat.isFile()) {
7113
+ return "file";
7114
+ }
7115
+ } catch (_) {
7116
+ return "unknown";
7117
+ }
7118
+ return "unknown";
7119
+ }
7120
+ var Tracker = class _Tracker {
7121
+ static instance;
7122
+ gateway;
7123
+ product;
7124
+ source;
7125
+ disabled;
7126
+ constructor(gateway, product) {
7127
+ this.gateway = trimTrailingSlash2(
7128
+ gateway || process.env.PINME_TRACKER_GATEWAY || DEFAULT_GATEWAY
7129
+ );
7130
+ this.product = product || DEFAULT_PRODUCT;
7131
+ this.source = sanitizeTrackValue(process.env.PINME_TRACK_SOURCE);
7132
+ this.disabled = shouldDisableTracking();
7133
+ }
7134
+ static getInstance(gateway, product) {
7135
+ if (!_Tracker.instance) {
7136
+ _Tracker.instance = new _Tracker(gateway, product);
7137
+ }
7138
+ return _Tracker.instance;
7139
+ }
7140
+ trackEvent(event, page, data = {}) {
7141
+ if (this.disabled || !this.gateway) {
7142
+ return Promise.resolve();
7143
+ }
7144
+ try {
7145
+ const payload = this.buildPayload(event, page, data);
7146
+ const params = new URLSearchParams(payload).toString();
7147
+ const url2 = `${this.gateway}/track.gif?${params}`;
7148
+ this.dispatch(url2);
7149
+ } catch (_) {
7150
+ }
7151
+ return Promise.resolve();
7152
+ }
7153
+ buildPayload(event, page, data) {
7154
+ const projectContext = resolveProjectContext();
7155
+ const payload = {
7156
+ u: getUid(),
7157
+ s: this.source,
7158
+ pd: this.product,
7159
+ p: page,
7160
+ event,
7161
+ project_name: projectContext.projectName,
7162
+ project_dir: projectContext.projectDir,
7163
+ cli_version: version,
7164
+ node_version: process.version,
7165
+ os: import_os4.default.platform(),
7166
+ arch: import_os4.default.arch(),
7167
+ ...data
7168
+ };
7169
+ const filtered = {};
7170
+ for (const [key, value] of Object.entries(payload)) {
7171
+ const normalized = sanitizeTrackValue(value);
7172
+ if (normalized) {
7173
+ filtered[key] = normalized;
7174
+ }
7175
+ }
7176
+ return filtered;
7177
+ }
7178
+ dispatch(url2) {
7179
+ const child = (0, import_child_process2.spawn)(process.execPath, ["-e", TRACK_CHILD_SCRIPT, url2], {
7180
+ detached: true,
7181
+ stdio: "ignore",
7182
+ windowsHide: true
7183
+ });
7184
+ child.unref();
7185
+ }
7186
+ };
7187
+ var tracker = Tracker.getInstance();
7188
+ var tracker_default = tracker;
7189
+
7190
+ // bin/utils/trackerEvents.ts
7191
+ var TRACK_PAGES = {
7192
+ auth: "cli_auth",
7193
+ login: "cli_login",
7194
+ upload: "cli_upload",
7195
+ import: "cli_import",
7196
+ export: "cli_export",
7197
+ remove: "cli_remove",
7198
+ domain: "cli_domain",
7199
+ wallet: "cli_wallet",
7200
+ project: "cli_project",
7201
+ deploy: "cli_deploy"
7202
+ };
7203
+ var TRACK_EVENTS = {
7204
+ cliLoginSuccess: "cli_login_success",
7205
+ cliLoginFailed: "cli_login_failed",
7206
+ appKeySetSuccess: "appkey_set_success",
7207
+ appKeySetFailed: "appkey_set_failed",
7208
+ logoutSuccess: "logout_success",
7209
+ logoutFailed: "logout_failed",
7210
+ uploadSuccess: "upload_success",
7211
+ uploadFailed: "upload_failed",
7212
+ importSuccess: "import_success",
7213
+ importFailed: "import_failed",
7214
+ exportSuccess: "export_success",
7215
+ exportFailed: "export_failed",
7216
+ removeSuccess: "remove_success",
7217
+ removeFailed: "remove_failed",
7218
+ domainBindSuccess: "domain_bind_success",
7219
+ domainBindFailed: "domain_bind_failed",
7220
+ myDomainsSuccess: "my_domains_success",
7221
+ myDomainsFailed: "my_domains_failed",
7222
+ walletBalanceSuccess: "wallet_balance_success",
7223
+ walletBalanceFailed: "wallet_balance_failed",
7224
+ projectCreateSuccess: "project_create_success",
7225
+ projectCreateFailed: "project_create_failed",
7226
+ projectSaveSuccess: "project_save_success",
7227
+ projectSaveFailed: "project_save_failed",
7228
+ projectDeleteSuccess: "project_delete_success",
7229
+ projectDeleteFailed: "project_delete_failed",
7230
+ projectUpdateWebSuccess: "project_update_web_success",
7231
+ projectUpdateWebFailed: "project_update_web_failed"
7232
+ };
7233
+
7007
7234
  // bin/upload.ts
7008
7235
  checkNodeVersion();
7009
7236
  function checkPathSync(inputPath) {
7010
7237
  try {
7011
- const absolutePath = import_path6.default.resolve(inputPath);
7012
- if (import_fs2.default.existsSync(absolutePath)) {
7238
+ const absolutePath = import_path7.default.resolve(inputPath);
7239
+ if (import_fs3.default.existsSync(absolutePath)) {
7013
7240
  return absolutePath;
7014
7241
  }
7015
7242
  return null;
@@ -7070,6 +7297,7 @@ async function checkWalletBalanceStatus(authConfig) {
7070
7297
  }
7071
7298
  async function bindDomain(domain, contentHash, isDns, authConfig) {
7072
7299
  const displayDomain = normalizeDomain(domain);
7300
+ const domainType = isDns ? "dns" : "pinme_subdomain";
7073
7301
  if (isDns) {
7074
7302
  console.log(import_chalk7.default.blue("Binding DNS domain..."));
7075
7303
  const dnsResult = await bindDnsDomainV4(
@@ -7079,9 +7307,20 @@ async function bindDomain(domain, contentHash, isDns, authConfig) {
7079
7307
  authConfig.token
7080
7308
  );
7081
7309
  if (dnsResult.code !== 200) {
7310
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
7311
+ domain_type: domainType,
7312
+ domain_name: displayDomain,
7313
+ bind_source: "upload",
7314
+ reason: dnsResult.msg || "dns_bind_failed"
7315
+ });
7082
7316
  console.log(import_chalk7.default.red(`DNS binding failed: ${dnsResult.msg}`));
7083
7317
  return false;
7084
7318
  }
7319
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindSuccess, TRACK_PAGES.domain, {
7320
+ domain_type: domainType,
7321
+ domain_name: displayDomain,
7322
+ bind_source: "upload"
7323
+ });
7085
7324
  console.log(import_chalk7.default.green(`DNS bind success: ${displayDomain}`));
7086
7325
  console.log(import_chalk7.default.white(`Visit: https://${displayDomain}`));
7087
7326
  console.log(
@@ -7093,9 +7332,20 @@ async function bindDomain(domain, contentHash, isDns, authConfig) {
7093
7332
  console.log(import_chalk7.default.blue("Binding Pinme subdomain..."));
7094
7333
  const ok = await bindPinmeDomain(displayDomain, contentHash);
7095
7334
  if (!ok) {
7335
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
7336
+ domain_type: domainType,
7337
+ domain_name: displayDomain,
7338
+ bind_source: "upload",
7339
+ reason: "pinme_bind_failed"
7340
+ });
7096
7341
  console.log(import_chalk7.default.red("Binding failed. Please try again later."));
7097
7342
  return false;
7098
7343
  }
7344
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindSuccess, TRACK_PAGES.domain, {
7345
+ domain_type: domainType,
7346
+ domain_name: displayDomain,
7347
+ bind_source: "upload"
7348
+ });
7099
7349
  console.log(import_chalk7.default.green(`Bind success: ${displayDomain}`));
7100
7350
  const rootDomain = await (await Promise.resolve().then(() => (init_pinmeApi(), pinmeApi_exports))).getRootDomain();
7101
7351
  console.log(import_chalk7.default.white(`Visit: https://${displayDomain}.${rootDomain}`));
@@ -7127,6 +7377,7 @@ var upload_default = async (options) => {
7127
7377
  console.log(import_chalk7.default.red(`path ${argPath} does not exist`));
7128
7378
  return;
7129
7379
  }
7380
+ const pathKind = getPathKind(absolutePath);
7130
7381
  const isDns = dnsArg || (domainArg ? isDnsDomain(domainArg) : false);
7131
7382
  const displayDomain = domainArg == null ? void 0 : domainArg.replace(/^https?:\/\//, "").replace(/\/$/, "");
7132
7383
  if (isDns && domainArg) {
@@ -7182,13 +7433,28 @@ var upload_default = async (options) => {
7182
7433
  uid: authConfig == null ? void 0 : authConfig.address
7183
7434
  });
7184
7435
  } catch (error) {
7436
+ void tracker_default.trackEvent(TRACK_EVENTS.uploadFailed, TRACK_PAGES.upload, {
7437
+ path_kind: pathKind,
7438
+ has_domain: Boolean(domainArg),
7439
+ reason: getTrackErrorReason(error)
7440
+ });
7185
7441
  printCliError(error, "Upload failed.");
7186
7442
  process.exit(1);
7187
7443
  }
7188
7444
  if (!result) {
7445
+ void tracker_default.trackEvent(TRACK_EVENTS.uploadFailed, TRACK_PAGES.upload, {
7446
+ path_kind: pathKind,
7447
+ has_domain: Boolean(domainArg),
7448
+ reason: "no_result_returned"
7449
+ });
7189
7450
  console.error(import_chalk7.default.red("Upload failed: no result returned"));
7190
7451
  process.exit(1);
7191
7452
  }
7453
+ void tracker_default.trackEvent(TRACK_EVENTS.uploadSuccess, TRACK_PAGES.upload, {
7454
+ path_kind: pathKind,
7455
+ has_domain: Boolean(domainArg),
7456
+ project_name: APP_CONFIG.pinmeProjectName
7457
+ });
7192
7458
  console.log(
7193
7459
  import_chalk7.default.cyan(import_figlet.default.textSync("Successful", { horizontalLayout: "full" }))
7194
7460
  );
@@ -7314,11 +7580,11 @@ var upload_default = async (options) => {
7314
7580
  };
7315
7581
 
7316
7582
  // bin/importCar.ts
7317
- var import_path7 = __toESM(require("path"));
7583
+ var import_path8 = __toESM(require("path"));
7318
7584
  var import_chalk8 = __toESM(require("chalk"));
7319
7585
  var import_inquirer2 = __toESM(require("inquirer"));
7320
7586
  var import_figlet2 = __toESM(require("figlet"));
7321
- var import_fs3 = __toESM(require("fs"));
7587
+ var import_fs4 = __toESM(require("fs"));
7322
7588
  var import_crypto_js2 = __toESM(require("crypto-js"));
7323
7589
  init_pinmeApi();
7324
7590
  init_cliError();
@@ -7341,8 +7607,8 @@ function encryptHash2(contentHash, key, uid) {
7341
7607
  }
7342
7608
  function checkPathSync2(inputPath) {
7343
7609
  try {
7344
- const absolutePath = import_path7.default.resolve(inputPath);
7345
- if (import_fs3.default.existsSync(absolutePath)) {
7610
+ const absolutePath = import_path8.default.resolve(inputPath);
7611
+ if (import_fs4.default.existsSync(absolutePath)) {
7346
7612
  return absolutePath;
7347
7613
  }
7348
7614
  return null;
@@ -7390,6 +7656,7 @@ var importCar_default = async (options) => {
7390
7656
  console.log(import_chalk8.default.red(`path ${argPath} does not exist`));
7391
7657
  return;
7392
7658
  }
7659
+ const pathKind = getPathKind(absolutePath);
7393
7660
  if (domainArg) {
7394
7661
  const check = await checkDomainAvailable(domainArg);
7395
7662
  if (!check.is_valid) {
@@ -7409,6 +7676,10 @@ var importCar_default = async (options) => {
7409
7676
  uid: getUid2()
7410
7677
  });
7411
7678
  if (result) {
7679
+ void tracker_default.trackEvent(TRACK_EVENTS.importSuccess, TRACK_PAGES.import, {
7680
+ path_kind: pathKind,
7681
+ has_domain: Boolean(domainArg)
7682
+ });
7412
7683
  const uid = getUid2();
7413
7684
  const encryptedCID = encryptHash2(
7414
7685
  result.contentHash,
@@ -7433,6 +7704,11 @@ var importCar_default = async (options) => {
7433
7704
  );
7434
7705
  const ok = await bindPinmeDomain(domainArg, result.contentHash);
7435
7706
  if (ok) {
7707
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindSuccess, TRACK_PAGES.domain, {
7708
+ domain_type: "pinme_subdomain",
7709
+ domain_name: domainArg,
7710
+ bind_source: "import"
7711
+ });
7436
7712
  console.log(import_chalk8.default.green(`Bind success: ${domainArg}`));
7437
7713
  const rootDomain = await getRootDomain();
7438
7714
  console.log(
@@ -7441,12 +7717,23 @@ var importCar_default = async (options) => {
7441
7717
  )
7442
7718
  );
7443
7719
  } else {
7720
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
7721
+ domain_type: "pinme_subdomain",
7722
+ domain_name: domainArg,
7723
+ bind_source: "import",
7724
+ reason: "pinme_bind_failed"
7725
+ });
7444
7726
  console.log(import_chalk8.default.red("Binding failed. Please try again later."));
7445
7727
  }
7446
7728
  }
7447
7729
  console.log(import_chalk8.default.green("\n\u{1F389} import successful, program exit"));
7448
7730
  }
7449
7731
  } catch (error) {
7732
+ void tracker_default.trackEvent(TRACK_EVENTS.importFailed, TRACK_PAGES.import, {
7733
+ path_kind: pathKind,
7734
+ has_domain: Boolean(domainArg),
7735
+ reason: getTrackErrorReason(error)
7736
+ });
7450
7737
  printCliError(error, "Import failed.");
7451
7738
  }
7452
7739
  process.exit(0);
@@ -7464,6 +7751,7 @@ var importCar_default = async (options) => {
7464
7751
  console.log(import_chalk8.default.red(`path ${answer.path} does not exist`));
7465
7752
  return;
7466
7753
  }
7754
+ const pathKind = getPathKind(absolutePath);
7467
7755
  if (domainArg) {
7468
7756
  const check = await checkDomainAvailable(domainArg);
7469
7757
  if (!check.is_valid) {
@@ -7483,6 +7771,10 @@ var importCar_default = async (options) => {
7483
7771
  uid: getUid2()
7484
7772
  });
7485
7773
  if (result) {
7774
+ void tracker_default.trackEvent(TRACK_EVENTS.importSuccess, TRACK_PAGES.import, {
7775
+ path_kind: pathKind,
7776
+ has_domain: Boolean(domainArg)
7777
+ });
7486
7778
  const uid = getUid2();
7487
7779
  const encryptedCID = encryptHash2(
7488
7780
  result.contentHash,
@@ -7507,6 +7799,11 @@ var importCar_default = async (options) => {
7507
7799
  );
7508
7800
  const ok = await bindPinmeDomain(domainArg, result.contentHash);
7509
7801
  if (ok) {
7802
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindSuccess, TRACK_PAGES.domain, {
7803
+ domain_type: "pinme_subdomain",
7804
+ domain_name: domainArg,
7805
+ bind_source: "import"
7806
+ });
7510
7807
  console.log(import_chalk8.default.green(`Bind success: ${domainArg}`));
7511
7808
  const rootDomain = await getRootDomain();
7512
7809
  console.log(
@@ -7515,27 +7812,41 @@ var importCar_default = async (options) => {
7515
7812
  )
7516
7813
  );
7517
7814
  } else {
7815
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
7816
+ domain_type: "pinme_subdomain",
7817
+ domain_name: domainArg,
7818
+ bind_source: "import",
7819
+ reason: "pinme_bind_failed"
7820
+ });
7518
7821
  console.log(import_chalk8.default.red("Binding failed. Please try again later."));
7519
7822
  }
7520
7823
  }
7521
7824
  console.log(import_chalk8.default.green("\n\u{1F389} import successful, program exit"));
7522
7825
  }
7523
7826
  } catch (error) {
7827
+ void tracker_default.trackEvent(TRACK_EVENTS.importFailed, TRACK_PAGES.import, {
7828
+ path_kind: pathKind,
7829
+ has_domain: Boolean(domainArg),
7830
+ reason: getTrackErrorReason(error)
7831
+ });
7524
7832
  printCliError(error, "Import failed.");
7525
7833
  }
7526
7834
  process.exit(0);
7527
7835
  }
7528
7836
  } catch (error) {
7837
+ void tracker_default.trackEvent(TRACK_EVENTS.importFailed, TRACK_PAGES.import, {
7838
+ reason: getTrackErrorReason(error)
7839
+ });
7529
7840
  printCliError(error, "Import failed.");
7530
7841
  }
7531
7842
  };
7532
7843
 
7533
7844
  // bin/exportCar.ts
7534
- var import_path8 = __toESM(require("path"));
7845
+ var import_path9 = __toESM(require("path"));
7535
7846
  var import_chalk9 = __toESM(require("chalk"));
7536
7847
  var import_inquirer3 = __toESM(require("inquirer"));
7537
7848
  var import_figlet3 = __toESM(require("figlet"));
7538
- var import_fs4 = __toESM(require("fs"));
7849
+ var import_fs5 = __toESM(require("fs"));
7539
7850
  init_axios2();
7540
7851
  var import_ora2 = __toESM(require("ora"));
7541
7852
  init_cliError();
@@ -7578,7 +7889,7 @@ async function downloadCarFile(downloadUrl, outputPath) {
7578
7889
  timeout: 18e5
7579
7890
  // 30 minutes timeout
7580
7891
  });
7581
- const writer = import_fs4.default.createWriteStream(outputPath);
7892
+ const writer = import_fs5.default.createWriteStream(outputPath);
7582
7893
  let downloadedBytes = 0;
7583
7894
  const totalBytes = parseInt(response.headers["content-length"] || "0", 10);
7584
7895
  response.data.on("data", (chunk) => {
@@ -7674,15 +7985,15 @@ var exportCar_default = async () => {
7674
7985
  ]);
7675
7986
  outputDir = answer.output.trim() || currentDir;
7676
7987
  }
7677
- outputDir = import_path8.default.resolve(outputDir);
7678
- if (!import_fs4.default.existsSync(outputDir)) {
7679
- import_fs4.default.mkdirSync(outputDir, { recursive: true });
7680
- } else if (!import_fs4.default.statSync(outputDir).isDirectory()) {
7988
+ outputDir = import_path9.default.resolve(outputDir);
7989
+ if (!import_fs5.default.existsSync(outputDir)) {
7990
+ import_fs5.default.mkdirSync(outputDir, { recursive: true });
7991
+ } else if (!import_fs5.default.statSync(outputDir).isDirectory()) {
7681
7992
  console.log(import_chalk9.default.red(`Error: ${outputDir} exists but is not a directory.`));
7682
7993
  return;
7683
7994
  }
7684
- const finalOutputPath = import_path8.default.join(outputDir, `${cid}.car`);
7685
- if (import_fs4.default.existsSync(finalOutputPath)) {
7995
+ const finalOutputPath = import_path9.default.join(outputDir, `${cid}.car`);
7996
+ if (import_fs5.default.existsSync(finalOutputPath)) {
7686
7997
  const answer = await import_inquirer3.default.prompt([
7687
7998
  {
7688
7999
  type: "confirm",
@@ -7710,12 +8021,20 @@ var exportCar_default = async () => {
7710
8021
  startTime
7711
8022
  );
7712
8023
  if (!downloadUrl) {
8024
+ void tracker_default.trackEvent(TRACK_EVENTS.exportFailed, TRACK_PAGES.export, {
8025
+ cid,
8026
+ reason: "export_failed_or_timed_out"
8027
+ });
7713
8028
  console.log(import_chalk9.default.red("Export failed or timed out."));
7714
8029
  return;
7715
8030
  }
7716
8031
  const success = await downloadCarFile(downloadUrl, finalOutputPath);
7717
8032
  if (success) {
7718
- const fileSize = import_fs4.default.statSync(finalOutputPath).size;
8033
+ void tracker_default.trackEvent(TRACK_EVENTS.exportSuccess, TRACK_PAGES.export, {
8034
+ cid,
8035
+ output_dir: outputDir
8036
+ });
8037
+ const fileSize = import_fs5.default.statSync(finalOutputPath).size;
7719
8038
  const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(2);
7720
8039
  console.log(
7721
8040
  import_chalk9.default.cyan(
@@ -7728,13 +8047,24 @@ var exportCar_default = async () => {
7728
8047
  console.log(import_chalk9.default.cyan(`Size: ${fileSizeMB} MB`));
7729
8048
  console.log(import_chalk9.default.cyan(`CID: ${cid}`));
7730
8049
  } else {
8050
+ void tracker_default.trackEvent(TRACK_EVENTS.exportFailed, TRACK_PAGES.export, {
8051
+ cid,
8052
+ reason: "download_failed"
8053
+ });
7731
8054
  console.log(import_chalk9.default.red("Download failed."));
7732
8055
  }
7733
8056
  } catch (error) {
8057
+ void tracker_default.trackEvent(TRACK_EVENTS.exportFailed, TRACK_PAGES.export, {
8058
+ cid,
8059
+ reason: getTrackErrorReason(error)
8060
+ });
7734
8061
  spinner.fail(`Error: ${error.message}`);
7735
8062
  printCliError(error, "Export failed.");
7736
8063
  }
7737
8064
  } catch (error) {
8065
+ void tracker_default.trackEvent(TRACK_EVENTS.exportFailed, TRACK_PAGES.export, {
8066
+ reason: getTrackErrorReason(error)
8067
+ });
7738
8068
  printCliError(error, "Export failed.");
7739
8069
  }
7740
8070
  };
@@ -7882,6 +8212,9 @@ var remove_default = async (options) => {
7882
8212
  try {
7883
8213
  const success = await removeFromIpfs(parsedInput.value, parsedInput.type);
7884
8214
  if (success) {
8215
+ void tracker_default.trackEvent(TRACK_EVENTS.removeSuccess, TRACK_PAGES.remove, {
8216
+ input_type: parsedInput.type
8217
+ });
7885
8218
  console.log(
7886
8219
  import_chalk11.default.cyan(
7887
8220
  import_figlet4.default.textSync("Successful", { horizontalLayout: "full" })
@@ -7889,6 +8222,10 @@ var remove_default = async (options) => {
7889
8222
  );
7890
8223
  }
7891
8224
  } catch (error) {
8225
+ void tracker_default.trackEvent(TRACK_EVENTS.removeFailed, TRACK_PAGES.remove, {
8226
+ input_type: parsedInput.type,
8227
+ reason: getTrackErrorReason(error)
8228
+ });
7892
8229
  console.error(import_chalk11.default.red(`Error: ${error.message}`));
7893
8230
  }
7894
8231
  return;
@@ -7946,6 +8283,9 @@ var remove_default = async (options) => {
7946
8283
  try {
7947
8284
  const success = await removeFromIpfs(parsedInput.value, parsedInput.type);
7948
8285
  if (success) {
8286
+ void tracker_default.trackEvent(TRACK_EVENTS.removeSuccess, TRACK_PAGES.remove, {
8287
+ input_type: parsedInput.type
8288
+ });
7949
8289
  console.log(
7950
8290
  import_chalk11.default.cyan(
7951
8291
  import_figlet4.default.textSync("Successful", { horizontalLayout: "full" })
@@ -7953,10 +8293,17 @@ var remove_default = async (options) => {
7953
8293
  );
7954
8294
  }
7955
8295
  } catch (error) {
8296
+ void tracker_default.trackEvent(TRACK_EVENTS.removeFailed, TRACK_PAGES.remove, {
8297
+ input_type: parsedInput.type,
8298
+ reason: getTrackErrorReason(error)
8299
+ });
7956
8300
  console.error(import_chalk11.default.red(`Error: ${error.message}`));
7957
8301
  }
7958
8302
  }
7959
8303
  } catch (error) {
8304
+ void tracker_default.trackEvent(TRACK_EVENTS.removeFailed, TRACK_PAGES.remove, {
8305
+ reason: getTrackErrorReason(error)
8306
+ });
7960
8307
  console.error(import_chalk11.default.red(`Error executing remove command: ${error.message}`));
7961
8308
  console.error(error.stack);
7962
8309
  }
@@ -7994,7 +8341,14 @@ async function setAppKeyCmd() {
7994
8341
  } else {
7995
8342
  console.log(import_chalk12.default.yellow("Anonymous history merge not confirmed. You may retry later."));
7996
8343
  }
8344
+ void tracker_default.trackEvent(TRACK_EVENTS.appKeySetSuccess, TRACK_PAGES.auth, {
8345
+ merged_anonymous_history: ok,
8346
+ has_token_address: Boolean(saved.address)
8347
+ });
7997
8348
  } catch (e) {
8349
+ void tracker_default.trackEvent(TRACK_EVENTS.appKeySetFailed, TRACK_PAGES.auth, {
8350
+ reason: getTrackErrorReason(e)
8351
+ });
7998
8352
  console.log(import_chalk12.default.red(`Failed to set AppKey: ${(e == null ? void 0 : e.message) || e}`));
7999
8353
  }
8000
8354
  }
@@ -8023,9 +8377,15 @@ async function logoutCmd() {
8023
8377
  return;
8024
8378
  }
8025
8379
  clearAuthToken();
8380
+ void tracker_default.trackEvent(TRACK_EVENTS.logoutSuccess, TRACK_PAGES.auth, {
8381
+ had_session: true
8382
+ });
8026
8383
  console.log(import_chalk13.default.green("Successfully logged out."));
8027
8384
  console.log(import_chalk13.default.gray(`Address ${auth.address} has been removed from local storage.`));
8028
8385
  } catch (e) {
8386
+ void tracker_default.trackEvent(TRACK_EVENTS.logoutFailed, TRACK_PAGES.auth, {
8387
+ reason: getTrackErrorReason(e)
8388
+ });
8029
8389
  console.log(import_chalk13.default.red(`Failed to logout: ${(e == null ? void 0 : e.message) || e}`));
8030
8390
  }
8031
8391
  }
@@ -8070,6 +8430,9 @@ init_pinmeApi();
8070
8430
  async function myDomainsCmd() {
8071
8431
  try {
8072
8432
  const list = await getMyDomains();
8433
+ void tracker_default.trackEvent(TRACK_EVENTS.myDomainsSuccess, TRACK_PAGES.domain, {
8434
+ domain_count: list.length
8435
+ });
8073
8436
  if (!list.length) {
8074
8437
  console.log(import_chalk15.default.yellow("No bound domains found."));
8075
8438
  return;
@@ -8089,6 +8452,9 @@ async function myDomainsCmd() {
8089
8452
  console.log(import_chalk15.default.cyan("-".repeat(80)));
8090
8453
  });
8091
8454
  } catch (e) {
8455
+ void tracker_default.trackEvent(TRACK_EVENTS.myDomainsFailed, TRACK_PAGES.domain, {
8456
+ reason: getTrackErrorReason(e)
8457
+ });
8092
8458
  printCliError(e, "Failed to fetch domains.");
8093
8459
  }
8094
8460
  }
@@ -8110,9 +8476,16 @@ async function walletBalanceCmd() {
8110
8476
  const result = await getWalletBalance(auth.address, auth.token);
8111
8477
  const balance = Number(((_a2 = result.data) == null ? void 0 : _a2.wallet_balance_usd) ?? 0);
8112
8478
  if (!Number.isFinite(balance)) {
8479
+ void tracker_default.trackEvent(TRACK_EVENTS.walletBalanceFailed, TRACK_PAGES.wallet, {
8480
+ reason: "invalid_balance_value"
8481
+ });
8113
8482
  console.log(import_chalk16.default.red("Failed to parse wallet balance."));
8114
8483
  return;
8115
8484
  }
8485
+ void tracker_default.trackEvent(TRACK_EVENTS.walletBalanceSuccess, TRACK_PAGES.wallet, {
8486
+ has_balance: balance > 0,
8487
+ balance_usd: balance.toFixed(2)
8488
+ });
8116
8489
  console.log(import_chalk16.default.cyan("Wallet balance:"));
8117
8490
  console.log(import_chalk16.default.green(` USD: $${balance.toFixed(2)}`));
8118
8491
  if (balance <= 0) {
@@ -8120,12 +8493,15 @@ async function walletBalanceCmd() {
8120
8493
  printRechargeUrl(getWalletRechargeUrl());
8121
8494
  }
8122
8495
  } catch (e) {
8496
+ void tracker_default.trackEvent(TRACK_EVENTS.walletBalanceFailed, TRACK_PAGES.wallet, {
8497
+ reason: getTrackErrorReason(e)
8498
+ });
8123
8499
  printCliError(e, "Failed to fetch wallet balance.");
8124
8500
  }
8125
8501
  }
8126
8502
 
8127
8503
  // bin/bind.ts
8128
- var import_path9 = __toESM(require("path"));
8504
+ var import_path10 = __toESM(require("path"));
8129
8505
  var import_chalk17 = __toESM(require("chalk"));
8130
8506
  var import_inquirer7 = __toESM(require("inquirer"));
8131
8507
  init_pinmeApi();
@@ -8214,6 +8590,8 @@ async function bindCmd() {
8214
8590
  }
8215
8591
  const isDns = dns || isDnsDomain(domain);
8216
8592
  const displayDomain = normalizeDomain(domain);
8593
+ const pathKind = getPathKind(import_path10.default.resolve(targetPath));
8594
+ const domainType = isDns ? "dns" : "pinme_subdomain";
8217
8595
  if (isDns) {
8218
8596
  const validation = validateDnsDomain(domain);
8219
8597
  if (!validation.valid) {
@@ -8253,13 +8631,22 @@ async function bindCmd() {
8253
8631
  }
8254
8632
  throw e;
8255
8633
  }
8256
- const absolutePath = import_path9.default.resolve(targetPath);
8634
+ const absolutePath = import_path10.default.resolve(targetPath);
8257
8635
  console.log(import_chalk17.default.blue(`Uploading: ${absolutePath}`));
8258
8636
  const up = await uploadPath(absolutePath, { uid: authConfig.address });
8259
8637
  if (!(up == null ? void 0 : up.contentHash)) {
8638
+ void tracker_default.trackEvent(TRACK_EVENTS.uploadFailed, TRACK_PAGES.upload, {
8639
+ path_kind: pathKind,
8640
+ has_domain: true,
8641
+ reason: "no_content_hash"
8642
+ });
8260
8643
  console.log(import_chalk17.default.red("Upload failed, binding aborted."));
8261
8644
  return;
8262
8645
  }
8646
+ void tracker_default.trackEvent(TRACK_EVENTS.uploadSuccess, TRACK_PAGES.upload, {
8647
+ path_kind: pathKind,
8648
+ has_domain: true
8649
+ });
8263
8650
  console.log(import_chalk17.default.green(`Upload success, CID: ${up.contentHash}`));
8264
8651
  try {
8265
8652
  if (isDns) {
@@ -8271,9 +8658,20 @@ async function bindCmd() {
8271
8658
  authConfig.token
8272
8659
  );
8273
8660
  if (dnsResult.code !== 200) {
8661
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
8662
+ domain_type: domainType,
8663
+ domain_name: displayDomain,
8664
+ bind_source: "bind",
8665
+ reason: dnsResult.msg || "dns_bind_failed"
8666
+ });
8274
8667
  console.log(import_chalk17.default.red(`DNS binding failed: ${dnsResult.msg}`));
8275
8668
  return;
8276
8669
  }
8670
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindSuccess, TRACK_PAGES.domain, {
8671
+ domain_type: domainType,
8672
+ domain_name: displayDomain,
8673
+ bind_source: "bind"
8674
+ });
8277
8675
  console.log(import_chalk17.default.green(`DNS bind success: ${displayDomain}`));
8278
8676
  console.log(import_chalk17.default.white(`Visit: https://${displayDomain}`));
8279
8677
  console.log(
@@ -8285,9 +8683,20 @@ async function bindCmd() {
8285
8683
  console.log(import_chalk17.default.blue("Binding Pinme subdomain..."));
8286
8684
  const ok = await bindPinmeDomain(displayDomain, up.contentHash);
8287
8685
  if (!ok) {
8686
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
8687
+ domain_type: domainType,
8688
+ domain_name: displayDomain,
8689
+ bind_source: "bind",
8690
+ reason: "pinme_bind_failed"
8691
+ });
8288
8692
  console.log(import_chalk17.default.red("Binding failed. Please try again later."));
8289
8693
  return;
8290
8694
  }
8695
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindSuccess, TRACK_PAGES.domain, {
8696
+ domain_type: domainType,
8697
+ domain_name: displayDomain,
8698
+ bind_source: "bind"
8699
+ });
8291
8700
  console.log(import_chalk17.default.green(`Bind success: ${displayDomain}`));
8292
8701
  const rootDomain = await getRootDomain();
8293
8702
  console.log(
@@ -8301,6 +8710,10 @@ async function bindCmd() {
8301
8710
  throw e;
8302
8711
  }
8303
8712
  } catch (e) {
8713
+ void tracker_default.trackEvent(TRACK_EVENTS.domainBindFailed, TRACK_PAGES.domain, {
8714
+ bind_source: "bind",
8715
+ reason: getTrackErrorReason(e)
8716
+ });
8304
8717
  printCliError(e, "Bind failed.");
8305
8718
  }
8306
8719
  }
@@ -8315,9 +8728,9 @@ var ENV_URLS = {
8315
8728
  prod: "https://pinme.eth.limo"
8316
8729
  };
8317
8730
  async function loginCmd(options = {}) {
8731
+ const env = (options.env || "prod").toLowerCase();
8318
8732
  try {
8319
8733
  let webBaseUrl;
8320
- const env = (options.env || "prod").toLowerCase();
8321
8734
  if (ENV_URLS[env]) {
8322
8735
  webBaseUrl = ENV_URLS[env];
8323
8736
  console.log(import_chalk18.default.blue(`Using ${env} environment: ${webBaseUrl}`));
@@ -8338,8 +8751,17 @@ async function loginCmd(options = {}) {
8338
8751
  if (ok) {
8339
8752
  console.log(import_chalk18.default.green("History merged to your account"));
8340
8753
  }
8754
+ void tracker_default.trackEvent(TRACK_EVENTS.cliLoginSuccess, TRACK_PAGES.login, {
8755
+ env,
8756
+ has_token_address: true,
8757
+ merged_anonymous_history: ok
8758
+ });
8341
8759
  process.exit(0);
8342
8760
  } catch (e) {
8761
+ void tracker_default.trackEvent(TRACK_EVENTS.cliLoginFailed, TRACK_PAGES.login, {
8762
+ env,
8763
+ reason: getTrackErrorReason(e)
8764
+ });
8343
8765
  console.log(import_chalk18.default.red(`
8344
8766
  Login failed: ${(e == null ? void 0 : e.message) || e}`));
8345
8767
  process.exit(1);
@@ -8349,23 +8771,23 @@ Login failed: ${(e == null ? void 0 : e.message) || e}`));
8349
8771
  // bin/create.ts
8350
8772
  var import_chalk20 = __toESM(require("chalk"));
8351
8773
  var import_fs_extra6 = __toESM(require("fs-extra"));
8352
- var import_path11 = __toESM(require("path"));
8774
+ var import_path12 = __toESM(require("path"));
8353
8775
  var import_inquirer8 = __toESM(require("inquirer"));
8354
8776
  init_axios2();
8355
- var import_child_process3 = require("child_process");
8777
+ var import_child_process4 = require("child_process");
8356
8778
  init_webLogin();
8357
8779
 
8358
8780
  // bin/utils/installProjectDependencies.ts
8359
8781
  var import_fs_extra5 = __toESM(require("fs-extra"));
8360
- var import_os4 = __toESM(require("os"));
8361
- var import_path10 = __toESM(require("path"));
8782
+ var import_os5 = __toESM(require("os"));
8783
+ var import_path11 = __toESM(require("path"));
8362
8784
  var import_chalk19 = __toESM(require("chalk"));
8363
- var import_child_process2 = require("child_process");
8785
+ var import_child_process3 = require("child_process");
8364
8786
  function makeTempCacheDir() {
8365
- return import_fs_extra5.default.mkdtempSync(import_path10.default.join(import_os4.default.tmpdir(), "pinme-npm-cache-"));
8787
+ return import_fs_extra5.default.mkdtempSync(import_path11.default.join(import_os5.default.tmpdir(), "pinme-npm-cache-"));
8366
8788
  }
8367
8789
  function runInstall(cwd, cacheDir) {
8368
- (0, import_child_process2.execFileSync)("npm", ["install", "--cache", cacheDir, "--no-audit", "--no-fund"], {
8790
+ (0, import_child_process3.execFileSync)("npm", ["install", "--cache", cacheDir, "--no-audit", "--no-fund"], {
8369
8791
  cwd,
8370
8792
  stdio: "inherit",
8371
8793
  env: {
@@ -8434,7 +8856,7 @@ function resolveExtractedTemplateDir(extractDir) {
8434
8856
  `Template branch: ${TEMPLATE_BRANCH}`
8435
8857
  ]);
8436
8858
  }
8437
- return import_path11.default.join(extractDir, templateDir.name);
8859
+ return import_path12.default.join(extractDir, templateDir.name);
8438
8860
  }
8439
8861
  function updateFrontendUrlInConfig(configPath, frontendUrl) {
8440
8862
  let config = import_fs_extra6.default.readFileSync(configPath, "utf-8");
@@ -8483,7 +8905,7 @@ async function createCmd(options) {
8483
8905
  ]);
8484
8906
  projectName = answers.projectName;
8485
8907
  }
8486
- const targetDir = import_path11.default.join(PROJECT_DIR, projectName);
8908
+ const targetDir = import_path12.default.join(PROJECT_DIR, projectName);
8487
8909
  if (import_fs_extra6.default.existsSync(targetDir) && !options.force) {
8488
8910
  console.log(import_chalk20.default.yellow(`
8489
8911
  Directory "${projectName}" already exists.`));
@@ -8534,15 +8956,15 @@ Directory "${projectName}" already exists.`));
8534
8956
  ]);
8535
8957
  }
8536
8958
  console.log(import_chalk20.default.blue("\n2. Downloading template from repository..."));
8537
- const zipPath = import_path11.default.join(PROJECT_DIR, "template.zip");
8538
- const extractDir = import_path11.default.join(PROJECT_DIR, `.pinme-template-${Date.now()}`);
8959
+ const zipPath = import_path12.default.join(PROJECT_DIR, "template.zip");
8960
+ const extractDir = import_path12.default.join(PROJECT_DIR, `.pinme-template-${Date.now()}`);
8539
8961
  const templateZipUrl = getTemplateZipUrl(TEMPLATE_BRANCH);
8540
8962
  let downloadSuccess = false;
8541
8963
  console.log(import_chalk20.default.gray(` Template branch: ${TEMPLATE_BRANCH}`));
8542
8964
  for (let attempt = 1; attempt <= 3 && !downloadSuccess; attempt++) {
8543
8965
  try {
8544
8966
  console.log(import_chalk20.default.gray(` Download attempt ${attempt}/3...`));
8545
- (0, import_child_process3.execSync)(`curl -L --retry 3 --retry-delay 2 -o "${zipPath}" "${templateZipUrl}"`, {
8967
+ (0, import_child_process4.execSync)(`curl -L --retry 3 --retry-delay 2 -o "${zipPath}" "${templateZipUrl}"`, {
8546
8968
  stdio: "inherit"
8547
8969
  });
8548
8970
  if (!import_fs_extra6.default.existsSync(zipPath) || import_fs_extra6.default.statSync(zipPath).size < 100) {
@@ -8561,15 +8983,15 @@ Directory "${projectName}" already exists.`));
8561
8983
  }
8562
8984
  try {
8563
8985
  import_fs_extra6.default.ensureDirSync(extractDir);
8564
- (0, import_child_process3.execSync)(`unzip -o "${zipPath}" -d "${extractDir}"`, {
8986
+ (0, import_child_process4.execSync)(`unzip -o "${zipPath}" -d "${extractDir}"`, {
8565
8987
  stdio: "inherit"
8566
8988
  });
8567
8989
  const subDir = resolveExtractedTemplateDir(extractDir);
8568
8990
  import_fs_extra6.default.copySync(subDir, targetDir);
8569
8991
  import_fs_extra6.default.removeSync(zipPath);
8570
8992
  import_fs_extra6.default.removeSync(extractDir);
8571
- const nodeModulesPath = import_path11.default.join(targetDir, "node_modules");
8572
- const packageLockPath = import_path11.default.join(targetDir, "package-lock.json");
8993
+ const nodeModulesPath = import_path12.default.join(targetDir, "node_modules");
8994
+ const packageLockPath = import_path12.default.join(targetDir, "package-lock.json");
8573
8995
  if (import_fs_extra6.default.existsSync(nodeModulesPath)) {
8574
8996
  console.log(import_chalk20.default.gray(" Removing existing node_modules..."));
8575
8997
  import_fs_extra6.default.removeSync(nodeModulesPath);
@@ -8578,10 +9000,10 @@ Directory "${projectName}" already exists.`));
8578
9000
  console.log(import_chalk20.default.gray(" Removing existing package-lock.json..."));
8579
9001
  import_fs_extra6.default.removeSync(packageLockPath);
8580
9002
  }
8581
- const frontendNodeModules = import_path11.default.join(targetDir, "frontend", "node_modules");
8582
- const backendNodeModules = import_path11.default.join(targetDir, "backend", "node_modules");
8583
- const frontendPackageLock = import_path11.default.join(targetDir, "frontend", "package-lock.json");
8584
- const backendPackageLock = import_path11.default.join(targetDir, "backend", "package-lock.json");
9003
+ const frontendNodeModules = import_path12.default.join(targetDir, "frontend", "node_modules");
9004
+ const backendNodeModules = import_path12.default.join(targetDir, "backend", "node_modules");
9005
+ const frontendPackageLock = import_path12.default.join(targetDir, "frontend", "package-lock.json");
9006
+ const backendPackageLock = import_path12.default.join(targetDir, "backend", "package-lock.json");
8585
9007
  if (import_fs_extra6.default.existsSync(frontendNodeModules)) import_fs_extra6.default.removeSync(frontendNodeModules);
8586
9008
  if (import_fs_extra6.default.existsSync(backendNodeModules)) import_fs_extra6.default.removeSync(backendNodeModules);
8587
9009
  if (import_fs_extra6.default.existsSync(frontendPackageLock)) import_fs_extra6.default.removeSync(frontendPackageLock);
@@ -8593,7 +9015,7 @@ Directory "${projectName}" already exists.`));
8593
9015
  ]);
8594
9016
  }
8595
9017
  console.log(import_chalk20.default.blue("\n3. Updating configuration..."));
8596
- const configPath = import_path11.default.join(targetDir, "pinme.toml");
9018
+ const configPath = import_path12.default.join(targetDir, "pinme.toml");
8597
9019
  const config = import_fs_extra6.default.readFileSync(configPath, "utf-8");
8598
9020
  let updatedConfig = config.replace(
8599
9021
  /project_name = ".*"/,
@@ -8602,16 +9024,16 @@ Directory "${projectName}" already exists.`));
8602
9024
  import_fs_extra6.default.writeFileSync(configPath, updatedConfig);
8603
9025
  console.log(import_chalk20.default.green(` Updated pinme.toml`));
8604
9026
  console.log(import_chalk20.default.gray(` metadata: ${workerData.metadata}`));
8605
- const backendDir = import_path11.default.join(targetDir, "backend");
9027
+ const backendDir = import_path12.default.join(targetDir, "backend");
8606
9028
  if (import_fs_extra6.default.existsSync(backendDir) && workerData.metadata) {
8607
9029
  const metadataContent = typeof workerData.metadata === "string" ? workerData.metadata : JSON.stringify(workerData.metadata, null, 2);
8608
9030
  import_fs_extra6.default.writeFileSync(
8609
- import_path11.default.join(backendDir, "metadata.json"),
9031
+ import_path12.default.join(backendDir, "metadata.json"),
8610
9032
  metadataContent
8611
9033
  );
8612
9034
  console.log(import_chalk20.default.green(` Saved metadata.json`));
8613
9035
  }
8614
- const wranglerPath = import_path11.default.join(backendDir, "wrangler.toml");
9036
+ const wranglerPath = import_path12.default.join(backendDir, "wrangler.toml");
8615
9037
  if (import_fs_extra6.default.existsSync(wranglerPath) && workerData.api_key) {
8616
9038
  let wranglerContent = import_fs_extra6.default.readFileSync(wranglerPath, "utf-8");
8617
9039
  wranglerContent = wranglerContent.replace(
@@ -8621,18 +9043,18 @@ Directory "${projectName}" already exists.`));
8621
9043
  import_fs_extra6.default.writeFileSync(wranglerPath, wranglerContent);
8622
9044
  console.log(import_chalk20.default.green(` Updated backend/wrangler.toml API_KEY`));
8623
9045
  }
8624
- const frontendConfigPath = import_path11.default.join(targetDir, "frontend", "src", "utils", "config.ts");
9046
+ const frontendConfigPath = import_path12.default.join(targetDir, "frontend", "src", "utils", "config.ts");
8625
9047
  if (workerData.public_client_config) {
8626
9048
  const frontendConfigContent = import_fs_extra6.default.existsSync(frontendConfigPath) ? import_fs_extra6.default.readFileSync(frontendConfigPath, "utf-8") : "";
8627
- import_fs_extra6.default.ensureDirSync(import_path11.default.dirname(frontendConfigPath));
9049
+ import_fs_extra6.default.ensureDirSync(import_path12.default.dirname(frontendConfigPath));
8628
9050
  import_fs_extra6.default.writeFileSync(
8629
9051
  frontendConfigPath,
8630
9052
  injectPublicClientConfigIntoFile(frontendConfigContent, workerData.public_client_config)
8631
9053
  );
8632
9054
  console.log(import_chalk20.default.green(` Updated frontend/src/utils/config.ts public_client_config`));
8633
9055
  }
8634
- const envExamplePath = import_path11.default.join(targetDir, "frontend", ".env.example");
8635
- const envPath = import_path11.default.join(targetDir, "frontend", ".env");
9056
+ const envExamplePath = import_path12.default.join(targetDir, "frontend", ".env.example");
9057
+ const envPath = import_path12.default.join(targetDir, "frontend", ".env");
8636
9058
  if (import_fs_extra6.default.existsSync(envExamplePath)) {
8637
9059
  let envContent = import_fs_extra6.default.readFileSync(envExamplePath, "utf-8");
8638
9060
  envContent = envContent.replace(/your-project/g, workerData.project_name);
@@ -8707,7 +9129,7 @@ Directory "${projectName}" already exists.`));
8707
9129
  }
8708
9130
  console.log(import_chalk20.default.blue("\n5. Building backend worker..."));
8709
9131
  try {
8710
- (0, import_child_process3.execSync)("npm run build:worker", {
9132
+ (0, import_child_process4.execSync)("npm run build:worker", {
8711
9133
  cwd: targetDir,
8712
9134
  stdio: "inherit"
8713
9135
  });
@@ -8717,8 +9139,8 @@ Directory "${projectName}" already exists.`));
8717
9139
  "Fix the build error shown above, then rerun `pinme create`."
8718
9140
  ]);
8719
9141
  }
8720
- const distWorkerDir = import_path11.default.join(targetDir, "dist-worker");
8721
- const workerJsPath = import_path11.default.join(distWorkerDir, "worker.js");
9142
+ const distWorkerDir = import_path12.default.join(targetDir, "dist-worker");
9143
+ const workerJsPath = import_path12.default.join(distWorkerDir, "worker.js");
8722
9144
  if (!import_fs_extra6.default.existsSync(distWorkerDir) || !import_fs_extra6.default.existsSync(workerJsPath)) {
8723
9145
  throw createConfigError("Built worker output not found: `dist-worker/worker.js`.", [
8724
9146
  "Make sure `npm run build:worker` completed successfully."
@@ -8728,15 +9150,15 @@ Directory "${projectName}" already exists.`));
8728
9150
  const files = import_fs_extra6.default.readdirSync(distWorkerDir);
8729
9151
  for (const file of files) {
8730
9152
  if (file.endsWith(".js") && file !== "worker.js") {
8731
- modulePaths.push(import_path11.default.join(distWorkerDir, file));
9153
+ modulePaths.push(import_path12.default.join(distWorkerDir, file));
8732
9154
  }
8733
9155
  }
8734
- const sqlDir = import_path11.default.join(targetDir, "db");
9156
+ const sqlDir = import_path12.default.join(targetDir, "db");
8735
9157
  const sqlFiles = [];
8736
9158
  if (import_fs_extra6.default.existsSync(sqlDir)) {
8737
9159
  const sqlFileNames = import_fs_extra6.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
8738
9160
  for (const filename of sqlFileNames) {
8739
- sqlFiles.push(import_path11.default.join(sqlDir, filename));
9161
+ sqlFiles.push(import_path12.default.join(sqlDir, filename));
8740
9162
  console.log(import_chalk20.default.gray(` Including SQL: ${filename}`));
8741
9163
  }
8742
9164
  }
@@ -8756,14 +9178,14 @@ Directory "${projectName}" already exists.`));
8756
9178
  type: "application/javascript+module"
8757
9179
  }), "worker.js");
8758
9180
  for (const modulePath of modulePaths) {
8759
- const filename = import_path11.default.basename(modulePath);
9181
+ const filename = import_path12.default.basename(modulePath);
8760
9182
  const content = import_fs_extra6.default.readFileSync(modulePath, "utf-8");
8761
9183
  formData.append(filename, new Blob2([content], {
8762
9184
  type: "application/javascript+module"
8763
9185
  }), filename);
8764
9186
  }
8765
9187
  for (const sqlFile of sqlFiles) {
8766
- const filename = import_path11.default.basename(sqlFile);
9188
+ const filename = import_path12.default.basename(sqlFile);
8767
9189
  const content = import_fs_extra6.default.readFileSync(sqlFile, "utf-8");
8768
9190
  formData.append("sql_file", new Blob2([content], {
8769
9191
  type: "application/sql"
@@ -8797,10 +9219,10 @@ Directory "${projectName}" already exists.`));
8797
9219
  ]);
8798
9220
  }
8799
9221
  console.log(import_chalk20.default.blue("\n7. Building frontend..."));
8800
- const frontendDir = import_path11.default.join(targetDir, "frontend");
9222
+ const frontendDir = import_path12.default.join(targetDir, "frontend");
8801
9223
  if (import_fs_extra6.default.existsSync(frontendDir)) {
8802
9224
  try {
8803
- (0, import_child_process3.execSync)("npm run build:frontend", {
9225
+ (0, import_child_process4.execSync)("npm run build:frontend", {
8804
9226
  cwd: targetDir,
8805
9227
  stdio: "inherit"
8806
9228
  });
@@ -8812,13 +9234,13 @@ Directory "${projectName}" already exists.`));
8812
9234
  }
8813
9235
  console.log(import_chalk20.default.blue(" Uploading to IPFS..."));
8814
9236
  try {
8815
- const uploadResult = await uploadPath(import_path11.default.join(frontendDir, "dist"), {
9237
+ const uploadResult = await uploadPath(import_path12.default.join(frontendDir, "dist"), {
8816
9238
  projectName: workerData.project_name,
8817
9239
  uid: headers["token-address"]
8818
9240
  });
8819
9241
  printHighlightedUrl("Frontend URL", uploadResult.publicUrl, "primary");
8820
9242
  updateFrontendUrlInConfig(
8821
- import_path11.default.join(targetDir, "pinme.toml"),
9243
+ import_path12.default.join(targetDir, "pinme.toml"),
8822
9244
  uploadResult.publicUrl
8823
9245
  );
8824
9246
  console.log(import_chalk20.default.green(" Updated pinme.toml with frontend URL"));
@@ -8840,8 +9262,27 @@ Project Details:`));
8840
9262
  Next steps:`));
8841
9263
  console.log(import_chalk20.default.gray(` cd ${projectName}`));
8842
9264
  console.log(import_chalk20.default.gray(` pinme save`));
9265
+ void tracker_default.trackEvent(
9266
+ TRACK_EVENTS.projectCreateSuccess,
9267
+ TRACK_PAGES.project,
9268
+ {
9269
+ project_name: workerData.project_name,
9270
+ template_branch: TEMPLATE_BRANCH,
9271
+ force: Boolean(options.force)
9272
+ }
9273
+ );
8843
9274
  process.exit(0);
8844
9275
  } catch (error) {
9276
+ void tracker_default.trackEvent(
9277
+ TRACK_EVENTS.projectCreateFailed,
9278
+ TRACK_PAGES.project,
9279
+ {
9280
+ project_name: options.name,
9281
+ template_branch: TEMPLATE_BRANCH,
9282
+ force: Boolean(options.force),
9283
+ reason: getTrackErrorReason(error)
9284
+ }
9285
+ );
8845
9286
  printCliError(error, "Project creation failed.");
8846
9287
  process.exit(1);
8847
9288
  }
@@ -8850,9 +9291,9 @@ Next steps:`));
8850
9291
  // bin/save.ts
8851
9292
  var import_chalk21 = __toESM(require("chalk"));
8852
9293
  var import_fs_extra7 = __toESM(require("fs-extra"));
8853
- var import_path12 = __toESM(require("path"));
9294
+ var import_path13 = __toESM(require("path"));
8854
9295
  init_axios2();
8855
- var import_child_process4 = require("child_process");
9296
+ var import_child_process5 = require("child_process");
8856
9297
  init_webLogin();
8857
9298
  init_pinmeApi();
8858
9299
  init_domainValidator();
@@ -8860,7 +9301,7 @@ init_cliError();
8860
9301
  init_config();
8861
9302
  var PROJECT_DIR2 = process.cwd();
8862
9303
  function loadConfig() {
8863
- const configPath = import_path12.default.join(PROJECT_DIR2, "pinme.toml");
9304
+ const configPath = import_path13.default.join(PROJECT_DIR2, "pinme.toml");
8864
9305
  if (!import_fs_extra7.default.existsSync(configPath)) {
8865
9306
  throw createConfigError("`pinme.toml` not found in the current directory.", [
8866
9307
  "Run this command from the Pinme project root.",
@@ -8877,7 +9318,7 @@ function getProjectManagementUrl2(projectName) {
8877
9318
  return `${APP_CONFIG.projectPeviewUrl}${projectName}`;
8878
9319
  }
8879
9320
  function getMetadata() {
8880
- const metadataPath = import_path12.default.join(PROJECT_DIR2, "backend", "metadata.json");
9321
+ const metadataPath = import_path13.default.join(PROJECT_DIR2, "backend", "metadata.json");
8881
9322
  if (!import_fs_extra7.default.existsSync(metadataPath)) {
8882
9323
  console.log(import_chalk21.default.yellow(" Warning: metadata.json not found, using empty metadata"));
8883
9324
  return {};
@@ -8887,7 +9328,7 @@ function getMetadata() {
8887
9328
  function buildWorker() {
8888
9329
  console.log(import_chalk21.default.blue("Building worker..."));
8889
9330
  try {
8890
- (0, import_child_process4.execSync)("npm run build:worker", {
9331
+ (0, import_child_process5.execSync)("npm run build:worker", {
8891
9332
  cwd: PROJECT_DIR2,
8892
9333
  stdio: "inherit"
8893
9334
  });
@@ -8943,13 +9384,13 @@ function installDependencies() {
8943
9384
  }
8944
9385
  }
8945
9386
  function getBuiltWorker() {
8946
- const distWorkerDir = import_path12.default.join(PROJECT_DIR2, "dist-worker");
9387
+ const distWorkerDir = import_path13.default.join(PROJECT_DIR2, "dist-worker");
8947
9388
  if (!import_fs_extra7.default.existsSync(distWorkerDir)) {
8948
9389
  throw createConfigError("Built worker output not found: `dist-worker/`.", [
8949
9390
  "Make sure `npm run build:worker` completed successfully."
8950
9391
  ]);
8951
9392
  }
8952
- const workerJsPath = import_path12.default.join(distWorkerDir, "worker.js");
9393
+ const workerJsPath = import_path13.default.join(distWorkerDir, "worker.js");
8953
9394
  if (!import_fs_extra7.default.existsSync(workerJsPath)) {
8954
9395
  throw createConfigError("Built worker entry file not found: `dist-worker/worker.js`.", [
8955
9396
  "Check the worker build output and bundler config."
@@ -8959,18 +9400,18 @@ function getBuiltWorker() {
8959
9400
  const files = import_fs_extra7.default.readdirSync(distWorkerDir);
8960
9401
  for (const file of files) {
8961
9402
  if (file.endsWith(".js") && file !== "worker.js") {
8962
- modulePaths.push(import_path12.default.join(distWorkerDir, file));
9403
+ modulePaths.push(import_path13.default.join(distWorkerDir, file));
8963
9404
  }
8964
9405
  }
8965
9406
  return { workerJsPath, modulePaths };
8966
9407
  }
8967
9408
  function getSqlFiles() {
8968
- const sqlDir = import_path12.default.join(PROJECT_DIR2, "db");
9409
+ const sqlDir = import_path13.default.join(PROJECT_DIR2, "db");
8969
9410
  if (!import_fs_extra7.default.existsSync(sqlDir)) {
8970
9411
  return [];
8971
9412
  }
8972
9413
  const files = import_fs_extra7.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
8973
- return files.map((f) => import_path12.default.join(sqlDir, f));
9414
+ return files.map((f) => import_path13.default.join(sqlDir, f));
8974
9415
  }
8975
9416
  async function saveWorker(workerJsPath, modulePaths, sqlFiles, metadata, projectName) {
8976
9417
  var _a2, _b;
@@ -8995,14 +9436,14 @@ async function saveWorker(workerJsPath, modulePaths, sqlFiles, metadata, project
8995
9436
  type: "application/javascript+module"
8996
9437
  }), "worker.js");
8997
9438
  for (const modulePath of modulePaths) {
8998
- const filename = import_path12.default.basename(modulePath);
9439
+ const filename = import_path13.default.basename(modulePath);
8999
9440
  const content = import_fs_extra7.default.readFileSync(modulePath, "utf-8");
9000
9441
  formData.append(filename, new Blob2([content], {
9001
9442
  type: "application/javascript+module"
9002
9443
  }), filename);
9003
9444
  }
9004
9445
  for (const sqlFile of sqlFiles) {
9005
- const filename = import_path12.default.basename(sqlFile);
9446
+ const filename = import_path13.default.basename(sqlFile);
9006
9447
  const content = import_fs_extra7.default.readFileSync(sqlFile, "utf-8");
9007
9448
  formData.append("sql_file", new Blob2([content], {
9008
9449
  type: "application/sql"
@@ -9041,7 +9482,7 @@ async function saveWorker(workerJsPath, modulePaths, sqlFiles, metadata, project
9041
9482
  function buildFrontend() {
9042
9483
  console.log(import_chalk21.default.blue("Building frontend..."));
9043
9484
  try {
9044
- (0, import_child_process4.execSync)("npm run build:frontend", {
9485
+ (0, import_child_process5.execSync)("npm run build:frontend", {
9045
9486
  cwd: PROJECT_DIR2,
9046
9487
  stdio: "inherit"
9047
9488
  });
@@ -9072,11 +9513,11 @@ async function deployFrontend(projectName) {
9072
9513
  console.log(import_chalk21.default.blue("Deploying frontend to IPFS..."));
9073
9514
  try {
9074
9515
  const headers = getAuthHeaders();
9075
- const uploadResult = await uploadPath(import_path12.default.join(PROJECT_DIR2, "frontend", "dist"), {
9516
+ const uploadResult = await uploadPath(import_path13.default.join(PROJECT_DIR2, "frontend", "dist"), {
9076
9517
  projectName,
9077
9518
  uid: headers["token-address"]
9078
9519
  });
9079
- updateFrontendUrlInConfig2(import_path12.default.join(PROJECT_DIR2, "pinme.toml"), uploadResult.publicUrl);
9520
+ updateFrontendUrlInConfig2(import_path13.default.join(PROJECT_DIR2, "pinme.toml"), uploadResult.publicUrl);
9080
9521
  return {
9081
9522
  contentHash: uploadResult.contentHash,
9082
9523
  publicUrl: uploadResult.publicUrl
@@ -9126,9 +9567,9 @@ async function saveCmd(options) {
9126
9567
  "Run `pinme login` and retry."
9127
9568
  ]);
9128
9569
  }
9129
- const projectDir = options.projectName || options.name ? import_path12.default.join(PROJECT_DIR2, options.projectName || options.name) : PROJECT_DIR2;
9130
- const tokenFileSrc = import_path12.default.join(PROJECT_DIR2, ".token.json");
9131
- const tokenFileDst = import_path12.default.join(projectDir, ".token.json");
9570
+ const projectDir = options.projectName || options.name ? import_path13.default.join(PROJECT_DIR2, options.projectName || options.name) : PROJECT_DIR2;
9571
+ const tokenFileSrc = import_path13.default.join(PROJECT_DIR2, ".token.json");
9572
+ const tokenFileDst = import_path13.default.join(projectDir, ".token.json");
9132
9573
  if (import_fs_extra7.default.existsSync(tokenFileSrc) && !import_fs_extra7.default.existsSync(tokenFileDst)) {
9133
9574
  import_fs_extra7.default.copySync(tokenFileSrc, tokenFileDst);
9134
9575
  }
@@ -9174,8 +9615,18 @@ async function saveCmd(options) {
9174
9615
  "management"
9175
9616
  );
9176
9617
  console.log(import_chalk21.default.green("\nDeployment complete."));
9618
+ void tracker_default.trackEvent(TRACK_EVENTS.projectSaveSuccess, TRACK_PAGES.deploy, {
9619
+ project_name: projectName,
9620
+ has_domain: Boolean(options.domain),
9621
+ domain_type: options.domain ? isDnsDomain(options.domain) ? "dns" : "pinme_subdomain" : void 0
9622
+ });
9177
9623
  process.exit(0);
9178
9624
  } catch (error) {
9625
+ void tracker_default.trackEvent(TRACK_EVENTS.projectSaveFailed, TRACK_PAGES.deploy, {
9626
+ project_name: options.projectName || options.name,
9627
+ has_domain: Boolean(options.domain),
9628
+ reason: getTrackErrorReason(error)
9629
+ });
9179
9630
  printCliError(error, "Save failed.");
9180
9631
  process.exit(1);
9181
9632
  }
@@ -9184,14 +9635,14 @@ async function saveCmd(options) {
9184
9635
  // bin/updateDb.ts
9185
9636
  var import_chalk22 = __toESM(require("chalk"));
9186
9637
  var import_fs_extra8 = __toESM(require("fs-extra"));
9187
- var import_path13 = __toESM(require("path"));
9638
+ var import_path14 = __toESM(require("path"));
9188
9639
  init_axios2();
9189
9640
  init_webLogin();
9190
9641
  init_cliError();
9191
9642
  init_config();
9192
9643
  var PROJECT_DIR3 = process.cwd();
9193
9644
  function loadConfig2() {
9194
- const configPath = import_path13.default.join(PROJECT_DIR3, "pinme.toml");
9645
+ const configPath = import_path14.default.join(PROJECT_DIR3, "pinme.toml");
9195
9646
  if (!import_fs_extra8.default.existsSync(configPath)) {
9196
9647
  throw createConfigError("`pinme.toml` not found in the current directory.", [
9197
9648
  "Run this command from the Pinme project root."
@@ -9204,7 +9655,7 @@ function loadConfig2() {
9204
9655
  };
9205
9656
  }
9206
9657
  function getSqlFiles2() {
9207
- const sqlDir = import_path13.default.join(PROJECT_DIR3, "db");
9658
+ const sqlDir = import_path14.default.join(PROJECT_DIR3, "db");
9208
9659
  if (!import_fs_extra8.default.existsSync(sqlDir)) {
9209
9660
  throw createConfigError("SQL directory not found: `db/`.", [
9210
9661
  "Create a `db/` directory and add at least one `.sql` migration file."
@@ -9216,7 +9667,7 @@ function getSqlFiles2() {
9216
9667
  "Add one or more migration files before running `pinme update-db`."
9217
9668
  ]);
9218
9669
  }
9219
- return files.map((f) => import_path13.default.join(sqlDir, f));
9670
+ return files.map((f) => import_path14.default.join(sqlDir, f));
9220
9671
  }
9221
9672
  async function updateDb(sqlFiles, projectName) {
9222
9673
  console.log(import_chalk22.default.blue("Importing SQL files to database..."));
@@ -9231,7 +9682,7 @@ async function updateDb(sqlFiles, projectName) {
9231
9682
  const formData = new FormData4();
9232
9683
  let totalSize = 0;
9233
9684
  for (const sqlFile of sqlFiles) {
9234
- const filename = import_path13.default.basename(sqlFile);
9685
+ const filename = import_path14.default.basename(sqlFile);
9235
9686
  const content = import_fs_extra8.default.readFileSync(sqlFile);
9236
9687
  totalSize += content.length;
9237
9688
  if (totalSize > 10 * 1024 * 1024) {
@@ -9287,9 +9738,9 @@ async function updateDbCmd(options) {
9287
9738
  "Run `pinme login` and retry."
9288
9739
  ]);
9289
9740
  }
9290
- const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path13.default.join(PROJECT_DIR3, options.projectName || options.name) : PROJECT_DIR3;
9291
- const tokenFileSrc = import_path13.default.join(PROJECT_DIR3, ".token.json");
9292
- const tokenFileDst = import_path13.default.join(projectDir, ".token.json");
9741
+ const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path14.default.join(PROJECT_DIR3, options.projectName || options.name) : PROJECT_DIR3;
9742
+ const tokenFileSrc = import_path14.default.join(PROJECT_DIR3, ".token.json");
9743
+ const tokenFileDst = import_path14.default.join(projectDir, ".token.json");
9293
9744
  if (import_fs_extra8.default.existsSync(tokenFileSrc) && !import_fs_extra8.default.existsSync(tokenFileDst)) {
9294
9745
  import_fs_extra8.default.copySync(tokenFileSrc, tokenFileDst);
9295
9746
  }
@@ -9317,15 +9768,15 @@ async function updateDbCmd(options) {
9317
9768
  // bin/updateWorker.ts
9318
9769
  var import_chalk23 = __toESM(require("chalk"));
9319
9770
  var import_fs_extra9 = __toESM(require("fs-extra"));
9320
- var import_path14 = __toESM(require("path"));
9771
+ var import_path15 = __toESM(require("path"));
9321
9772
  init_axios2();
9322
- var import_child_process5 = require("child_process");
9773
+ var import_child_process6 = require("child_process");
9323
9774
  init_webLogin();
9324
9775
  init_cliError();
9325
9776
  init_config();
9326
9777
  var PROJECT_DIR4 = process.cwd();
9327
9778
  function loadConfig3() {
9328
- const configPath = import_path14.default.join(PROJECT_DIR4, "pinme.toml");
9779
+ const configPath = import_path15.default.join(PROJECT_DIR4, "pinme.toml");
9329
9780
  if (!import_fs_extra9.default.existsSync(configPath)) {
9330
9781
  throw createConfigError("`pinme.toml` not found in the current directory.", [
9331
9782
  "Run this command from the Pinme project root."
@@ -9338,7 +9789,7 @@ function loadConfig3() {
9338
9789
  };
9339
9790
  }
9340
9791
  function getMetadata2() {
9341
- const metadataPath = import_path14.default.join(PROJECT_DIR4, "backend", "metadata.json");
9792
+ const metadataPath = import_path15.default.join(PROJECT_DIR4, "backend", "metadata.json");
9342
9793
  if (!import_fs_extra9.default.existsSync(metadataPath)) {
9343
9794
  throw createConfigError("`backend/metadata.json` not found.", [
9344
9795
  "Create `backend/metadata.json` or restore it from the project template."
@@ -9349,7 +9800,7 @@ function getMetadata2() {
9349
9800
  function buildWorker2() {
9350
9801
  console.log(import_chalk23.default.blue("Building worker..."));
9351
9802
  try {
9352
- (0, import_child_process5.execSync)("npm run build:worker", {
9803
+ (0, import_child_process6.execSync)("npm run build:worker", {
9353
9804
  cwd: PROJECT_DIR4,
9354
9805
  stdio: "inherit"
9355
9806
  });
@@ -9361,13 +9812,13 @@ function buildWorker2() {
9361
9812
  }
9362
9813
  }
9363
9814
  function getBuiltWorker2() {
9364
- const distWorkerDir = import_path14.default.join(PROJECT_DIR4, "dist-worker");
9815
+ const distWorkerDir = import_path15.default.join(PROJECT_DIR4, "dist-worker");
9365
9816
  if (!import_fs_extra9.default.existsSync(distWorkerDir)) {
9366
9817
  throw createConfigError("Built worker output not found: `dist-worker/`.", [
9367
9818
  "Make sure `npm run build:worker` completed successfully."
9368
9819
  ]);
9369
9820
  }
9370
- const workerJsPath = import_path14.default.join(distWorkerDir, "worker.js");
9821
+ const workerJsPath = import_path15.default.join(distWorkerDir, "worker.js");
9371
9822
  if (!import_fs_extra9.default.existsSync(workerJsPath)) {
9372
9823
  throw createConfigError("Built worker entry file not found: `dist-worker/worker.js`.", [
9373
9824
  "Check the worker build output and bundler config."
@@ -9377,7 +9828,7 @@ function getBuiltWorker2() {
9377
9828
  const files = import_fs_extra9.default.readdirSync(distWorkerDir);
9378
9829
  for (const file of files) {
9379
9830
  if (file.endsWith(".js") && file !== "worker.js") {
9380
- modulePaths.push(import_path14.default.join(distWorkerDir, file));
9831
+ modulePaths.push(import_path15.default.join(distWorkerDir, file));
9381
9832
  }
9382
9833
  }
9383
9834
  return { workerJsPath, modulePaths };
@@ -9403,7 +9854,7 @@ async function updateWorker(workerJsPath, modulePaths, metadata, projectName) {
9403
9854
  type: "application/javascript+module"
9404
9855
  }), "worker.js");
9405
9856
  for (const modulePath of modulePaths) {
9406
- const filename = import_path14.default.basename(modulePath);
9857
+ const filename = import_path15.default.basename(modulePath);
9407
9858
  const content = import_fs_extra9.default.readFileSync(modulePath, "utf-8");
9408
9859
  formData.append(filename, new Blob2([content], {
9409
9860
  type: "application/javascript+module"
@@ -9466,9 +9917,9 @@ async function updateWorkerCmd(options) {
9466
9917
  "Run `pinme login` and retry."
9467
9918
  ]);
9468
9919
  }
9469
- const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path14.default.join(PROJECT_DIR4, options.projectName || options.name) : PROJECT_DIR4;
9470
- const tokenFileSrc = import_path14.default.join(PROJECT_DIR4, ".token.json");
9471
- const tokenFileDst = import_path14.default.join(projectDir, ".token.json");
9920
+ const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path15.default.join(PROJECT_DIR4, options.projectName || options.name) : PROJECT_DIR4;
9921
+ const tokenFileSrc = import_path15.default.join(PROJECT_DIR4, ".token.json");
9922
+ const tokenFileDst = import_path15.default.join(projectDir, ".token.json");
9472
9923
  if (import_fs_extra9.default.existsSync(tokenFileSrc) && !import_fs_extra9.default.existsSync(tokenFileDst)) {
9473
9924
  import_fs_extra9.default.copySync(tokenFileSrc, tokenFileDst);
9474
9925
  }
@@ -9501,14 +9952,14 @@ async function updateWorkerCmd(options) {
9501
9952
  // bin/updateWeb.ts
9502
9953
  var import_chalk24 = __toESM(require("chalk"));
9503
9954
  var import_fs_extra10 = __toESM(require("fs-extra"));
9504
- var import_path15 = __toESM(require("path"));
9505
- var import_child_process6 = require("child_process");
9955
+ var import_path16 = __toESM(require("path"));
9956
+ var import_child_process7 = require("child_process");
9506
9957
  init_webLogin();
9507
9958
  init_cliError();
9508
9959
  init_config();
9509
9960
  var PROJECT_DIR5 = process.cwd();
9510
9961
  function loadConfig4() {
9511
- const configPath = import_path15.default.join(PROJECT_DIR5, "pinme.toml");
9962
+ const configPath = import_path16.default.join(PROJECT_DIR5, "pinme.toml");
9512
9963
  if (!import_fs_extra10.default.existsSync(configPath)) {
9513
9964
  throw createConfigError("`pinme.toml` not found in the current directory.", [
9514
9965
  "Run this command from the Pinme project root."
@@ -9526,7 +9977,7 @@ function getProjectManagementUrl3(projectName) {
9526
9977
  function buildFrontend2() {
9527
9978
  console.log(import_chalk24.default.blue("Building frontend..."));
9528
9979
  try {
9529
- (0, import_child_process6.execSync)("npm run build:frontend", {
9980
+ (0, import_child_process7.execSync)("npm run build:frontend", {
9530
9981
  cwd: PROJECT_DIR5,
9531
9982
  stdio: "inherit"
9532
9983
  });
@@ -9541,7 +9992,7 @@ async function deployFrontend2(projectName) {
9541
9992
  console.log(import_chalk24.default.blue("Deploying frontend to IPFS..."));
9542
9993
  try {
9543
9994
  const headers = getAuthHeaders();
9544
- const uploadResult = await uploadPath(import_path15.default.join(PROJECT_DIR5, "frontend", "dist"), {
9995
+ const uploadResult = await uploadPath(import_path16.default.join(PROJECT_DIR5, "frontend", "dist"), {
9545
9996
  projectName,
9546
9997
  uid: headers["token-address"]
9547
9998
  });
@@ -9565,9 +10016,9 @@ async function updateWebCmd(options) {
9565
10016
  "Run `pinme login` and retry."
9566
10017
  ]);
9567
10018
  }
9568
- const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path15.default.join(PROJECT_DIR5, options.projectName || options.name) : PROJECT_DIR5;
9569
- const tokenFileSrc = import_path15.default.join(PROJECT_DIR5, ".token.json");
9570
- const tokenFileDst = import_path15.default.join(projectDir, ".token.json");
10019
+ const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path16.default.join(PROJECT_DIR5, options.projectName || options.name) : PROJECT_DIR5;
10020
+ const tokenFileSrc = import_path16.default.join(PROJECT_DIR5, ".token.json");
10021
+ const tokenFileDst = import_path16.default.join(projectDir, ".token.json");
9571
10022
  if (import_fs_extra10.default.existsSync(tokenFileSrc) && !import_fs_extra10.default.existsSync(tokenFileDst)) {
9572
10023
  import_fs_extra10.default.copySync(tokenFileSrc, tokenFileDst);
9573
10024
  }
@@ -9585,8 +10036,23 @@ async function updateWebCmd(options) {
9585
10036
  buildFrontend2();
9586
10037
  await deployFrontend2(projectName);
9587
10038
  console.log(import_chalk24.default.green("\nWeb update complete."));
10039
+ void tracker_default.trackEvent(
10040
+ TRACK_EVENTS.projectUpdateWebSuccess,
10041
+ TRACK_PAGES.deploy,
10042
+ {
10043
+ project_name: projectName
10044
+ }
10045
+ );
9588
10046
  process.exit(0);
9589
10047
  } catch (error) {
10048
+ void tracker_default.trackEvent(
10049
+ TRACK_EVENTS.projectUpdateWebFailed,
10050
+ TRACK_PAGES.deploy,
10051
+ {
10052
+ project_name: (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name),
10053
+ reason: getTrackErrorReason(error)
10054
+ }
10055
+ );
9590
10056
  printCliError(error, "Web update failed.");
9591
10057
  process.exit(1);
9592
10058
  }
@@ -9597,11 +10063,11 @@ var import_chalk25 = __toESM(require("chalk"));
9597
10063
  var import_inquirer9 = __toESM(require("inquirer"));
9598
10064
  init_axios2();
9599
10065
  var import_fs_extra11 = __toESM(require("fs-extra"));
9600
- var import_path16 = __toESM(require("path"));
10066
+ var import_path17 = __toESM(require("path"));
9601
10067
  init_webLogin();
9602
10068
  init_config();
9603
10069
  function getProjectName() {
9604
- const configPath = import_path16.default.join(process.cwd(), "pinme.toml");
10070
+ const configPath = import_path17.default.join(process.cwd(), "pinme.toml");
9605
10071
  if (!import_fs_extra11.default.existsSync(configPath)) {
9606
10072
  return null;
9607
10073
  }
@@ -9668,6 +10134,16 @@ async function deleteCmd(options) {
9668
10134
  });
9669
10135
  const data = response.data;
9670
10136
  if (data.code === 200) {
10137
+ void tracker_default.trackEvent(
10138
+ TRACK_EVENTS.projectDeleteSuccess,
10139
+ TRACK_PAGES.project,
10140
+ {
10141
+ project_name: data.data.project_name,
10142
+ domain_deleted: Boolean(data.data.domain_deleted),
10143
+ worker_deleted: Boolean(data.data.worker_deleted),
10144
+ database_deleted: Boolean(data.data.database_deleted)
10145
+ }
10146
+ );
9671
10147
  console.log(import_chalk25.default.green("\n\u2705 Project deleted successfully!"));
9672
10148
  console.log(import_chalk25.default.gray(`
9673
10149
  Project: ${data.data.project_name}`));
@@ -9681,6 +10157,15 @@ Project: ${data.data.project_name}`));
9681
10157
  }
9682
10158
  process.exit(0);
9683
10159
  } catch (error) {
10160
+ void tracker_default.trackEvent(
10161
+ TRACK_EVENTS.projectDeleteFailed,
10162
+ TRACK_PAGES.project,
10163
+ {
10164
+ project_name: options.name || getProjectName() || void 0,
10165
+ force: Boolean(options.force),
10166
+ reason: getTrackErrorReason(error)
10167
+ }
10168
+ );
9684
10169
  console.log(import_chalk25.default.red(error));
9685
10170
  const errorMsg = ((_b = (_a2 = error.response) == null ? void 0 : _a2.data) == null ? void 0 : _b.msg) || error.message || "Failed to delete project";
9686
10171
  console.error(import_chalk25.default.red(`