@ansible-flow/core 0.85.0 → 0.87.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/README.md +1 -1
- package/dist/ai/describe.js +4 -3
- package/dist/ai/handlers.js +17 -16
- package/dist/ai/handlers.js.map +1 -1
- package/dist/ai/ops.js +5 -4
- package/dist/ai/scenarios.js +9 -7
- package/dist/awx/import.js +6 -5
- package/dist/catalog/draft.d.ts +2 -0
- package/dist/catalog/draft.js +23 -4
- package/dist/catalog/draft.js.map +2 -2
- package/dist/chunks/{chunk-BXHI5EQM.js → chunk-2DT5DOSO.js} +43 -1
- package/dist/chunks/chunk-2DT5DOSO.js.map +7 -0
- package/dist/chunks/{chunk-CXVJWFGT.js → chunk-2MJKBPGG.js} +2 -2
- package/dist/chunks/{chunk-JTWR3TGG.js → chunk-2P3JEHLH.js} +4 -4
- package/dist/chunks/{chunk-6M3OG3E4.js → chunk-3Z4WABFK.js} +6 -6
- package/dist/chunks/{chunk-ZAYNYPCX.js → chunk-ARA3VJR2.js} +2 -2
- package/dist/chunks/{chunk-2HMLC2AO.js → chunk-BNMW6KWK.js} +6 -6
- package/dist/chunks/{chunk-CM23ODBB.js → chunk-DL4LYODQ.js} +2 -2
- package/dist/chunks/chunk-FIKPXL6E.js +23 -0
- package/dist/chunks/chunk-FIKPXL6E.js.map +7 -0
- package/dist/chunks/{chunk-ABYJBONR.js → chunk-FMCBTYUM.js} +3 -3
- package/dist/chunks/{chunk-J7KCGVHU.js → chunk-HPRG2672.js} +2 -2
- package/dist/chunks/{chunk-V2SPY2EI.js → chunk-IXW7A4M7.js} +2 -2
- package/dist/chunks/{chunk-22D2NC2L.js → chunk-IZJPLWDY.js} +5 -5
- package/dist/chunks/{chunk-MZ6IJWB2.js → chunk-KZALUEFT.js} +2 -2
- package/dist/chunks/{chunk-XOPGOWNQ.js → chunk-O5Y3AZ4X.js} +1 -1
- package/dist/chunks/chunk-O5Y3AZ4X.js.map +7 -0
- package/dist/chunks/{chunk-2QQC4IZ7.js → chunk-PNLY5IWM.js} +8 -8
- package/dist/chunks/chunk-PNLY5IWM.js.map +7 -0
- package/dist/chunks/{chunk-T5UB4MBB.js → chunk-TOTSB4HG.js} +41 -1
- package/dist/chunks/chunk-TOTSB4HG.js.map +7 -0
- package/dist/chunks/{chunk-7GLSXIZ3.js → chunk-W2CSOAIB.js} +2 -2
- package/dist/chunks/{chunk-UXIXXEIW.js → chunk-WSARMPYU.js} +2 -2
- package/dist/engine/bypass.js +4 -2
- package/dist/engine/engines.js +6 -4
- package/dist/engine/files.js +6 -4
- package/dist/engine/optionA.js +5 -3
- package/dist/engine/partial.js +3 -1
- package/dist/engine/partial.js.map +1 -1
- package/dist/engine/preview.js +6 -4
- package/dist/engine/preview.js.map +1 -1
- package/dist/engine/writePlan.js +9 -8
- package/dist/flow/commands.d.ts +10 -0
- package/dist/flow/commands.js +3 -1
- package/dist/flow/facts.d.ts +6 -0
- package/dist/flow/facts.js +13 -0
- package/dist/flow/facts.js.map +7 -0
- package/dist/flow/merge.d.ts +27 -0
- package/dist/flow/merge.js +422 -0
- package/dist/flow/merge.js.map +7 -0
- package/dist/flow/mergeText.d.ts +3 -0
- package/dist/flow/mergeText.js +71 -0
- package/dist/flow/mergeText.js.map +7 -0
- package/dist/flow/save.js +3 -1
- package/dist/flow/save.js.map +1 -1
- package/dist/flow/validate.js +3 -2
- package/dist/flow/valueText.d.ts +6 -0
- package/dist/flow/valueText.js +56 -0
- package/dist/flow/valueText.js.map +7 -0
- package/dist/import/outline.js +6 -5
- package/dist/import/playbook.js +5 -4
- package/dist/lens/caption.js +1 -1
- package/dist/lens/data.js +3 -1
- package/dist/lens/index.js +6 -4
- package/dist/lens/index.js.map +1 -1
- package/dist/lens/types.d.ts +2 -0
- package/dist/lens/types.js +1 -1
- package/dist/messageCheck.js +4 -0
- package/dist/messageCheck.js.map +2 -2
- package/dist/protocol.d.ts +45 -0
- package/dist/scenario/live.js +7 -5
- package/dist/scenario/simulate.js +6 -4
- package/dist/view/flowFacts.js +9 -8
- package/dist/view/flowFacts.js.map +1 -1
- package/dist/view/jinjaComplete.js +3 -3
- package/dist/view/serverChange.d.ts +23 -0
- package/dist/view/serverChange.js +48 -0
- package/dist/view/serverChange.js.map +7 -0
- package/package.json +1 -1
- package/dist/chunks/chunk-2QQC4IZ7.js.map +0 -7
- package/dist/chunks/chunk-BXHI5EQM.js.map +0 -7
- package/dist/chunks/chunk-T5UB4MBB.js.map +0 -7
- package/dist/chunks/chunk-XOPGOWNQ.js.map +0 -7
- /package/dist/chunks/{chunk-CXVJWFGT.js.map → chunk-2MJKBPGG.js.map} +0 -0
- /package/dist/chunks/{chunk-JTWR3TGG.js.map → chunk-2P3JEHLH.js.map} +0 -0
- /package/dist/chunks/{chunk-6M3OG3E4.js.map → chunk-3Z4WABFK.js.map} +0 -0
- /package/dist/chunks/{chunk-ZAYNYPCX.js.map → chunk-ARA3VJR2.js.map} +0 -0
- /package/dist/chunks/{chunk-2HMLC2AO.js.map → chunk-BNMW6KWK.js.map} +0 -0
- /package/dist/chunks/{chunk-CM23ODBB.js.map → chunk-DL4LYODQ.js.map} +0 -0
- /package/dist/chunks/{chunk-ABYJBONR.js.map → chunk-FMCBTYUM.js.map} +0 -0
- /package/dist/chunks/{chunk-J7KCGVHU.js.map → chunk-HPRG2672.js.map} +0 -0
- /package/dist/chunks/{chunk-V2SPY2EI.js.map → chunk-IXW7A4M7.js.map} +0 -0
- /package/dist/chunks/{chunk-22D2NC2L.js.map → chunk-IZJPLWDY.js.map} +0 -0
- /package/dist/chunks/{chunk-MZ6IJWB2.js.map → chunk-KZALUEFT.js.map} +0 -0
- /package/dist/chunks/{chunk-7GLSXIZ3.js.map → chunk-W2CSOAIB.js.map} +0 -0
- /package/dist/chunks/{chunk-UXIXXEIW.js.map → chunk-WSARMPYU.js.map} +0 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import {
|
|
2
|
+
canonical
|
|
3
|
+
} from "../chunks/chunk-TG3C3GIL.js";
|
|
4
|
+
import {
|
|
5
|
+
withIds
|
|
6
|
+
} from "../chunks/chunk-XRGZNPPO.js";
|
|
7
|
+
import "../chunks/chunk-VG3RKETK.js";
|
|
8
|
+
import "../chunks/chunk-TS4N2EIO.js";
|
|
9
|
+
import "../chunks/chunk-BCX7P6SV.js";
|
|
10
|
+
import "../chunks/chunk-3Z2U3LN7.js";
|
|
11
|
+
import "../chunks/chunk-GHG3VINX.js";
|
|
12
|
+
import "../chunks/chunk-5TUAMVIV.js";
|
|
13
|
+
import "../chunks/chunk-45CE2RUH.js";
|
|
14
|
+
import "../chunks/chunk-E2YZJWO7.js";
|
|
15
|
+
import "../chunks/chunk-ZP5LQ4XC.js";
|
|
16
|
+
import {
|
|
17
|
+
ROOT
|
|
18
|
+
} from "../chunks/chunk-2OD7UZ7V.js";
|
|
19
|
+
import "../chunks/chunk-AGWQ3ANE.js";
|
|
20
|
+
|
|
21
|
+
// src/core/flow/merge.ts
|
|
22
|
+
function flatten(doc) {
|
|
23
|
+
const flat = {
|
|
24
|
+
doc,
|
|
25
|
+
nodes: /* @__PURE__ */ new Map(),
|
|
26
|
+
edges: /* @__PURE__ */ new Map(),
|
|
27
|
+
annotations: /* @__PURE__ */ new Map(),
|
|
28
|
+
rootKeys: ["annotations", "layout", "decisions"].filter((k) => k in doc)
|
|
29
|
+
};
|
|
30
|
+
const visit = (level, nodes, edges, annotations, layout) => {
|
|
31
|
+
for (const node of nodes ?? []) {
|
|
32
|
+
if (!node?.id) continue;
|
|
33
|
+
const { subflow, ...own } = node;
|
|
34
|
+
flat.nodes.set(node.id, {
|
|
35
|
+
level,
|
|
36
|
+
own,
|
|
37
|
+
...subflow ? {
|
|
38
|
+
body: {
|
|
39
|
+
...subflow.boundary ? { boundary: subflow.boundary } : {},
|
|
40
|
+
keys: Object.keys(subflow)
|
|
41
|
+
}
|
|
42
|
+
} : {},
|
|
43
|
+
...layout?.[node.id] ? { position: layout[node.id] } : {}
|
|
44
|
+
});
|
|
45
|
+
if (subflow)
|
|
46
|
+
visit(node.id, subflow.nodes, subflow.edges, subflow.annotations, subflow.layout);
|
|
47
|
+
}
|
|
48
|
+
for (const edge of edges ?? []) if (edge?.id) flat.edges.set(edge.id, { level, edge });
|
|
49
|
+
for (const a of annotations ?? [])
|
|
50
|
+
if (a?.id) flat.annotations.set(a.id, { level, annotation: a });
|
|
51
|
+
};
|
|
52
|
+
visit(ROOT, doc.nodes, doc.edges, doc.annotations, doc.layout);
|
|
53
|
+
return flat;
|
|
54
|
+
}
|
|
55
|
+
var same = (a, b) => JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));
|
|
56
|
+
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
57
|
+
var Merger = class {
|
|
58
|
+
constructor(choices) {
|
|
59
|
+
this.choices = choices;
|
|
60
|
+
}
|
|
61
|
+
choices;
|
|
62
|
+
conflicts = [];
|
|
63
|
+
pick(id) {
|
|
64
|
+
return this.choices[id] ?? "ours";
|
|
65
|
+
}
|
|
66
|
+
conflict(c) {
|
|
67
|
+
this.conflicts.push(c);
|
|
68
|
+
return this.pick(c.id);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* One value, three ways. Records are merged key by key `depth` levels down; a value both sides
|
|
72
|
+
* changed differently is a conflict named by `id` (`<owner>:<field>`).
|
|
73
|
+
*/
|
|
74
|
+
value(base, ours, theirs, at, depth) {
|
|
75
|
+
if (same(ours, theirs)) return ours;
|
|
76
|
+
if (same(base, ours)) return theirs;
|
|
77
|
+
if (same(base, theirs)) return ours;
|
|
78
|
+
if (depth > 0 && isRecord(ours) && isRecord(theirs) && (base === void 0 || isRecord(base))) {
|
|
79
|
+
const out = {};
|
|
80
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(ours), ...Object.keys(theirs)])) {
|
|
81
|
+
const v = this.value(
|
|
82
|
+
base?.[key],
|
|
83
|
+
ours[key],
|
|
84
|
+
theirs[key],
|
|
85
|
+
{
|
|
86
|
+
...at,
|
|
87
|
+
id: `${at.id}.${key}`,
|
|
88
|
+
field: at.field ? `${at.field}.${key}` : key
|
|
89
|
+
},
|
|
90
|
+
depth - 1
|
|
91
|
+
);
|
|
92
|
+
if (v !== void 0) out[key] = v;
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
const side = this.conflict({
|
|
97
|
+
...at.owner,
|
|
98
|
+
id: at.id,
|
|
99
|
+
kind: "value",
|
|
100
|
+
label: at.field ? `${at.label}: ${at.field}` : at.label,
|
|
101
|
+
...at.field ? { field: at.field } : {},
|
|
102
|
+
base,
|
|
103
|
+
ours,
|
|
104
|
+
theirs
|
|
105
|
+
});
|
|
106
|
+
return side === "ours" ? ours : theirs;
|
|
107
|
+
}
|
|
108
|
+
/** The fields of a record, each merged on its own (`depth` levels down inside each). */
|
|
109
|
+
fields(base, ours, theirs, at, depth) {
|
|
110
|
+
const out = {};
|
|
111
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(ours), ...Object.keys(theirs)])) {
|
|
112
|
+
const v = this.value(
|
|
113
|
+
base?.[key],
|
|
114
|
+
ours[key],
|
|
115
|
+
theirs[key],
|
|
116
|
+
{ ...at, id: `${at.id}:${key}`, field: key },
|
|
117
|
+
depth
|
|
118
|
+
);
|
|
119
|
+
if (v !== void 0) out[key] = v;
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
function quiet(base, ours, theirs) {
|
|
125
|
+
return same(base, ours) ? theirs : ours;
|
|
126
|
+
}
|
|
127
|
+
function mergeFlows(baseDoc, oursDoc, theirsDoc, choices = {}) {
|
|
128
|
+
const m = new Merger(choices);
|
|
129
|
+
if (oursDoc.schema_version !== theirsDoc.schema_version) {
|
|
130
|
+
const side = m.conflict({
|
|
131
|
+
id: "format",
|
|
132
|
+
kind: "format",
|
|
133
|
+
label: `The flow's format: ${oursDoc.schema_version} here, ${theirsDoc.schema_version} in theirs (upgrade both first)`,
|
|
134
|
+
ours: oursDoc.schema_version,
|
|
135
|
+
theirs: theirsDoc.schema_version
|
|
136
|
+
});
|
|
137
|
+
return { doc: side === "ours" ? oursDoc : theirsDoc, conflicts: m.conflicts };
|
|
138
|
+
}
|
|
139
|
+
const base = flatten(withIds(baseDoc));
|
|
140
|
+
const ours = flatten(withIds(oursDoc));
|
|
141
|
+
const theirs = flatten(withIds(theirsDoc));
|
|
142
|
+
const titleOf = (id) => (ours.nodes.get(id) ?? theirs.nodes.get(id) ?? base.nodes.get(id))?.own.title ?? id;
|
|
143
|
+
const touched = (side, id, seen = /* @__PURE__ */ new Set()) => {
|
|
144
|
+
if (seen.has(id)) return false;
|
|
145
|
+
seen.add(id);
|
|
146
|
+
const now = side.nodes.get(id);
|
|
147
|
+
const was = base.nodes.get(id);
|
|
148
|
+
if (!now) return false;
|
|
149
|
+
if (!was || !same(now.own, was.own) || now.level !== was.level || !same(now.body, was.body))
|
|
150
|
+
return true;
|
|
151
|
+
for (const [eid, e] of side.edges)
|
|
152
|
+
if ((e.edge.from.node === id || e.edge.to.node === id) && !same(e, base.edges.get(eid)))
|
|
153
|
+
return true;
|
|
154
|
+
for (const [aid, a] of side.annotations)
|
|
155
|
+
if ((a.annotation.on === id || a.level === id) && !same(a, base.annotations.get(aid)))
|
|
156
|
+
return true;
|
|
157
|
+
for (const [cid, c] of side.nodes) if (c.level === id && touched(side, cid, seen)) return true;
|
|
158
|
+
return false;
|
|
159
|
+
};
|
|
160
|
+
const order = (key) => [
|
|
161
|
+
.../* @__PURE__ */ new Set([...ours[key].keys(), ...theirs[key].keys(), ...base[key].keys()])
|
|
162
|
+
];
|
|
163
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
164
|
+
for (const id of order("nodes")) {
|
|
165
|
+
const b = base.nodes.get(id);
|
|
166
|
+
const o = ours.nodes.get(id);
|
|
167
|
+
const t = theirs.nodes.get(id);
|
|
168
|
+
if (!o && !t) continue;
|
|
169
|
+
if (b && (!o || !t)) {
|
|
170
|
+
const kept = o ?? t;
|
|
171
|
+
if (!touched(o ? ours : theirs, id)) continue;
|
|
172
|
+
const side = m.conflict({
|
|
173
|
+
id: `node:${id}`,
|
|
174
|
+
kind: "removed",
|
|
175
|
+
node: id,
|
|
176
|
+
label: `${titleOf(id)}: removed ${o ? "in theirs" : "here"}, changed ${o ? "here" : "in theirs"}`,
|
|
177
|
+
ours: o ? "changed" : "removed",
|
|
178
|
+
theirs: o ? "removed" : "changed"
|
|
179
|
+
});
|
|
180
|
+
if (side === "ours" === !!o) nodes.set(id, kept);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (!o || !t) {
|
|
184
|
+
nodes.set(id, o ?? t);
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const owner = { node: id };
|
|
188
|
+
const label = titleOf(id);
|
|
189
|
+
const own = m.fields(
|
|
190
|
+
b?.own,
|
|
191
|
+
o.own,
|
|
192
|
+
t.own,
|
|
193
|
+
{ id: `node:${id}`, label, owner },
|
|
194
|
+
3
|
|
195
|
+
);
|
|
196
|
+
const level2 = m.value(
|
|
197
|
+
b?.level,
|
|
198
|
+
o.level,
|
|
199
|
+
t.level,
|
|
200
|
+
{ id: `node:${id}:level`, label, field: "level (moved into another subflow)", owner },
|
|
201
|
+
0
|
|
202
|
+
);
|
|
203
|
+
let body;
|
|
204
|
+
const hasBody = m.value(
|
|
205
|
+
!!b?.body,
|
|
206
|
+
!!o.body,
|
|
207
|
+
!!t.body,
|
|
208
|
+
{ id: `node:${id}:subflow`, label, field: "subflow", owner },
|
|
209
|
+
0
|
|
210
|
+
);
|
|
211
|
+
if (hasBody) {
|
|
212
|
+
const boundary = m.value(
|
|
213
|
+
b?.body?.boundary,
|
|
214
|
+
o.body?.boundary,
|
|
215
|
+
t.body?.boundary,
|
|
216
|
+
{ id: `node:${id}:boundary`, label, field: "boundary", owner },
|
|
217
|
+
2
|
|
218
|
+
);
|
|
219
|
+
body = {
|
|
220
|
+
...boundary ? { boundary } : {},
|
|
221
|
+
keys: [.../* @__PURE__ */ new Set([...o.body?.keys ?? [], ...t.body?.keys ?? []])]
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
const position = quiet(b?.position, o.position, t.position);
|
|
225
|
+
nodes.set(id, {
|
|
226
|
+
level: level2,
|
|
227
|
+
own,
|
|
228
|
+
...body ? { body } : {},
|
|
229
|
+
...position ? { position } : {}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
for (let again = true; again; ) {
|
|
233
|
+
again = false;
|
|
234
|
+
for (const [id, n] of nodes)
|
|
235
|
+
if (n.level !== ROOT && !nodes.get(n.level)?.body) {
|
|
236
|
+
nodes.delete(id);
|
|
237
|
+
again = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const edges = /* @__PURE__ */ new Map();
|
|
241
|
+
for (const id of order("edges")) {
|
|
242
|
+
const b = base.edges.get(id);
|
|
243
|
+
const o = ours.edges.get(id);
|
|
244
|
+
const t = theirs.edges.get(id);
|
|
245
|
+
if (!o && !t) continue;
|
|
246
|
+
if (b && (!o || !t)) {
|
|
247
|
+
const kept = o ?? t;
|
|
248
|
+
if (same(kept, b)) continue;
|
|
249
|
+
const side = m.conflict({
|
|
250
|
+
id: `wire:${id}`,
|
|
251
|
+
kind: "wire",
|
|
252
|
+
edge: id,
|
|
253
|
+
label: `The wire from ${titleOf(kept.edge.from.node)} (${kept.edge.from.port}): removed ${o ? "in theirs" : "here"}, changed ${o ? "here" : "in theirs"}`,
|
|
254
|
+
ours: o ? kept.edge : void 0,
|
|
255
|
+
theirs: o ? void 0 : kept.edge
|
|
256
|
+
});
|
|
257
|
+
if (side === "ours" === !!o) edges.set(id, { ...kept, from: o ? "ours" : "theirs" });
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (!o || !t) {
|
|
261
|
+
edges.set(id, { ...o ?? t, from: o ? "ours" : "theirs" });
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const merged = m.value(
|
|
265
|
+
b,
|
|
266
|
+
o,
|
|
267
|
+
t,
|
|
268
|
+
{
|
|
269
|
+
id: `wire:${id}`,
|
|
270
|
+
label: `The wire from ${titleOf(o.edge.from.node)} (${o.edge.from.port})`,
|
|
271
|
+
field: "",
|
|
272
|
+
owner: { edge: id }
|
|
273
|
+
},
|
|
274
|
+
0
|
|
275
|
+
);
|
|
276
|
+
edges.set(id, { ...merged, from: "both" });
|
|
277
|
+
}
|
|
278
|
+
const ends = /* @__PURE__ */ new Set();
|
|
279
|
+
for (const [id, e] of edges) {
|
|
280
|
+
const a = nodes.get(e.edge.from.node);
|
|
281
|
+
const z = nodes.get(e.edge.to.node);
|
|
282
|
+
const key = `${e.level}|${e.edge.from.node}.${e.edge.from.port}>${e.edge.to.node}.${e.edge.to.port}`;
|
|
283
|
+
if (!a || !z || a.level !== e.level || z.level !== e.level || ends.has(key)) edges.delete(id);
|
|
284
|
+
else ends.add(key);
|
|
285
|
+
}
|
|
286
|
+
const byPort = /* @__PURE__ */ new Map();
|
|
287
|
+
for (const [id, e] of edges) {
|
|
288
|
+
const key = `${e.edge.from.node}|${e.edge.from.port}`;
|
|
289
|
+
byPort.set(key, [...byPort.get(key) ?? [], id]);
|
|
290
|
+
}
|
|
291
|
+
for (const [key, ids] of byPort) {
|
|
292
|
+
if (ids.length < 2) continue;
|
|
293
|
+
const sides = new Set(ids.map((id) => edges.get(id)?.from));
|
|
294
|
+
if (!sides.has("ours") && !sides.has("theirs")) continue;
|
|
295
|
+
const [node = "", port = ""] = key.split("|");
|
|
296
|
+
const target = (s) => ids.filter((id) => (s === "ours" ? ours : theirs).edges.has(id)).map((id) => titleOf(edges.get(id)?.edge.to.node ?? "")).join(", ");
|
|
297
|
+
const side = m.conflict({
|
|
298
|
+
id: `port:${node}.${port}`,
|
|
299
|
+
kind: "wire",
|
|
300
|
+
node,
|
|
301
|
+
label: `${titleOf(node)}: port ${port} wired to ${target("ours") || "nothing"} here, to ${target("theirs") || "nothing"} in theirs`,
|
|
302
|
+
field: `ports.${port}`,
|
|
303
|
+
ours: target("ours"),
|
|
304
|
+
theirs: target("theirs")
|
|
305
|
+
});
|
|
306
|
+
const keep = side === "ours" ? ours : theirs;
|
|
307
|
+
for (const id of ids) if (!keep.edges.has(id)) edges.delete(id);
|
|
308
|
+
}
|
|
309
|
+
const annotations = /* @__PURE__ */ new Map();
|
|
310
|
+
const PLACE = ["x", "y", "width", "height"];
|
|
311
|
+
for (const id of order("annotations")) {
|
|
312
|
+
const b = base.annotations.get(id);
|
|
313
|
+
const o = ours.annotations.get(id);
|
|
314
|
+
const t = theirs.annotations.get(id);
|
|
315
|
+
if (!o && !t) continue;
|
|
316
|
+
if (b && (!o || !t)) {
|
|
317
|
+
const kept = o ?? t;
|
|
318
|
+
if (same(kept, b)) continue;
|
|
319
|
+
const side = m.conflict({
|
|
320
|
+
id: `note:${id}`,
|
|
321
|
+
kind: "removed",
|
|
322
|
+
annotation: id,
|
|
323
|
+
label: `The note "${kept.annotation.text.split("\n")[0]}": removed ${o ? "in theirs" : "here"}, changed ${o ? "here" : "in theirs"}`,
|
|
324
|
+
ours: o ? "changed" : "removed",
|
|
325
|
+
theirs: o ? "removed" : "changed"
|
|
326
|
+
});
|
|
327
|
+
if (side === "ours" === !!o) annotations.set(id, kept);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (!o || !t) {
|
|
331
|
+
annotations.set(id, o ?? t);
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
const strip = (a) => a && Object.fromEntries(Object.entries(a).filter(([k]) => !PLACE.includes(k)));
|
|
335
|
+
const label = `The note "${o.annotation.text.split("\n")[0]}"`;
|
|
336
|
+
const fields = m.fields(
|
|
337
|
+
strip(b?.annotation),
|
|
338
|
+
strip(o.annotation),
|
|
339
|
+
strip(t.annotation),
|
|
340
|
+
{ id: `note:${id}`, label, owner: { annotation: id } },
|
|
341
|
+
1
|
|
342
|
+
);
|
|
343
|
+
const place = {};
|
|
344
|
+
for (const k of PLACE) {
|
|
345
|
+
const v = quiet(
|
|
346
|
+
b?.annotation?.[k],
|
|
347
|
+
o.annotation[k],
|
|
348
|
+
t.annotation[k]
|
|
349
|
+
);
|
|
350
|
+
if (v !== void 0) place[k] = v;
|
|
351
|
+
}
|
|
352
|
+
const level2 = quiet(b?.level, o.level, t.level) ?? o.level;
|
|
353
|
+
annotations.set(id, { level: level2, annotation: { ...fields, ...place } });
|
|
354
|
+
}
|
|
355
|
+
for (const [id, a] of annotations)
|
|
356
|
+
if (a.level !== ROOT && !nodes.get(a.level)?.body || a.annotation.on && !nodes.has(a.annotation.on))
|
|
357
|
+
annotations.delete(id);
|
|
358
|
+
const { version: vb, ...hb } = base.doc.flow;
|
|
359
|
+
const { version: vo, ...ho } = ours.doc.flow;
|
|
360
|
+
const { version: vt, ...ht } = theirs.doc.flow;
|
|
361
|
+
const header = m.fields(
|
|
362
|
+
hb,
|
|
363
|
+
ho,
|
|
364
|
+
ht,
|
|
365
|
+
{ id: "flow", label: "The flow", owner: {} },
|
|
366
|
+
2
|
|
367
|
+
);
|
|
368
|
+
const version = vo === vt ? vo : vo === vb ? vt : vt === vb ? vo : Math.max(vo, vt) + 1;
|
|
369
|
+
const ident = (d) => JSON.stringify(canonical(d));
|
|
370
|
+
const baseDecisions = new Set((base.doc.decisions ?? []).map(ident));
|
|
371
|
+
const theirsDecisions = new Set((theirs.doc.decisions ?? []).map(ident));
|
|
372
|
+
const decisions = [
|
|
373
|
+
...(ours.doc.decisions ?? []).filter(
|
|
374
|
+
(d) => !baseDecisions.has(ident(d)) || theirsDecisions.has(ident(d))
|
|
375
|
+
),
|
|
376
|
+
...(theirs.doc.decisions ?? []).filter(
|
|
377
|
+
(d) => !baseDecisions.has(ident(d)) && !(ours.doc.decisions ?? []).some((x) => ident(x) === ident(d))
|
|
378
|
+
)
|
|
379
|
+
];
|
|
380
|
+
const level = (id) => {
|
|
381
|
+
const levelNodes = [];
|
|
382
|
+
const layout = {};
|
|
383
|
+
for (const [nid, n] of nodes) {
|
|
384
|
+
if (n.level !== id) continue;
|
|
385
|
+
const node = { ...n.own };
|
|
386
|
+
if (n.body) {
|
|
387
|
+
const inner = level(nid);
|
|
388
|
+
const keys2 = new Set(n.body.keys);
|
|
389
|
+
const body = { nodes: inner.nodes, edges: inner.edges };
|
|
390
|
+
if (inner.annotations.length || keys2.has("annotations"))
|
|
391
|
+
body.annotations = inner.annotations;
|
|
392
|
+
if (Object.keys(inner.layout).length || keys2.has("layout")) body.layout = inner.layout;
|
|
393
|
+
if (n.body.boundary) body.boundary = n.body.boundary;
|
|
394
|
+
node.subflow = body;
|
|
395
|
+
}
|
|
396
|
+
levelNodes.push(node);
|
|
397
|
+
if (n.position) layout[nid] = n.position;
|
|
398
|
+
}
|
|
399
|
+
return {
|
|
400
|
+
nodes: levelNodes,
|
|
401
|
+
edges: [...edges.values()].filter((e) => e.level === id).map((e) => e.edge),
|
|
402
|
+
annotations: [...annotations.values()].filter((a) => a.level === id).map((a) => a.annotation),
|
|
403
|
+
layout
|
|
404
|
+
};
|
|
405
|
+
};
|
|
406
|
+
const top = level(ROOT);
|
|
407
|
+
const keys = /* @__PURE__ */ new Set([...ours.rootKeys, ...theirs.rootKeys]);
|
|
408
|
+
const doc = {
|
|
409
|
+
schema_version: oursDoc.schema_version,
|
|
410
|
+
flow: { ...header, version },
|
|
411
|
+
nodes: top.nodes,
|
|
412
|
+
edges: top.edges,
|
|
413
|
+
...top.annotations.length || keys.has("annotations") ? { annotations: top.annotations } : {},
|
|
414
|
+
...Object.keys(top.layout).length || keys.has("layout") ? { layout: top.layout } : {},
|
|
415
|
+
...decisions.length || keys.has("decisions") ? { decisions } : {}
|
|
416
|
+
};
|
|
417
|
+
return { doc, conflicts: m.conflicts };
|
|
418
|
+
}
|
|
419
|
+
export {
|
|
420
|
+
mergeFlows
|
|
421
|
+
};
|
|
422
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/core/flow/merge.ts"],
|
|
4
|
+
"sourcesContent": ["// AFD-283: a three-way merge of a flow, by the nodes' IDs rather than the YAML's lines. Two people\n// change one flow apart (two clones, a push through the server, a live session whose branch moved\n// on); what they changed in different places comes together on its own, and what they changed in\n// the same place is a conflict with both sides named. Pure: the merge driver, the designer and\n// the server call it with the three versions and the choices made so far.\n//\n// The flow is taken apart into its nodes, wires and Notes with the level each is on, so a step\n// one side moved into a subflow is still the same step. Fields are merged one by one (records a\n// few levels deep: a step's settings, inputs, its binding's parameters); a value both sides\n// changed differently is a conflict, kept as \"ours\" until someone chooses. Positions never\n// conflict: ours wins. Rules a merge could break on its own are conflicts too: a step one side\n// removed and the other changed or wired, and two wires on one output port.\nimport { withIds } from './completeIds';\nimport { ROOT } from './model';\nimport { canonical } from './semantic';\nimport type {\n Annotation,\n Decision,\n Edge,\n FlowDocument,\n FlowHeader,\n FlowNode,\n Position,\n SubflowBody,\n Ulid,\n} from './types';\n\nexport type MergeSide = 'ours' | 'theirs';\n\nexport interface MergeConflict {\n /** Stable across merges of the same versions: choices are given by it. */\n id: string;\n kind: 'value' | 'removed' | 'wire' | 'format';\n /** Where and what, in words: \"Say hello: settings.timeout\". */\n label: string;\n node?: Ulid;\n annotation?: Ulid;\n edge?: Ulid;\n /** The field, dotted (`settings.timeout`); absent for a whole step, wire or the format. */\n field?: string;\n base?: unknown;\n ours?: unknown;\n theirs?: unknown;\n}\n\nexport interface FlowMerge {\n /** The merged flow, each conflict as its choice says (ours until chosen). */\n doc: FlowDocument;\n conflicts: MergeConflict[];\n}\n\n// --- taking a flow apart\n\ninterface FlatNode {\n level: string;\n /** The node without its inner level. */\n own: Omit<FlowNode, 'subflow'>;\n /** Present for a subflow: its boundary, and which keys its body had (kept as they were). */\n body?: { boundary?: SubflowBody['boundary']; keys: string[] };\n position?: Position;\n}\ninterface FlatEdge {\n level: string;\n edge: Edge;\n}\ninterface FlatAnnotation {\n level: string;\n annotation: Annotation;\n}\ninterface Flat {\n doc: FlowDocument;\n nodes: Map<Ulid, FlatNode>;\n edges: Map<Ulid, FlatEdge>;\n annotations: Map<Ulid, FlatAnnotation>;\n /** Which optional keys the top level had (kept as they were). */\n rootKeys: string[];\n}\n\nfunction flatten(doc: FlowDocument): Flat {\n const flat: Flat = {\n doc,\n nodes: new Map(),\n edges: new Map(),\n annotations: new Map(),\n rootKeys: ['annotations', 'layout', 'decisions'].filter((k) => k in doc),\n };\n const visit = (\n level: string,\n nodes: FlowNode[] | undefined,\n edges: Edge[] | undefined,\n annotations: Annotation[] | undefined,\n layout: Record<string, Position> | undefined,\n ) => {\n for (const node of nodes ?? []) {\n if (!node?.id) continue;\n const { subflow, ...own } = node;\n flat.nodes.set(node.id, {\n level,\n own,\n ...(subflow\n ? {\n body: {\n ...(subflow.boundary ? { boundary: subflow.boundary } : {}),\n keys: Object.keys(subflow),\n },\n }\n : {}),\n ...(layout?.[node.id] ? { position: layout[node.id] } : {}),\n });\n if (subflow)\n visit(node.id, subflow.nodes, subflow.edges, subflow.annotations, subflow.layout);\n }\n for (const edge of edges ?? []) if (edge?.id) flat.edges.set(edge.id, { level, edge });\n for (const a of annotations ?? [])\n if (a?.id) flat.annotations.set(a.id, { level, annotation: a });\n };\n visit(ROOT, doc.nodes, doc.edges, doc.annotations, doc.layout);\n return flat;\n}\n\n// --- merging values\n\nconst same = (a: unknown, b: unknown) =>\n JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\n\nclass Merger {\n readonly conflicts: MergeConflict[] = [];\n constructor(private readonly choices: Record<string, MergeSide>) {}\n\n pick(id: string): MergeSide {\n return this.choices[id] ?? 'ours';\n }\n\n conflict(c: MergeConflict): MergeSide {\n this.conflicts.push(c);\n return this.pick(c.id);\n }\n\n /**\n * One value, three ways. Records are merged key by key `depth` levels down; a value both sides\n * changed differently is a conflict named by `id` (`<owner>:<field>`).\n */\n value(\n base: unknown,\n ours: unknown,\n theirs: unknown,\n at: { id: string; label: string; field: string; owner: Partial<MergeConflict> },\n depth: number,\n ): unknown {\n if (same(ours, theirs)) return ours;\n if (same(base, ours)) return theirs;\n if (same(base, theirs)) return ours;\n if (depth > 0 && isRecord(ours) && isRecord(theirs) && (base === undefined || isRecord(base))) {\n const out: Record<string, unknown> = {};\n for (const key of new Set([...Object.keys(ours), ...Object.keys(theirs)])) {\n const v = this.value(\n (base as Record<string, unknown> | undefined)?.[key],\n ours[key],\n theirs[key],\n {\n ...at,\n id: `${at.id}.${key}`,\n field: at.field ? `${at.field}.${key}` : key,\n },\n depth - 1,\n );\n if (v !== undefined) out[key] = v;\n }\n return out;\n }\n const side = this.conflict({\n ...at.owner,\n id: at.id,\n kind: 'value',\n label: at.field ? `${at.label}: ${at.field}` : at.label,\n ...(at.field ? { field: at.field } : {}),\n base,\n ours,\n theirs,\n });\n return side === 'ours' ? ours : theirs;\n }\n\n /** The fields of a record, each merged on its own (`depth` levels down inside each). */\n fields(\n base: Record<string, unknown> | undefined,\n ours: Record<string, unknown>,\n theirs: Record<string, unknown>,\n at: { id: string; label: string; owner: Partial<MergeConflict> },\n depth: number,\n ): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const key of new Set([...Object.keys(ours), ...Object.keys(theirs)])) {\n const v = this.value(\n base?.[key],\n ours[key],\n theirs[key],\n { ...at, id: `${at.id}:${key}`, field: key },\n depth,\n );\n if (v !== undefined) out[key] = v;\n }\n return out;\n }\n}\n\n/** A position, or another value that never conflicts: the side that moved it, else ours. */\nfunction quiet<T>(base: T | undefined, ours: T | undefined, theirs: T | undefined): T | undefined {\n return same(base, ours) ? theirs : ours;\n}\n\n// --- the merge\n\n/**\n * Merges what `ours` and `theirs` changed since `base`. `choices` settle conflicts by id (ours\n * when not given). Flows without IDs are matched by the IDs their keys give (Complete IDs).\n */\nexport function mergeFlows(\n baseDoc: FlowDocument,\n oursDoc: FlowDocument,\n theirsDoc: FlowDocument,\n choices: Record<string, MergeSide> = {},\n): FlowMerge {\n const m = new Merger(choices);\n if (oursDoc.schema_version !== theirsDoc.schema_version) {\n const side = m.conflict({\n id: 'format',\n kind: 'format',\n label: `The flow's format: ${oursDoc.schema_version} here, ${theirsDoc.schema_version} in theirs (upgrade both first)`,\n ours: oursDoc.schema_version,\n theirs: theirsDoc.schema_version,\n });\n return { doc: side === 'ours' ? oursDoc : theirsDoc, conflicts: m.conflicts };\n }\n const base = flatten(withIds(baseDoc));\n const ours = flatten(withIds(oursDoc));\n const theirs = flatten(withIds(theirsDoc));\n const titleOf = (id: Ulid) =>\n (ours.nodes.get(id) ?? theirs.nodes.get(id) ?? base.nodes.get(id))?.own.title ?? id;\n\n // What a side did to a step, its wires, or anything inside it: a removal by the other side then\n // loses work and is a conflict.\n const touched = (side: Flat, id: Ulid, seen = new Set<Ulid>()): boolean => {\n if (seen.has(id)) return false;\n seen.add(id);\n const now = side.nodes.get(id);\n const was = base.nodes.get(id);\n if (!now) return false;\n if (!was || !same(now.own, was.own) || now.level !== was.level || !same(now.body, was.body))\n return true;\n for (const [eid, e] of side.edges)\n if ((e.edge.from.node === id || e.edge.to.node === id) && !same(e, base.edges.get(eid)))\n return true;\n for (const [aid, a] of side.annotations)\n if ((a.annotation.on === id || a.level === id) && !same(a, base.annotations.get(aid)))\n return true;\n for (const [cid, c] of side.nodes) if (c.level === id && touched(side, cid, seen)) return true;\n return false;\n };\n\n // Steps.\n const order = (key: 'nodes' | 'edges' | 'annotations') => [\n ...new Set([...ours[key].keys(), ...theirs[key].keys(), ...base[key].keys()]),\n ];\n const nodes = new Map<Ulid, FlatNode>();\n for (const id of order('nodes')) {\n const b = base.nodes.get(id);\n const o = ours.nodes.get(id);\n const t = theirs.nodes.get(id);\n if (!o && !t) continue;\n if (b && (!o || !t)) {\n // One side removed it: gone, unless the other side changed it meanwhile.\n const kept = (o ?? t) as FlatNode;\n if (!touched(o ? ours : theirs, id)) continue;\n const side = m.conflict({\n id: `node:${id}`,\n kind: 'removed',\n node: id,\n label: `${titleOf(id)}: removed ${o ? 'in theirs' : 'here'}, changed ${o ? 'here' : 'in theirs'}`,\n ours: o ? 'changed' : 'removed',\n theirs: o ? 'removed' : 'changed',\n });\n if ((side === 'ours') === !!o) nodes.set(id, kept);\n continue;\n }\n if (!o || !t) {\n nodes.set(id, (o ?? t) as FlatNode);\n continue;\n }\n const owner = { node: id };\n const label = titleOf(id);\n const own = m.fields(\n b?.own as Record<string, unknown> | undefined,\n o.own as Record<string, unknown>,\n t.own as Record<string, unknown>,\n { id: `node:${id}`, label, owner },\n 3,\n ) as FlatNode['own'];\n const level = m.value(\n b?.level,\n o.level,\n t.level,\n { id: `node:${id}:level`, label, field: 'level (moved into another subflow)', owner },\n 0,\n ) as string;\n let body: FlatNode['body'];\n const hasBody = m.value(\n !!b?.body,\n !!o.body,\n !!t.body,\n { id: `node:${id}:subflow`, label, field: 'subflow', owner },\n 0,\n );\n if (hasBody) {\n const boundary = m.value(\n b?.body?.boundary,\n o.body?.boundary,\n t.body?.boundary,\n { id: `node:${id}:boundary`, label, field: 'boundary', owner },\n 2,\n ) as SubflowBody['boundary'];\n body = {\n ...(boundary ? { boundary } : {}),\n keys: [...new Set([...(o.body?.keys ?? []), ...(t.body?.keys ?? [])])],\n };\n }\n const position = quiet(b?.position, o.position, t.position);\n nodes.set(id, {\n level,\n own,\n ...(body ? { body } : {}),\n ...(position ? { position } : {}),\n });\n }\n // A step whose subflow is gone goes with it.\n for (let again = true; again; ) {\n again = false;\n for (const [id, n] of nodes)\n if (n.level !== ROOT && !nodes.get(n.level)?.body) {\n nodes.delete(id);\n again = true;\n }\n }\n\n // Wires.\n const edges = new Map<Ulid, FlatEdge & { from: MergeSide | 'both' }>();\n for (const id of order('edges')) {\n const b = base.edges.get(id);\n const o = ours.edges.get(id);\n const t = theirs.edges.get(id);\n if (!o && !t) continue;\n if (b && (!o || !t)) {\n const kept = (o ?? t) as FlatEdge;\n if (same(kept, b)) continue;\n // Removed on one side, rewired on the other.\n const side = m.conflict({\n id: `wire:${id}`,\n kind: 'wire',\n edge: id,\n label: `The wire from ${titleOf(kept.edge.from.node)} (${kept.edge.from.port}): removed ${o ? 'in theirs' : 'here'}, changed ${o ? 'here' : 'in theirs'}`,\n ours: o ? kept.edge : undefined,\n theirs: o ? undefined : kept.edge,\n });\n if ((side === 'ours') === !!o) edges.set(id, { ...kept, from: o ? 'ours' : 'theirs' });\n continue;\n }\n if (!o || !t) {\n edges.set(id, { ...((o ?? t) as FlatEdge), from: o ? 'ours' : 'theirs' });\n continue;\n }\n const merged = m.value(\n b,\n o,\n t,\n {\n id: `wire:${id}`,\n label: `The wire from ${titleOf(o.edge.from.node)} (${o.edge.from.port})`,\n field: '',\n owner: { edge: id },\n },\n 0,\n ) as FlatEdge;\n edges.set(id, { ...merged, from: 'both' });\n }\n // Wires whose ends are gone or now on another level go; the same wire added twice is one.\n const ends = new Set<string>();\n for (const [id, e] of edges) {\n const a = nodes.get(e.edge.from.node);\n const z = nodes.get(e.edge.to.node);\n const key = `${e.level}|${e.edge.from.node}.${e.edge.from.port}>${e.edge.to.node}.${e.edge.to.port}`;\n if (!a || !z || a.level !== e.level || z.level !== e.level || ends.has(key)) edges.delete(id);\n else ends.add(key);\n }\n // One wire per output port: two from different sides are a conflict.\n const byPort = new Map<string, Ulid[]>();\n for (const [id, e] of edges) {\n const key = `${e.edge.from.node}|${e.edge.from.port}`;\n byPort.set(key, [...(byPort.get(key) ?? []), id]);\n }\n for (const [key, ids] of byPort) {\n if (ids.length < 2) continue;\n const sides = new Set(ids.map((id) => edges.get(id)?.from));\n if (!sides.has('ours') && !sides.has('theirs')) continue;\n const [node = '', port = ''] = key.split('|');\n const target = (s: MergeSide) =>\n ids\n .filter((id) => (s === 'ours' ? ours : theirs).edges.has(id))\n .map((id) => titleOf(edges.get(id)?.edge.to.node ?? ''))\n .join(', ');\n const side = m.conflict({\n id: `port:${node}.${port}`,\n kind: 'wire',\n node,\n label: `${titleOf(node)}: port ${port} wired to ${target('ours') || 'nothing'} here, to ${target('theirs') || 'nothing'} in theirs`,\n field: `ports.${port}`,\n ours: target('ours'),\n theirs: target('theirs'),\n });\n const keep = side === 'ours' ? ours : theirs;\n for (const id of ids) if (!keep.edges.has(id)) edges.delete(id);\n }\n\n // Notes, Sections and Text.\n const annotations = new Map<Ulid, FlatAnnotation>();\n const PLACE = ['x', 'y', 'width', 'height'];\n for (const id of order('annotations')) {\n const b = base.annotations.get(id);\n const o = ours.annotations.get(id);\n const t = theirs.annotations.get(id);\n if (!o && !t) continue;\n if (b && (!o || !t)) {\n const kept = (o ?? t) as FlatAnnotation;\n if (same(kept, b)) continue;\n const side = m.conflict({\n id: `note:${id}`,\n kind: 'removed',\n annotation: id,\n label: `The note \"${kept.annotation.text.split('\\n')[0]}\": removed ${o ? 'in theirs' : 'here'}, changed ${o ? 'here' : 'in theirs'}`,\n ours: o ? 'changed' : 'removed',\n theirs: o ? 'removed' : 'changed',\n });\n if ((side === 'ours') === !!o) annotations.set(id, kept);\n continue;\n }\n if (!o || !t) {\n annotations.set(id, (o ?? t) as FlatAnnotation);\n continue;\n }\n const strip = (a?: Annotation) =>\n a && Object.fromEntries(Object.entries(a).filter(([k]) => !PLACE.includes(k)));\n const label = `The note \"${o.annotation.text.split('\\n')[0]}\"`;\n const fields = m.fields(\n strip(b?.annotation),\n strip(o.annotation) as Record<string, unknown>,\n strip(t.annotation) as Record<string, unknown>,\n { id: `note:${id}`, label, owner: { annotation: id } },\n 1,\n );\n const place: Record<string, unknown> = {};\n for (const k of PLACE) {\n const v = quiet(\n (b?.annotation as unknown as Record<string, unknown> | undefined)?.[k],\n (o.annotation as unknown as Record<string, unknown>)[k],\n (t.annotation as unknown as Record<string, unknown>)[k],\n );\n if (v !== undefined) place[k] = v;\n }\n const level = quiet(b?.level, o.level, t.level) ?? o.level;\n annotations.set(id, { level, annotation: { ...fields, ...place } as unknown as Annotation });\n }\n for (const [id, a] of annotations)\n if (\n (a.level !== ROOT && !nodes.get(a.level)?.body) ||\n (a.annotation.on && !nodes.has(a.annotation.on))\n )\n annotations.delete(id);\n\n // The flow itself: its fields; its version moves on when both sides moved it.\n const { version: vb, ...hb } = base.doc.flow;\n const { version: vo, ...ho } = ours.doc.flow;\n const { version: vt, ...ht } = theirs.doc.flow;\n const header = m.fields(\n hb as Record<string, unknown>,\n ho as Record<string, unknown>,\n ht as Record<string, unknown>,\n { id: 'flow', label: 'The flow', owner: {} },\n 2,\n ) as Omit<FlowHeader, 'version'>;\n const version = vo === vt ? vo : vo === vb ? vt : vt === vb ? vo : Math.max(vo, vt) + 1;\n\n // Decisions: a set; what a side added is in, what a side took out is out.\n const ident = (d: Decision) => JSON.stringify(canonical(d));\n const baseDecisions = new Set((base.doc.decisions ?? []).map(ident));\n const theirsDecisions = new Set((theirs.doc.decisions ?? []).map(ident));\n const decisions = [\n ...(ours.doc.decisions ?? []).filter(\n (d) => !baseDecisions.has(ident(d)) || theirsDecisions.has(ident(d)),\n ),\n ...(theirs.doc.decisions ?? []).filter(\n (d) =>\n !baseDecisions.has(ident(d)) &&\n !(ours.doc.decisions ?? []).some((x) => ident(x) === ident(d)),\n ),\n ];\n\n // Put it back together, level by level, in ours's order with theirs's new parts after.\n const level = (id: string) => {\n const levelNodes: FlowNode[] = [];\n const layout: Record<string, Position> = {};\n for (const [nid, n] of nodes) {\n if (n.level !== id) continue;\n const node = { ...n.own } as FlowNode;\n if (n.body) {\n const inner = level(nid);\n const keys = new Set(n.body.keys);\n const body: SubflowBody = { nodes: inner.nodes, edges: inner.edges };\n if (inner.annotations.length || keys.has('annotations'))\n body.annotations = inner.annotations;\n if (Object.keys(inner.layout).length || keys.has('layout')) body.layout = inner.layout;\n if (n.body.boundary) body.boundary = n.body.boundary;\n node.subflow = body;\n }\n levelNodes.push(node);\n if (n.position) layout[nid] = n.position;\n }\n return {\n nodes: levelNodes,\n edges: [...edges.values()].filter((e) => e.level === id).map((e) => e.edge),\n annotations: [...annotations.values()].filter((a) => a.level === id).map((a) => a.annotation),\n layout,\n };\n };\n const top = level(ROOT);\n const keys = new Set([...ours.rootKeys, ...theirs.rootKeys]);\n const doc: FlowDocument = {\n schema_version: oursDoc.schema_version,\n flow: { ...header, version } as FlowHeader,\n nodes: top.nodes,\n edges: top.edges,\n ...(top.annotations.length || keys.has('annotations') ? { annotations: top.annotations } : {}),\n ...(Object.keys(top.layout).length || keys.has('layout') ? { layout: top.layout } : {}),\n ...(decisions.length || keys.has('decisions') ? { decisions } : {}),\n };\n return { doc, conflicts: m.conflicts };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["level", "keys"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
canonical
|
|
3
|
+
} from "../chunks/chunk-TG3C3GIL.js";
|
|
4
|
+
import "../chunks/chunk-VG3RKETK.js";
|
|
5
|
+
import {
|
|
6
|
+
YamlTransaction
|
|
7
|
+
} from "../chunks/chunk-3Z2U3LN7.js";
|
|
8
|
+
import "../chunks/chunk-GHG3VINX.js";
|
|
9
|
+
import {
|
|
10
|
+
deleteKey,
|
|
11
|
+
insertItem,
|
|
12
|
+
removeItem,
|
|
13
|
+
setIn
|
|
14
|
+
} from "../chunks/chunk-5TUAMVIV.js";
|
|
15
|
+
import {
|
|
16
|
+
parseYaml
|
|
17
|
+
} from "../chunks/chunk-45CE2RUH.js";
|
|
18
|
+
import "../chunks/chunk-E2YZJWO7.js";
|
|
19
|
+
import "../chunks/chunk-AGWQ3ANE.js";
|
|
20
|
+
|
|
21
|
+
// src/core/flow/mergeText.ts
|
|
22
|
+
var same = (a, b) => JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));
|
|
23
|
+
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
24
|
+
var idOf = (v) => isRecord(v) && typeof v.id === "string" ? v.id : void 0;
|
|
25
|
+
var byId = (list) => list.length > 0 && list.every((v) => idOf(v) !== void 0);
|
|
26
|
+
function writeMergedFlow(text, doc) {
|
|
27
|
+
const tx = new YamlTransaction(text);
|
|
28
|
+
const current = parseYaml(text).doc.toJS();
|
|
29
|
+
sync(tx, [], current, doc);
|
|
30
|
+
return tx.text;
|
|
31
|
+
}
|
|
32
|
+
function sync(tx, path, was, now) {
|
|
33
|
+
if (same(was, now)) return;
|
|
34
|
+
if (isRecord(was) && isRecord(now)) {
|
|
35
|
+
for (const key of Object.keys(was))
|
|
36
|
+
if (!(key in now) || now[key] === void 0) tx.apply((f) => deleteKey(f, path, key));
|
|
37
|
+
for (const [key, value] of Object.entries(now)) {
|
|
38
|
+
if (value === void 0) continue;
|
|
39
|
+
if (key in was) sync(tx, [...path, key], was[key], value);
|
|
40
|
+
else tx.apply((f) => setIn(f, [...path, key], value));
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(was) && Array.isArray(now) && byId(was) && byId(now)) {
|
|
45
|
+
const wanted = new Set(now.map(idOf));
|
|
46
|
+
const list = [...was];
|
|
47
|
+
for (let i = list.length - 1; i >= 0; i--)
|
|
48
|
+
if (!wanted.has(idOf(list[i]))) {
|
|
49
|
+
tx.apply((f) => removeItem(f, path, i));
|
|
50
|
+
list.splice(i, 1);
|
|
51
|
+
}
|
|
52
|
+
now.forEach((item, i) => {
|
|
53
|
+
const at = list.findIndex((x) => idOf(x) === idOf(item));
|
|
54
|
+
if (at >= 0) {
|
|
55
|
+
sync(tx, [...path, at], list[at], item);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const index = Math.min(i, list.length);
|
|
59
|
+
tx.apply(
|
|
60
|
+
(f) => insertItem(f, path, index === list.length ? "end" : index, item)
|
|
61
|
+
);
|
|
62
|
+
list.splice(index, 0, item);
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
tx.apply((f) => setIn(f, path, now));
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
writeMergedFlow
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=mergeText.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/core/flow/mergeText.ts"],
|
|
4
|
+
"sourcesContent": ["// AFD-283: a merged flow written over \"ours\" text with the fewest edits, so its comments, quoting\n// and order stay where they were and the file's diff shows only what the merge brought in. Lists\n// of things with IDs (steps, wires, notes) are matched by ID; anything else changed is replaced.\n\nimport { deleteKey, insertItem, removeItem, setIn } from '../yaml/ops';\nimport { type Path, parseYaml } from '../yaml/parse';\nimport type { YamlValue } from '../yaml/render';\nimport { YamlTransaction } from '../yaml/transaction';\nimport { canonical } from './semantic';\nimport type { FlowDocument } from './types';\n\nconst same = (a: unknown, b: unknown) =>\n JSON.stringify(canonical(a)) === JSON.stringify(canonical(b));\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\nconst idOf = (v: unknown) => (isRecord(v) && typeof v.id === 'string' ? v.id : undefined);\nconst byId = (list: unknown[]) => list.length > 0 && list.every((v) => idOf(v) !== undefined);\n\n/** `text` (ours) rewritten to say `doc`. */\nexport function writeMergedFlow(text: string, doc: FlowDocument): string {\n const tx = new YamlTransaction(text);\n const current = parseYaml(text).doc.toJS() as unknown;\n sync(tx, [], current, doc);\n return tx.text;\n}\n\nfunction sync(tx: YamlTransaction, path: Path, was: unknown, now: unknown): void {\n if (same(was, now)) return;\n if (isRecord(was) && isRecord(now)) {\n for (const key of Object.keys(was))\n if (!(key in now) || now[key] === undefined) tx.apply((f) => deleteKey(f, path, key));\n for (const [key, value] of Object.entries(now)) {\n if (value === undefined) continue;\n if (key in was) sync(tx, [...path, key], was[key], value);\n else tx.apply((f) => setIn(f, [...path, key], value as YamlValue));\n }\n return;\n }\n if (Array.isArray(was) && Array.isArray(now) && byId(was) && byId(now)) {\n const wanted = new Set(now.map(idOf));\n // Removals first, from the end, so the earlier indexes hold.\n const list = [...was];\n for (let i = list.length - 1; i >= 0; i--)\n if (!wanted.has(idOf(list[i]))) {\n tx.apply((f) => removeItem(f, path, i));\n list.splice(i, 1);\n }\n now.forEach((item, i) => {\n const at = list.findIndex((x) => idOf(x) === idOf(item));\n if (at >= 0) {\n sync(tx, [...path, at], list[at], item);\n return;\n }\n const index = Math.min(i, list.length);\n tx.apply((f) =>\n insertItem(f, path, index === list.length ? 'end' : index, item as YamlValue),\n );\n list.splice(index, 0, item);\n });\n return;\n }\n tx.apply((f) => setIn(f, path, now as YamlValue));\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;AAWA,IAAM,OAAO,CAAC,GAAY,MACxB,KAAK,UAAU,UAAU,CAAC,CAAC,MAAM,KAAK,UAAU,UAAU,CAAC,CAAC;AAC9D,IAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AACzD,IAAM,OAAO,CAAC,MAAgB,SAAS,CAAC,KAAK,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK;AAC/E,IAAM,OAAO,CAAC,SAAoB,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,MAAM,KAAK,CAAC,MAAM,MAAS;AAGrF,SAAS,gBAAgB,MAAc,KAA2B;AACvE,QAAM,KAAK,IAAI,gBAAgB,IAAI;AACnC,QAAM,UAAU,UAAU,IAAI,EAAE,IAAI,KAAK;AACzC,OAAK,IAAI,CAAC,GAAG,SAAS,GAAG;AACzB,SAAO,GAAG;AACZ;AAEA,SAAS,KAAK,IAAqB,MAAY,KAAc,KAAoB;AAC/E,MAAI,KAAK,KAAK,GAAG,EAAG;AACpB,MAAI,SAAS,GAAG,KAAK,SAAS,GAAG,GAAG;AAClC,eAAW,OAAO,OAAO,KAAK,GAAG;AAC/B,UAAI,EAAE,OAAO,QAAQ,IAAI,GAAG,MAAM,OAAW,IAAG,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC;AACtF,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,UAAI,UAAU,OAAW;AACzB,UAAI,OAAO,IAAK,MAAK,IAAI,CAAC,GAAG,MAAM,GAAG,GAAG,IAAI,GAAG,GAAG,KAAK;AAAA,UACnD,IAAG,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,GAAG,KAAkB,CAAC;AAAA,IACnE;AACA;AAAA,EACF;AACA,MAAI,MAAM,QAAQ,GAAG,KAAK,MAAM,QAAQ,GAAG,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,GAAG;AACtE,UAAM,SAAS,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;AAEpC,UAAM,OAAO,CAAC,GAAG,GAAG;AACpB,aAAS,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG;AACpC,UAAI,CAAC,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG;AAC9B,WAAG,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC;AACtC,aAAK,OAAO,GAAG,CAAC;AAAA,MAClB;AACF,QAAI,QAAQ,CAAC,MAAM,MAAM;AACvB,YAAM,KAAK,KAAK,UAAU,CAAC,MAAM,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC;AACvD,UAAI,MAAM,GAAG;AACX,aAAK,IAAI,CAAC,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI;AACtC;AAAA,MACF;AACA,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM;AACrC,SAAG;AAAA,QAAM,CAAC,MACR,WAAW,GAAG,MAAM,UAAU,KAAK,SAAS,QAAQ,OAAO,IAAiB;AAAA,MAC9E;AACA,WAAK,OAAO,OAAO,GAAG,IAAI;AAAA,IAC5B,CAAC;AACD;AAAA,EACF;AACA,KAAG,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,GAAgB,CAAC;AAClD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/flow/save.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
implementedAgain
|
|
3
|
-
} from "../chunks/chunk-
|
|
3
|
+
} from "../chunks/chunk-TOTSB4HG.js";
|
|
4
4
|
import "../chunks/chunk-SN7X6FYV.js";
|
|
5
5
|
import "../chunks/chunk-24G5UVEF.js";
|
|
6
6
|
import {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
versionBump
|
|
17
17
|
} from "../chunks/chunk-TG3C3GIL.js";
|
|
18
18
|
import "../chunks/chunk-WISXIO3I.js";
|
|
19
|
+
import "../chunks/chunk-FIKPXL6E.js";
|
|
19
20
|
import "../chunks/chunk-WG7O3OBV.js";
|
|
20
21
|
import "../chunks/chunk-NUGJSYSP.js";
|
|
21
22
|
import "../chunks/chunk-XRGZNPPO.js";
|
|
@@ -28,6 +29,7 @@ import "../chunks/chunk-HFHXHOBC.js";
|
|
|
28
29
|
import "../chunks/chunk-RKLF3DLT.js";
|
|
29
30
|
import "../chunks/chunk-GTHXWNCC.js";
|
|
30
31
|
import "../chunks/chunk-OEQXGULI.js";
|
|
32
|
+
import "../chunks/chunk-T6SZLRDM.js";
|
|
31
33
|
import "../chunks/chunk-BVEW6MKL.js";
|
|
32
34
|
import "../chunks/chunk-BUPWGYNF.js";
|
|
33
35
|
import "../chunks/chunk-WKETMTKT.js";
|
package/dist/flow/save.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/core/flow/save.ts"],
|
|
4
4
|
"sourcesContent": ["// Edits made on save: tested nodes whose design changed since the file on disk are implemented again\n// (decision 15; hand edits in the text editor, canvas commands already did it), then flow.version\n// moves once relative to Git HEAD or the last saved text (ADR-0006).\nimport type { TextEdit } from '../yaml/edits';\nimport { setIn } from '../yaml/ops';\nimport { YamlTransaction } from '../yaml/transaction';\nimport { implementedAgain } from './commands';\nimport { flowFromFile, parseFlow } from './document';\nimport { testedDropBack, versionBump } from './semantic';\nimport type { Ulid } from './types';\n\nexport interface SavePlan {\n edits: TextEdit[];\n dropped: Ulid[];\n}\n\n/** `saved` is the file on disk before this save, `base` the version bump's base. */\nexport function planSave(text: string, saved?: string, base?: string): SavePlan {\n const current = parseFlow(text);\n if (!current.doc) return { edits: [], dropped: [] };\n const tx = new YamlTransaction(text, current.file);\n const savedDoc = saved === undefined ? undefined : parseFlow(saved).doc;\n const dropped = savedDoc ? testedDropBack(savedDoc, current.doc) : [];\n if (dropped.length > 0) implementedAgain(tx, dropped);\n const baseDoc = base === undefined ? undefined : parseFlow(base).doc;\n const now = flowFromFile(tx.current).doc;\n const next = baseDoc && now ? versionBump(now, baseDoc) : undefined;\n if (next !== undefined) tx.apply((f) => setIn(f, ['flow', 'version'], next));\n return { edits: tx.edits(), dropped };\n}\n"],
|
|
5
|
-
"mappings": "
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBO,SAAS,SAAS,MAAc,OAAgB,MAAyB;AAC9E,QAAM,UAAU,UAAU,IAAI;AAC9B,MAAI,CAAC,QAAQ,IAAK,QAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,EAAE;AAClD,QAAM,KAAK,IAAI,gBAAgB,MAAM,QAAQ,IAAI;AACjD,QAAM,WAAW,UAAU,SAAY,SAAY,UAAU,KAAK,EAAE;AACpE,QAAM,UAAU,WAAW,eAAe,UAAU,QAAQ,GAAG,IAAI,CAAC;AACpE,MAAI,QAAQ,SAAS,EAAG,kBAAiB,IAAI,OAAO;AACpD,QAAM,UAAU,SAAS,SAAY,SAAY,UAAU,IAAI,EAAE;AACjE,QAAM,MAAM,aAAa,GAAG,OAAO,EAAE;AACrC,QAAM,OAAO,WAAW,MAAM,YAAY,KAAK,OAAO,IAAI;AAC1D,MAAI,SAAS,OAAW,IAAG,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,SAAS,GAAG,IAAI,CAAC;AAC3E,SAAO,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ;AACtC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/flow/validate.js
CHANGED
|
@@ -5,15 +5,15 @@ import {
|
|
|
5
5
|
bareParams,
|
|
6
6
|
pointerToPath,
|
|
7
7
|
validateFlow
|
|
8
|
-
} from "../chunks/chunk-
|
|
8
|
+
} from "../chunks/chunk-PNLY5IWM.js";
|
|
9
9
|
import "../chunks/chunk-OREXQ4IZ.js";
|
|
10
10
|
import "../chunks/chunk-KSM4O2XL.js";
|
|
11
|
-
import "../chunks/chunk-T6SZLRDM.js";
|
|
12
11
|
import "../chunks/chunk-7D55CRGU.js";
|
|
13
12
|
import "../chunks/chunk-GK3SD3WE.js";
|
|
14
13
|
import "../chunks/chunk-H6ARLMMI.js";
|
|
15
14
|
import "../chunks/chunk-TG3C3GIL.js";
|
|
16
15
|
import "../chunks/chunk-WISXIO3I.js";
|
|
16
|
+
import "../chunks/chunk-FIKPXL6E.js";
|
|
17
17
|
import "../chunks/chunk-WG7O3OBV.js";
|
|
18
18
|
import "../chunks/chunk-NUGJSYSP.js";
|
|
19
19
|
import "../chunks/chunk-XRGZNPPO.js";
|
|
@@ -26,6 +26,7 @@ import "../chunks/chunk-HFHXHOBC.js";
|
|
|
26
26
|
import "../chunks/chunk-RKLF3DLT.js";
|
|
27
27
|
import "../chunks/chunk-GTHXWNCC.js";
|
|
28
28
|
import "../chunks/chunk-OEQXGULI.js";
|
|
29
|
+
import "../chunks/chunk-T6SZLRDM.js";
|
|
29
30
|
import "../chunks/chunk-AJRIS5VY.js";
|
|
30
31
|
import "../chunks/chunk-GQ2W4RTY.js";
|
|
31
32
|
import "../chunks/chunk-BVEW6MKL.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** What a typed line means: a list or map in YAML flow syntax, else its text. */
|
|
2
|
+
export declare function valueOfText(text: string): unknown;
|
|
3
|
+
/** The same value, whatever the text: a field keeps what was typed while it means this. */
|
|
4
|
+
export declare function sameValue(a: unknown, b: unknown): boolean;
|
|
5
|
+
/** The line that means `value` again in `valueOfText`, or undefined when it needs several lines. */
|
|
6
|
+
export declare function textOfValue(value: unknown): string | undefined;
|