@calo-design/cli 0.11.0 → 0.12.0

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/bin/mirror-push.js +33 -3
  2. package/package.json +1 -1
@@ -102,11 +102,19 @@ function extractEasGroup(captured) {
102
102
  return found ? found[1] : undefined;
103
103
  }
104
104
 
105
+ // The per-version EAS branch/channel name. Deterministic from (slug, group) so any
106
+ // party — CLI, broker page, Mirror launcher — can derive it, but it's also stored in
107
+ // artifact.easBranch so the convention can evolve without re-deriving. EAS channel
108
+ // names share the slug charset; slug ≤63 + "--g" + 8 = ≤74, under EAS's limits.
109
+ const versionBranchOf = (slug, group) => `${slug}--g${String(group).slice(0, 8).toLowerCase()}`;
110
+
105
111
  function runtimeDir() {
106
112
  const home = process.env.DESIGNCHEF_HOME || path.join(os.homedir(), ".designchef");
107
113
  return path.join(home, "runtime");
108
114
  }
109
- const slugify = (s) => String(s).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "prototype";
115
+ // Capped at 63 (SLUG_RE's bound everywhere else) an uncapped slug would silently
116
+ // break the checkpoint stamp and overflow EAS channel-name limits on version pins.
117
+ const slugify = (s) => String(s).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63).replace(/-+$/, "") || "prototype";
110
118
  const titleize = (s) => String(s).replace(/[-_]+/g, " ").replace(/\b\w/g, (m) => m.toUpperCase());
111
119
 
112
120
  function appDir(root) {
@@ -854,6 +862,7 @@ async function cmdPush(args) {
854
862
  // capture is best-effort (a quick update:list after the publish); so is the whole
855
863
  // stamp — never fails the push. (Lazy require: mirror-push is also loaded by art-push.)
856
864
  let easGroup;
865
+ let easBranch;
857
866
  try {
858
867
  // easCapture → { status, out }. Tolerant extraction: eas --json shapes (and
859
868
  // banner noise) vary by version, so regex the output for the first uuid-shaped
@@ -861,6 +870,21 @@ async function cmdPush(args) {
861
870
  // lists the branch head, so a concurrent push to the same slug in this window
862
871
  // could stamp the other push's group — rare, and a stamp is advisory metadata.
863
872
  easGroup = extractEasGroup(easCapture(["update:list", "--branch", slug, "--limit", "1", "--json", "--non-interactive"], { cwd: stage }));
873
+ if (easGroup) {
874
+ // Pin this exact version behind its own channel: `slug--g<group[:8]>`.
875
+ // republish is a metadata copy (no rebundle); ensureChannel links channel →
876
+ // branch of the same name, which is what the Mirror's channel-name header
877
+ // switch loads. This is what makes "open v3 on your phone" possible after
878
+ // the channel head (slug) has moved on. Best-effort like the whole stamp.
879
+ const vb = versionBranchOf(slug, easGroup);
880
+ ensureChannel(stage, vb);
881
+ const rp = easCapture(
882
+ ["update:republish", "--group", easGroup, "--destination-branch", vb, "-m", `pin ${slug} @ ${easGroup.slice(0, 8)}`, "--non-interactive"],
883
+ { cwd: stage }
884
+ );
885
+ if (rp.status === 0) easBranch = vb;
886
+ else warn(`version pin skipped (republish → ${rp.out.trim().split("\n").slice(-1)[0] || rp.status})`);
887
+ }
864
888
  } catch {
865
889
  /* no artifact ref — the stamp still records source + deep link */
866
890
  }
@@ -868,7 +892,13 @@ async function cmdPush(args) {
868
892
  root: process.cwd(),
869
893
  note: flag(args, "note") || `pushed to the Mirror (${slug})`,
870
894
  publishedUrl: `designchef://open/${slug}`,
871
- artifact: { kind: "mirror", channel: slug, runtimeVersion: RUNTIME_VERSION, ...(easGroup ? { easGroup } : {}) },
895
+ artifact: {
896
+ kind: "mirror",
897
+ channel: slug,
898
+ runtimeVersion: RUNTIME_VERSION,
899
+ ...(easGroup ? { easGroup } : {}),
900
+ ...(easBranch ? { easBranch } : {}),
901
+ },
872
902
  });
873
903
 
874
904
  // Share target: the deep link the Mirror scanner (and iOS camera) opens.
@@ -889,4 +919,4 @@ async function cmdPush(args) {
889
919
  }
890
920
  }
891
921
 
892
- module.exports = { cmdPush, _s3Put: s3Put, _upsertRegistry: upsertRegistry, _publicBase: PUBLIC_BASE, _extractEasGroup: extractEasGroup };
922
+ module.exports = { cmdPush, _s3Put: s3Put, _upsertRegistry: upsertRegistry, _publicBase: PUBLIC_BASE, _extractEasGroup: extractEasGroup, _versionBranchOf: versionBranchOf };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calo-design/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "One-line setup for Calo design tooling: logs in with your Calo email and installs the calo-design skill + design-system packages. No GitHub account needed.",
5
5
  "bin": {
6
6
  "calo-design": "bin/cli.js"