@pygmalionjs/pygmalion 0.2.16 → 0.2.18

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.
@@ -114,6 +114,34 @@ function escapeRegExp(value) {
114
114
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
115
115
  }
116
116
 
117
+ /**
118
+ * Revisions the mirror can be repointed at: local branches first, then remote
119
+ * tracking branches. Listing them is what lets an editor offer a choice instead
120
+ * of asking for a ref string.
121
+ */
122
+ export async function listSourceRefs(repoRoot, remote = 'origin') {
123
+ const format = '%(refname:short)%09%(objectname:short=8)%09%(refname)';
124
+ const read = async (...patterns) => {
125
+ const raw = await git(repoRoot, 'for-each-ref', `--format=${format}`, ...patterns);
126
+ if (!raw) return [];
127
+ return raw
128
+ .split('\n')
129
+ .map((line) => line.split('\t'))
130
+ .filter((parts) => parts.length === 3 && parts[0])
131
+ .map(([name, commit, fullName]) => ({ name, commit, fullName }));
132
+ };
133
+ const locals = (await read('refs/heads')).map((item) => ({ ...item, kind: 'local' }));
134
+ const remotes = (await read(`refs/remotes/${remote}`))
135
+ .filter((item) => !item.name.endsWith('/HEAD'))
136
+ .map((item) => ({ ...item, kind: 'remote' }));
137
+ const seen = new Set();
138
+ return [...locals, ...remotes].filter((item) => {
139
+ if (seen.has(item.name)) return false;
140
+ seen.add(item.name);
141
+ return true;
142
+ });
143
+ }
144
+
117
145
  /**
118
146
  * Renders the current working tree, uncommitted changes included, instead of a
119
147
  * committed ref. Resolved to a throwaway commit at sync time.
@@ -673,6 +701,22 @@ export function pygmalionDevMirrorPlugin(options) {
673
701
  json(res, 200, status);
674
702
  return;
675
703
  }
704
+ if (url.pathname === `${control}/refs` && req.method === 'GET') {
705
+ try {
706
+ json(res, 200, {
707
+ refs: await listSourceRefs(repoRoot, remote),
708
+ sourceRef: ref,
709
+ defaultRef: `${remote}/${branch}`,
710
+ worktreeRef: PYGMALION_WORKTREE_SOURCE_REF,
711
+ });
712
+ } catch (error) {
713
+ json(res, 500, {
714
+ ok: false,
715
+ error: error instanceof Error ? error.message : String(error),
716
+ });
717
+ }
718
+ return;
719
+ }
676
720
  if (url.pathname === `${control}/refresh` && req.method === 'POST') {
677
721
  let requestedRef;
678
722
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pygmalionjs/pygmalion",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "description": "Code-backed DOM design sandbox and visual QA editor",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
package/types.d.ts CHANGED
@@ -1545,6 +1545,39 @@ export interface PygmalionProjectRuntimeOptions {
1545
1545
  ) => string | undefined;
1546
1546
  }
1547
1547
 
1548
+ /** One revision the mirror can be repointed at. */
1549
+ export interface PygmalionSourceRef {
1550
+ name: string;
1551
+ commit: string;
1552
+ fullName: string;
1553
+ kind: 'local' | 'remote';
1554
+ }
1555
+
1556
+ /** Revisions available to `switchSource`, listed from the mirror repository. */
1557
+ export interface PygmalionSourceRefs {
1558
+ refs: readonly PygmalionSourceRef[];
1559
+ /** Revision followed when none is pinned. */
1560
+ defaultRef: string | null;
1561
+ /** Ref that renders uncommitted work. */
1562
+ worktreeRef: string | null;
1563
+ }
1564
+
1565
+ export interface SourceRefControlProps {
1566
+ value: string | null;
1567
+ refs: readonly PygmalionSourceRef[];
1568
+ onChange(ref: string): void;
1569
+ busy?: boolean;
1570
+ defaultRef?: string | null;
1571
+ worktreeRef?: string | null;
1572
+ label?: string;
1573
+ /** Trigger content. Defaults to the selected revision. */
1574
+ children?: ReactNode;
1575
+ className?: string;
1576
+ }
1577
+
1578
+ /** Selects the revision the dev mirror follows. Owned by Pygmalion, not by the host. */
1579
+ export declare function SourceRefControl(props: SourceRefControlProps): ReactElement;
1580
+
1548
1581
  export interface PygmalionProjectRuntime {
1549
1582
  mirror: PygmalionDevMirrorStatus;
1550
1583
  session: PygmalionDesignSessionStatus | null;
@@ -1567,6 +1600,12 @@ export interface PygmalionProjectRuntime {
1567
1600
  sourceRef: string,
1568
1601
  options?: { discardEdits?: boolean },
1569
1602
  ): Promise<void>;
1603
+ /**
1604
+ * Revisions `switchSource` can be given. Empty until listed, so a host can
1605
+ * offer a choice instead of asking for a ref string.
1606
+ */
1607
+ sourceRefs: PygmalionSourceRefs;
1608
+ loadSourceRefs(): Promise<PygmalionSourceRefs>;
1570
1609
  previewVisual(payload: InspectApplyPayload): Promise<InspectPreviewResult>;
1571
1610
  inspectImpact(componentFiles: string[]): Promise<InspectImpactResult>;
1572
1611
  applyVisual(payload: InspectApplyPayload): Promise<InspectApplyResult>;