@wildwinter/toolkit 0.1.0 → 0.2.1
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/CHANGELOG.md +54 -0
- package/README.md +17 -2
- package/conformance/extensions/defaults.json +69 -0
- package/conformance/extensions/manifest.json +1129 -0
- package/conformance/extensions/merge.json +154 -0
- package/conformance/extensions/values.json +741 -0
- package/dist/chunk-ONEAWPDZ.js +11 -0
- package/dist/chunk-ONEAWPDZ.js.map +1 -0
- package/dist/extensions.cjs +948 -0
- package/dist/extensions.cjs.map +1 -0
- package/dist/extensions.d.cts +324 -0
- package/dist/extensions.d.ts +324 -0
- package/dist/extensions.js +902 -0
- package/dist/extensions.js.map +1 -0
- package/dist/index.js +2 -6
- package/dist/index.js.map +1 -1
- package/extensions.md +192 -0
- package/package.json +29 -3
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"about": "The merge. `tree` cases run mergeTree with a strategy given as data, expecting the merged value and each clash's path and kind. `data` cases run mergeExtensionData over extension shards, with the manifest (or null for none), expecting the merged shard, `unresolved` mark included. A base of {} is a shard that did not exist at the base.",
|
|
3
|
+
"tree": [
|
|
4
|
+
{ "name": "atomic: one side's change wins", "strategy": { "kind": "atomic" },
|
|
5
|
+
"base": 1, "ours": 1, "theirs": 2, "merged": 2, "conflicts": [] },
|
|
6
|
+
{ "name": "atomic: the same change on both sides is no clash", "strategy": { "kind": "atomic" },
|
|
7
|
+
"base": 1, "ours": 3, "theirs": 3, "merged": 3, "conflicts": [] },
|
|
8
|
+
{ "name": "atomic: two different changes clash and keep ours", "strategy": { "kind": "atomic" },
|
|
9
|
+
"base": 1, "ours": 2, "theirs": 3, "merged": 2, "conflicts": [{ "path": "", "kind": "both-changed" }] },
|
|
10
|
+
{ "name": "atomic: objects compare by content, not key order", "strategy": { "kind": "atomic" },
|
|
11
|
+
"base": { "a": 1, "b": 2 }, "ours": { "b": 2, "a": 1 }, "theirs": { "a": 1, "b": 3 }, "merged": { "a": 1, "b": 3 }, "conflicts": [] },
|
|
12
|
+
{ "name": "map: different keys merge", "strategy": { "kind": "map", "of": { "kind": "atomic" } },
|
|
13
|
+
"base": { "a": 1 }, "ours": { "a": 1, "b": 2 }, "theirs": { "a": 5, "c": 3 }, "merged": { "a": 5, "b": 2, "c": 3 }, "conflicts": [] },
|
|
14
|
+
{ "name": "map: a delete against an edit clashes", "strategy": { "kind": "map", "of": { "kind": "atomic" } },
|
|
15
|
+
"base": { "a": 1 }, "ours": {}, "theirs": { "a": 2 }, "merged": {}, "conflicts": [{ "path": ".a", "kind": "delete-vs-edit" }] },
|
|
16
|
+
{ "name": "set: additions union, deletions respected", "strategy": { "kind": "set" },
|
|
17
|
+
"base": ["a", "b"], "ours": ["a", "b", "c"], "theirs": ["b", "d"], "merged": ["b", "c", "d"], "conflicts": [] },
|
|
18
|
+
{ "name": "keyed, sorted: union by key, each item merged", "strategy": { "kind": "keyed", "key": "id", "of": { "kind": "object", "fields": {} } },
|
|
19
|
+
"base": [{ "id": "b", "n": 1, "m": 1 }],
|
|
20
|
+
"ours": [{ "id": "c" }, { "id": "b", "n": 2, "m": 1 }],
|
|
21
|
+
"theirs": [{ "id": "b", "n": 1, "m": 2 }, { "id": "a" }],
|
|
22
|
+
"merged": [{ "id": "a" }, { "id": "b", "n": 2, "m": 2 }, { "id": "c" }], "conflicts": [] },
|
|
23
|
+
{ "name": "keyed: the same key added twice differently clashes", "strategy": { "kind": "keyed", "key": "id", "of": { "kind": "atomic" } },
|
|
24
|
+
"base": [], "ours": [{ "id": "a", "n": 1 }], "theirs": [{ "id": "a", "n": 2 }],
|
|
25
|
+
"merged": [{ "id": "a", "n": 1 }], "conflicts": [{ "path": "[a]", "kind": "added-both" }] },
|
|
26
|
+
{ "name": "keyed: a delete against an edit clashes and keeps ours", "strategy": { "kind": "keyed", "key": "id", "of": { "kind": "atomic" } },
|
|
27
|
+
"base": [{ "id": "a", "n": 1 }], "ours": [], "theirs": [{ "id": "a", "n": 2 }],
|
|
28
|
+
"merged": [], "conflicts": [{ "path": "[a]", "kind": "delete-vs-edit" }] },
|
|
29
|
+
{ "name": "keyed, preserved: theirs reordered, ours added; the order is theirs with ours's addition after its neighbour",
|
|
30
|
+
"strategy": { "kind": "keyed", "key": "id", "order": "preserve", "of": { "kind": "atomic" } },
|
|
31
|
+
"base": [{ "id": "a" }, { "id": "b" }, { "id": "c" }],
|
|
32
|
+
"ours": [{ "id": "a" }, { "id": "x" }, { "id": "b" }, { "id": "c" }],
|
|
33
|
+
"theirs": [{ "id": "c" }, { "id": "a" }, { "id": "b" }],
|
|
34
|
+
"merged": [{ "id": "c" }, { "id": "a" }, { "id": "x" }, { "id": "b" }], "conflicts": [] },
|
|
35
|
+
{ "name": "keyed, preserved: an addition at the front stays at the front",
|
|
36
|
+
"strategy": { "kind": "keyed", "key": "id", "order": "preserve", "of": { "kind": "atomic" } },
|
|
37
|
+
"base": [{ "id": "a" }], "ours": [{ "id": "a" }], "theirs": [{ "id": "z" }, { "id": "a" }],
|
|
38
|
+
"merged": [{ "id": "z" }, { "id": "a" }], "conflicts": [] },
|
|
39
|
+
{ "name": "keyed, preserved: both reordered differently clashes and keeps ours",
|
|
40
|
+
"strategy": { "kind": "keyed", "key": "id", "order": "preserve", "of": { "kind": "atomic" } },
|
|
41
|
+
"base": [{ "id": "a" }, { "id": "b" }, { "id": "c" }],
|
|
42
|
+
"ours": [{ "id": "b" }, { "id": "a" }, { "id": "c" }],
|
|
43
|
+
"theirs": [{ "id": "a" }, { "id": "c" }, { "id": "b" }],
|
|
44
|
+
"merged": [{ "id": "b" }, { "id": "a" }, { "id": "c" }], "conflicts": [{ "path": ":order", "kind": "both-changed" }] },
|
|
45
|
+
{ "name": "object: named keys by their strategy, others atomic", "strategy": { "kind": "object", "fields": { "tags": { "kind": "set" } } },
|
|
46
|
+
"base": { "tags": ["a"], "n": 1 }, "ours": { "tags": ["a", "b"], "n": 2 }, "theirs": { "tags": ["c"], "n": 1 },
|
|
47
|
+
"merged": { "n": 2, "tags": ["b", "c"] }, "conflicts": [] },
|
|
48
|
+
{ "name": "object: other keys take `other` when it is given", "strategy": { "kind": "object", "fields": {}, "other": { "kind": "map", "of": { "kind": "atomic" } } },
|
|
49
|
+
"base": { "k": { "a": 1 } }, "ours": { "k": { "a": 2 } }, "theirs": { "k": { "a": 1, "b": 1 } },
|
|
50
|
+
"merged": { "k": { "a": 2, "b": 1 } }, "conflicts": [] },
|
|
51
|
+
{ "name": "a value whose shape no longer fits its strategy merges as one value", "strategy": { "kind": "map", "of": { "kind": "atomic" } },
|
|
52
|
+
"base": { "a": 1 }, "ours": "gone", "theirs": { "a": 2 }, "merged": "gone", "conflicts": [{ "path": "", "kind": "both-changed" }] }
|
|
53
|
+
],
|
|
54
|
+
"manifest": {
|
|
55
|
+
"schema": "wildwinter/extension@0", "id": "probe", "name": "Probe", "version": "1.0.0",
|
|
56
|
+
"targets": { "storylets": {
|
|
57
|
+
"card": { "fields": [
|
|
58
|
+
{ "name": "note", "type": "text" },
|
|
59
|
+
{ "name": "loud", "type": "boolean" },
|
|
60
|
+
{ "name": "marks", "type": "flags", "values": ["a", "b", "c"] },
|
|
61
|
+
{ "name": "cue", "type": "record", "fields": [{ "name": "sound", "type": "text" }, { "name": "gain", "type": "number" }] },
|
|
62
|
+
{ "name": "perf", "type": "map", "key": { "type": "reference", "to": "tag" }, "of": { "type": "record", "fields": [{ "name": "look", "type": "text" }, { "name": "gesture", "type": "text" }] } },
|
|
63
|
+
{ "name": "beats", "type": "list", "id": "id", "of": { "type": "record", "fields": [{ "name": "id", "type": "text" }, { "name": "at", "type": "number" }] } },
|
|
64
|
+
{ "name": "words", "type": "list", "of": { "type": "text" } }
|
|
65
|
+
] }
|
|
66
|
+
} }
|
|
67
|
+
},
|
|
68
|
+
"data": [
|
|
69
|
+
{ "name": "different nodes never clash",
|
|
70
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" } } } },
|
|
71
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" } } } },
|
|
72
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" }, "c_2": { "note": "z" } } } },
|
|
73
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" }, "c_2": { "note": "z" } } } } },
|
|
74
|
+
{ "name": "different fields of one node merge",
|
|
75
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" } } } },
|
|
76
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" } } } },
|
|
77
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a", "loud": true } } } },
|
|
78
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "loud": true, "note": "b" } } } } },
|
|
79
|
+
{ "name": "flags merge value by value",
|
|
80
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "marks": ["a"] } } } },
|
|
81
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "marks": ["a", "b"] } } } },
|
|
82
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "marks": ["c"] } } } },
|
|
83
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "marks": ["b", "c"] } } } } },
|
|
84
|
+
{ "name": "a record merges field by field",
|
|
85
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "cue": { "sound": "bell", "gain": 1 } } } } },
|
|
86
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "cue": { "sound": "gong", "gain": 1 } } } } },
|
|
87
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "cue": { "sound": "bell", "gain": 2 } } } } },
|
|
88
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "cue": { "gain": 2, "sound": "gong" } } } } } },
|
|
89
|
+
{ "name": "a map merges key by key, then by the value's type: different characters merge, one character's two looks clash",
|
|
90
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "perf": { "v_ann": { "look": "down" }, "v_bo": { "look": "up" } } } } } },
|
|
91
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "perf": { "v_ann": { "look": "left" }, "v_bo": { "look": "up", "gesture": "shrug" } } } } } },
|
|
92
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "perf": { "v_ann": { "look": "right" }, "v_bo": { "look": "away" } } } } } },
|
|
93
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "perf": { "v_ann": { "look": "left" }, "v_bo": { "gesture": "shrug", "look": "away" } } } } },
|
|
94
|
+
"unresolved": [{ "path": "entries.card.c_1.perf.v_ann.look", "kind": "both-changed", "base": "down", "ours": "left", "theirs": "right" }] } },
|
|
95
|
+
{ "name": "a list with ids merges by id and keeps the authored order",
|
|
96
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "beats": [{ "id": "b2", "at": 1 }, { "id": "b1", "at": 2 }] } } } },
|
|
97
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "beats": [{ "id": "b2", "at": 5 }, { "id": "b1", "at": 2 }] } } } },
|
|
98
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "beats": [{ "id": "b2", "at": 1 }, { "id": "b1", "at": 2 }, { "id": "b0", "at": 9 }] } } } },
|
|
99
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "beats": [{ "id": "b2", "at": 5 }, { "id": "b1", "at": 2 }, { "id": "b0", "at": 9 }] } } } } },
|
|
100
|
+
{ "name": "a list without ids merges whole",
|
|
101
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "words": ["a"] } } } },
|
|
102
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "words": ["a", "b"] } } } },
|
|
103
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "words": ["c", "a"] } } } },
|
|
104
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "words": ["a", "b"] } } },
|
|
105
|
+
"unresolved": [{ "path": "entries.card.c_1.words", "kind": "both-changed", "base": ["a"], "ours": ["a", "b"], "theirs": ["c", "a"] }] } },
|
|
106
|
+
{ "name": "a node's entry deleted on one side while edited on the other clashes, keeps ours, and the mark holds theirs",
|
|
107
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" } } } },
|
|
108
|
+
"ours": { "extension": "probe", "entries": { "card": {} } },
|
|
109
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" } } } },
|
|
110
|
+
"merged": { "extension": "probe", "entries": { "card": {} },
|
|
111
|
+
"unresolved": [{ "path": "entries.card.c_1", "kind": "delete-vs-edit", "base": { "note": "a" }, "theirs": { "note": "b" } }] } },
|
|
112
|
+
{ "name": "without the manifest, a node's whole entry merges as one value",
|
|
113
|
+
"manifest": null,
|
|
114
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" }, "c_2": { "note": "a" } } } },
|
|
115
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" }, "c_2": { "note": "a" } } } },
|
|
116
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a", "loud": true }, "c_2": { "note": "z" } } } },
|
|
117
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" }, "c_2": { "note": "z" } } },
|
|
118
|
+
"unresolved": [{ "path": "entries.card.c_1", "kind": "both-changed", "base": { "note": "a" }, "ours": { "note": "b" }, "theirs": { "loud": true, "note": "a" } }] } },
|
|
119
|
+
{ "name": "a kind the manifest does not target merges per node as one value",
|
|
120
|
+
"base": { "extension": "probe", "entries": { "deck": { "k_1": { "x": 1 } } } },
|
|
121
|
+
"ours": { "extension": "probe", "entries": { "deck": { "k_1": { "x": 2 } } } },
|
|
122
|
+
"theirs": { "extension": "probe", "entries": { "deck": { "k_1": { "x": 1 }, "k_2": { "x": 3 } } } },
|
|
123
|
+
"merged": { "extension": "probe", "entries": { "deck": { "k_1": { "x": 2 }, "k_2": { "x": 3 } } } } },
|
|
124
|
+
{ "name": "a shard added on both sides merges two-sided",
|
|
125
|
+
"base": {},
|
|
126
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" } } } },
|
|
127
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_2": { "note": "b" } } } },
|
|
128
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" }, "c_2": { "note": "b" } } } } },
|
|
129
|
+
{ "name": "a mark already on one side is carried until it is resolved",
|
|
130
|
+
"base": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" } } } },
|
|
131
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_1": { "note": "a" } } },
|
|
132
|
+
"unresolved": [{ "path": "entries.card.c_9.note", "kind": "both-changed", "ours": "x", "theirs": "y" }] },
|
|
133
|
+
"theirs": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" } } } },
|
|
134
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_1": { "note": "b" } } },
|
|
135
|
+
"unresolved": [{ "path": "entries.card.c_9.note", "kind": "both-changed", "ours": "x", "theirs": "y" }] } },
|
|
136
|
+
{ "name": "a mark one side resolved stays resolved",
|
|
137
|
+
"base": { "extension": "probe", "entries": { "card": {} },
|
|
138
|
+
"unresolved": [{ "path": "entries.card.c_9.note", "kind": "both-changed", "ours": "x", "theirs": "y" }] },
|
|
139
|
+
"ours": { "extension": "probe", "entries": { "card": { "c_9": { "note": "x" } } } },
|
|
140
|
+
"theirs": { "extension": "probe", "entries": { "card": {} },
|
|
141
|
+
"unresolved": [{ "path": "entries.card.c_9.note", "kind": "both-changed", "ours": "x", "theirs": "y" }] },
|
|
142
|
+
"merged": { "extension": "probe", "entries": { "card": { "c_9": { "note": "x" } } } } }
|
|
143
|
+
],
|
|
144
|
+
"unresolved": [
|
|
145
|
+
{ "name": "a shard with no mark passes", "shard": { "extension": "probe", "entries": {} }, "problems": [] },
|
|
146
|
+
{ "name": "a shard carrying the mark is refused, once per clash",
|
|
147
|
+
"shard": { "extension": "probe", "entries": {}, "unresolved": [
|
|
148
|
+
{ "path": "entries.card.c_1.note", "kind": "both-changed", "ours": "a", "theirs": "b" },
|
|
149
|
+
{ "path": "entries.card.c_2", "kind": "delete-vs-edit", "theirs": {} }
|
|
150
|
+
] },
|
|
151
|
+
"problems": [{ "path": "entries.card.c_1.note", "code": "unresolved" }, { "path": "entries.card.c_2", "code": "unresolved" }] },
|
|
152
|
+
{ "name": "an empty mark is still a mark", "shard": { "unresolved": [] }, "problems": [{ "path": "unresolved", "code": "unresolved" }] }
|
|
153
|
+
]
|
|
154
|
+
}
|