@calo-design/cli 0.10.0 → 0.11.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.
- package/bin/checkpoints.js +4 -3
- package/bin/mirror-push.js +27 -3
- package/bin/share.js +11 -4
- package/package.json +1 -1
package/bin/checkpoints.js
CHANGED
|
@@ -160,15 +160,15 @@ async function cmdSave(args = []) {
|
|
|
160
160
|
* user doing anything. Best-effort by contract — a checkpoint hiccup must never turn a
|
|
161
161
|
* successful deploy into a failed command.
|
|
162
162
|
*/
|
|
163
|
-
async function autoCheckpoint({ root, note, publishedUrl }) {
|
|
163
|
+
async function autoCheckpoint({ root, note, publishedUrl, artifact }) {
|
|
164
164
|
try {
|
|
165
|
-
await saveFlow({ root, note, publishedUrl, force: true, quiet: true });
|
|
165
|
+
await saveFlow({ root, note, publishedUrl, artifact, force: true, quiet: true });
|
|
166
166
|
} catch (e) {
|
|
167
167
|
elog(`${c.y("!")} deploy succeeded, but the source checkpoint didn't: ${e.message}`);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
async function saveFlow({ root, slugOverride, note = "", force = false, json = false, quiet = false, publishedUrl }) {
|
|
171
|
+
async function saveFlow({ root, slugOverride, note = "", force = false, json = false, quiet = false, publishedUrl, artifact }) {
|
|
172
172
|
if (!fs.existsSync(path.join(root, "package.json"))) {
|
|
173
173
|
throw new Error("no package.json here — run `calo-design save` from a prototype folder");
|
|
174
174
|
}
|
|
@@ -212,6 +212,7 @@ async function saveFlow({ root, slugOverride, note = "", force = false, json = f
|
|
|
212
212
|
...(basedOn != null ? { "x-calo-based-on": String(basedOn) } : {}),
|
|
213
213
|
...(isFork && forkedFrom ? { "x-calo-forked-from": forkedFrom } : {}),
|
|
214
214
|
...(publishedUrl ? { "x-calo-published-url": publishedUrl } : {}),
|
|
215
|
+
...(artifact ? { "x-calo-artifact": encodeURIComponent(JSON.stringify(artifact)) } : {}),
|
|
215
216
|
...(force ? { "x-calo-force": "1" } : {}),
|
|
216
217
|
},
|
|
217
218
|
body: tgz,
|
package/bin/mirror-push.js
CHANGED
|
@@ -93,6 +93,15 @@ let easEnv = process.env;
|
|
|
93
93
|
const easRun = (argv, opts = {}) => { const [b, ...p] = easPrefix(); return run(b, [...p, ...argv], { env: easEnv, ...opts }); };
|
|
94
94
|
const easCapture = (argv, opts = {}) => { const [b, ...p] = easPrefix(); return capture(b, [...p, ...argv], { env: easEnv, ...opts }); };
|
|
95
95
|
|
|
96
|
+
// Pull the EAS update GROUP id (the immutable per-version ref checkpoints record) out
|
|
97
|
+
// of a `capture()` result from `eas update:list --json`. Regex, not JSON.parse: eas
|
|
98
|
+
// output shapes and banner noise vary by version, and this must stay best-effort.
|
|
99
|
+
function extractEasGroup(captured) {
|
|
100
|
+
if (!captured || captured.status !== 0 || typeof captured.out !== "string") return undefined;
|
|
101
|
+
const found = captured.out.match(/"group":\s*"([0-9a-fA-F-]{16,64})"/);
|
|
102
|
+
return found ? found[1] : undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
96
105
|
function runtimeDir() {
|
|
97
106
|
const home = process.env.DESIGNCHEF_HOME || path.join(os.homedir(), ".designchef");
|
|
98
107
|
return path.join(home, "runtime");
|
|
@@ -839,12 +848,27 @@ async function cmdPush(args) {
|
|
|
839
848
|
log(c.b("\n✨ Live in the Mirror.") + " Open Calo Mirror and tap Refresh — your prototype is at the top.");
|
|
840
849
|
|
|
841
850
|
// Deploy-stamped versioning: every successful push leaves a source checkpoint, so
|
|
842
|
-
// the thing on the phone and its exact source are permanently paired.
|
|
843
|
-
//
|
|
851
|
+
// the thing on the phone and its exact source are permanently paired. The artifact
|
|
852
|
+
// records the EAS update GROUP id — the immutable per-version bundle — so a future
|
|
853
|
+
// Mirror shell can load exactly this version (channel head keeps moving). Group id
|
|
854
|
+
// capture is best-effort (a quick update:list after the publish); so is the whole
|
|
855
|
+
// stamp — never fails the push. (Lazy require: mirror-push is also loaded by art-push.)
|
|
856
|
+
let easGroup;
|
|
857
|
+
try {
|
|
858
|
+
// easCapture → { status, out }. Tolerant extraction: eas --json shapes (and
|
|
859
|
+
// banner noise) vary by version, so regex the output for the first uuid-shaped
|
|
860
|
+
// `group` value instead of parsing. Known race, accepted as best-effort: this
|
|
861
|
+
// lists the branch head, so a concurrent push to the same slug in this window
|
|
862
|
+
// could stamp the other push's group — rare, and a stamp is advisory metadata.
|
|
863
|
+
easGroup = extractEasGroup(easCapture(["update:list", "--branch", slug, "--limit", "1", "--json", "--non-interactive"], { cwd: stage }));
|
|
864
|
+
} catch {
|
|
865
|
+
/* no artifact ref — the stamp still records source + deep link */
|
|
866
|
+
}
|
|
844
867
|
await require("./checkpoints").autoCheckpoint({
|
|
845
868
|
root: process.cwd(),
|
|
846
869
|
note: flag(args, "note") || `pushed to the Mirror (${slug})`,
|
|
847
870
|
publishedUrl: `designchef://open/${slug}`,
|
|
871
|
+
artifact: { kind: "mirror", channel: slug, runtimeVersion: RUNTIME_VERSION, ...(easGroup ? { easGroup } : {}) },
|
|
848
872
|
});
|
|
849
873
|
|
|
850
874
|
// Share target: the deep link the Mirror scanner (and iOS camera) opens.
|
|
@@ -865,4 +889,4 @@ async function cmdPush(args) {
|
|
|
865
889
|
}
|
|
866
890
|
}
|
|
867
891
|
|
|
868
|
-
module.exports = { cmdPush, _s3Put: s3Put, _upsertRegistry: upsertRegistry, _publicBase: PUBLIC_BASE };
|
|
892
|
+
module.exports = { cmdPush, _s3Put: s3Put, _upsertRegistry: upsertRegistry, _publicBase: PUBLIC_BASE, _extractEasGroup: extractEasGroup };
|
package/bin/share.js
CHANGED
|
@@ -168,10 +168,17 @@ async function cmdShare(args = []) {
|
|
|
168
168
|
log(c.dim(` Re-run \`calo-design share\` to update “${slug}” in place. Share the link above.`));
|
|
169
169
|
}
|
|
170
170
|
if (r.version) log(c.dim(` this version: ${r.version}`));
|
|
171
|
-
// Deploy-stamped versioning: every successful share leaves a source checkpoint
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
171
|
+
// Deploy-stamped versioning: every successful share leaves a source checkpoint, so
|
|
172
|
+
// the deployed thing and its exact source are permanently paired. publishedUrl
|
|
173
|
+
// prefers the IMMUTABLE per-deploy URL (Cloudflare Pages keeps every deployment
|
|
174
|
+
// forever) so the version page opens exactly this version, not whatever the alias
|
|
175
|
+
// points at by then; the artifact keeps both. Best-effort — never fails the share.
|
|
176
|
+
await autoCheckpoint({
|
|
177
|
+
root,
|
|
178
|
+
note: flag(args, "note") || `shared to the web (${slug})`,
|
|
179
|
+
publishedUrl: r.version || url,
|
|
180
|
+
artifact: { kind: "web", aliasUrl: url, ...(r.version ? { deployUrl: r.version } : {}) },
|
|
181
|
+
});
|
|
175
182
|
} finally {
|
|
176
183
|
try { fs.rmSync(tgz); } catch {}
|
|
177
184
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calo-design/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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"
|