pinme 2.0.10-beta.1 → 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 +244 -36
  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.10-beta.1";
5981
+ var version = "2.0.10-beta.2";
5982
5982
 
5983
5983
  // bin/upload.ts
5984
5984
  var import_path7 = __toESM(require("path"));
@@ -9090,10 +9090,24 @@ var import_chalk19 = __toESM(require("chalk"));
9090
9090
  var import_child_process3 = require("child_process");
9091
9091
  var INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
9092
9092
  var SLOW_INSTALL_NOTICE_MS = 60 * 1e3;
9093
+ var CAPTURED_OUTPUT_LIMIT = 12e3;
9093
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;
9094
9098
  var INSTALL_LOG_FILE = ".pinme-install.log";
9095
9099
  var INSTALL_EXITCODE_FILE = ".pinme-install.exitcode";
9096
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
+ };
9097
9111
  function makeTempCacheDir() {
9098
9112
  return import_fs_extra5.default.mkdtempSync(import_path11.default.join(import_os5.default.tmpdir(), "pinme-npm-cache-"));
9099
9113
  }
@@ -9113,10 +9127,8 @@ function getInstallScript(cwd, mode) {
9113
9127
  return hasPackageLock(cwd) ? "ci" : "install";
9114
9128
  }
9115
9129
  function getInstallArgs(script, cacheDir) {
9116
- return [
9130
+ const args = [
9117
9131
  script,
9118
- "--cache",
9119
- cacheDir,
9120
9132
  "--no-audit",
9121
9133
  "--no-fund",
9122
9134
  "--fetch-retries=3",
@@ -9125,6 +9137,100 @@ function getInstallArgs(script, cacheDir) {
9125
9137
  "--fetch-retry-maxtimeout=60000",
9126
9138
  "--fetch-timeout=60000"
9127
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
+ });
9128
9234
  }
9129
9235
  function quoteForShell(value) {
9130
9236
  if (process.platform === "win32") {
@@ -9134,8 +9240,7 @@ function quoteForShell(value) {
9134
9240
  }
9135
9241
  function startBackgroundInstall(cwd) {
9136
9242
  const script = getInstallScript(cwd, "auto");
9137
- const cacheDir = makeTempCacheDir();
9138
- const args = getInstallArgs(script, cacheDir);
9243
+ const args = getInstallArgs(script);
9139
9244
  const logPath = import_path11.default.join(cwd, INSTALL_LOG_FILE);
9140
9245
  const exitCodePath = import_path11.default.join(cwd, INSTALL_EXITCODE_FILE);
9141
9246
  const pidPath = import_path11.default.join(cwd, INSTALL_PID_FILE);
@@ -9164,7 +9269,6 @@ function startBackgroundInstall(cwd) {
9164
9269
  stdio: "ignore",
9165
9270
  env: {
9166
9271
  ...process.env,
9167
- npm_config_cache: cacheDir,
9168
9272
  npm_config_audit: "false",
9169
9273
  npm_config_fund: "false",
9170
9274
  npm_config_fetch_retries: "3",
@@ -9199,6 +9303,56 @@ function readPidFile(pidPath) {
9199
9303
  }
9200
9304
  return pid;
9201
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
+ }
9202
9356
  function isStaleLogOnlyMarker(logPath) {
9203
9357
  try {
9204
9358
  const ageMs = Date.now() - import_fs_extra5.default.statSync(logPath).mtimeMs;
@@ -9243,6 +9397,44 @@ function readBackgroundInstallLogTail(cwd, maxChars = 1500) {
9243
9397
  const content = import_fs_extra5.default.readFileSync(logPath, "utf-8");
9244
9398
  return content.length > maxChars ? content.slice(content.length - maxChars) : content;
9245
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
+ }
9246
9438
 
9247
9439
  // bin/create.ts
9248
9440
  init_cliError();
@@ -9922,10 +10114,10 @@ function isMissingDependencyError(error) {
9922
10114
  function dependenciesPresent() {
9923
10115
  return hasLocalBinary("wrangler") && hasLocalBinary("vite");
9924
10116
  }
9925
- function sleep(ms) {
10117
+ function sleep2(ms) {
9926
10118
  return new Promise((resolve) => setTimeout(resolve, ms));
9927
10119
  }
9928
- var WAIT_FOR_INSTALL_TIMEOUT_MS = 2 * 60 * 1e3;
10120
+ var WAIT_FOR_INSTALL_TIMEOUT_MS = 15 * 1e3;
9929
10121
  var WAIT_POLL_INTERVAL_MS = 2e3;
9930
10122
  async function ensureDependenciesReady() {
9931
10123
  if (dependenciesPresent()) {
@@ -9934,26 +10126,25 @@ async function ensureDependenciesReady() {
9934
10126
  }
9935
10127
  const initial = readBackgroundInstallStatus(PROJECT_DIR2);
9936
10128
  if (initial.status === "idle") {
9937
- throw dependenciesMissingError(
9938
- "Project dependencies are not installed and no install is running."
9939
- );
10129
+ await installDependenciesInForeground();
10130
+ return;
9940
10131
  }
9941
10132
  if (initial.status === "failed") {
9942
- throw dependenciesMissingError(
9943
- `The background dependency install (started by \`pinme create\`) failed with exit code ${initial.exitCode}.`,
9944
- readBackgroundInstallLogTail(PROJECT_DIR2)
9945
- );
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;
9946
10138
  }
9947
10139
  if (initial.status === "interrupted") {
9948
- throw dependenciesMissingError(
9949
- "The background dependency install appears to have been interrupted.",
9950
- readBackgroundInstallLogTail(PROJECT_DIR2)
9951
- );
10140
+ console.log(import_chalk21.default.yellow("Background dependency install was interrupted. Continuing in this terminal..."));
10141
+ await installDependenciesInForeground();
10142
+ return;
9952
10143
  }
9953
- 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();
9954
10145
  const startedAt = Date.now();
9955
10146
  while (true) {
9956
- await sleep(WAIT_POLL_INTERVAL_MS);
10147
+ await sleep2(WAIT_POLL_INTERVAL_MS);
9957
10148
  if (dependenciesPresent()) {
9958
10149
  spinner.succeed("Dependencies installed.");
9959
10150
  return;
@@ -9961,17 +10152,16 @@ async function ensureDependenciesReady() {
9961
10152
  const state = readBackgroundInstallStatus(PROJECT_DIR2);
9962
10153
  if (state.status === "failed") {
9963
10154
  spinner.fail("Background dependency install failed.");
9964
- throw dependenciesMissingError(
9965
- `The background dependency install (started by \`pinme create\`) failed with exit code ${state.exitCode}.`,
9966
- readBackgroundInstallLogTail(PROJECT_DIR2)
9967
- );
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;
9968
10160
  }
9969
10161
  if (state.status === "interrupted") {
9970
10162
  spinner.fail("Background dependency install was interrupted.");
9971
- throw dependenciesMissingError(
9972
- "The background dependency install appears to have been interrupted.",
9973
- readBackgroundInstallLogTail(PROJECT_DIR2)
9974
- );
10163
+ await installDependenciesInForeground();
10164
+ return;
9975
10165
  }
9976
10166
  if (state.status === "success") {
9977
10167
  spinner.succeed("Dependencies installed.");
@@ -9979,14 +10169,32 @@ async function ensureDependenciesReady() {
9979
10169
  }
9980
10170
  const elapsedMs = Date.now() - startedAt;
9981
10171
  if (elapsedMs > WAIT_FOR_INSTALL_TIMEOUT_MS) {
9982
- spinner.fail("Timed out waiting for the dependency install.");
9983
- throw dependenciesMissingError(
9984
- "Timed out waiting for the background dependency install to finish. It may still be running slowly.",
9985
- readBackgroundInstallLogTail(PROJECT_DIR2)
9986
- );
10172
+ spinner.warn("Background dependency install is not ready yet; continuing in this terminal.");
10173
+ await stopBackgroundInstall(PROJECT_DIR2);
10174
+ await installDependenciesInForeground();
10175
+ return;
9987
10176
  }
9988
- 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
+ );
9989
10196
  }
10197
+ console.log(import_chalk21.default.green("Project dependencies installed."));
9990
10198
  }
9991
10199
  function cleanupInstallMarkers() {
9992
10200
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinme",
3
- "version": "2.0.10-beta.1",
3
+ "version": "2.0.10-beta.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },