Files
hyperframes/packages/cli/src/commands/publish.test.ts
T
Miguel Ángel 4495cb7355 feat(cli): stable public URL for hyperframes publish (re-publish updates the same link) (#2363)
* feat(cli): stable-URL re-publish (send owned id, honest UX, --update, team id file)

Resolve a stable project id (committed team id > machine store > mint), send it
when authenticated so an owned re-publish updates the same URL in place, and
persist the server id+url. Report updated-vs-created honestly, add --update to
target a project explicitly, write a committable .hyperframes/project.json so a
team shares one link, and show the prior URL on re-publish.

* test(cli): env-gated E2E round-trip for stable-URL re-publish

Publish -> edit -> re-publish asserts one URL with updated content against a
live EF (HYPERFRAMES_E2E_API_URL + an authenticated runner); skipped otherwise.

* fix(cli): real team space, auth-gate --update/--space, safe team-file write

- --space + committed .hyperframes/project.json (projectId+spaceId) send X-Space-Id so a
  team converges on one link; personal space stays the default for solo users
- --update/--space error when unauthenticated, and warn loudly when a resolved-but-invalid
  token silently downgrades to a new anonymous URL (no more generic-tip-only)
- team-file write in its own try/catch so a read-only dir can't fake 'Publish failed'
- parseUpdateTarget handles scheme-less URLs + query/hash; X-Space-Id on metadata only (not S3 PUT)
- share readJsonRecord across the local + team descriptors

* test(cli): e2e team-space convergence + cross-space hijack guard

* test(cli): unit-test parseUpdateTarget url shapes (export for test)

* fix(cli): warn on committed-team miss too, not just --update
2026-07-13 22:47:28 -04:00

28 lines
947 B
TypeScript

import { describe, expect, it } from "vitest";
import { parseUpdateTarget } from "./publish.js";
describe("parseUpdateTarget", () => {
it("extracts the id from a full published URL", () => {
expect(parseUpdateTarget("https://hyperframes.dev/p/hfp_abc123")).toBe("hfp_abc123");
});
it("handles a scheme-less URL (which new URL() rejects)", () => {
expect(parseUpdateTarget("hyperframes.dev/p/hfp_abc123")).toBe("hfp_abc123");
});
it("strips a trailing query and hash", () => {
expect(parseUpdateTarget("https://hyperframes.dev/p/hfp_abc123?claim_token=x#frag")).toBe(
"hfp_abc123",
);
});
it("accepts a bare id unchanged and trims surrounding whitespace", () => {
expect(parseUpdateTarget(" hfp_abc123 ")).toBe("hfp_abc123");
});
it("falls back to the last path segment for a non-/p/ URL", () => {
expect(parseUpdateTarget("https://example.com/foo/hfp_abc123")).toBe("hfp_abc123");
});
});