pinme 2.0.9-beta.1 → 2.0.9-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 +162 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -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-beta.1";
5981
+ var version = "2.0.9-beta.2";
5982
5982
 
5983
5983
  // bin/upload.ts
5984
5984
  var import_path7 = __toESM(require("path"));
@@ -9069,6 +9069,8 @@ var import_chalk19 = __toESM(require("chalk"));
9069
9069
  var import_child_process3 = require("child_process");
9070
9070
  var INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
9071
9071
  var SLOW_INSTALL_NOTICE_MS = 60 * 1e3;
9072
+ var INSTALL_LOG_FILE = ".pinme-install.log";
9073
+ var INSTALL_EXITCODE_FILE = ".pinme-install.exitcode";
9072
9074
  function makeTempCacheDir() {
9073
9075
  return import_fs_extra5.default.mkdtempSync(import_path11.default.join(import_os5.default.tmpdir(), "pinme-npm-cache-"));
9074
9076
  }
@@ -9101,22 +9103,40 @@ function getInstallArgs(script, cacheDir) {
9101
9103
  "--fetch-timeout=60000"
9102
9104
  ];
9103
9105
  }
9106
+ function quoteForShell(value) {
9107
+ if (process.platform === "win32") {
9108
+ return `"${value}"`;
9109
+ }
9110
+ return `'${value.replace(/'/g, `'\\''`)}'`;
9111
+ }
9104
9112
  function startBackgroundInstall(cwd) {
9105
- const npm = getNpmCommand();
9106
9113
  const script = getInstallScript(cwd, "auto");
9107
9114
  const cacheDir = makeTempCacheDir();
9108
9115
  const args = getInstallArgs(script, cacheDir);
9109
- const logPath = import_path11.default.join(cwd, ".pinme-install.log");
9110
- const header = `
9111
- [pinme] ${(/* @__PURE__ */ new Date()).toISOString()} starting "npm ${script}"
9112
- `;
9113
- import_fs_extra5.default.writeFileSync(logPath, header);
9114
- const logFd = import_fs_extra5.default.openSync(logPath, "a");
9115
- const child = (0, import_child_process3.spawn)(npm, args, {
9116
+ const logPath = import_path11.default.join(cwd, INSTALL_LOG_FILE);
9117
+ const exitCodePath = import_path11.default.join(cwd, INSTALL_EXITCODE_FILE);
9118
+ import_fs_extra5.default.removeSync(exitCodePath);
9119
+ import_fs_extra5.default.writeFileSync(logPath, `[pinme] ${(/* @__PURE__ */ new Date()).toISOString()} starting "npm ${script}"
9120
+ `);
9121
+ const npmCmd = process.platform === "win32" ? "npm" : getNpmCommand();
9122
+ const installCmd = `${npmCmd} ${args.map(quoteForShell).join(" ")}`;
9123
+ const qLog = quoteForShell(logPath);
9124
+ const qExit = quoteForShell(exitCodePath);
9125
+ let shellBin;
9126
+ let shellArgs;
9127
+ if (process.platform === "win32") {
9128
+ const command = `${installCmd} >> ${qLog} 2>&1 & echo %errorlevel% > ${qExit}`;
9129
+ shellBin = process.env.ComSpec || "cmd.exe";
9130
+ shellArgs = ["/d", "/s", "/c", command];
9131
+ } else {
9132
+ const command = `${installCmd} >> ${qLog} 2>&1; printf '%s' "$?" > ${qExit}`;
9133
+ shellBin = "/bin/sh";
9134
+ shellArgs = ["-c", command];
9135
+ }
9136
+ const child = (0, import_child_process3.spawn)(shellBin, shellArgs, {
9116
9137
  cwd,
9117
9138
  detached: true,
9118
- stdio: ["ignore", logFd, logFd],
9119
- shell: true,
9139
+ stdio: "ignore",
9120
9140
  env: {
9121
9141
  ...process.env,
9122
9142
  npm_config_cache: cacheDir,
@@ -9129,10 +9149,33 @@ function startBackgroundInstall(cwd) {
9129
9149
  npm_config_fetch_timeout: "60000"
9130
9150
  }
9131
9151
  });
9132
- import_fs_extra5.default.closeSync(logFd);
9133
9152
  child.unref();
9134
9153
  return { logPath };
9135
9154
  }
9155
+ function readBackgroundInstallStatus(cwd) {
9156
+ const logPath = import_path11.default.join(cwd, INSTALL_LOG_FILE);
9157
+ const exitCodePath = import_path11.default.join(cwd, INSTALL_EXITCODE_FILE);
9158
+ if (import_fs_extra5.default.existsSync(exitCodePath)) {
9159
+ const raw = import_fs_extra5.default.readFileSync(exitCodePath, "utf-8").trim();
9160
+ const code = Number.parseInt(raw, 10);
9161
+ if (Number.isNaN(code)) {
9162
+ return { status: "running", exitCode: null, logPath };
9163
+ }
9164
+ return { status: code === 0 ? "success" : "failed", exitCode: code, logPath };
9165
+ }
9166
+ if (import_fs_extra5.default.existsSync(logPath)) {
9167
+ return { status: "running", exitCode: null, logPath };
9168
+ }
9169
+ return { status: "idle", exitCode: null, logPath };
9170
+ }
9171
+ function readBackgroundInstallLogTail(cwd, maxChars = 1500) {
9172
+ const logPath = import_path11.default.join(cwd, INSTALL_LOG_FILE);
9173
+ if (!import_fs_extra5.default.existsSync(logPath)) {
9174
+ return "";
9175
+ }
9176
+ const content = import_fs_extra5.default.readFileSync(logPath, "utf-8");
9177
+ return content.length > maxChars ? content.slice(content.length - maxChars) : content;
9178
+ }
9136
9179
 
9137
9180
  // bin/create.ts
9138
9181
  init_cliError();
@@ -9397,6 +9440,7 @@ Directory "${projectName}" already exists.`));
9397
9440
  const { logPath } = startBackgroundInstall(targetDir);
9398
9441
  console.log(import_chalk20.default.gray(" Dependencies are installing in the background; create will continue."));
9399
9442
  console.log(import_chalk20.default.gray(` Install progress is logged to: ${logPath}`));
9443
+ console.log(import_chalk20.default.gray(" `pinme save` will automatically wait for this install to finish."));
9400
9444
  } catch (error) {
9401
9445
  console.log(import_chalk20.default.yellow(" Warning: could not start background dependency install."));
9402
9446
  console.log(import_chalk20.default.yellow(" Run `npm install` inside the project before `pinme save`."));
@@ -9553,6 +9597,7 @@ Next steps:`));
9553
9597
 
9554
9598
  // bin/save.ts
9555
9599
  var import_chalk21 = __toESM(require("chalk"));
9600
+ var import_ora3 = __toESM(require("ora"));
9556
9601
  var import_fs_extra7 = __toESM(require("fs-extra"));
9557
9602
  var import_path13 = __toESM(require("path"));
9558
9603
  init_axios2();
@@ -9597,30 +9642,116 @@ function buildWorker() {
9597
9642
  });
9598
9643
  console.log(import_chalk21.default.green("Worker built"));
9599
9644
  } catch (error) {
9645
+ if (isMissingDependencyError(error)) {
9646
+ throw dependenciesMissingError(
9647
+ "Worker build failed because a required CLI (e.g. `wrangler`) was not found. Project dependencies are missing or incomplete."
9648
+ );
9649
+ }
9600
9650
  throw createCommandError("worker build", "npm run build:worker", error, [
9601
9651
  "Fix the build error shown above, then rerun `pinme save`."
9602
9652
  ]);
9603
9653
  }
9604
9654
  }
9605
- function ensureDependenciesInstalled() {
9606
- const nodeModulesPath = import_path13.default.join(PROJECT_DIR2, "node_modules");
9655
+ function dependenciesMissingError(summary, logTail) {
9607
9656
  const installLogPath = import_path13.default.join(PROJECT_DIR2, ".pinme-install.log");
9608
- if (import_fs_extra7.default.existsSync(nodeModulesPath)) {
9609
- console.log(import_chalk21.default.gray("Dependencies already installed; skipping install."));
9610
- return;
9611
- }
9612
9657
  const suggestions = [
9613
- "Dependencies are not installed. Run `npm install` in the project root, wait for it to finish, then rerun `pinme save`."
9658
+ "Run `npm install` in the project root, wait for it to finish, then rerun `pinme save`."
9614
9659
  ];
9615
9660
  if (import_fs_extra7.default.existsSync(installLogPath)) {
9616
9661
  suggestions.push(
9617
- `A background install may still be running (started by \`pinme create\`). Check progress in \`${installLogPath}\` before retrying.`
9662
+ `Background install log: ${installLogPath}`
9618
9663
  );
9619
9664
  }
9620
- throw createConfigError(
9621
- "Project dependencies are not installed: `node_modules` is missing.",
9622
- suggestions
9623
- );
9665
+ const error = createConfigError(summary, suggestions);
9666
+ const trimmedTail = logTail == null ? void 0 : logTail.trim();
9667
+ if (trimmedTail) {
9668
+ error.details = [
9669
+ ...error.details,
9670
+ "Install log (tail):",
9671
+ ...trimmedTail.split("\n").slice(-20)
9672
+ ];
9673
+ }
9674
+ return error;
9675
+ }
9676
+ function isMissingDependencyError(error) {
9677
+ const exitCode = (error == null ? void 0 : error.status) ?? (error == null ? void 0 : error.code);
9678
+ if (exitCode === 127) {
9679
+ return true;
9680
+ }
9681
+ const haystack = [error == null ? void 0 : error.message, error == null ? void 0 : error.stderr, error == null ? void 0 : error.stdout].map((value) => String(value || "")).join(" ").toLowerCase();
9682
+ return /command not found|not found|is not recognized|cannot find module|cannot find package/.test(haystack);
9683
+ }
9684
+ function dependenciesPresent() {
9685
+ return hasLocalBinary("wrangler") && hasLocalBinary("vite");
9686
+ }
9687
+ function sleep(ms) {
9688
+ return new Promise((resolve) => setTimeout(resolve, ms));
9689
+ }
9690
+ var WAIT_FOR_INSTALL_TIMEOUT_MS = 12 * 60 * 1e3;
9691
+ var WAIT_POLL_INTERVAL_MS = 2e3;
9692
+ async function ensureDependenciesReady() {
9693
+ if (dependenciesPresent()) {
9694
+ console.log(import_chalk21.default.gray("Dependencies are installed."));
9695
+ return;
9696
+ }
9697
+ const initial = readBackgroundInstallStatus(PROJECT_DIR2);
9698
+ if (initial.status === "idle") {
9699
+ throw dependenciesMissingError(
9700
+ "Project dependencies are not installed and no install is running."
9701
+ );
9702
+ }
9703
+ 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
+ );
9708
+ }
9709
+ const spinner = (0, import_ora3.default)("Waiting for background dependency install to finish...").start();
9710
+ const startedAt = Date.now();
9711
+ while (true) {
9712
+ await sleep(WAIT_POLL_INTERVAL_MS);
9713
+ if (dependenciesPresent()) {
9714
+ spinner.succeed("Dependencies installed.");
9715
+ return;
9716
+ }
9717
+ const state = readBackgroundInstallStatus(PROJECT_DIR2);
9718
+ if (state.status === "failed") {
9719
+ 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
+ );
9724
+ }
9725
+ if (state.status === "success") {
9726
+ spinner.succeed("Dependencies installed.");
9727
+ return;
9728
+ }
9729
+ const elapsedMs = Date.now() - startedAt;
9730
+ 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
+ );
9736
+ }
9737
+ spinner.text = `Waiting for background dependency install to finish... (${Math.round(elapsedMs / 1e3)}s)`;
9738
+ }
9739
+ }
9740
+ function cleanupInstallMarkers() {
9741
+ 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));
9744
+ } catch {
9745
+ }
9746
+ }
9747
+ function hasLocalBinary(name) {
9748
+ 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")
9752
+ ];
9753
+ 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))));
9624
9755
  }
9625
9756
  function getBuiltWorker() {
9626
9757
  const distWorkerDir = import_path13.default.join(PROJECT_DIR2, "dist-worker");
@@ -9727,6 +9858,11 @@ function buildFrontend() {
9727
9858
  });
9728
9859
  console.log(import_chalk21.default.green("Frontend built"));
9729
9860
  } catch (error) {
9861
+ if (isMissingDependencyError(error)) {
9862
+ throw dependenciesMissingError(
9863
+ "Frontend build failed because a required CLI (e.g. `vite`) was not found. Project dependencies are missing or incomplete."
9864
+ );
9865
+ }
9730
9866
  throw createCommandError("frontend build", "npm run build:frontend", error, [
9731
9867
  "Fix the frontend build error shown above, then rerun `pinme save`."
9732
9868
  ]);
@@ -9826,7 +9962,7 @@ async function saveCmd(options) {
9826
9962
  const apiUrl = `${getPinmeApiUrl("/save_worker")}?project_name=${encodeURIComponent(projectName)}`;
9827
9963
  console.log(import_chalk21.default.gray(`API URL: ${apiUrl}`));
9828
9964
  console.log(import_chalk21.default.blue("\n--- Backend ---"));
9829
- ensureDependenciesInstalled();
9965
+ await ensureDependenciesReady();
9830
9966
  buildWorker();
9831
9967
  const metadata = getMetadata();
9832
9968
  const { workerJsPath, modulePaths } = getBuiltWorker();
@@ -9855,6 +9991,7 @@ async function saveCmd(options) {
9855
9991
  "management"
9856
9992
  );
9857
9993
  console.log(import_chalk21.default.green("\nDeployment complete."));
9994
+ cleanupInstallMarkers();
9858
9995
  void tracker_default.trackEvent(TRACK_EVENTS.projectSaveSuccess, TRACK_PAGES.deploy, {
9859
9996
  a: resolveTrackAction2(TRACK_EVENTS.projectSaveSuccess),
9860
9997
  project_name: projectName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinme",
3
- "version": "2.0.9-beta.1",
3
+ "version": "2.0.9-beta.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },