@tuongaz/seeflow 0.1.105 → 0.1.107
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/web/assets/{architectureDiagram-3BPJPVTR-Dn9FQt2V.js → architectureDiagram-3BPJPVTR-C4n2LFo2.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-Difk1XOK.js → blockDiagram-GPEHLZMM-DmYJl-4W.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-2-WiMvCN.js → c4Diagram-AAUBKEIU-BRtrAah9.js} +1 -1
- package/dist/web/assets/channel-Cwz40yCU.js +1 -0
- package/dist/web/assets/{chart-D2hW0kXw.js → chart-BJADfkvF.js} +1 -1
- package/dist/web/assets/{chunk-2J33WTMH-BPHmI1De.js → chunk-2J33WTMH-Cwse2MLm.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-Ay38fe5g.js → chunk-4BX2VUAB-C7yQ1hNl.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-5ygNV__l.js → chunk-55IACEB6-C4JH4uPC.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-kQNWdsxV.js → chunk-727SXJPM-CH7_QMCX.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-DzeeRd3w.js → chunk-AQP2D5EJ-JANvO0oT.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-CUar6TO-.js → chunk-FMBD7UC4-tMpbfhjf.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-CNZ3763c.js → chunk-ND2GUHAM-D9eBypg9.js} +1 -1
- package/dist/web/assets/{chunk-QZHKN3VN-FKGOAesZ.js → chunk-QZHKN3VN-geJeqOM8.js} +1 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-DQJOq1dg.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-DQJOq1dg.js +1 -0
- package/dist/web/assets/{code-block-SZDhhr7T.js → code-block-DNQhzmPc.js} +1 -1
- package/dist/web/assets/{cose-bilkent-S5V4N54A--DNtr1GO.js → cose-bilkent-S5V4N54A-BddhusFd.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-cIlGgsEQ.js → dagre-BM42HDAG-DgzvId-E.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-DjoBzBLH.js → diagram-2AECGRRQ-MDnqZTUO.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-mmesu8tu.js → diagram-5GNKFQAL-CNp33BbA.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-DeKWe4-a.js → diagram-KO2AKTUF-KiwbE7kH.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-NHxUC_r2.js → diagram-LMA3HP47-CbVgSz8_.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-DoVcjbAs.js → diagram-OG6HWLK6-CbuPIx97.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-DOr0sCAJ.js → erDiagram-TEJ5UH35-Cb0DMX_h.js} +1 -1
- package/dist/web/assets/{flowDiagram-I6XJVG4X-Blcjaj5z.js → flowDiagram-I6XJVG4X-BXWZO2JG.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-XOZAg1O8.js → ganttDiagram-6RSMTGT7-BLNBpY-f.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-CwWAqRfA.js → gitGraphDiagram-PVQCEYII-CezBV45Y.js} +1 -1
- package/dist/web/assets/{iconify-pbuBzLPb.js → iconify-Dq4nFnfE.js} +1 -1
- package/dist/web/assets/{index-COPB-kTN.js → index-DOA-g04P.js} +276 -276
- package/dist/web/assets/{index-BfhCAb_k.css → index-TDj3HTQM.css} +1 -1
- package/dist/web/assets/{index.es-BnIUUbgb.js → index.es-DcaYIQmY.js} +1 -1
- package/dist/web/assets/{infoDiagram-5YYISTIA-BDrdYBmZ.js → infoDiagram-5YYISTIA-CCWYa3Vp.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-Ccq3BiV9.js → ishikawaDiagram-YF4QCWOH-CcOMRswO.js} +1 -1
- package/dist/web/assets/{journeyDiagram-JHISSGLW-Byhhmys_.js → journeyDiagram-JHISSGLW-CGh3OzMJ.js} +1 -1
- package/dist/web/assets/{jspdf.es.min-DRscdcGG.js → jspdf.es.min-BND60C1X.js} +3 -3
- package/dist/web/assets/{kanban-definition-UN3LZRKU-C4V7XsI8.js → kanban-definition-UN3LZRKU-wc19qf9j.js} +1 -1
- package/dist/web/assets/{linear-9s7Nhsku.js → linear-DI6gQRSO.js} +1 -1
- package/dist/web/assets/{markdown--co0piIh.js → markdown-CZ5OQFXP.js} +1 -1
- package/dist/web/assets/{mermaid.core-BzxthQo1.js → mermaid.core-CAZGzK0l.js} +4 -4
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-DPEOdrP-.js → mindmap-definition-RKZ34NQL-DEN6ul-4.js} +1 -1
- package/dist/web/assets/{pieDiagram-4H26LBE5-JUVRBM8g.js → pieDiagram-4H26LBE5-BzK5WQ02.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-B-O3T7Ql.js → quadrantDiagram-W4KKPZXB-WpYq-pQF.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-cMHqY0_G.js → requirementDiagram-4Y6WPE33-Ca5ORxLp.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-CO0aG09B.js → sankeyDiagram-5OEKKPKP-DBWaB1Is.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DkvyDkYb.js → sequenceDiagram-3UESZ5HK-BGEYL2Uw.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-DKseQ2AJ.js → stateDiagram-AJRCARHV-Bt3xrb-F.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-DyUVzYNm.js +1 -0
- package/dist/web/assets/{time-E94H-3Js.js → time-DRdnjU-r.js} +1 -1
- package/dist/web/assets/{timeline-definition-PNZ67QCA-B9uWXMTl.js → timeline-definition-PNZ67QCA-D3Avg3RH.js} +1 -1
- package/dist/web/assets/{vennDiagram-CIIHVFJN-DuHHMFEd.js → vennDiagram-CIIHVFJN-DK0Y12Yp.js} +1 -1
- package/dist/web/assets/{wardley-L42UT6IY-C_uCcesD.js → wardley-L42UT6IY-Th41Nnnt.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-DbA4lTWI.js → wardleyDiagram-YWT4CUSO-DYq6kX6q.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-BX4GX1ip.js → xychartDiagram-2RQKCTM6-_nwsSoOi.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/api.ts +53 -3
- package/src/server.ts +1 -0
- package/src/share-envelope.ts +3 -0
- package/src/share.ts +111 -9
- package/dist/web/assets/channel-CrVPaFj0.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-yNcOh78q.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-yNcOh78q.js +0 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-C30cJIVE.js +0 -1
package/src/share.ts
CHANGED
|
@@ -81,13 +81,31 @@ import { type SseTap, createSseTap } from './share/sse-tap.ts';
|
|
|
81
81
|
// re-validate join/leave with their strict required fields so malformed
|
|
82
82
|
// join/leave frames are dropped rather than treated as sideband. Cursor,
|
|
83
83
|
// viewport, and any other future `kind` no-op in v1 per the design doc.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
// Presence payload shapes accepted on the wire. The cloud relay uses
|
|
85
|
+
// `state: 'joined' | 'left' | 'active' | 'idle' | 'host-offline'`; older host
|
|
86
|
+
// builds emitted `kind: 'join' | 'leave'`. We accept either to stay
|
|
87
|
+
// forward/backward compatible.
|
|
88
|
+
const PresenceBaseSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
kind: z.string().optional(),
|
|
91
|
+
state: z.string().optional(),
|
|
92
|
+
})
|
|
93
|
+
.passthrough();
|
|
94
|
+
const PresenceJoinSchema = z
|
|
95
|
+
.object({
|
|
96
|
+
peerId: z.string(),
|
|
97
|
+
displayName: z.string(),
|
|
98
|
+
kind: z.literal('join').optional(),
|
|
99
|
+
state: z.literal('joined').optional(),
|
|
100
|
+
})
|
|
101
|
+
.passthrough();
|
|
102
|
+
const PresenceLeaveSchema = z
|
|
103
|
+
.object({
|
|
104
|
+
peerId: z.string(),
|
|
105
|
+
kind: z.literal('leave').optional(),
|
|
106
|
+
state: z.literal('left').optional(),
|
|
107
|
+
})
|
|
108
|
+
.passthrough();
|
|
91
109
|
|
|
92
110
|
export interface PeerSummary {
|
|
93
111
|
peerId: string;
|
|
@@ -800,15 +818,43 @@ export function createShareController(deps: ShareDeps): ShareController {
|
|
|
800
818
|
});
|
|
801
819
|
};
|
|
802
820
|
|
|
821
|
+
// The studio API receives a flat node-patch body (`name`, `description`,
|
|
822
|
+
// color tokens, `width` / `height`, …) which `mergeNodeUpdates` dispatches
|
|
823
|
+
// into `node.data.*`. The peer SPA applies the wire diff as a shallow merge
|
|
824
|
+
// against the node root, so a flat patch would land at the root and leave
|
|
825
|
+
// `data.*` stale — the renderer reads `data.name` and would silently keep
|
|
826
|
+
// the old label. Normalize the wire shape by reading the post-mutation node
|
|
827
|
+
// from the watcher's snapshot and forwarding the full merged `data` (plus
|
|
828
|
+
// `position` / `type` if they moved). Keeps the peer's shallow-merge
|
|
829
|
+
// semantics correct without changing the wire schema.
|
|
830
|
+
const NODE_ROOT_PATCH_KEYS = new Set(['position', 'type']);
|
|
831
|
+
const canonicalizePatchNode = (op: RpcOp): RpcOp => {
|
|
832
|
+
if (op.op !== 'patchNode') return op;
|
|
833
|
+
const watcher = deps.operationsDeps?.watcher;
|
|
834
|
+
const snap = watcher?.snapshot(op.flowId);
|
|
835
|
+
const node = snap?.flow?.nodes.find((n) => n.id === op.nodeId);
|
|
836
|
+
if (!node) return op;
|
|
837
|
+
const newPatch: Record<string, unknown> = {};
|
|
838
|
+
for (const key of Object.keys(op.patch)) {
|
|
839
|
+
if (NODE_ROOT_PATCH_KEYS.has(key)) {
|
|
840
|
+
newPatch[key] = (node as unknown as Record<string, unknown>)[key];
|
|
841
|
+
} else {
|
|
842
|
+
newPatch.data = node.data;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return { ...op, patch: newPatch };
|
|
846
|
+
};
|
|
847
|
+
|
|
803
848
|
// Build + emit a `node-patched` envelope for an accepted op. Centralized so
|
|
804
849
|
// peer-rpc and host-local edits assemble the wire payload identically (only
|
|
805
850
|
// the `attributedTo` value differs). Returns the version assigned so callers
|
|
806
851
|
// can echo it back into rpc-result if needed.
|
|
807
852
|
const broadcastNodePatched = (
|
|
808
|
-
|
|
853
|
+
rawOp: RpcOp,
|
|
809
854
|
outcome: RpcDispatchOutcome,
|
|
810
855
|
attributedTo: { peerId: string; displayName: string },
|
|
811
856
|
): number => {
|
|
857
|
+
const op = canonicalizePatchNode(rawOp);
|
|
812
858
|
const nextVersion = (flowVersions.get(op.flowId) ?? 0) + 1;
|
|
813
859
|
flowVersions.set(op.flowId, nextVersion);
|
|
814
860
|
const diff = computeNodePatchedDiff(op, outcome);
|
|
@@ -986,6 +1032,50 @@ export function createShareController(deps: ShareDeps): ShareController {
|
|
|
986
1032
|
}
|
|
987
1033
|
};
|
|
988
1034
|
|
|
1035
|
+
// Emit a `flow-snapshot` envelope to a freshly-joined peer so its canvas can
|
|
1036
|
+
// render the host's flow graph. Prefers the watcher's resolved snapshot
|
|
1037
|
+
// (file refs inlined, style merged, schema-validated) so component / icon
|
|
1038
|
+
// / image nodes render without the peer needing to walk the host's
|
|
1039
|
+
// filesystem. Falls back to raw on-disk JSON for setups that boot without
|
|
1040
|
+
// a watcher (CLI smoke tests, integration). Without this the peer is stuck
|
|
1041
|
+
// on "CONNECTING…" forever (viewer's share-session.tsx blocks until
|
|
1042
|
+
// `snapshot` is populated). Errors only warn — the peer can refresh /
|
|
1043
|
+
// rotate to retry.
|
|
1044
|
+
const emitFlowSnapshotForPeer = (peerConnId: string): void => {
|
|
1045
|
+
const registry = deps.operationsDeps?.registry;
|
|
1046
|
+
const watcher = deps.operationsDeps?.watcher;
|
|
1047
|
+
if (!registry) return;
|
|
1048
|
+
const entries = registry.list();
|
|
1049
|
+
if (entries.length === 0) return;
|
|
1050
|
+
const flows: Record<string, unknown> = {};
|
|
1051
|
+
let activeFlowId: string | null = null;
|
|
1052
|
+
for (const entry of entries) {
|
|
1053
|
+
let flow: unknown = null;
|
|
1054
|
+
const snap = watcher?.snapshot(entry.id) ?? watcher?.reparse(entry.id) ?? null;
|
|
1055
|
+
if (snap?.valid && snap.flow) {
|
|
1056
|
+
flow = snap.flow;
|
|
1057
|
+
} else {
|
|
1058
|
+
try {
|
|
1059
|
+
flow = JSON.parse(readFileSync(join(entry.repoPath, entry.flowPath), 'utf8'));
|
|
1060
|
+
} catch (err) {
|
|
1061
|
+
console.warn(`[share] flow-snapshot read failed for ${entry.id}:`, err);
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
flows[entry.id] = flow;
|
|
1066
|
+
if (activeFlowId === null) activeFlowId = entry.id;
|
|
1067
|
+
if (entry.isDefault) activeFlowId = entry.id;
|
|
1068
|
+
}
|
|
1069
|
+
if (!activeFlowId) return;
|
|
1070
|
+
try {
|
|
1071
|
+
broadcast(
|
|
1072
|
+
makeEnvelope('flow-snapshot', { flows, activeFlowId }, { to: peerConnId, from: 'host' }),
|
|
1073
|
+
);
|
|
1074
|
+
} catch (err) {
|
|
1075
|
+
console.warn('[share] flow-snapshot broadcast failed:', err);
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
|
|
989
1079
|
const handleFrame = (env: Envelope) => {
|
|
990
1080
|
if (env.type === 'presence') {
|
|
991
1081
|
const base = PresenceBaseSchema.safeParse(env.payload);
|
|
@@ -993,7 +1083,15 @@ export function createShareController(deps: ShareDeps): ShareController {
|
|
|
993
1083
|
console.warn('[share] dropped presence frame: invalid payload');
|
|
994
1084
|
return;
|
|
995
1085
|
}
|
|
996
|
-
|
|
1086
|
+
// Relay uses `state: 'joined'/'left'/...`; older host builds emitted
|
|
1087
|
+
// `kind: 'join'/'leave'`. Map either onto our internal verbs.
|
|
1088
|
+
const kind =
|
|
1089
|
+
base.data.kind ??
|
|
1090
|
+
(base.data.state === 'joined'
|
|
1091
|
+
? 'join'
|
|
1092
|
+
: base.data.state === 'left'
|
|
1093
|
+
? 'leave'
|
|
1094
|
+
: base.data.state);
|
|
997
1095
|
if (kind === 'join') {
|
|
998
1096
|
const parsed = PresenceJoinSchema.safeParse(env.payload);
|
|
999
1097
|
if (!parsed.success) {
|
|
@@ -1020,6 +1118,10 @@ export function createShareController(deps: ShareDeps): ShareController {
|
|
|
1020
1118
|
...current,
|
|
1021
1119
|
peers: [...current.peers, { peerId, displayName, joinedAt: Date.now() }],
|
|
1022
1120
|
});
|
|
1121
|
+
// Prime the new peer with the host's flow graph first — without this
|
|
1122
|
+
// the peer is stuck on "CONNECTING…" forever (viewer waits on
|
|
1123
|
+
// snapshot before rendering the canvas).
|
|
1124
|
+
emitFlowSnapshotForPeer(env.from);
|
|
1023
1125
|
// Prime the new peer with a one-shot files-manifest snapshot so its
|
|
1024
1126
|
// canvas can render placeholder sizing before any file-request fires.
|
|
1025
1127
|
// Fire-and-forget; emit failures are warned, never propagated.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{U as a,C as n}from"./mermaid.core-BzxthQo1.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,a as s,c as e,C as t}from"./chunk-727SXJPM-kQNWdsxV.js";import{a as i}from"./mermaid.core-BzxthQo1.js";import"./index-COPB-kTN.js";import"./chunk-FMBD7UC4-CUar6TO-.js";import"./chunk-ND2GUHAM-CNZ3763c.js";import"./chunk-55IACEB6-5ygNV__l.js";import"./chunk-2J33WTMH-BPHmI1De.js";import"./purify.es-CLGrRn1w.js";import"./step-CWvwoXpJ.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,a as s,c as e,C as t}from"./chunk-727SXJPM-kQNWdsxV.js";import{a as i}from"./mermaid.core-BzxthQo1.js";import"./index-COPB-kTN.js";import"./chunk-FMBD7UC4-CUar6TO-.js";import"./chunk-ND2GUHAM-CNZ3763c.js";import"./chunk-55IACEB6-5ygNV__l.js";import"./chunk-2J33WTMH-BPHmI1De.js";import"./purify.es-CLGrRn1w.js";import"./step-CWvwoXpJ.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as r,a as e,s as a,S as s}from"./chunk-AQP2D5EJ-DzeeRd3w.js";import{a as i}from"./mermaid.core-BzxthQo1.js";import"./index-COPB-kTN.js";import"./chunk-55IACEB6-5ygNV__l.js";import"./chunk-2J33WTMH-BPHmI1De.js";import"./purify.es-CLGrRn1w.js";import"./step-CWvwoXpJ.js";var n={parser:a,get db(){return new s(2)},renderer:e,styles:r,init:i(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{n as diagram};
|