pinme 2.0.9 → 2.0.10-beta.2

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 (2) hide show
  1. package/dist/index.js +689 -229
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -103,8 +103,8 @@ 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 fs17 = require("fs");
107
- var path18 = require("path");
106
+ var fs18 = require("fs");
107
+ var path19 = require("path");
108
108
  var os6 = require("os");
109
109
  var crypto3 = require("crypto");
110
110
  var packageJson = require_package();
@@ -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 (fs17.existsSync(filepath)) {
210
+ if (fs18.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 = path18.resolve(process.cwd(), ".env.vault");
218
+ possibleVaultPath = path19.resolve(process.cwd(), ".env.vault");
219
219
  }
220
- if (fs17.existsSync(possibleVaultPath)) {
220
+ if (fs18.existsSync(possibleVaultPath)) {
221
221
  return possibleVaultPath;
222
222
  }
223
223
  return null;
224
224
  }
225
225
  function _resolveHome(envPath) {
226
- return envPath[0] === "~" ? path18.join(os6.homedir(), envPath.slice(1)) : envPath;
226
+ return envPath[0] === "~" ? path19.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 = path18.resolve(process.cwd(), ".env");
242
+ const dotenvPath = path19.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 path19 of optionPaths) {
265
+ for (const path20 of optionPaths) {
266
266
  try {
267
- const parsed = DotenvModule.parse(fs17.readFileSync(path19, { encoding }));
267
+ const parsed = DotenvModule.parse(fs18.readFileSync(path20, { encoding }));
268
268
  DotenvModule.populate(parsedAll, parsed, options);
269
269
  } catch (e) {
270
270
  if (debug) {
271
- _debug(`Failed to load ${path19} ${e.message}`);
271
+ _debug(`Failed to load ${path20} ${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(path18, key, dots) {
832
- if (!path18) return key;
833
- return path18.concat(key).map(function each(token, i) {
831
+ function renderKey(path19, key, dots) {
832
+ if (!path19) return key;
833
+ return path19.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, path18) {
875
+ function defaultVisitor(value, key, path19) {
876
876
  let arr = value;
877
- if (value && !path18 && typeof value === "object") {
877
+ if (value && !path19 && 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(path18, key, dots), convertValue(value));
896
+ formData.append(renderKey(path19, 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, path18) {
905
+ function build(value, path19) {
906
906
  if (utils_default.isUndefined(value)) return;
907
907
  if (stack.indexOf(value) !== -1) {
908
- throw Error("Circular reference detected in " + path18.join("."));
908
+ throw Error("Circular reference detected in " + path19.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
- path18,
916
+ path19,
917
917
  exposedHelpers
918
918
  );
919
919
  if (result === true) {
920
- build(el, path18 ? path18.concat(key) : [key]);
920
+ build(el, path19 ? path19.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, path18, helpers) {
1140
+ visitor: function(value, key, path19, 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(path18, value, target, index) {
1178
- let name = path18[index++];
1177
+ function buildPath(path19, value, target, index) {
1178
+ let name = path19[index++];
1179
1179
  const isNumericKey = Number.isFinite(+name);
1180
- const isLast = index >= path18.length;
1180
+ const isLast = index >= path19.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(path18, value, target[name], index);
1193
+ const result = buildPath(path19, value, target[name], index);
1194
1194
  if (result && utils_default.isArray(target[name])) {
1195
1195
  target[name] = arrayToObject(target[name]);
1196
1196
  }
@@ -3516,9 +3516,9 @@ var init_http = __esm({
3516
3516
  auth = urlUsername + ":" + urlPassword;
3517
3517
  }
3518
3518
  auth && headers.delete("authorization");
3519
- let path18;
3519
+ let path19;
3520
3520
  try {
3521
- path18 = buildURL(
3521
+ path19 = 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: path18,
3539
+ path: path19,
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, path18, domain, secure) {
3766
+ write: function write(name, value, expires, path19, 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(path18)) {
3773
- cookie.push("path=" + path18);
3772
+ if (utils_default.isString(path19)) {
3773
+ cookie.push("path=" + path19);
3774
3774
  }
3775
3775
  if (utils_default.isString(domain)) {
3776
3776
  cookie.push("domain=" + domain);
@@ -5978,7 +5978,7 @@ var import_chalk26 = __toESM(require("chalk"));
5978
5978
  var import_figlet5 = __toESM(require("figlet"));
5979
5979
 
5980
5980
  // package.json
5981
- var version = "2.0.9";
5981
+ var version = "2.0.10-beta.2";
5982
5982
 
5983
5983
  // bin/upload.ts
5984
5984
  var import_path7 = __toESM(require("path"));
@@ -6089,6 +6089,8 @@ var import_fs2 = __toESM(require("fs"));
6089
6089
  var import_path4 = __toESM(require("path"));
6090
6090
  var import_child_process2 = require("child_process");
6091
6091
  var REQUEST_TIMEOUT_MS = 1500;
6092
+ var TRACK_VALUE_LIMIT = 200;
6093
+ var TRACK_REASON_LIMIT = 255;
6092
6094
  var DEFAULT_GATEWAY = "https://pinme.dev";
6093
6095
  var DEFAULT_PRODUCT = "pinme-cli";
6094
6096
  var ACTION_OVERRIDES = {
@@ -6106,6 +6108,12 @@ var ACTION_OVERRIDES = {
6106
6108
  upload_history_cleared: "click",
6107
6109
  upload_history_failed: "fail"
6108
6110
  };
6111
+ var EV_OVERRIDES = {
6112
+ upload_success: "upload",
6113
+ upload_failed: "upload",
6114
+ project_save_success: "project_save",
6115
+ project_save_failed: "project_save"
6116
+ };
6109
6117
  var TRACK_CHILD_SCRIPT = `
6110
6118
  const rawUrl = process.argv[1];
6111
6119
  if (!rawUrl) process.exit(0);
@@ -6132,11 +6140,11 @@ function trimTrailingSlash2(value) {
6132
6140
  function shouldDisableTracking() {
6133
6141
  return process.env.PINME_TRACKING_DISABLED === "1" || process.env.DO_NOT_TRACK === "1";
6134
6142
  }
6135
- function sanitizeTrackValue(value) {
6143
+ function sanitizeTrackValue(value, maxLength = TRACK_VALUE_LIMIT) {
6136
6144
  if (value === void 0 || value === null) {
6137
6145
  return void 0;
6138
6146
  }
6139
- return String(value).trim().slice(0, 200);
6147
+ return String(value).trim().slice(0, maxLength);
6140
6148
  }
6141
6149
  function getTrackErrorReason(error) {
6142
6150
  var _a2, _b, _c, _d, _e;
@@ -6171,6 +6179,12 @@ function resolveTrackAction(event, data = {}) {
6171
6179
  }
6172
6180
  return "view";
6173
6181
  }
6182
+ function resolveTrackEvent(event) {
6183
+ return EV_OVERRIDES[event] || event;
6184
+ }
6185
+ function resolveTrackReason(data) {
6186
+ return sanitizeTrackValue(data.re || data.reason, TRACK_REASON_LIMIT);
6187
+ }
6174
6188
  var cachedProjectContext = null;
6175
6189
  var cachedProjectContextCwd = null;
6176
6190
  function resolveProjectContext() {
@@ -6248,6 +6262,7 @@ var Tracker = class _Tracker {
6248
6262
  buildPayload(event, page, data) {
6249
6263
  const projectContext = resolveProjectContext();
6250
6264
  const action = resolveTrackAction(event, data);
6265
+ const ev = resolveTrackEvent(event);
6251
6266
  const payload = {
6252
6267
  ...data,
6253
6268
  u: getUid(),
@@ -6255,9 +6270,10 @@ var Tracker = class _Tracker {
6255
6270
  pd: this.product,
6256
6271
  p: page,
6257
6272
  a: action,
6258
- ev: event,
6273
+ ev,
6259
6274
  event,
6260
- project_name: projectContext.projectName,
6275
+ re: resolveTrackReason(data),
6276
+ project_name: projectContext.projectName || data.project_name,
6261
6277
  project_dir: projectContext.projectDir,
6262
6278
  cli_version: version,
6263
6279
  node_version: process.version,
@@ -6266,7 +6282,10 @@ var Tracker = class _Tracker {
6266
6282
  };
6267
6283
  const filtered = {};
6268
6284
  for (const [key, value] of Object.entries(payload)) {
6269
- const normalized = sanitizeTrackValue(value);
6285
+ const normalized = sanitizeTrackValue(
6286
+ value,
6287
+ key === "re" ? TRACK_REASON_LIMIT : TRACK_VALUE_LIMIT
6288
+ );
6270
6289
  if (normalized) {
6271
6290
  filtered[key] = normalized;
6272
6291
  }
@@ -9035,6 +9054,7 @@ async function loginCmd(options = {}) {
9035
9054
  void tracker_default.trackEvent(TRACK_EVENTS.cliLoginSuccess, TRACK_PAGES.login, {
9036
9055
  a: resolveTrackAction2(TRACK_EVENTS.cliLoginSuccess),
9037
9056
  env,
9057
+ source: "cli",
9038
9058
  has_token_address: true,
9039
9059
  merged_anonymous_history: ok
9040
9060
  });
@@ -9043,6 +9063,7 @@ async function loginCmd(options = {}) {
9043
9063
  void tracker_default.trackEvent(TRACK_EVENTS.cliLoginFailed, TRACK_PAGES.login, {
9044
9064
  a: resolveTrackAction2(TRACK_EVENTS.cliLoginFailed),
9045
9065
  env,
9066
+ source: "cli",
9046
9067
  reason: getTrackErrorReason(e)
9047
9068
  });
9048
9069
  console.log(import_chalk18.default.red(`
@@ -9053,8 +9074,8 @@ Login failed: ${(e == null ? void 0 : e.message) || e}`));
9053
9074
 
9054
9075
  // bin/create.ts
9055
9076
  var import_chalk20 = __toESM(require("chalk"));
9056
- var import_fs_extra6 = __toESM(require("fs-extra"));
9057
- var import_path12 = __toESM(require("path"));
9077
+ var import_fs_extra7 = __toESM(require("fs-extra"));
9078
+ var import_path13 = __toESM(require("path"));
9058
9079
  var import_inquirer8 = __toESM(require("inquirer"));
9059
9080
  init_axios2();
9060
9081
  var import_adm_zip = __toESM(require("adm-zip"));
@@ -9069,8 +9090,24 @@ var import_chalk19 = __toESM(require("chalk"));
9069
9090
  var import_child_process3 = require("child_process");
9070
9091
  var INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
9071
9092
  var SLOW_INSTALL_NOTICE_MS = 60 * 1e3;
9093
+ var CAPTURED_OUTPUT_LIMIT = 12e3;
9094
+ var STALE_LOG_ONLY_MARKER_MS = 90 * 1e3;
9095
+ var STOP_BACKGROUND_GRACE_MS = 3e3;
9096
+ var STOP_BACKGROUND_KILL_GRACE_MS = 2e3;
9097
+ var STOP_BACKGROUND_POLL_MS = 200;
9072
9098
  var INSTALL_LOG_FILE = ".pinme-install.log";
9073
9099
  var INSTALL_EXITCODE_FILE = ".pinme-install.exitcode";
9100
+ var INSTALL_PID_FILE = ".pinme-install.pid";
9101
+ var DependencyInstallError = class extends Error {
9102
+ command;
9103
+ constructor(command, cause) {
9104
+ const reason = cause instanceof Error ? cause.message : String(cause);
9105
+ super(`${command} failed: ${reason}`);
9106
+ this.name = "DependencyInstallError";
9107
+ this.command = command;
9108
+ this.cause = cause;
9109
+ }
9110
+ };
9074
9111
  function makeTempCacheDir() {
9075
9112
  return import_fs_extra5.default.mkdtempSync(import_path11.default.join(import_os5.default.tmpdir(), "pinme-npm-cache-"));
9076
9113
  }
@@ -9090,10 +9127,8 @@ function getInstallScript(cwd, mode) {
9090
9127
  return hasPackageLock(cwd) ? "ci" : "install";
9091
9128
  }
9092
9129
  function getInstallArgs(script, cacheDir) {
9093
- return [
9130
+ const args = [
9094
9131
  script,
9095
- "--cache",
9096
- cacheDir,
9097
9132
  "--no-audit",
9098
9133
  "--no-fund",
9099
9134
  "--fetch-retries=3",
@@ -9102,6 +9137,100 @@ function getInstallArgs(script, cacheDir) {
9102
9137
  "--fetch-retry-maxtimeout=60000",
9103
9138
  "--fetch-timeout=60000"
9104
9139
  ];
9140
+ if (cacheDir) {
9141
+ args.splice(1, 0, "--cache", cacheDir);
9142
+ }
9143
+ return args;
9144
+ }
9145
+ function formatInstallCommand(script, cacheMode = "default") {
9146
+ const parts = [
9147
+ `npm ${script}`,
9148
+ "--no-audit",
9149
+ "--no-fund",
9150
+ "--fetch-retries=3",
9151
+ "--fetch-timeout=60000"
9152
+ ];
9153
+ if (cacheMode === "isolated") {
9154
+ parts.splice(1, 0, "--cache <isolated npm cache>");
9155
+ }
9156
+ return parts.join(" ");
9157
+ }
9158
+ function appendCapturedOutput(output, chunk) {
9159
+ const next = output + chunk.toString();
9160
+ if (next.length <= CAPTURED_OUTPUT_LIMIT) {
9161
+ return next;
9162
+ }
9163
+ return next.slice(next.length - CAPTURED_OUTPUT_LIMIT);
9164
+ }
9165
+ function runInstall(cwd, script, cacheDir) {
9166
+ const npm = getNpmCommand();
9167
+ const args = getInstallArgs(script, cacheDir);
9168
+ const env = {
9169
+ ...process.env,
9170
+ npm_config_audit: "false",
9171
+ npm_config_fund: "false",
9172
+ npm_config_fetch_retries: "3",
9173
+ npm_config_fetch_retry_factor: "2",
9174
+ npm_config_fetch_retry_mintimeout: "10000",
9175
+ npm_config_fetch_retry_maxtimeout: "60000",
9176
+ npm_config_fetch_timeout: "60000"
9177
+ };
9178
+ if (cacheDir) {
9179
+ env.npm_config_cache = cacheDir;
9180
+ }
9181
+ return new Promise((resolve, reject) => {
9182
+ var _a2, _b;
9183
+ let capturedOutput = "";
9184
+ let settled = false;
9185
+ let timedOut = false;
9186
+ const child = (0, import_child_process3.spawn)(npm, args, {
9187
+ cwd,
9188
+ stdio: ["inherit", "pipe", "pipe"],
9189
+ shell: process.platform === "win32",
9190
+ env
9191
+ });
9192
+ const slowNoticeTimer = setTimeout(() => {
9193
+ console.log(import_chalk19.default.yellow(" Still installing dependencies. Slow npm registry or network can make this take a few minutes..."));
9194
+ }, SLOW_INSTALL_NOTICE_MS);
9195
+ const timeoutTimer = setTimeout(() => {
9196
+ timedOut = true;
9197
+ child.kill();
9198
+ }, INSTALL_TIMEOUT_MS);
9199
+ const cleanup = () => {
9200
+ clearTimeout(slowNoticeTimer);
9201
+ clearTimeout(timeoutTimer);
9202
+ };
9203
+ (_a2 = child.stdout) == null ? void 0 : _a2.on("data", (chunk) => {
9204
+ process.stdout.write(chunk);
9205
+ capturedOutput = appendCapturedOutput(capturedOutput, chunk);
9206
+ });
9207
+ (_b = child.stderr) == null ? void 0 : _b.on("data", (chunk) => {
9208
+ process.stderr.write(chunk);
9209
+ capturedOutput = appendCapturedOutput(capturedOutput, chunk);
9210
+ });
9211
+ child.on("error", (error) => {
9212
+ if (settled) return;
9213
+ settled = true;
9214
+ cleanup();
9215
+ reject(error);
9216
+ });
9217
+ child.on("close", (code, signal) => {
9218
+ if (settled) return;
9219
+ settled = true;
9220
+ cleanup();
9221
+ if (timedOut) {
9222
+ reject(new Error(`npm ${script} timed out after 10 minutes.
9223
+ ${capturedOutput}`));
9224
+ return;
9225
+ }
9226
+ if (code !== 0) {
9227
+ reject(new Error(`npm ${script} failed with exit code ${code}${signal ? ` and signal ${signal}` : ""}.
9228
+ ${capturedOutput}`));
9229
+ return;
9230
+ }
9231
+ resolve();
9232
+ });
9233
+ });
9105
9234
  }
9106
9235
  function quoteForShell(value) {
9107
9236
  if (process.platform === "win32") {
@@ -9111,11 +9240,12 @@ function quoteForShell(value) {
9111
9240
  }
9112
9241
  function startBackgroundInstall(cwd) {
9113
9242
  const script = getInstallScript(cwd, "auto");
9114
- const cacheDir = makeTempCacheDir();
9115
- const args = getInstallArgs(script, cacheDir);
9243
+ const args = getInstallArgs(script);
9116
9244
  const logPath = import_path11.default.join(cwd, INSTALL_LOG_FILE);
9117
9245
  const exitCodePath = import_path11.default.join(cwd, INSTALL_EXITCODE_FILE);
9246
+ const pidPath = import_path11.default.join(cwd, INSTALL_PID_FILE);
9118
9247
  import_fs_extra5.default.removeSync(exitCodePath);
9248
+ import_fs_extra5.default.removeSync(pidPath);
9119
9249
  import_fs_extra5.default.writeFileSync(logPath, `[pinme] ${(/* @__PURE__ */ new Date()).toISOString()} starting "npm ${script}"
9120
9250
  `);
9121
9251
  const npmCmd = process.platform === "win32" ? "npm" : getNpmCommand();
@@ -9139,7 +9269,6 @@ function startBackgroundInstall(cwd) {
9139
9269
  stdio: "ignore",
9140
9270
  env: {
9141
9271
  ...process.env,
9142
- npm_config_cache: cacheDir,
9143
9272
  npm_config_audit: "false",
9144
9273
  npm_config_fund: "false",
9145
9274
  npm_config_fetch_retries: "3",
@@ -9150,11 +9279,92 @@ function startBackgroundInstall(cwd) {
9150
9279
  }
9151
9280
  });
9152
9281
  child.unref();
9282
+ if (child.pid) {
9283
+ import_fs_extra5.default.writeFileSync(pidPath, String(child.pid));
9284
+ }
9153
9285
  return { logPath };
9154
9286
  }
9287
+ function isProcessAlive(pid) {
9288
+ try {
9289
+ process.kill(pid, 0);
9290
+ return true;
9291
+ } catch (error) {
9292
+ return (error == null ? void 0 : error.code) === "EPERM";
9293
+ }
9294
+ }
9295
+ function readPidFile(pidPath) {
9296
+ if (!import_fs_extra5.default.existsSync(pidPath)) {
9297
+ return null;
9298
+ }
9299
+ const raw = import_fs_extra5.default.readFileSync(pidPath, "utf-8").trim();
9300
+ const pid = Number.parseInt(raw, 10);
9301
+ if (!Number.isFinite(pid) || pid <= 0) {
9302
+ return null;
9303
+ }
9304
+ return pid;
9305
+ }
9306
+ function sleep(ms) {
9307
+ return new Promise((resolve) => setTimeout(resolve, ms));
9308
+ }
9309
+ function signalInstallProcess(pid, signal) {
9310
+ try {
9311
+ if (process.platform === "win32") {
9312
+ process.kill(pid, signal);
9313
+ } else {
9314
+ process.kill(-pid, signal);
9315
+ }
9316
+ return true;
9317
+ } catch {
9318
+ try {
9319
+ process.kill(pid, signal);
9320
+ return true;
9321
+ } catch {
9322
+ return false;
9323
+ }
9324
+ }
9325
+ }
9326
+ async function waitForProcessExit(pid, timeoutMs) {
9327
+ const startedAt = Date.now();
9328
+ while (Date.now() - startedAt < timeoutMs) {
9329
+ if (!isProcessAlive(pid)) {
9330
+ return true;
9331
+ }
9332
+ await sleep(STOP_BACKGROUND_POLL_MS);
9333
+ }
9334
+ return !isProcessAlive(pid);
9335
+ }
9336
+ async function stopBackgroundInstall(cwd) {
9337
+ const pidPath = import_path11.default.join(cwd, INSTALL_PID_FILE);
9338
+ const pid = readPidFile(pidPath);
9339
+ let stopped = false;
9340
+ if (pid !== null && isProcessAlive(pid)) {
9341
+ if (signalInstallProcess(pid, "SIGTERM")) {
9342
+ stopped = true;
9343
+ const stoppedGracefully = await waitForProcessExit(
9344
+ pid,
9345
+ STOP_BACKGROUND_GRACE_MS
9346
+ );
9347
+ if (!stoppedGracefully) {
9348
+ signalInstallProcess(pid, "SIGKILL");
9349
+ await waitForProcessExit(pid, STOP_BACKGROUND_KILL_GRACE_MS);
9350
+ }
9351
+ }
9352
+ }
9353
+ import_fs_extra5.default.removeSync(pidPath);
9354
+ return stopped;
9355
+ }
9356
+ function isStaleLogOnlyMarker(logPath) {
9357
+ try {
9358
+ const ageMs = Date.now() - import_fs_extra5.default.statSync(logPath).mtimeMs;
9359
+ return ageMs > STALE_LOG_ONLY_MARKER_MS;
9360
+ } catch {
9361
+ return false;
9362
+ }
9363
+ }
9155
9364
  function readBackgroundInstallStatus(cwd) {
9156
9365
  const logPath = import_path11.default.join(cwd, INSTALL_LOG_FILE);
9157
9366
  const exitCodePath = import_path11.default.join(cwd, INSTALL_EXITCODE_FILE);
9367
+ const pidPath = import_path11.default.join(cwd, INSTALL_PID_FILE);
9158
9368
  if (import_fs_extra5.default.existsSync(exitCodePath)) {
9159
9369
  const raw = import_fs_extra5.default.readFileSync(exitCodePath, "utf-8").trim();
9160
9370
  const code = Number.parseInt(raw, 10);
@@ -9164,6 +9374,17 @@ function readBackgroundInstallStatus(cwd) {
9164
9374
  return { status: code === 0 ? "success" : "failed", exitCode: code, logPath };
9165
9375
  }
9166
9376
  if (import_fs_extra5.default.existsSync(logPath)) {
9377
+ const pid = readPidFile(pidPath);
9378
+ if (pid !== null) {
9379
+ return {
9380
+ status: isProcessAlive(pid) ? "running" : "interrupted",
9381
+ exitCode: null,
9382
+ logPath
9383
+ };
9384
+ }
9385
+ if (isStaleLogOnlyMarker(logPath)) {
9386
+ return { status: "interrupted", exitCode: null, logPath };
9387
+ }
9167
9388
  return { status: "running", exitCode: null, logPath };
9168
9389
  }
9169
9390
  return { status: "idle", exitCode: null, logPath };
@@ -9176,12 +9397,214 @@ function readBackgroundInstallLogTail(cwd, maxChars = 1500) {
9176
9397
  const content = import_fs_extra5.default.readFileSync(logPath, "utf-8");
9177
9398
  return content.length > maxChars ? content.slice(content.length - maxChars) : content;
9178
9399
  }
9400
+ async function installProjectDependencies(cwd, options = {}) {
9401
+ const mode = options.mode || "auto";
9402
+ const script = getInstallScript(cwd, mode);
9403
+ const command = formatInstallCommand(script);
9404
+ let lastError;
9405
+ if (script === "ci" && !hasPackageLock(cwd)) {
9406
+ throw new DependencyInstallError(
9407
+ command,
9408
+ new Error("package-lock.json is required for npm ci but was not found.")
9409
+ );
9410
+ }
9411
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
9412
+ const useIsolatedCache = attempt > 1;
9413
+ const cacheDir = useIsolatedCache ? makeTempCacheDir() : void 0;
9414
+ try {
9415
+ if (attempt > 1) {
9416
+ console.log(import_chalk19.default.yellow(" Retrying dependency install with a fresh npm cache..."));
9417
+ }
9418
+ if (attempt === 1 && script === "ci" && mode === "auto") {
9419
+ console.log(import_chalk19.default.gray(" package-lock.json found; using npm ci for a reproducible install."));
9420
+ } else if (attempt === 1 && script === "ci") {
9421
+ console.log(import_chalk19.default.gray(" Using npm ci for a clean, reproducible install."));
9422
+ }
9423
+ await runInstall(cwd, script, cacheDir);
9424
+ return;
9425
+ } catch (error) {
9426
+ lastError = error;
9427
+ } finally {
9428
+ if (cacheDir) {
9429
+ import_fs_extra5.default.removeSync(cacheDir);
9430
+ }
9431
+ }
9432
+ }
9433
+ throw new DependencyInstallError(
9434
+ formatInstallCommand(script, "isolated"),
9435
+ lastError
9436
+ );
9437
+ }
9179
9438
 
9180
9439
  // bin/create.ts
9181
9440
  init_cliError();
9182
9441
  init_config();
9442
+
9443
+ // bin/utils/prebuiltDistConfig.ts
9444
+ var import_fs_extra6 = __toESM(require("fs-extra"));
9445
+ var import_path12 = __toESM(require("path"));
9446
+ init_cliError();
9447
+ var PLACEHOLDERS = {
9448
+ apiUrl: "__PINME_VITE_API_URL__",
9449
+ authApiKey: "__PINME_AUTH_API_KEY__",
9450
+ authDomain: "__PINME_AUTH_DOMAIN__",
9451
+ authProjectId: "__PINME_AUTH_PROJECT_ID__",
9452
+ tenantId: "__PINME_TENANT_ID__"
9453
+ };
9454
+ var PATCHABLE_EXTENSIONS = /* @__PURE__ */ new Set([
9455
+ ".html",
9456
+ ".js",
9457
+ ".css",
9458
+ ".json",
9459
+ ".map"
9460
+ ]);
9461
+ function toReplacementValue(value) {
9462
+ if (value === void 0 || value === null) {
9463
+ return "";
9464
+ }
9465
+ return String(value);
9466
+ }
9467
+ function countOccurrences(content, needle) {
9468
+ if (!needle) {
9469
+ return 0;
9470
+ }
9471
+ return content.split(needle).length - 1;
9472
+ }
9473
+ function listPatchableFiles(dir) {
9474
+ const result = [];
9475
+ for (const entry of import_fs_extra6.default.readdirSync(dir, { withFileTypes: true })) {
9476
+ const entryPath = import_path12.default.join(dir, entry.name);
9477
+ if (entry.isDirectory()) {
9478
+ result.push(...listPatchableFiles(entryPath));
9479
+ continue;
9480
+ }
9481
+ if (entry.isFile() && PATCHABLE_EXTENSIONS.has(import_path12.default.extname(entry.name))) {
9482
+ result.push(entryPath);
9483
+ }
9484
+ }
9485
+ return result;
9486
+ }
9487
+ function patchPrebuiltFrontendDist(frontendDistDir, workerData) {
9488
+ if (!workerData.api_domain) {
9489
+ throw createConfigError("`api_domain` is missing from project creation response.", [
9490
+ "Retry `pinme create`.",
9491
+ "If the problem persists, check the `/create_worker` API response."
9492
+ ]);
9493
+ }
9494
+ if (!import_fs_extra6.default.existsSync(frontendDistDir)) {
9495
+ throw createConfigError("Prebuilt frontend output not found: `frontend/dist/`.", [
9496
+ "The template should ship a prebuilt `frontend/dist/`.",
9497
+ "Once dependencies finish installing, run `npm run build:frontend` in the project, then `pinme save`."
9498
+ ]);
9499
+ }
9500
+ const authConfig = workerData.public_client_config ?? {};
9501
+ const replacements = /* @__PURE__ */ new Map([
9502
+ [PLACEHOLDERS.apiUrl, workerData.api_domain],
9503
+ [PLACEHOLDERS.authApiKey, toReplacementValue(authConfig.auth_api_key)],
9504
+ [PLACEHOLDERS.authDomain, toReplacementValue(authConfig.auth_domain)],
9505
+ [PLACEHOLDERS.authProjectId, toReplacementValue(authConfig.auth_project_id)],
9506
+ [PLACEHOLDERS.tenantId, toReplacementValue(authConfig.tenant_id)]
9507
+ ]);
9508
+ const files = listPatchableFiles(frontendDistDir);
9509
+ let filesPatched = 0;
9510
+ let apiUrlReplacements = 0;
9511
+ let authReplacements = 0;
9512
+ for (const filePath of files) {
9513
+ const content = import_fs_extra6.default.readFileSync(filePath, "utf8");
9514
+ let nextContent = content;
9515
+ for (const [placeholder, replacement] of replacements) {
9516
+ const count = countOccurrences(nextContent, placeholder);
9517
+ if (count === 0) {
9518
+ continue;
9519
+ }
9520
+ if (placeholder === PLACEHOLDERS.apiUrl) {
9521
+ apiUrlReplacements += count;
9522
+ } else {
9523
+ authReplacements += count;
9524
+ }
9525
+ nextContent = nextContent.split(placeholder).join(replacement);
9526
+ }
9527
+ if (nextContent !== content) {
9528
+ import_fs_extra6.default.writeFileSync(filePath, nextContent);
9529
+ filesPatched += 1;
9530
+ }
9531
+ }
9532
+ if (apiUrlReplacements === 0) {
9533
+ throw createConfigError("Prebuilt frontend dist is missing required Pinme config placeholder.", [
9534
+ "Expected to find `__PINME_VITE_API_URL__` in `frontend/dist`.",
9535
+ "Rebuild the template frontend from placeholder-enabled source before publishing the template.",
9536
+ "After dependencies finish installing, users can recover by running `npm run build:frontend` and `pinme save`."
9537
+ ]);
9538
+ }
9539
+ return {
9540
+ filesScanned: files.length,
9541
+ filesPatched,
9542
+ apiUrlReplacements,
9543
+ authReplacements
9544
+ };
9545
+ }
9546
+
9547
+ // bin/utils/workerMetadata.ts
9548
+ init_cliError();
9549
+ function parseWorkerMetadata(metadataContent) {
9550
+ try {
9551
+ return JSON.parse(metadataContent);
9552
+ } catch (error) {
9553
+ throw createConfigError("Worker metadata must be valid JSON.", [
9554
+ "The `/create_worker` API should return JSON metadata for backend deployment.",
9555
+ "Retry `pinme create`."
9556
+ ]);
9557
+ }
9558
+ }
9559
+ function isRealBindingValue(value) {
9560
+ if (typeof value !== "string") {
9561
+ return false;
9562
+ }
9563
+ const trimmed = value.trim();
9564
+ return Boolean(trimmed) && trimmed !== "xxx" && trimmed !== "project_name" && !trimmed.startsWith("__PINME_");
9565
+ }
9566
+ function findBinding(metadata, name) {
9567
+ var _a2;
9568
+ return (_a2 = metadata.bindings) == null ? void 0 : _a2.find((binding) => binding.name === name);
9569
+ }
9570
+ function validateWorkerMetadataForCreate(metadataContent, projectName) {
9571
+ const metadata = parseWorkerMetadata(metadataContent);
9572
+ const apiKeyBinding = findBinding(metadata, "API_KEY");
9573
+ const projectNameBinding = findBinding(metadata, "PROJECT_NAME");
9574
+ if (!isRealBindingValue(apiKeyBinding == null ? void 0 : apiKeyBinding.text)) {
9575
+ throw createConfigError("Worker metadata is missing a real API_KEY binding.", [
9576
+ "The template metadata contains placeholder values and cannot be deployed as-is.",
9577
+ "Retry `pinme create` so Pinme can fetch fresh worker metadata from `/create_worker`."
9578
+ ]);
9579
+ }
9580
+ if ((projectNameBinding == null ? void 0 : projectNameBinding.text) !== projectName) {
9581
+ throw createConfigError("Worker metadata is missing a matching PROJECT_NAME binding.", [
9582
+ `Expected PROJECT_NAME binding text to be \`${projectName}\`.`,
9583
+ "Retry `pinme create` so Pinme can fetch fresh worker metadata from `/create_worker`."
9584
+ ]);
9585
+ }
9586
+ if (metadata.project_name && metadata.project_name !== projectName) {
9587
+ throw createConfigError("Worker metadata project_name does not match the created project.", [
9588
+ `Expected metadata project_name to be \`${projectName}\`.`,
9589
+ `Received metadata project_name \`${metadata.project_name}\`.`
9590
+ ]);
9591
+ }
9592
+ }
9593
+ function getValidatedWorkerMetadataContent(metadata, projectName) {
9594
+ if (!metadata) {
9595
+ throw createConfigError("Worker metadata is missing from project creation response.", [
9596
+ "The `/create_worker` API should return backend metadata before the prebuilt worker is deployed.",
9597
+ "Retry `pinme create`."
9598
+ ]);
9599
+ }
9600
+ const metadataContent = typeof metadata === "string" ? metadata : JSON.stringify(metadata, null, 2);
9601
+ validateWorkerMetadataForCreate(metadataContent, projectName);
9602
+ return metadataContent;
9603
+ }
9604
+
9605
+ // bin/create.ts
9183
9606
  var PROJECT_DIR = process.cwd();
9184
- var TEMPLATE_BRANCH = "main";
9607
+ var TEMPLATE_BRANCH = "feat/dev";
9185
9608
  var TEMPLATE_REPO = "glitternetwork/pinme-worker-template";
9186
9609
  var TEMPLATE_REPO_NAME = TEMPLATE_REPO.split("/").pop() || "pinme-worker-template";
9187
9610
  function getTemplateZipUrl(branch) {
@@ -9208,7 +9631,7 @@ ${configExport}
9208
9631
  `;
9209
9632
  }
9210
9633
  function resolveExtractedTemplateDir(extractDir) {
9211
- const entries = import_fs_extra6.default.readdirSync(extractDir, { withFileTypes: true });
9634
+ const entries = import_fs_extra7.default.readdirSync(extractDir, { withFileTypes: true });
9212
9635
  const templateDir = entries.find((entry) => entry.isDirectory() && entry.name.startsWith(`${TEMPLATE_REPO_NAME}-`));
9213
9636
  if (!templateDir) {
9214
9637
  throw createConfigError("Downloaded template archive structure is invalid.", [
@@ -9216,10 +9639,10 @@ function resolveExtractedTemplateDir(extractDir) {
9216
9639
  `Template branch: ${TEMPLATE_BRANCH}`
9217
9640
  ]);
9218
9641
  }
9219
- return import_path12.default.join(extractDir, templateDir.name);
9642
+ return import_path13.default.join(extractDir, templateDir.name);
9220
9643
  }
9221
9644
  function updateFrontendUrlInConfig(configPath, frontendUrl) {
9222
- let config = import_fs_extra6.default.readFileSync(configPath, "utf-8");
9645
+ let config = import_fs_extra7.default.readFileSync(configPath, "utf-8");
9223
9646
  if (config.includes("frontend_url")) {
9224
9647
  config = config.replace(
9225
9648
  /frontend_url\s*=\s*"[^"]*"/,
@@ -9232,7 +9655,7 @@ function updateFrontendUrlInConfig(configPath, frontendUrl) {
9232
9655
  `
9233
9656
  );
9234
9657
  }
9235
- import_fs_extra6.default.writeFileSync(configPath, config);
9658
+ import_fs_extra7.default.writeFileSync(configPath, config);
9236
9659
  }
9237
9660
  function getProjectManagementUrl(projectName) {
9238
9661
  return `${APP_CONFIG.projectPeviewUrl}${projectName}`;
@@ -9265,8 +9688,8 @@ async function createCmd(options) {
9265
9688
  ]);
9266
9689
  projectName = answers.projectName;
9267
9690
  }
9268
- const targetDir = import_path12.default.join(PROJECT_DIR, projectName);
9269
- if (import_fs_extra6.default.existsSync(targetDir) && !options.force) {
9691
+ const targetDir = import_path13.default.join(PROJECT_DIR, projectName);
9692
+ if (import_fs_extra7.default.existsSync(targetDir) && !options.force) {
9270
9693
  console.log(import_chalk20.default.yellow(`
9271
9694
  Directory "${projectName}" already exists.`));
9272
9695
  const answers = await import_inquirer8.default.prompt([
@@ -9281,7 +9704,7 @@ Directory "${projectName}" already exists.`));
9281
9704
  console.log(import_chalk20.default.gray("Cancelled."));
9282
9705
  process.exit(0);
9283
9706
  }
9284
- import_fs_extra6.default.removeSync(targetDir);
9707
+ import_fs_extra7.default.removeSync(targetDir);
9285
9708
  }
9286
9709
  console.log(import_chalk20.default.blue("\n1. Creating worker and database..."));
9287
9710
  const apiUrl = getPinmeApiUrl("/create_worker");
@@ -9316,8 +9739,8 @@ Directory "${projectName}" already exists.`));
9316
9739
  ]);
9317
9740
  }
9318
9741
  console.log(import_chalk20.default.blue("\n2. Downloading template from repository..."));
9319
- const zipPath = import_path12.default.join(PROJECT_DIR, "template.zip");
9320
- const extractDir = import_path12.default.join(PROJECT_DIR, `.pinme-template-${Date.now()}`);
9742
+ const zipPath = import_path13.default.join(PROJECT_DIR, "template.zip");
9743
+ const extractDir = import_path13.default.join(PROJECT_DIR, `.pinme-template-${Date.now()}`);
9321
9744
  const templateZipUrl = getTemplateZipUrl(TEMPLATE_BRANCH);
9322
9745
  let downloadSuccess = false;
9323
9746
  console.log(import_chalk20.default.gray(` Template branch: ${TEMPLATE_BRANCH}`));
@@ -9327,14 +9750,14 @@ Directory "${projectName}" already exists.`));
9327
9750
  (0, import_child_process4.execSync)(`curl -L --retry 3 --retry-delay 2 -o "${zipPath}" "${templateZipUrl}"`, {
9328
9751
  stdio: "inherit"
9329
9752
  });
9330
- if (!import_fs_extra6.default.existsSync(zipPath) || import_fs_extra6.default.statSync(zipPath).size < 100) {
9753
+ if (!import_fs_extra7.default.existsSync(zipPath) || import_fs_extra7.default.statSync(zipPath).size < 100) {
9331
9754
  throw new Error("Downloaded file is too small or empty");
9332
9755
  }
9333
9756
  downloadSuccess = true;
9334
9757
  } catch (downloadError) {
9335
9758
  console.log(import_chalk20.default.yellow(` Attempt ${attempt} failed: ${downloadError.message}`));
9336
- if (import_fs_extra6.default.existsSync(zipPath)) {
9337
- import_fs_extra6.default.removeSync(zipPath);
9759
+ if (import_fs_extra7.default.existsSync(zipPath)) {
9760
+ import_fs_extra7.default.removeSync(zipPath);
9338
9761
  }
9339
9762
  if (attempt === 3) {
9340
9763
  throw new Error(`Failed to download template after 3 attempts: ${downloadError.message}`);
@@ -9342,22 +9765,22 @@ Directory "${projectName}" already exists.`));
9342
9765
  }
9343
9766
  }
9344
9767
  try {
9345
- import_fs_extra6.default.ensureDirSync(extractDir);
9768
+ import_fs_extra7.default.ensureDirSync(extractDir);
9346
9769
  const templateZip = new import_adm_zip.default(zipPath);
9347
9770
  templateZip.extractAllTo(extractDir, true);
9348
9771
  const subDir = resolveExtractedTemplateDir(extractDir);
9349
- import_fs_extra6.default.copySync(subDir, targetDir);
9350
- import_fs_extra6.default.removeSync(zipPath);
9351
- import_fs_extra6.default.removeSync(extractDir);
9352
- const nodeModulesPath = import_path12.default.join(targetDir, "node_modules");
9353
- if (import_fs_extra6.default.existsSync(nodeModulesPath)) {
9772
+ import_fs_extra7.default.copySync(subDir, targetDir);
9773
+ import_fs_extra7.default.removeSync(zipPath);
9774
+ import_fs_extra7.default.removeSync(extractDir);
9775
+ const nodeModulesPath = import_path13.default.join(targetDir, "node_modules");
9776
+ if (import_fs_extra7.default.existsSync(nodeModulesPath)) {
9354
9777
  console.log(import_chalk20.default.gray(" Removing existing node_modules..."));
9355
- import_fs_extra6.default.removeSync(nodeModulesPath);
9778
+ import_fs_extra7.default.removeSync(nodeModulesPath);
9356
9779
  }
9357
- const frontendNodeModules = import_path12.default.join(targetDir, "frontend", "node_modules");
9358
- const backendNodeModules = import_path12.default.join(targetDir, "backend", "node_modules");
9359
- if (import_fs_extra6.default.existsSync(frontendNodeModules)) import_fs_extra6.default.removeSync(frontendNodeModules);
9360
- if (import_fs_extra6.default.existsSync(backendNodeModules)) import_fs_extra6.default.removeSync(backendNodeModules);
9780
+ const frontendNodeModules = import_path13.default.join(targetDir, "frontend", "node_modules");
9781
+ const backendNodeModules = import_path13.default.join(targetDir, "backend", "node_modules");
9782
+ if (import_fs_extra7.default.existsSync(frontendNodeModules)) import_fs_extra7.default.removeSync(frontendNodeModules);
9783
+ if (import_fs_extra7.default.existsSync(backendNodeModules)) import_fs_extra7.default.removeSync(backendNodeModules);
9361
9784
  console.log(import_chalk20.default.green(` Template downloaded to: ${targetDir}`));
9362
9785
  } catch (error) {
9363
9786
  throw createCommandError("template extraction", `extract "${zipPath}" to "${extractDir}"`, error, [
@@ -9365,58 +9788,61 @@ Directory "${projectName}" already exists.`));
9365
9788
  ]);
9366
9789
  }
9367
9790
  console.log(import_chalk20.default.blue("\n3. Updating configuration..."));
9368
- const configPath = import_path12.default.join(targetDir, "pinme.toml");
9369
- const config = import_fs_extra6.default.readFileSync(configPath, "utf-8");
9791
+ const configPath = import_path13.default.join(targetDir, "pinme.toml");
9792
+ const config = import_fs_extra7.default.readFileSync(configPath, "utf-8");
9370
9793
  let updatedConfig = config.replace(
9371
9794
  /project_name = ".*"/,
9372
9795
  `project_name = "${workerData.project_name}"`
9373
9796
  );
9374
- import_fs_extra6.default.writeFileSync(configPath, updatedConfig);
9797
+ import_fs_extra7.default.writeFileSync(configPath, updatedConfig);
9375
9798
  console.log(import_chalk20.default.green(` Updated pinme.toml`));
9376
9799
  console.log(import_chalk20.default.gray(` metadata: ${workerData.metadata}`));
9377
- const backendDir = import_path12.default.join(targetDir, "backend");
9378
- if (import_fs_extra6.default.existsSync(backendDir) && workerData.metadata) {
9379
- const metadataContent = typeof workerData.metadata === "string" ? workerData.metadata : JSON.stringify(workerData.metadata, null, 2);
9380
- import_fs_extra6.default.writeFileSync(
9381
- import_path12.default.join(backendDir, "metadata.json"),
9382
- metadataContent
9800
+ const workerMetadataContent = getValidatedWorkerMetadataContent(
9801
+ workerData.metadata,
9802
+ workerData.project_name
9803
+ );
9804
+ const backendDir = import_path13.default.join(targetDir, "backend");
9805
+ if (import_fs_extra7.default.existsSync(backendDir)) {
9806
+ import_fs_extra7.default.writeFileSync(
9807
+ import_path13.default.join(backendDir, "metadata.json"),
9808
+ workerMetadataContent
9383
9809
  );
9384
9810
  console.log(import_chalk20.default.green(` Saved metadata.json`));
9385
9811
  }
9386
- const wranglerPath = import_path12.default.join(backendDir, "wrangler.toml");
9387
- if (import_fs_extra6.default.existsSync(wranglerPath) && workerData.api_key) {
9388
- let wranglerContent = import_fs_extra6.default.readFileSync(wranglerPath, "utf-8");
9812
+ const wranglerPath = import_path13.default.join(backendDir, "wrangler.toml");
9813
+ if (import_fs_extra7.default.existsSync(wranglerPath) && workerData.api_key) {
9814
+ let wranglerContent = import_fs_extra7.default.readFileSync(wranglerPath, "utf-8");
9389
9815
  wranglerContent = wranglerContent.replace(
9390
9816
  /^name = ".*"$/m,
9391
9817
  `name = "${workerData.project_name}"`
9392
9818
  );
9393
- import_fs_extra6.default.writeFileSync(wranglerPath, wranglerContent);
9819
+ import_fs_extra7.default.writeFileSync(wranglerPath, wranglerContent);
9394
9820
  console.log(import_chalk20.default.green(` Updated backend/wrangler.toml API_KEY`));
9395
9821
  }
9396
- const frontendConfigPath = import_path12.default.join(targetDir, "frontend", "src", "utils", "config.ts");
9822
+ const frontendConfigPath = import_path13.default.join(targetDir, "frontend", "src", "utils", "config.ts");
9397
9823
  if (workerData.public_client_config) {
9398
- const frontendConfigContent = import_fs_extra6.default.existsSync(frontendConfigPath) ? import_fs_extra6.default.readFileSync(frontendConfigPath, "utf-8") : "";
9399
- import_fs_extra6.default.ensureDirSync(import_path12.default.dirname(frontendConfigPath));
9400
- import_fs_extra6.default.writeFileSync(
9824
+ const frontendConfigContent = import_fs_extra7.default.existsSync(frontendConfigPath) ? import_fs_extra7.default.readFileSync(frontendConfigPath, "utf-8") : "";
9825
+ import_fs_extra7.default.ensureDirSync(import_path13.default.dirname(frontendConfigPath));
9826
+ import_fs_extra7.default.writeFileSync(
9401
9827
  frontendConfigPath,
9402
9828
  injectPublicClientConfigIntoFile(frontendConfigContent, workerData.public_client_config)
9403
9829
  );
9404
9830
  console.log(import_chalk20.default.green(` Updated frontend/src/utils/config.ts public_client_config`));
9405
9831
  }
9406
- const envExamplePath = import_path12.default.join(targetDir, "frontend", ".env.example");
9407
- const envPath = import_path12.default.join(targetDir, "frontend", ".env");
9408
- if (import_fs_extra6.default.existsSync(envExamplePath)) {
9409
- let envContent = import_fs_extra6.default.readFileSync(envExamplePath, "utf-8");
9832
+ const envExamplePath = import_path13.default.join(targetDir, "frontend", ".env.example");
9833
+ const envPath = import_path13.default.join(targetDir, "frontend", ".env");
9834
+ if (import_fs_extra7.default.existsSync(envExamplePath)) {
9835
+ let envContent = import_fs_extra7.default.readFileSync(envExamplePath, "utf-8");
9410
9836
  envContent = envContent.replace(/your-project/g, workerData.project_name);
9411
9837
  envContent = envContent.replace(
9412
9838
  /^VITE_API_URL=.*$/m,
9413
9839
  `VITE_API_URL=${workerData.api_domain}`
9414
9840
  );
9415
- import_fs_extra6.default.writeFileSync(envPath, envContent);
9841
+ import_fs_extra7.default.writeFileSync(envPath, envContent);
9416
9842
  console.log(import_chalk20.default.green(` Created frontend/.env file`));
9417
9843
  console.log(import_chalk20.default.gray(` VITE_API_URL: ${workerData.api_domain}`));
9418
9844
  }
9419
- let pinmeConfig = import_fs_extra6.default.readFileSync(configPath, "utf-8");
9845
+ let pinmeConfig = import_fs_extra7.default.readFileSync(configPath, "utf-8");
9420
9846
  if (pinmeConfig.includes("api_url")) {
9421
9847
  pinmeConfig = pinmeConfig.replace(
9422
9848
  /api_url\s*=\s*"[^"]*"/,
@@ -9433,7 +9859,7 @@ Directory "${projectName}" already exists.`));
9433
9859
  }
9434
9860
  pinmeConfig = newLines.join("\n");
9435
9861
  }
9436
- import_fs_extra6.default.writeFileSync(configPath, pinmeConfig);
9862
+ import_fs_extra7.default.writeFileSync(configPath, pinmeConfig);
9437
9863
  console.log(import_chalk20.default.green(` Updated pinme.toml with api_url`));
9438
9864
  console.log(import_chalk20.default.blue("\n4. Installing dependencies in the background..."));
9439
9865
  try {
@@ -9446,27 +9872,27 @@ Directory "${projectName}" already exists.`));
9446
9872
  console.log(import_chalk20.default.yellow(" Run `npm install` inside the project before `pinme save`."));
9447
9873
  }
9448
9874
  console.log(import_chalk20.default.blue("\n5. Preparing backend worker..."));
9449
- const distWorkerDir = import_path12.default.join(targetDir, "dist-worker");
9450
- const workerJsPath = import_path12.default.join(distWorkerDir, "worker.js");
9451
- if (!import_fs_extra6.default.existsSync(distWorkerDir) || !import_fs_extra6.default.existsSync(workerJsPath)) {
9875
+ const distWorkerDir = import_path13.default.join(targetDir, "dist-worker");
9876
+ const workerJsPath = import_path13.default.join(distWorkerDir, "worker.js");
9877
+ if (!import_fs_extra7.default.existsSync(distWorkerDir) || !import_fs_extra7.default.existsSync(workerJsPath)) {
9452
9878
  throw createConfigError("Prebuilt worker output not found: `dist-worker/worker.js`.", [
9453
9879
  "The template should ship a prebuilt `dist-worker/`.",
9454
9880
  "Once dependencies finish installing, run `npm run build:worker` in the project, then `pinme save`."
9455
9881
  ]);
9456
9882
  }
9457
9883
  const modulePaths = [];
9458
- const files = import_fs_extra6.default.readdirSync(distWorkerDir);
9884
+ const files = import_fs_extra7.default.readdirSync(distWorkerDir);
9459
9885
  for (const file of files) {
9460
9886
  if (file.endsWith(".js") && file !== "worker.js") {
9461
- modulePaths.push(import_path12.default.join(distWorkerDir, file));
9887
+ modulePaths.push(import_path13.default.join(distWorkerDir, file));
9462
9888
  }
9463
9889
  }
9464
- const sqlDir = import_path12.default.join(targetDir, "db");
9890
+ const sqlDir = import_path13.default.join(targetDir, "db");
9465
9891
  const sqlFiles = [];
9466
- if (import_fs_extra6.default.existsSync(sqlDir)) {
9467
- const sqlFileNames = import_fs_extra6.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
9892
+ if (import_fs_extra7.default.existsSync(sqlDir)) {
9893
+ const sqlFileNames = import_fs_extra7.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
9468
9894
  for (const filename of sqlFileNames) {
9469
- sqlFiles.push(import_path12.default.join(sqlDir, filename));
9895
+ sqlFiles.push(import_path13.default.join(sqlDir, filename));
9470
9896
  console.log(import_chalk20.default.gray(` Including SQL: ${filename}`));
9471
9897
  }
9472
9898
  }
@@ -9477,24 +9903,23 @@ Directory "${projectName}" already exists.`));
9477
9903
  const FormData4 = (await import("formdata-node")).FormData;
9478
9904
  const Blob2 = (await import("formdata-node")).Blob;
9479
9905
  const formData = new FormData4();
9480
- const metadataContent = typeof workerData.metadata === "string" ? workerData.metadata : JSON.stringify(workerData.metadata, null, 2);
9481
- formData.append("metadata", new Blob2([metadataContent], {
9906
+ formData.append("metadata", new Blob2([workerMetadataContent], {
9482
9907
  type: "application/json"
9483
9908
  }), "metadata.json");
9484
- const workerCode = import_fs_extra6.default.readFileSync(workerJsPath, "utf-8");
9909
+ const workerCode = import_fs_extra7.default.readFileSync(workerJsPath, "utf-8");
9485
9910
  formData.append("worker.js", new Blob2([workerCode], {
9486
9911
  type: "application/javascript+module"
9487
9912
  }), "worker.js");
9488
9913
  for (const modulePath of modulePaths) {
9489
- const filename = import_path12.default.basename(modulePath);
9490
- const content = import_fs_extra6.default.readFileSync(modulePath, "utf-8");
9914
+ const filename = import_path13.default.basename(modulePath);
9915
+ const content = import_fs_extra7.default.readFileSync(modulePath, "utf-8");
9491
9916
  formData.append(filename, new Blob2([content], {
9492
9917
  type: "application/javascript+module"
9493
9918
  }), filename);
9494
9919
  }
9495
9920
  for (const sqlFile of sqlFiles) {
9496
- const filename = import_path12.default.basename(sqlFile);
9497
- const content = import_fs_extra6.default.readFileSync(sqlFile, "utf-8");
9921
+ const filename = import_path13.default.basename(sqlFile);
9922
+ const content = import_fs_extra7.default.readFileSync(sqlFile, "utf-8");
9498
9923
  formData.append("sql_file", new Blob2([content], {
9499
9924
  type: "application/sql"
9500
9925
  }), filename);
@@ -9527,15 +9952,20 @@ Directory "${projectName}" already exists.`));
9527
9952
  ]);
9528
9953
  }
9529
9954
  console.log(import_chalk20.default.blue("\n7. Preparing frontend..."));
9530
- const frontendDir = import_path12.default.join(targetDir, "frontend");
9531
- const frontendDistDir = import_path12.default.join(frontendDir, "dist");
9532
- if (import_fs_extra6.default.existsSync(frontendDir)) {
9533
- if (!import_fs_extra6.default.existsSync(frontendDistDir)) {
9955
+ const frontendDir = import_path13.default.join(targetDir, "frontend");
9956
+ const frontendDistDir = import_path13.default.join(frontendDir, "dist");
9957
+ if (import_fs_extra7.default.existsSync(frontendDir)) {
9958
+ if (!import_fs_extra7.default.existsSync(frontendDistDir)) {
9534
9959
  throw createConfigError("Prebuilt frontend output not found: `frontend/dist/`.", [
9535
9960
  "The template should ship a prebuilt `frontend/dist/`.",
9536
9961
  "Once dependencies finish installing, run `npm run build:frontend` in the project, then `pinme save`."
9537
9962
  ]);
9538
9963
  }
9964
+ const patchResult = patchPrebuiltFrontendDist(frontendDistDir, workerData);
9965
+ console.log(import_chalk20.default.green(" Patched prebuilt frontend dist config"));
9966
+ console.log(import_chalk20.default.gray(
9967
+ ` Replacements: API URL ${patchResult.apiUrlReplacements}, auth ${patchResult.authReplacements}`
9968
+ ));
9539
9969
  console.log(import_chalk20.default.blue(" Uploading to IPFS..."));
9540
9970
  try {
9541
9971
  const uploadResult = await uploadPath(frontendDistDir, {
@@ -9545,7 +9975,7 @@ Directory "${projectName}" already exists.`));
9545
9975
  });
9546
9976
  printHighlightedUrl("Frontend URL", uploadResult.publicUrl, "primary");
9547
9977
  updateFrontendUrlInConfig(
9548
- import_path12.default.join(targetDir, "pinme.toml"),
9978
+ import_path13.default.join(targetDir, "pinme.toml"),
9549
9979
  uploadResult.publicUrl
9550
9980
  );
9551
9981
  console.log(import_chalk20.default.green(" Updated pinme.toml with frontend URL"));
@@ -9598,8 +10028,8 @@ Next steps:`));
9598
10028
  // bin/save.ts
9599
10029
  var import_chalk21 = __toESM(require("chalk"));
9600
10030
  var import_ora3 = __toESM(require("ora"));
9601
- var import_fs_extra7 = __toESM(require("fs-extra"));
9602
- var import_path13 = __toESM(require("path"));
10031
+ var import_fs_extra8 = __toESM(require("fs-extra"));
10032
+ var import_path14 = __toESM(require("path"));
9603
10033
  init_axios2();
9604
10034
  var import_child_process5 = require("child_process");
9605
10035
  init_webLogin();
@@ -9609,14 +10039,14 @@ init_cliError();
9609
10039
  init_config();
9610
10040
  var PROJECT_DIR2 = process.cwd();
9611
10041
  function loadConfig() {
9612
- const configPath = import_path13.default.join(PROJECT_DIR2, "pinme.toml");
9613
- if (!import_fs_extra7.default.existsSync(configPath)) {
10042
+ const configPath = import_path14.default.join(PROJECT_DIR2, "pinme.toml");
10043
+ if (!import_fs_extra8.default.existsSync(configPath)) {
9614
10044
  throw createConfigError("`pinme.toml` not found in the current directory.", [
9615
10045
  "Run this command from the Pinme project root.",
9616
10046
  "If the project has not been initialized yet, create or restore `pinme.toml` first."
9617
10047
  ]);
9618
10048
  }
9619
- const configContent = import_fs_extra7.default.readFileSync(configPath, "utf-8");
10049
+ const configContent = import_fs_extra8.default.readFileSync(configPath, "utf-8");
9620
10050
  const projectNameMatch = configContent.match(/project_name\s*=\s*"([^"]+)"/);
9621
10051
  return {
9622
10052
  project_name: (projectNameMatch == null ? void 0 : projectNameMatch[1]) || ""
@@ -9626,12 +10056,12 @@ function getProjectManagementUrl2(projectName) {
9626
10056
  return `${APP_CONFIG.projectPeviewUrl}${projectName}`;
9627
10057
  }
9628
10058
  function getMetadata() {
9629
- const metadataPath = import_path13.default.join(PROJECT_DIR2, "backend", "metadata.json");
9630
- if (!import_fs_extra7.default.existsSync(metadataPath)) {
10059
+ const metadataPath = import_path14.default.join(PROJECT_DIR2, "backend", "metadata.json");
10060
+ if (!import_fs_extra8.default.existsSync(metadataPath)) {
9631
10061
  console.log(import_chalk21.default.yellow(" Warning: metadata.json not found, using empty metadata"));
9632
10062
  return {};
9633
10063
  }
9634
- return import_fs_extra7.default.readJsonSync(metadataPath);
10064
+ return import_fs_extra8.default.readJsonSync(metadataPath);
9635
10065
  }
9636
10066
  function buildWorker() {
9637
10067
  console.log(import_chalk21.default.blue("Building worker..."));
@@ -9653,11 +10083,11 @@ function buildWorker() {
9653
10083
  }
9654
10084
  }
9655
10085
  function dependenciesMissingError(summary, logTail) {
9656
- const installLogPath = import_path13.default.join(PROJECT_DIR2, ".pinme-install.log");
10086
+ const installLogPath = import_path14.default.join(PROJECT_DIR2, ".pinme-install.log");
9657
10087
  const suggestions = [
9658
10088
  "Run `npm install` in the project root, wait for it to finish, then rerun `pinme save`."
9659
10089
  ];
9660
- if (import_fs_extra7.default.existsSync(installLogPath)) {
10090
+ if (import_fs_extra8.default.existsSync(installLogPath)) {
9661
10091
  suggestions.push(
9662
10092
  `Background install log: ${installLogPath}`
9663
10093
  );
@@ -9684,10 +10114,10 @@ function isMissingDependencyError(error) {
9684
10114
  function dependenciesPresent() {
9685
10115
  return hasLocalBinary("wrangler") && hasLocalBinary("vite");
9686
10116
  }
9687
- function sleep(ms) {
10117
+ function sleep2(ms) {
9688
10118
  return new Promise((resolve) => setTimeout(resolve, ms));
9689
10119
  }
9690
- var WAIT_FOR_INSTALL_TIMEOUT_MS = 12 * 60 * 1e3;
10120
+ var WAIT_FOR_INSTALL_TIMEOUT_MS = 15 * 1e3;
9691
10121
  var WAIT_POLL_INTERVAL_MS = 2e3;
9692
10122
  async function ensureDependenciesReady() {
9693
10123
  if (dependenciesPresent()) {
@@ -9696,20 +10126,25 @@ async function ensureDependenciesReady() {
9696
10126
  }
9697
10127
  const initial = readBackgroundInstallStatus(PROJECT_DIR2);
9698
10128
  if (initial.status === "idle") {
9699
- throw dependenciesMissingError(
9700
- "Project dependencies are not installed and no install is running."
9701
- );
10129
+ await installDependenciesInForeground();
10130
+ return;
9702
10131
  }
9703
10132
  if (initial.status === "failed") {
9704
- throw dependenciesMissingError(
9705
- `The background dependency install (started by \`pinme create\`) failed with exit code ${initial.exitCode}.`,
9706
- readBackgroundInstallLogTail(PROJECT_DIR2)
9707
- );
10133
+ console.log(import_chalk21.default.yellow(
10134
+ `Background dependency install failed with exit code ${initial.exitCode}. Retrying in this terminal...`
10135
+ ));
10136
+ await installDependenciesInForeground();
10137
+ return;
10138
+ }
10139
+ if (initial.status === "interrupted") {
10140
+ console.log(import_chalk21.default.yellow("Background dependency install was interrupted. Continuing in this terminal..."));
10141
+ await installDependenciesInForeground();
10142
+ return;
9708
10143
  }
9709
- const spinner = (0, import_ora3.default)("Waiting for background dependency install to finish...").start();
10144
+ const spinner = (0, import_ora3.default)("Waiting briefly for background dependency install...").start();
9710
10145
  const startedAt = Date.now();
9711
10146
  while (true) {
9712
- await sleep(WAIT_POLL_INTERVAL_MS);
10147
+ await sleep2(WAIT_POLL_INTERVAL_MS);
9713
10148
  if (dependenciesPresent()) {
9714
10149
  spinner.succeed("Dependencies installed.");
9715
10150
  return;
@@ -9717,10 +10152,16 @@ async function ensureDependenciesReady() {
9717
10152
  const state = readBackgroundInstallStatus(PROJECT_DIR2);
9718
10153
  if (state.status === "failed") {
9719
10154
  spinner.fail("Background dependency install failed.");
9720
- throw dependenciesMissingError(
9721
- `The background dependency install (started by \`pinme create\`) failed with exit code ${state.exitCode}.`,
9722
- readBackgroundInstallLogTail(PROJECT_DIR2)
9723
- );
10155
+ console.log(import_chalk21.default.yellow(
10156
+ `Retrying dependency install in this terminal after exit code ${state.exitCode}...`
10157
+ ));
10158
+ await installDependenciesInForeground();
10159
+ return;
10160
+ }
10161
+ if (state.status === "interrupted") {
10162
+ spinner.fail("Background dependency install was interrupted.");
10163
+ await installDependenciesInForeground();
10164
+ return;
9724
10165
  }
9725
10166
  if (state.status === "success") {
9726
10167
  spinner.succeed("Dependencies installed.");
@@ -9728,60 +10169,79 @@ async function ensureDependenciesReady() {
9728
10169
  }
9729
10170
  const elapsedMs = Date.now() - startedAt;
9730
10171
  if (elapsedMs > WAIT_FOR_INSTALL_TIMEOUT_MS) {
9731
- spinner.fail("Timed out waiting for the dependency install.");
9732
- throw dependenciesMissingError(
9733
- "Timed out waiting for the background dependency install to finish.",
9734
- readBackgroundInstallLogTail(PROJECT_DIR2)
9735
- );
10172
+ spinner.warn("Background dependency install is not ready yet; continuing in this terminal.");
10173
+ await stopBackgroundInstall(PROJECT_DIR2);
10174
+ await installDependenciesInForeground();
10175
+ return;
9736
10176
  }
9737
- spinner.text = `Waiting for background dependency install to finish... (${Math.round(elapsedMs / 1e3)}s)`;
10177
+ spinner.text = `Waiting briefly for background dependency install... (${Math.round(elapsedMs / 1e3)}s)`;
10178
+ }
10179
+ }
10180
+ async function installDependenciesInForeground() {
10181
+ console.log(import_chalk21.default.blue("Installing project dependencies..."));
10182
+ try {
10183
+ await stopBackgroundInstall(PROJECT_DIR2);
10184
+ await installProjectDependencies(PROJECT_DIR2);
10185
+ } catch (error) {
10186
+ throw dependenciesMissingError(
10187
+ "Project dependency install failed.",
10188
+ readBackgroundInstallLogTail(PROJECT_DIR2) || (error == null ? void 0 : error.message)
10189
+ );
10190
+ }
10191
+ if (!dependenciesPresent()) {
10192
+ throw dependenciesMissingError(
10193
+ "Project dependencies were installed, but required build CLIs are still missing.",
10194
+ readBackgroundInstallLogTail(PROJECT_DIR2)
10195
+ );
9738
10196
  }
10197
+ console.log(import_chalk21.default.green("Project dependencies installed."));
9739
10198
  }
9740
10199
  function cleanupInstallMarkers() {
9741
10200
  try {
9742
- import_fs_extra7.default.removeSync(import_path13.default.join(PROJECT_DIR2, INSTALL_LOG_FILE));
9743
- import_fs_extra7.default.removeSync(import_path13.default.join(PROJECT_DIR2, INSTALL_EXITCODE_FILE));
10201
+ import_fs_extra8.default.removeSync(import_path14.default.join(PROJECT_DIR2, INSTALL_LOG_FILE));
10202
+ import_fs_extra8.default.removeSync(import_path14.default.join(PROJECT_DIR2, INSTALL_EXITCODE_FILE));
10203
+ import_fs_extra8.default.removeSync(import_path14.default.join(PROJECT_DIR2, INSTALL_PID_FILE));
9744
10204
  } catch {
9745
10205
  }
9746
10206
  }
9747
10207
  function hasLocalBinary(name) {
9748
10208
  const binDirs = [
9749
- import_path13.default.join(PROJECT_DIR2, "node_modules", ".bin"),
9750
- import_path13.default.join(PROJECT_DIR2, "backend", "node_modules", ".bin"),
9751
- import_path13.default.join(PROJECT_DIR2, "frontend", "node_modules", ".bin")
10209
+ import_path14.default.join(PROJECT_DIR2, "node_modules", ".bin"),
10210
+ import_path14.default.join(PROJECT_DIR2, "backend", "node_modules", ".bin"),
10211
+ import_path14.default.join(PROJECT_DIR2, "frontend", "node_modules", ".bin")
9752
10212
  ];
9753
10213
  const candidates = process.platform === "win32" ? [name, `${name}.cmd`, `${name}.exe`, `${name}.ps1`] : [name];
9754
- return binDirs.some((dir) => candidates.some((candidate) => import_fs_extra7.default.existsSync(import_path13.default.join(dir, candidate))));
10214
+ return binDirs.some((dir) => candidates.some((candidate) => import_fs_extra8.default.existsSync(import_path14.default.join(dir, candidate))));
9755
10215
  }
9756
10216
  function getBuiltWorker() {
9757
- const distWorkerDir = import_path13.default.join(PROJECT_DIR2, "dist-worker");
9758
- if (!import_fs_extra7.default.existsSync(distWorkerDir)) {
10217
+ const distWorkerDir = import_path14.default.join(PROJECT_DIR2, "dist-worker");
10218
+ if (!import_fs_extra8.default.existsSync(distWorkerDir)) {
9759
10219
  throw createConfigError("Built worker output not found: `dist-worker/`.", [
9760
10220
  "Make sure `npm run build:worker` completed successfully."
9761
10221
  ]);
9762
10222
  }
9763
- const workerJsPath = import_path13.default.join(distWorkerDir, "worker.js");
9764
- if (!import_fs_extra7.default.existsSync(workerJsPath)) {
10223
+ const workerJsPath = import_path14.default.join(distWorkerDir, "worker.js");
10224
+ if (!import_fs_extra8.default.existsSync(workerJsPath)) {
9765
10225
  throw createConfigError("Built worker entry file not found: `dist-worker/worker.js`.", [
9766
10226
  "Check the worker build output and bundler config."
9767
10227
  ]);
9768
10228
  }
9769
10229
  const modulePaths = [];
9770
- const files = import_fs_extra7.default.readdirSync(distWorkerDir);
10230
+ const files = import_fs_extra8.default.readdirSync(distWorkerDir);
9771
10231
  for (const file of files) {
9772
10232
  if (file.endsWith(".js") && file !== "worker.js") {
9773
- modulePaths.push(import_path13.default.join(distWorkerDir, file));
10233
+ modulePaths.push(import_path14.default.join(distWorkerDir, file));
9774
10234
  }
9775
10235
  }
9776
10236
  return { workerJsPath, modulePaths };
9777
10237
  }
9778
10238
  function getSqlFiles() {
9779
- const sqlDir = import_path13.default.join(PROJECT_DIR2, "db");
9780
- if (!import_fs_extra7.default.existsSync(sqlDir)) {
10239
+ const sqlDir = import_path14.default.join(PROJECT_DIR2, "db");
10240
+ if (!import_fs_extra8.default.existsSync(sqlDir)) {
9781
10241
  return [];
9782
10242
  }
9783
- const files = import_fs_extra7.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
9784
- return files.map((f) => import_path13.default.join(sqlDir, f));
10243
+ const files = import_fs_extra8.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
10244
+ return files.map((f) => import_path14.default.join(sqlDir, f));
9785
10245
  }
9786
10246
  async function saveWorker(workerJsPath, modulePaths, sqlFiles, metadata, projectName) {
9787
10247
  var _a2, _b;
@@ -9801,20 +10261,20 @@ async function saveWorker(workerJsPath, modulePaths, sqlFiles, metadata, project
9801
10261
  formData.append("metadata", new Blob2([JSON.stringify(metadata)], {
9802
10262
  type: "application/json"
9803
10263
  }), "metadata.json");
9804
- const workerCode = import_fs_extra7.default.readFileSync(workerJsPath, "utf-8");
10264
+ const workerCode = import_fs_extra8.default.readFileSync(workerJsPath, "utf-8");
9805
10265
  formData.append("worker.js", new Blob2([workerCode], {
9806
10266
  type: "application/javascript+module"
9807
10267
  }), "worker.js");
9808
10268
  for (const modulePath of modulePaths) {
9809
- const filename = import_path13.default.basename(modulePath);
9810
- const content = import_fs_extra7.default.readFileSync(modulePath, "utf-8");
10269
+ const filename = import_path14.default.basename(modulePath);
10270
+ const content = import_fs_extra8.default.readFileSync(modulePath, "utf-8");
9811
10271
  formData.append(filename, new Blob2([content], {
9812
10272
  type: "application/javascript+module"
9813
10273
  }), filename);
9814
10274
  }
9815
10275
  for (const sqlFile of sqlFiles) {
9816
- const filename = import_path13.default.basename(sqlFile);
9817
- const content = import_fs_extra7.default.readFileSync(sqlFile, "utf-8");
10276
+ const filename = import_path14.default.basename(sqlFile);
10277
+ const content = import_fs_extra8.default.readFileSync(sqlFile, "utf-8");
9818
10278
  formData.append("sql_file", new Blob2([content], {
9819
10279
  type: "application/sql"
9820
10280
  }), filename);
@@ -9869,7 +10329,7 @@ function buildFrontend() {
9869
10329
  }
9870
10330
  }
9871
10331
  function updateFrontendUrlInConfig2(configPath, frontendUrl) {
9872
- let config = import_fs_extra7.default.readFileSync(configPath, "utf-8");
10332
+ let config = import_fs_extra8.default.readFileSync(configPath, "utf-8");
9873
10333
  if (config.includes("frontend_url")) {
9874
10334
  config = config.replace(
9875
10335
  /frontend_url\s*=\s*"[^"]*"/,
@@ -9882,18 +10342,18 @@ function updateFrontendUrlInConfig2(configPath, frontendUrl) {
9882
10342
  `
9883
10343
  );
9884
10344
  }
9885
- import_fs_extra7.default.writeFileSync(configPath, config);
10345
+ import_fs_extra8.default.writeFileSync(configPath, config);
9886
10346
  }
9887
10347
  async function deployFrontend(projectName) {
9888
10348
  console.log(import_chalk21.default.blue("Deploying frontend to IPFS..."));
9889
10349
  try {
9890
10350
  const headers = getAuthHeaders();
9891
- const uploadResult = await uploadPath(import_path13.default.join(PROJECT_DIR2, "frontend", "dist"), {
10351
+ const uploadResult = await uploadPath(import_path14.default.join(PROJECT_DIR2, "frontend", "dist"), {
9892
10352
  action: "project_save",
9893
10353
  projectName,
9894
10354
  uid: headers["token-address"]
9895
10355
  });
9896
- updateFrontendUrlInConfig2(import_path13.default.join(PROJECT_DIR2, "pinme.toml"), uploadResult.publicUrl);
10356
+ updateFrontendUrlInConfig2(import_path14.default.join(PROJECT_DIR2, "pinme.toml"), uploadResult.publicUrl);
9897
10357
  return {
9898
10358
  contentHash: uploadResult.contentHash,
9899
10359
  publicUrl: uploadResult.publicUrl
@@ -9943,11 +10403,11 @@ async function saveCmd(options) {
9943
10403
  "Run `pinme login` and retry."
9944
10404
  ]);
9945
10405
  }
9946
- const projectDir = options.projectName || options.name ? import_path13.default.join(PROJECT_DIR2, options.projectName || options.name) : PROJECT_DIR2;
9947
- const tokenFileSrc = import_path13.default.join(PROJECT_DIR2, ".token.json");
9948
- const tokenFileDst = import_path13.default.join(projectDir, ".token.json");
9949
- if (import_fs_extra7.default.existsSync(tokenFileSrc) && !import_fs_extra7.default.existsSync(tokenFileDst)) {
9950
- import_fs_extra7.default.copySync(tokenFileSrc, tokenFileDst);
10406
+ const projectDir = options.projectName || options.name ? import_path14.default.join(PROJECT_DIR2, options.projectName || options.name) : PROJECT_DIR2;
10407
+ const tokenFileSrc = import_path14.default.join(PROJECT_DIR2, ".token.json");
10408
+ const tokenFileDst = import_path14.default.join(projectDir, ".token.json");
10409
+ if (import_fs_extra8.default.existsSync(tokenFileSrc) && !import_fs_extra8.default.existsSync(tokenFileDst)) {
10410
+ import_fs_extra8.default.copySync(tokenFileSrc, tokenFileDst);
9951
10411
  }
9952
10412
  console.log(import_chalk21.default.blue("Deploying to platform...\n"));
9953
10413
  console.log(import_chalk21.default.gray(`Project dir: ${PROJECT_DIR2}`));
@@ -10013,40 +10473,40 @@ async function saveCmd(options) {
10013
10473
 
10014
10474
  // bin/updateDb.ts
10015
10475
  var import_chalk22 = __toESM(require("chalk"));
10016
- var import_fs_extra8 = __toESM(require("fs-extra"));
10017
- var import_path14 = __toESM(require("path"));
10476
+ var import_fs_extra9 = __toESM(require("fs-extra"));
10477
+ var import_path15 = __toESM(require("path"));
10018
10478
  init_axios2();
10019
10479
  init_webLogin();
10020
10480
  init_cliError();
10021
10481
  init_config();
10022
10482
  var PROJECT_DIR3 = process.cwd();
10023
10483
  function loadConfig2() {
10024
- const configPath = import_path14.default.join(PROJECT_DIR3, "pinme.toml");
10025
- if (!import_fs_extra8.default.existsSync(configPath)) {
10484
+ const configPath = import_path15.default.join(PROJECT_DIR3, "pinme.toml");
10485
+ if (!import_fs_extra9.default.existsSync(configPath)) {
10026
10486
  throw createConfigError("`pinme.toml` not found in the current directory.", [
10027
10487
  "Run this command from the Pinme project root."
10028
10488
  ]);
10029
10489
  }
10030
- const configContent = import_fs_extra8.default.readFileSync(configPath, "utf-8");
10490
+ const configContent = import_fs_extra9.default.readFileSync(configPath, "utf-8");
10031
10491
  const projectNameMatch = configContent.match(/project_name\s*=\s*"([^"]+)"/);
10032
10492
  return {
10033
10493
  project_name: (projectNameMatch == null ? void 0 : projectNameMatch[1]) || ""
10034
10494
  };
10035
10495
  }
10036
10496
  function getSqlFiles2() {
10037
- const sqlDir = import_path14.default.join(PROJECT_DIR3, "db");
10038
- if (!import_fs_extra8.default.existsSync(sqlDir)) {
10497
+ const sqlDir = import_path15.default.join(PROJECT_DIR3, "db");
10498
+ if (!import_fs_extra9.default.existsSync(sqlDir)) {
10039
10499
  throw createConfigError("SQL directory not found: `db/`.", [
10040
10500
  "Create a `db/` directory and add at least one `.sql` migration file."
10041
10501
  ]);
10042
10502
  }
10043
- const files = import_fs_extra8.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
10503
+ const files = import_fs_extra9.default.readdirSync(sqlDir).filter((f) => f.endsWith(".sql")).sort();
10044
10504
  if (files.length === 0) {
10045
10505
  throw createConfigError("No `.sql` files were found in `db/`.", [
10046
10506
  "Add one or more migration files before running `pinme update-db`."
10047
10507
  ]);
10048
10508
  }
10049
- return files.map((f) => import_path14.default.join(sqlDir, f));
10509
+ return files.map((f) => import_path15.default.join(sqlDir, f));
10050
10510
  }
10051
10511
  async function updateDb(sqlFiles, projectName) {
10052
10512
  console.log(import_chalk22.default.blue("Importing SQL files to database..."));
@@ -10061,8 +10521,8 @@ async function updateDb(sqlFiles, projectName) {
10061
10521
  const formData = new FormData4();
10062
10522
  let totalSize = 0;
10063
10523
  for (const sqlFile of sqlFiles) {
10064
- const filename = import_path14.default.basename(sqlFile);
10065
- const content = import_fs_extra8.default.readFileSync(sqlFile);
10524
+ const filename = import_path15.default.basename(sqlFile);
10525
+ const content = import_fs_extra9.default.readFileSync(sqlFile);
10066
10526
  totalSize += content.length;
10067
10527
  if (totalSize > 10 * 1024 * 1024) {
10068
10528
  throw createConfigError("Total SQL payload exceeds the 10MB platform limit.", [
@@ -10117,11 +10577,11 @@ async function updateDbCmd(options) {
10117
10577
  "Run `pinme login` and retry."
10118
10578
  ]);
10119
10579
  }
10120
- 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;
10121
- const tokenFileSrc = import_path14.default.join(PROJECT_DIR3, ".token.json");
10122
- const tokenFileDst = import_path14.default.join(projectDir, ".token.json");
10123
- if (import_fs_extra8.default.existsSync(tokenFileSrc) && !import_fs_extra8.default.existsSync(tokenFileDst)) {
10124
- import_fs_extra8.default.copySync(tokenFileSrc, tokenFileDst);
10580
+ const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path15.default.join(PROJECT_DIR3, options.projectName || options.name) : PROJECT_DIR3;
10581
+ const tokenFileSrc = import_path15.default.join(PROJECT_DIR3, ".token.json");
10582
+ const tokenFileDst = import_path15.default.join(projectDir, ".token.json");
10583
+ if (import_fs_extra9.default.existsSync(tokenFileSrc) && !import_fs_extra9.default.existsSync(tokenFileDst)) {
10584
+ import_fs_extra9.default.copySync(tokenFileSrc, tokenFileDst);
10125
10585
  }
10126
10586
  console.log(import_chalk22.default.blue("Importing SQL to database...\n"));
10127
10587
  console.log(import_chalk22.default.gray(`Project dir: ${PROJECT_DIR3}`));
@@ -10164,8 +10624,8 @@ async function updateDbCmd(options) {
10164
10624
 
10165
10625
  // bin/updateWorker.ts
10166
10626
  var import_chalk23 = __toESM(require("chalk"));
10167
- var import_fs_extra9 = __toESM(require("fs-extra"));
10168
- var import_path15 = __toESM(require("path"));
10627
+ var import_fs_extra10 = __toESM(require("fs-extra"));
10628
+ var import_path16 = __toESM(require("path"));
10169
10629
  init_axios2();
10170
10630
  var import_child_process6 = require("child_process");
10171
10631
  init_webLogin();
@@ -10173,26 +10633,26 @@ init_cliError();
10173
10633
  init_config();
10174
10634
  var PROJECT_DIR4 = process.cwd();
10175
10635
  function loadConfig3() {
10176
- const configPath = import_path15.default.join(PROJECT_DIR4, "pinme.toml");
10177
- if (!import_fs_extra9.default.existsSync(configPath)) {
10636
+ const configPath = import_path16.default.join(PROJECT_DIR4, "pinme.toml");
10637
+ if (!import_fs_extra10.default.existsSync(configPath)) {
10178
10638
  throw createConfigError("`pinme.toml` not found in the current directory.", [
10179
10639
  "Run this command from the Pinme project root."
10180
10640
  ]);
10181
10641
  }
10182
- const configContent = import_fs_extra9.default.readFileSync(configPath, "utf-8");
10642
+ const configContent = import_fs_extra10.default.readFileSync(configPath, "utf-8");
10183
10643
  const projectNameMatch = configContent.match(/project_name\s*=\s*"([^"]+)"/);
10184
10644
  return {
10185
10645
  project_name: (projectNameMatch == null ? void 0 : projectNameMatch[1]) || ""
10186
10646
  };
10187
10647
  }
10188
10648
  function getMetadata2() {
10189
- const metadataPath = import_path15.default.join(PROJECT_DIR4, "backend", "metadata.json");
10190
- if (!import_fs_extra9.default.existsSync(metadataPath)) {
10649
+ const metadataPath = import_path16.default.join(PROJECT_DIR4, "backend", "metadata.json");
10650
+ if (!import_fs_extra10.default.existsSync(metadataPath)) {
10191
10651
  throw createConfigError("`backend/metadata.json` not found.", [
10192
10652
  "Create `backend/metadata.json` or restore it from the project template."
10193
10653
  ]);
10194
10654
  }
10195
- return import_fs_extra9.default.readJsonSync(metadataPath);
10655
+ return import_fs_extra10.default.readJsonSync(metadataPath);
10196
10656
  }
10197
10657
  function buildWorker2() {
10198
10658
  console.log(import_chalk23.default.blue("Building worker..."));
@@ -10209,23 +10669,23 @@ function buildWorker2() {
10209
10669
  }
10210
10670
  }
10211
10671
  function getBuiltWorker2() {
10212
- const distWorkerDir = import_path15.default.join(PROJECT_DIR4, "dist-worker");
10213
- if (!import_fs_extra9.default.existsSync(distWorkerDir)) {
10672
+ const distWorkerDir = import_path16.default.join(PROJECT_DIR4, "dist-worker");
10673
+ if (!import_fs_extra10.default.existsSync(distWorkerDir)) {
10214
10674
  throw createConfigError("Built worker output not found: `dist-worker/`.", [
10215
10675
  "Make sure `npm run build:worker` completed successfully."
10216
10676
  ]);
10217
10677
  }
10218
- const workerJsPath = import_path15.default.join(distWorkerDir, "worker.js");
10219
- if (!import_fs_extra9.default.existsSync(workerJsPath)) {
10678
+ const workerJsPath = import_path16.default.join(distWorkerDir, "worker.js");
10679
+ if (!import_fs_extra10.default.existsSync(workerJsPath)) {
10220
10680
  throw createConfigError("Built worker entry file not found: `dist-worker/worker.js`.", [
10221
10681
  "Check the worker build output and bundler config."
10222
10682
  ]);
10223
10683
  }
10224
10684
  const modulePaths = [];
10225
- const files = import_fs_extra9.default.readdirSync(distWorkerDir);
10685
+ const files = import_fs_extra10.default.readdirSync(distWorkerDir);
10226
10686
  for (const file of files) {
10227
10687
  if (file.endsWith(".js") && file !== "worker.js") {
10228
- modulePaths.push(import_path15.default.join(distWorkerDir, file));
10688
+ modulePaths.push(import_path16.default.join(distWorkerDir, file));
10229
10689
  }
10230
10690
  }
10231
10691
  return { workerJsPath, modulePaths };
@@ -10246,13 +10706,13 @@ async function updateWorker(workerJsPath, modulePaths, metadata, projectName) {
10246
10706
  formData.append("metadata", new Blob2([JSON.stringify(metadata)], {
10247
10707
  type: "application/json"
10248
10708
  }), "metadata.json");
10249
- const workerCode = import_fs_extra9.default.readFileSync(workerJsPath, "utf-8");
10709
+ const workerCode = import_fs_extra10.default.readFileSync(workerJsPath, "utf-8");
10250
10710
  formData.append("worker.js", new Blob2([workerCode], {
10251
10711
  type: "application/javascript+module"
10252
10712
  }), "worker.js");
10253
10713
  for (const modulePath of modulePaths) {
10254
- const filename = import_path15.default.basename(modulePath);
10255
- const content = import_fs_extra9.default.readFileSync(modulePath, "utf-8");
10714
+ const filename = import_path16.default.basename(modulePath);
10715
+ const content = import_fs_extra10.default.readFileSync(modulePath, "utf-8");
10256
10716
  formData.append(filename, new Blob2([content], {
10257
10717
  type: "application/javascript+module"
10258
10718
  }), filename);
@@ -10314,11 +10774,11 @@ async function updateWorkerCmd(options) {
10314
10774
  "Run `pinme login` and retry."
10315
10775
  ]);
10316
10776
  }
10317
- 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;
10318
- const tokenFileSrc = import_path15.default.join(PROJECT_DIR4, ".token.json");
10319
- const tokenFileDst = import_path15.default.join(projectDir, ".token.json");
10320
- if (import_fs_extra9.default.existsSync(tokenFileSrc) && !import_fs_extra9.default.existsSync(tokenFileDst)) {
10321
- import_fs_extra9.default.copySync(tokenFileSrc, tokenFileDst);
10777
+ const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path16.default.join(PROJECT_DIR4, options.projectName || options.name) : PROJECT_DIR4;
10778
+ const tokenFileSrc = import_path16.default.join(PROJECT_DIR4, ".token.json");
10779
+ const tokenFileDst = import_path16.default.join(projectDir, ".token.json");
10780
+ if (import_fs_extra10.default.existsSync(tokenFileSrc) && !import_fs_extra10.default.existsSync(tokenFileDst)) {
10781
+ import_fs_extra10.default.copySync(tokenFileSrc, tokenFileDst);
10322
10782
  }
10323
10783
  console.log(import_chalk23.default.blue("Updating worker...\n"));
10324
10784
  console.log(import_chalk23.default.gray(`Project dir: ${PROJECT_DIR4}`));
@@ -10366,21 +10826,21 @@ async function updateWorkerCmd(options) {
10366
10826
 
10367
10827
  // bin/updateWeb.ts
10368
10828
  var import_chalk24 = __toESM(require("chalk"));
10369
- var import_fs_extra10 = __toESM(require("fs-extra"));
10370
- var import_path16 = __toESM(require("path"));
10829
+ var import_fs_extra11 = __toESM(require("fs-extra"));
10830
+ var import_path17 = __toESM(require("path"));
10371
10831
  var import_child_process7 = require("child_process");
10372
10832
  init_webLogin();
10373
10833
  init_cliError();
10374
10834
  init_config();
10375
10835
  var PROJECT_DIR5 = process.cwd();
10376
10836
  function loadConfig4() {
10377
- const configPath = import_path16.default.join(PROJECT_DIR5, "pinme.toml");
10378
- if (!import_fs_extra10.default.existsSync(configPath)) {
10837
+ const configPath = import_path17.default.join(PROJECT_DIR5, "pinme.toml");
10838
+ if (!import_fs_extra11.default.existsSync(configPath)) {
10379
10839
  throw createConfigError("`pinme.toml` not found in the current directory.", [
10380
10840
  "Run this command from the Pinme project root."
10381
10841
  ]);
10382
10842
  }
10383
- const configContent = import_fs_extra10.default.readFileSync(configPath, "utf-8");
10843
+ const configContent = import_fs_extra11.default.readFileSync(configPath, "utf-8");
10384
10844
  const projectNameMatch = configContent.match(/project_name\s*=\s*"([^"]+)"/);
10385
10845
  return {
10386
10846
  project_name: (projectNameMatch == null ? void 0 : projectNameMatch[1]) || ""
@@ -10407,7 +10867,7 @@ async function deployFrontend2(projectName) {
10407
10867
  console.log(import_chalk24.default.blue("Deploying frontend to IPFS..."));
10408
10868
  try {
10409
10869
  const headers = getAuthHeaders();
10410
- const uploadResult = await uploadPath(import_path16.default.join(PROJECT_DIR5, "frontend", "dist"), {
10870
+ const uploadResult = await uploadPath(import_path17.default.join(PROJECT_DIR5, "frontend", "dist"), {
10411
10871
  action: "project_update_web",
10412
10872
  projectName,
10413
10873
  uid: headers["token-address"]
@@ -10432,11 +10892,11 @@ async function updateWebCmd(options) {
10432
10892
  "Run `pinme login` and retry."
10433
10893
  ]);
10434
10894
  }
10435
- 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;
10436
- const tokenFileSrc = import_path16.default.join(PROJECT_DIR5, ".token.json");
10437
- const tokenFileDst = import_path16.default.join(projectDir, ".token.json");
10438
- if (import_fs_extra10.default.existsSync(tokenFileSrc) && !import_fs_extra10.default.existsSync(tokenFileDst)) {
10439
- import_fs_extra10.default.copySync(tokenFileSrc, tokenFileDst);
10895
+ const projectDir = (options == null ? void 0 : options.projectName) || (options == null ? void 0 : options.name) ? import_path17.default.join(PROJECT_DIR5, options.projectName || options.name) : PROJECT_DIR5;
10896
+ const tokenFileSrc = import_path17.default.join(PROJECT_DIR5, ".token.json");
10897
+ const tokenFileDst = import_path17.default.join(projectDir, ".token.json");
10898
+ if (import_fs_extra11.default.existsSync(tokenFileSrc) && !import_fs_extra11.default.existsSync(tokenFileDst)) {
10899
+ import_fs_extra11.default.copySync(tokenFileSrc, tokenFileDst);
10440
10900
  }
10441
10901
  console.log(import_chalk24.default.blue("Updating web (frontend)...\n"));
10442
10902
  console.log(import_chalk24.default.gray(`Project dir: ${PROJECT_DIR5}`));
@@ -10480,16 +10940,16 @@ async function updateWebCmd(options) {
10480
10940
  var import_chalk25 = __toESM(require("chalk"));
10481
10941
  var import_inquirer9 = __toESM(require("inquirer"));
10482
10942
  init_axios2();
10483
- var import_fs_extra11 = __toESM(require("fs-extra"));
10484
- var import_path17 = __toESM(require("path"));
10943
+ var import_fs_extra12 = __toESM(require("fs-extra"));
10944
+ var import_path18 = __toESM(require("path"));
10485
10945
  init_webLogin();
10486
10946
  init_config();
10487
10947
  function getProjectName() {
10488
- const configPath = import_path17.default.join(process.cwd(), "pinme.toml");
10489
- if (!import_fs_extra11.default.existsSync(configPath)) {
10948
+ const configPath = import_path18.default.join(process.cwd(), "pinme.toml");
10949
+ if (!import_fs_extra12.default.existsSync(configPath)) {
10490
10950
  return null;
10491
10951
  }
10492
- const config = import_fs_extra11.default.readFileSync(configPath, "utf-8");
10952
+ const config = import_fs_extra12.default.readFileSync(configPath, "utf-8");
10493
10953
  const match = config.match(/project_name\s*=\s*"([^"]+)"/);
10494
10954
  return (match == null ? void 0 : match[1]) || null;
10495
10955
  }