@minnovate/shadow-publisher 0.10.2 → 0.10.3

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "git-publisher",
3
3
  "displayName": "Git Publisher",
4
- "version": "0.10.2",
4
+ "version": "0.10.3",
5
5
  "description": "Publish an app folder's Git history to the serverless Git publishing backend and keep it updated (\"publish my app\", \"update my app\", \"fetch the engineered version\").",
6
6
  "author": { "name": "git-publisher project" },
7
7
  "keywords": ["git", "publish", "deploy", "serverless"]
@@ -3269,7 +3269,7 @@ async function runGit(args, opts = {}) {
3269
3269
  function startWatchdog(child, opts, kill, isClosed) {
3270
3270
  if (opts.maxMemoryBytes === void 0 && opts.maxDiskBytes === void 0) return { stop: () => void 0, done: Promise.resolve() };
3271
3271
  const sampler = opts.sampler ?? defaultResourceSampler;
3272
- const interval = Math.max(10, opts.sampleIntervalMs ?? 500);
3272
+ const interval2 = Math.max(10, opts.sampleIntervalMs ?? 500);
3273
3273
  const sampleBoundMs = opts.cleanupBoundMs ?? CLEANUP_BOUND_MS;
3274
3274
  const pgid = child.pid;
3275
3275
  let stopped = false;
@@ -3299,7 +3299,7 @@ function startWatchdog(child, opts, kill, isClosed) {
3299
3299
  }
3300
3300
  let tick = 0;
3301
3301
  while (!stopped) {
3302
- await sleep2(interval);
3302
+ await sleep2(interval2);
3303
3303
  if (stopped) return;
3304
3304
  if (opts.maxMemoryBytes !== void 0) {
3305
3305
  const rss = await sample("memory", (signal) => sampler.groupRss(pgid, signal));
@@ -4712,7 +4712,7 @@ async function followRun(input, opts) {
4712
4712
  const fetchImpl = opts.fetch ?? fetch;
4713
4713
  const sleep2 = opts.sleep ?? sleep;
4714
4714
  const now = opts.now ?? Date.now;
4715
- const interval = opts.intervalMs ?? POLL_INTERVAL_MS;
4715
+ const interval2 = opts.intervalMs ?? POLL_INTERVAL_MS;
4716
4716
  const deadline = now() + (opts.timeoutMs ?? FOLLOW_TIMEOUT_MS);
4717
4717
  const query = new URLSearchParams({ publication: input.publicationId, ref: input.ref, commit: input.commit });
4718
4718
  const url2 = `${input.portal.replace(/\/+$/, "")}/api/v1/terminal/repositories/${encodeURIComponent(input.repoId)}/runs?${query}`;
@@ -4758,8 +4758,8 @@ async function followRun(input, opts) {
4758
4758
  } else {
4759
4759
  lastError = answer.status === 0 ? "the portal could not be reached" : `the portal answered ${answer.status}`;
4760
4760
  }
4761
- if (now() + interval > deadline) return { kind: "timed-out", stages: last, lastError };
4762
- await sleep2(interval);
4761
+ if (now() + interval2 > deadline) return { kind: "timed-out", stages: last, lastError };
4762
+ await sleep2(interval2);
4763
4763
  }
4764
4764
  }
4765
4765
  function soleRun(body) {
@@ -5911,6 +5911,93 @@ function gitSupported(version2) {
5911
5911
  return compareVersions(version2, CLIENT_GIT_MINIMUM) >= 0;
5912
5912
  }
5913
5913
 
5914
+ // src/progress.ts
5915
+ var SAYS = {
5916
+ received: { doing: "Shadow is picking up your changes", done: "Shadow has your changes", still: "still picking up your changes" },
5917
+ running: { doing: "checking that everything still works", done: "everything still works", still: "still checking" },
5918
+ deploying: { doing: "putting the new version in place; the current one stays up meanwhile", done: "the new version is in place", still: "still putting it in place" },
5919
+ live: { doing: "going live", done: "everyone sees the new version", still: "still going live" }
5920
+ };
5921
+ var HEARTBEAT_MS = 3e4;
5922
+ var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5923
+ function took(ms) {
5924
+ const seconds = Math.max(0, Math.floor(ms / 1e3));
5925
+ if (seconds < 60) return `${seconds} s`;
5926
+ const minutes = Math.floor(seconds / 60);
5927
+ return minutes >= 10 ? `${minutes} min` : `${minutes} min ${String(seconds % 60).padStart(2, "0")} s`;
5928
+ }
5929
+ function interval(fn, ms) {
5930
+ const timer = setInterval(fn, ms);
5931
+ timer.unref();
5932
+ return { stop: () => clearInterval(timer) };
5933
+ }
5934
+ function settledLine(e, total) {
5935
+ const word = e.word.padEnd(10);
5936
+ switch (e.state) {
5937
+ case "done":
5938
+ return ` \u2713 ${word} ${SAYS[e.stage].done}${total}
5939
+ `;
5940
+ case "failed":
5941
+ return ` \u2717 ${word} it stopped here
5942
+ `;
5943
+ case "skipped":
5944
+ return ` \u2013 ${word} skipped
5945
+ `;
5946
+ default:
5947
+ return null;
5948
+ }
5949
+ }
5950
+ function stageReporter(io) {
5951
+ const now = io.now ?? Date.now;
5952
+ const every = io.every ?? interval;
5953
+ let ticking = null;
5954
+ let drawn = false;
5955
+ let receivedAt = null;
5956
+ const clear = () => {
5957
+ if (drawn) io.write("\r\x1B[2K");
5958
+ drawn = false;
5959
+ };
5960
+ const stopTicking = () => {
5961
+ ticking?.timer.stop();
5962
+ ticking = null;
5963
+ clear();
5964
+ };
5965
+ const since = (e) => {
5966
+ const at = e.at === null ? NaN : Date.parse(e.at);
5967
+ return Number.isFinite(at) ? Math.min(at, now()) : now();
5968
+ };
5969
+ return {
5970
+ onStage(e) {
5971
+ if (e.state === "in-progress" || ticking?.stage === e.stage) stopTicking();
5972
+ else clear();
5973
+ const says = SAYS[e.stage];
5974
+ if (e.stage === "received" && e.at !== null) receivedAt = since(e);
5975
+ if (e.state !== "in-progress") {
5976
+ const total = e.stage === "live" && e.state === "done" && receivedAt !== null ? ` (${took(since(e) - receivedAt)} after Shadow received it)` : "";
5977
+ const line = settledLine(e, total);
5978
+ if (line !== null) io.write(line);
5979
+ return;
5980
+ }
5981
+ io.write(` \u2026 ${e.word.padEnd(10)} ${says.doing}
5982
+ `);
5983
+ const from = since(e);
5984
+ if (io.isTTY) {
5985
+ let frame = 0;
5986
+ const draw = () => {
5987
+ io.write(`\r\x1B[2K ${SPINNER[frame++ % SPINNER.length]} ${says.still} \xB7 ${took(now() - from)}`);
5988
+ drawn = true;
5989
+ };
5990
+ draw();
5991
+ ticking = { stage: e.stage, timer: every(draw, 1e3) };
5992
+ } else {
5993
+ ticking = { stage: e.stage, timer: every(() => io.write(` ${says.still} (${took(now() - from)} so far)
5994
+ `), HEARTBEAT_MS) };
5995
+ }
5996
+ },
5997
+ stop: stopTicking
5998
+ };
5999
+ }
6000
+
5914
6001
  // src/follow.ts
5915
6002
  async function followPublication(p, endpoint, o, opts) {
5916
6003
  const derived = portalForEndpoint(endpoint);
@@ -5925,11 +6012,11 @@ async function followPublication(p, endpoint, o, opts) {
5925
6012
  const refs = Object.entries(o.refs ?? {});
5926
6013
  if (refs.length !== 1) return elsewhere("several-refs");
5927
6014
  const [ref, commit] = refs[0];
5928
- opts.log("Following it: received -> checked -> going live -> live. Ctrl-C stops watching; the publication is already saved.");
6015
+ opts.log("Following it to live: received -> checked -> going live -> live. Ctrl-C stops watching; the publication is saved and carries on without you.");
5929
6016
  const outcome = await p.followRun(
5930
6017
  { portal, repoId: o.repoId, publicationId: o.publicationId, ref, commit },
5931
6018
  { onStage: opts.onStage, ...opts.timeoutMs === void 0 ? {} : { timeoutMs: opts.timeoutMs }, ...opts.untilChange === true ? { untilChange: true } : {} }
5932
- );
6019
+ ).finally(() => opts.stopStages?.());
5933
6020
  const answerable = confirmed.terminal.includes(PREPARATION);
5934
6021
  const dir = shellWord(opts.dir);
5935
6022
  const next = outcome.kind === "timed-out" || outcome.kind === "moving" ? { action: "follow", command: `publisher follow ${dir} --publication ${o.publicationId}${opts.untilChange === true ? " --until-change" : ""} --json` } : outcome.kind === "waiting" && answerable ? { action: "question", command: `publisher question ${dir} --json` } : void 0;
@@ -5965,13 +6052,15 @@ function shellWord(path) {
5965
6052
  return /^[A-Za-z0-9_./-]+$/.test(path) ? path : `'${path.replace(/'/g, `'\\''`)}'`;
5966
6053
  }
5967
6054
  function stageEmitter(json, quiet) {
5968
- return (e) => {
5969
- if (json) process.stdout.write(stageLine(e, true) + "\n");
5970
- else if (!quiet) process.stderr.write(stageLine(e, false) + "\n");
6055
+ const nothing = () => {
5971
6056
  };
6057
+ if (json) return { onStage: (e) => process.stdout.write(stageLine(e) + "\n"), stopStages: nothing };
6058
+ if (quiet) return { onStage: nothing, stopStages: nothing };
6059
+ const { onStage, stop } = stageReporter({ write: (s) => process.stderr.write(s), isTTY: process.stderr.isTTY === true });
6060
+ return { onStage, stopStages: stop };
5972
6061
  }
5973
- function stageLine(e, json) {
5974
- return json ? JSON.stringify({ event: "stage", stage: e.stage, word: e.word, state: e.state, at: e.at }) : ` ${e.word}: ${e.state.replace("-", " ")}`;
6062
+ function stageLine(e) {
6063
+ return JSON.stringify({ event: "stage", stage: e.stage, word: e.word, state: e.state, at: e.at });
5975
6064
  }
5976
6065
  function inPortal(portal, lead, verb) {
5977
6066
  return `${lead} ${verb} in the portal${portal === null ? "" : `: ${portal}`}.`;
@@ -5993,7 +6082,7 @@ function progressHint(r, portal, answerable = false) {
5993
6082
  }
5994
6083
  break;
5995
6084
  case "moving": {
5996
- const now = r.stages.find((s) => s.state === "in-progress") ?? r.stages.filter((s) => s.state !== "pending").at(-1);
6085
+ const now = r.stages.filter((s) => s.state === "in-progress").at(-1) ?? r.stages.filter((s) => s.state !== "pending").at(-1);
5997
6086
  return `Now: ${now?.word ?? "received"}. Run next.command to wait for the next step.`;
5998
6087
  }
5999
6088
  case "timed-out":
@@ -6367,7 +6456,7 @@ async function main(argv) {
6367
6456
  if (e.phase === "done") process.stderr.write("\n");
6368
6457
  };
6369
6458
  const dirArg = (i) => (0, import_node_path8.resolve)(cmd[i] ?? ".");
6370
- const following = { onStage: stageEmitter(json, quiet), log, untilChange: flags["until-change"] === true };
6459
+ const following = { ...stageEmitter(json, quiet), log, untilChange: flags["until-change"] === true };
6371
6460
  const resolutionInput = async (dir) => {
6372
6461
  let association;
6373
6462
  if (dir && await isGitRepo(dir)) association = (await readAssociation(dir))?.endpoint;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minnovate/shadow-publisher",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "publisher: publish an app's Git history to the serverless Git backend",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",