ryugi-artifacts 1.31.3 → 1.31.5

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.
package/dist/cli.cjs CHANGED
@@ -384,6 +384,9 @@ var isVisibility = (value) => value === "private" || value === "public";
384
384
  var import_node_fs4 = __toESM(require("node:fs"), 1);
385
385
  var import_node_path2 = __toESM(require("node:path"), 1);
386
386
 
387
+ // src/shared/types.ts
388
+ var ARTIFACT_TYPES = ["artboard", "document", "html"];
389
+
387
390
  // src/shared/validate.ts
388
391
  var BOARD_NUMBERS = ["x", "y", "w", "h"];
389
392
  var BOARD_REQUIRED = ["file", "page", ...BOARD_NUMBERS];
@@ -515,17 +518,64 @@ function config(options, emit) {
515
518
 
516
519
  // src/cli/start.ts
517
520
  var import_node_child_process2 = require("node:child_process");
521
+ var import_node_crypto2 = __toESM(require("node:crypto"), 1);
522
+ var import_node_fs8 = __toESM(require("node:fs"), 1);
523
+ var import_node_path8 = __toESM(require("node:path"), 1);
524
+ var import_node_readline = __toESM(require("node:readline"), 1);
525
+
526
+ // src/server/artifact-address.ts
518
527
  var import_node_crypto = __toESM(require("node:crypto"), 1);
519
528
  var import_node_fs7 = __toESM(require("node:fs"), 1);
520
529
  var import_node_path7 = __toESM(require("node:path"), 1);
521
- var import_node_readline = __toESM(require("node:readline"), 1);
530
+
531
+ // src/shared/ids.ts
532
+ var ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
533
+ var isArtifactId = (id) => ID_PATTERN.test(id);
534
+ var isArtifactType = (type) => ARTIFACT_TYPES.includes(type);
535
+
536
+ // src/server/artifacts.ts
537
+ function artifactKeyOf(relative) {
538
+ const [type, id] = relative.split("/");
539
+ if (!type || !id || !isArtifactType(type) || !isArtifactId(id)) return null;
540
+ return { type, id };
541
+ }
542
+
543
+ // src/server/artifact-address.ts
544
+ function artifactId(dir) {
545
+ const file = import_node_path7.default.join(dir, ".artifact-id");
546
+ let id;
547
+ try {
548
+ id = import_node_fs7.default.readFileSync(file, "utf8").trim();
549
+ } catch (err) {
550
+ if (err.code !== "ENOENT") throw err;
551
+ id = import_node_crypto.default.randomBytes(16).toString("hex");
552
+ try {
553
+ import_node_fs7.default.writeFileSync(file, `${id}
554
+ `, { flag: "wx" });
555
+ } catch (writeError) {
556
+ if (writeError.code !== "EEXIST") throw writeError;
557
+ return artifactId(dir);
558
+ }
559
+ }
560
+ if (!/^[a-f0-9]{32}$/.test(id)) throw new Error(`Invalid artifact ID in ${file}`);
561
+ return id;
562
+ }
563
+ function artifactPath(root, type, slug) {
564
+ if (!isArtifactType(type) || !isArtifactId(slug)) throw new Error("Invalid artifact locator");
565
+ const dir = import_node_path7.default.join(root, type, slug);
566
+ import_node_fs7.default.mkdirSync(dir, { recursive: true });
567
+ return `/${type}/${artifactId(dir)}`;
568
+ }
569
+
570
+ // src/cli/start.ts
522
571
  var windowsLike = () => process.platform === "win32";
523
572
  function withLink(info, artifact, reused) {
524
573
  const out = { ...info };
525
574
  if (reused) out.reused = true;
526
575
  if (artifact && typeof out.url === "string") {
527
576
  const url = new URL(out.url);
528
- out.link = `${url.origin}/${artifact}?key=${url.searchParams.get("key")}`;
577
+ const ref = artifactKeyOf(artifact);
578
+ out.link = `${url.origin}${artifactPath(String(out.root), ref.type, ref.id)}?key=${url.searchParams.get("key")}`;
529
579
  }
530
580
  return out;
531
581
  }
@@ -551,13 +601,13 @@ async function withCloudLink(out, artifact) {
551
601
  async function acquireLock(lock) {
552
602
  for (let attempt = 0; attempt < 150; attempt++) {
553
603
  try {
554
- import_node_fs7.default.mkdirSync(lock);
604
+ import_node_fs8.default.mkdirSync(lock);
555
605
  return true;
556
606
  } catch {
557
607
  }
558
608
  try {
559
- if (Date.now() - import_node_fs7.default.statSync(lock).mtimeMs > 6e4) {
560
- import_node_fs7.default.rmdirSync(lock);
609
+ if (Date.now() - import_node_fs8.default.statSync(lock).mtimeMs > 6e4) {
610
+ import_node_fs8.default.rmdirSync(lock);
561
611
  continue;
562
612
  }
563
613
  } catch {
@@ -587,13 +637,13 @@ function registerOwner(paths) {
587
637
  const owner = ownerPid();
588
638
  if (owner) owners.add(owner);
589
639
  const tmp = `${paths.owners}.${process.pid}`;
590
- import_node_fs7.default.writeFileSync(tmp, [...owners].sort((a, b) => a - b).map((pid) => `${pid}
640
+ import_node_fs8.default.writeFileSync(tmp, [...owners].sort((a, b) => a - b).map((pid) => `${pid}
591
641
  `).join(""));
592
- import_node_fs7.default.renameSync(tmp, paths.owners);
642
+ import_node_fs8.default.renameSync(tmp, paths.owners);
593
643
  }
594
644
  function recordAgent(paths) {
595
645
  const markers = Object.fromEntries(AGENT_MARKERS.flatMap((key) => process.env[key] ? [[key, process.env[key]]] : []));
596
- if (Object.keys(markers).length) import_node_fs7.default.writeFileSync(paths.agent, `${JSON.stringify(markers)}
646
+ if (Object.keys(markers).length) import_node_fs8.default.writeFileSync(paths.agent, `${JSON.stringify(markers)}
597
647
  `);
598
648
  }
599
649
  async function replace(pid, paths) {
@@ -625,9 +675,9 @@ async function start(options, emit) {
625
675
  const foreground = options.foreground || !options.background && (!!process.env.CODEX_CI || windowsLike());
626
676
  process.umask(63);
627
677
  const paths = projectPaths(options.projectDir);
628
- import_node_fs7.default.mkdirSync(paths.state, { recursive: true });
629
- if (!import_node_fs7.default.existsSync(import_node_path7.default.join(paths.state, ".gitignore"))) import_node_fs7.default.writeFileSync(import_node_path7.default.join(paths.state, ".gitignore"), "*\n");
630
- const server = import_node_path7.default.join(__dirname, "server.cjs");
678
+ import_node_fs8.default.mkdirSync(paths.state, { recursive: true });
679
+ if (!import_node_fs8.default.existsSync(import_node_path8.default.join(paths.state, ".gitignore"))) import_node_fs8.default.writeFileSync(import_node_path8.default.join(paths.state, ".gitignore"), "*\n");
680
+ const server = import_node_path8.default.join(__dirname, "server.cjs");
631
681
  const version = process.env.RYUGI_ARTIFACTS_VERSION ?? "";
632
682
  if (!await acquireLock(paths.lock)) throw new CliError("Another start for this project is still starting; retry in a moment");
633
683
  let locked = true;
@@ -635,7 +685,7 @@ async function start(options, emit) {
635
685
  if (!locked) return;
636
686
  locked = false;
637
687
  try {
638
- import_node_fs7.default.rmdirSync(paths.lock);
688
+ import_node_fs8.default.rmdirSync(paths.lock);
639
689
  } catch {
640
690
  }
641
691
  };
@@ -653,17 +703,17 @@ async function start(options, emit) {
653
703
  }
654
704
  registerOwner(paths);
655
705
  recordAgent(paths);
656
- import_node_fs7.default.rmSync(paths.info, { force: true });
657
- const id = import_node_crypto.default.randomBytes(24).toString("hex");
658
- import_node_fs7.default.writeFileSync(paths.serverId, `${id}
706
+ import_node_fs8.default.rmSync(paths.info, { force: true });
707
+ const id = import_node_crypto2.default.randomBytes(24).toString("hex");
708
+ import_node_fs8.default.writeFileSync(paths.serverId, `${id}
659
709
  `);
660
- import_node_fs7.default.writeFileSync(paths.version, `${version}
710
+ import_node_fs8.default.writeFileSync(paths.version, `${version}
661
711
  `);
662
712
  const env = serverEnv(paths, options);
663
713
  const args = [server, `--artifacts-server-id=${id}`];
664
714
  if (foreground) {
665
715
  const child2 = (0, import_node_child_process2.spawn)(process.execPath, args, { env, stdio: ["ignore", "pipe", "inherit"] });
666
- import_node_fs7.default.writeFileSync(paths.pid, `${child2.pid}
716
+ import_node_fs8.default.writeFileSync(paths.pid, `${child2.pid}
667
717
  `);
668
718
  for (const signal of ["SIGINT", "SIGTERM"]) process.on(signal, () => child2.kill("SIGTERM"));
669
719
  import_node_readline.default.createInterface({ input: child2.stdout }).on("line", (line) => {
@@ -679,15 +729,15 @@ async function start(options, emit) {
679
729
  else void withCloudLink(withLink(value, options.artifact, false), options.artifact).then(emit);
680
730
  });
681
731
  const exited = new Promise((resolve) => child2.on("close", (code) => resolve(code ?? 1)));
682
- for (let waited = 0; waited < 5e3 && !import_node_fs7.default.existsSync(paths.info); waited += 100) await sleep(100);
732
+ for (let waited = 0; waited < 5e3 && !import_node_fs8.default.existsSync(paths.info); waited += 100) await sleep(100);
683
733
  unlock();
684
734
  return await exited;
685
735
  }
686
- const log = import_node_fs7.default.openSync(paths.log, "w");
736
+ const log = import_node_fs8.default.openSync(paths.log, "w");
687
737
  const child = (0, import_node_child_process2.spawn)(process.execPath, args, { env, detached: true, stdio: ["ignore", log, log] });
688
- import_node_fs7.default.closeSync(log);
738
+ import_node_fs8.default.closeSync(log);
689
739
  child.unref();
690
- import_node_fs7.default.writeFileSync(paths.pid, `${child.pid}
740
+ import_node_fs8.default.writeFileSync(paths.pid, `${child.pid}
691
741
  `);
692
742
  for (let waited = 0; waited < 5e3; waited += 100) {
693
743
  const lines = (readText(paths.log) ?? "").split("\n");
@@ -767,13 +817,13 @@ async function publish(options, emit) {
767
817
  }
768
818
 
769
819
  // src/cli/stop.ts
770
- var import_node_fs8 = __toESM(require("node:fs"), 1);
820
+ var import_node_fs9 = __toESM(require("node:fs"), 1);
771
821
  async function stop(projectDir, emit) {
772
822
  const paths = projectPaths(projectDir);
773
823
  const markStopped = (reason) => {
774
- import_node_fs8.default.rmSync(paths.info, { force: true });
775
- import_node_fs8.default.mkdirSync(paths.state, { recursive: true });
776
- import_node_fs8.default.writeFileSync(paths.stopped, `${JSON.stringify({ reason, timestamp: Math.floor(Date.now() / 1e3) })}
824
+ import_node_fs9.default.rmSync(paths.info, { force: true });
825
+ import_node_fs9.default.mkdirSync(paths.state, { recursive: true });
826
+ import_node_fs9.default.writeFileSync(paths.stopped, `${JSON.stringify({ reason, timestamp: Math.floor(Date.now() / 1e3) })}
777
827
  `);
778
828
  };
779
829
  const pid = Number(readText(paths.pid));
@@ -783,8 +833,8 @@ async function stop(projectDir, emit) {
783
833
  }
784
834
  const id = readText(paths.serverId) ?? "";
785
835
  if (!Number.isInteger(pid) || pid <= 0 || !/^[A-Za-z0-9_-]{32,64}$/.test(id) || !hasServerId(pid, id)) {
786
- import_node_fs8.default.rmSync(paths.pid, { force: true });
787
- import_node_fs8.default.rmSync(paths.serverId, { force: true });
836
+ import_node_fs9.default.rmSync(paths.pid, { force: true });
837
+ import_node_fs9.default.rmSync(paths.serverId, { force: true });
788
838
  markStopped("stale_pid");
789
839
  emit({ status: "stale_pid" });
790
840
  return 0;
@@ -804,7 +854,7 @@ async function stop(projectDir, emit) {
804
854
  emit({ status: "failed", error: "process still running" });
805
855
  return 1;
806
856
  }
807
- for (const file of [paths.pid, paths.serverId, paths.log, paths.owners]) import_node_fs8.default.rmSync(file, { force: true });
857
+ for (const file of [paths.pid, paths.serverId, paths.log, paths.owners]) import_node_fs9.default.rmSync(file, { force: true });
808
858
  markStopped("stop");
809
859
  emit({ status: "stopped" });
810
860
  return 0;
@@ -996,7 +1046,7 @@ async function main(argv) {
996
1046
  }, emit);
997
1047
  }
998
1048
  if (command === "--version" || command === "-v") {
999
- console.log("1.31.3");
1049
+ console.log("1.31.5");
1000
1050
  return 0;
1001
1051
  }
1002
1052
  if (command === "--help" || command === "-h") {