@braidlabs/studio 0.1.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/README.md +67 -0
- package/package.json +36 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +2 -0
- package/src/index.js.map +1 -0
- package/src/lib/payload-diff.d.ts +75 -0
- package/src/lib/payload-diff.js +202 -0
- package/src/lib/payload-diff.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @braidlabs/studio
|
|
2
|
+
|
|
3
|
+
Inspection tooling for version skew. Framework-free, no dependencies.
|
|
4
|
+
|
|
5
|
+
This package is being built incrementally alongside the web debugger
|
|
6
|
+
described in [`docs/skew-studio-plan.md`](../../docs/plans/skew-studio-plan.md).
|
|
7
|
+
What ships today is its most reusable piece.
|
|
8
|
+
|
|
9
|
+
## `diffPayloads`
|
|
10
|
+
|
|
11
|
+
A structural diff of one payload against another, in the vocabulary the
|
|
12
|
+
migration itself uses.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { diffPayloads } from '@braidlabs/studio';
|
|
16
|
+
|
|
17
|
+
const result = FundSchemaV1.read(body); // or readResolving, or a store get
|
|
18
|
+
|
|
19
|
+
const { lines, stats } = diffPayloads(sentByServer, result.value, {
|
|
20
|
+
derivedPaths: result.derivedPaths, // values the migration guessed
|
|
21
|
+
lossyPaths: result.lossyPaths, // values the target shape cannot carry
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`lines` is a flat list of `{ kind, indent, text, path, tag? }` — render it
|
|
26
|
+
however you like; a `<pre>` and thirty lines of CSS is enough. `stats` gives
|
|
27
|
+
`{ added, removed, derived, lost }` for a header.
|
|
28
|
+
|
|
29
|
+
### Why not a text diff
|
|
30
|
+
|
|
31
|
+
Running an LCS over two pretty-printed JSON strings produces plausible
|
|
32
|
+
garbage exactly when migrations are most interesting. A promotion — `nav`
|
|
33
|
+
going from `128450000` to `{ amount, asOf }`, or `cashPct` moving into
|
|
34
|
+
`liquidity.cashPct` — comes out as several unrelated line edits, and the one
|
|
35
|
+
change the reader needed to see has been dismantled. Pairing lines by key
|
|
36
|
+
path keeps a promotion legible as a promotion.
|
|
37
|
+
|
|
38
|
+
### Why the tags matter
|
|
39
|
+
|
|
40
|
+
A generic diff can say a line was added. It cannot say the value was
|
|
41
|
+
*guessed*: that the writer never recorded it and the migration filled in the
|
|
42
|
+
best answer available from an older shape. That is the distinction
|
|
43
|
+
`derivedPaths` and `lossyPaths` exist to carry, and rendering them as
|
|
44
|
+
ordinary green and red throws it away.
|
|
45
|
+
|
|
46
|
+
- **`derived`** — the value is the migration's invention. It can appear on
|
|
47
|
+
either side: a migration *adds* a guessed field going up, and a
|
|
48
|
+
reconciliation against an authoritative record *removes* the guess it had
|
|
49
|
+
been carrying.
|
|
50
|
+
- **`lost`** — only ever on a removed line: the older shape has nowhere to
|
|
51
|
+
put this, so a downgrade drops it.
|
|
52
|
+
|
|
53
|
+
### Path matching
|
|
54
|
+
|
|
55
|
+
Two vantage points always disagree, and both are handled:
|
|
56
|
+
|
|
57
|
+
- A read of a **list** reports paths against the list
|
|
58
|
+
(`[].liquidity.hqlaPct`) while a drill-down usually shows one element. The
|
|
59
|
+
leading hop is optional when matching.
|
|
60
|
+
- A result says "every holding loses its tier" (`holdings[].liquidityTier`)
|
|
61
|
+
while a line is about one holding (`holdings[3].liquidityTier`). Indices
|
|
62
|
+
collapse to `[]` on both sides.
|
|
63
|
+
|
|
64
|
+
Tags propagate **parent → child only**. A subtree that was dropped whole
|
|
65
|
+
marks every line inside it; a parent whose child alone was lost is *not*
|
|
66
|
+
marked, because saying `author` "cannot be carried" when it survives as a
|
|
67
|
+
bare string tells the reader the opposite of what happened.
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@braidlabs/studio",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Inspection tooling for version skew: structural payload diffs that speak the migration's own vocabulary.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"version-skew",
|
|
7
|
+
"migration",
|
|
8
|
+
"devtools",
|
|
9
|
+
"diff"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./src/index.js",
|
|
15
|
+
"types": "./src/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./src/index.d.ts",
|
|
19
|
+
"default": "./src/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/braidjs/braid.git",
|
|
29
|
+
"directory": "libs/studio"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/braidjs/braid#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/braidjs/braid/issues"
|
|
34
|
+
},
|
|
35
|
+
"module": "./src/index.js"
|
|
36
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/payload-diff.js';
|
package/src/index.js
ADDED
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/studio/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A structural diff of one payload against another, in the vocabulary the
|
|
3
|
+
* migration itself uses.
|
|
4
|
+
*
|
|
5
|
+
* This is the engine behind the demo's payload view and behind Studio's
|
|
6
|
+
* drill-down: click a trace event, get the record it carried, before and
|
|
7
|
+
* after. It is deliberately pure and framework-free — the renderer is a
|
|
8
|
+
* dozen lines of template in whatever framework is asking, and every caller
|
|
9
|
+
* should agree about what a change *is*.
|
|
10
|
+
*
|
|
11
|
+
* Two decisions worth knowing, because both are wrong in the obvious
|
|
12
|
+
* implementation:
|
|
13
|
+
*
|
|
14
|
+
* **Structural, not textual.** Running an LCS over two pretty-printed JSON
|
|
15
|
+
* strings produces plausible garbage exactly when migrations are most
|
|
16
|
+
* interesting — a promotion (`author` from a string to `{ name, email }`, or
|
|
17
|
+
* `cashPct` moving into `liquidity.cashPct`) shows up as several unrelated
|
|
18
|
+
* line edits, and the one change the reader needs to see is the one the diff
|
|
19
|
+
* has dismantled. Walking both values by key path pairs each line with its
|
|
20
|
+
* genuine counterpart.
|
|
21
|
+
*
|
|
22
|
+
* **Lines carry migration semantics.** A generic diff can say a line was
|
|
23
|
+
* added. It cannot say the value was *guessed* — that the writer never
|
|
24
|
+
* recorded it and the migration filled in the best answer available from an
|
|
25
|
+
* older shape. That distinction is the whole reason `derivedPaths` and
|
|
26
|
+
* `lossyPaths` exist on a result, and a plain red/green diff erases it.
|
|
27
|
+
*/
|
|
28
|
+
export type DiffLineKind = 'same' | 'add' | 'del';
|
|
29
|
+
/** Why a line is worth more than its `+`/`−`. */
|
|
30
|
+
export type DiffLineTag =
|
|
31
|
+
/** The migration invented this value; the writer never recorded it. */
|
|
32
|
+
'derived'
|
|
33
|
+
/** The target version has nowhere to carry this, so a downgrade drops it. */
|
|
34
|
+
| 'lost';
|
|
35
|
+
export interface DiffLine {
|
|
36
|
+
readonly kind: DiffLineKind;
|
|
37
|
+
/** Nesting depth, for the renderer to indent by. */
|
|
38
|
+
readonly indent: number;
|
|
39
|
+
/** The line's JSON text, without indentation. */
|
|
40
|
+
readonly text: string;
|
|
41
|
+
/** Dot/bracket path of the value this line belongs to. */
|
|
42
|
+
readonly path: string;
|
|
43
|
+
readonly tag?: DiffLineTag;
|
|
44
|
+
}
|
|
45
|
+
export interface DiffStats {
|
|
46
|
+
readonly added: number;
|
|
47
|
+
readonly removed: number;
|
|
48
|
+
readonly derived: number;
|
|
49
|
+
readonly lost: number;
|
|
50
|
+
}
|
|
51
|
+
export interface PayloadDiff {
|
|
52
|
+
readonly lines: readonly DiffLine[];
|
|
53
|
+
readonly stats: DiffStats;
|
|
54
|
+
}
|
|
55
|
+
export interface DiffOptions {
|
|
56
|
+
/** `derivedPaths` from a read result: values the migration guessed. */
|
|
57
|
+
readonly derivedPaths?: readonly string[];
|
|
58
|
+
/** `lossyPaths` from a read result: values a downgrade discarded. */
|
|
59
|
+
readonly lossyPaths?: readonly string[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Diffs two payloads.
|
|
63
|
+
*
|
|
64
|
+
* `before`/`after` are plain JSON values — pass the payload, not the
|
|
65
|
+
* envelope, so paths line up with the paths a result reports.
|
|
66
|
+
*/
|
|
67
|
+
export declare function diffPayloads(before: unknown, after: unknown, options?: DiffOptions): PayloadDiff;
|
|
68
|
+
/**
|
|
69
|
+
* Array indices collapse to `[]` on both sides before matching, because the
|
|
70
|
+
* two sides count differently on purpose: a result says "every holding loses
|
|
71
|
+
* its liquidityTier" (`holdings[].liquidityTier`) while a diff line is about
|
|
72
|
+
* one specific holding (`holdings[3].liquidityTier`). Same claim, and only
|
|
73
|
+
* one of them can be written per element.
|
|
74
|
+
*/
|
|
75
|
+
export declare function normalizePath(path: string): string;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A structural diff of one payload against another, in the vocabulary the
|
|
3
|
+
* migration itself uses.
|
|
4
|
+
*
|
|
5
|
+
* This is the engine behind the demo's payload view and behind Studio's
|
|
6
|
+
* drill-down: click a trace event, get the record it carried, before and
|
|
7
|
+
* after. It is deliberately pure and framework-free — the renderer is a
|
|
8
|
+
* dozen lines of template in whatever framework is asking, and every caller
|
|
9
|
+
* should agree about what a change *is*.
|
|
10
|
+
*
|
|
11
|
+
* Two decisions worth knowing, because both are wrong in the obvious
|
|
12
|
+
* implementation:
|
|
13
|
+
*
|
|
14
|
+
* **Structural, not textual.** Running an LCS over two pretty-printed JSON
|
|
15
|
+
* strings produces plausible garbage exactly when migrations are most
|
|
16
|
+
* interesting — a promotion (`author` from a string to `{ name, email }`, or
|
|
17
|
+
* `cashPct` moving into `liquidity.cashPct`) shows up as several unrelated
|
|
18
|
+
* line edits, and the one change the reader needs to see is the one the diff
|
|
19
|
+
* has dismantled. Walking both values by key path pairs each line with its
|
|
20
|
+
* genuine counterpart.
|
|
21
|
+
*
|
|
22
|
+
* **Lines carry migration semantics.** A generic diff can say a line was
|
|
23
|
+
* added. It cannot say the value was *guessed* — that the writer never
|
|
24
|
+
* recorded it and the migration filled in the best answer available from an
|
|
25
|
+
* older shape. That distinction is the whole reason `derivedPaths` and
|
|
26
|
+
* `lossyPaths` exist on a result, and a plain red/green diff erases it.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Diffs two payloads.
|
|
30
|
+
*
|
|
31
|
+
* `before`/`after` are plain JSON values — pass the payload, not the
|
|
32
|
+
* envelope, so paths line up with the paths a result reports.
|
|
33
|
+
*/
|
|
34
|
+
export function diffPayloads(before, after, options = {}) {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const raw = [];
|
|
37
|
+
walk(null, before, after, '', 0, true, raw);
|
|
38
|
+
const derivedPaths = (_a = options.derivedPaths) !== null && _a !== void 0 ? _a : [];
|
|
39
|
+
const lossyPaths = (_b = options.lossyPaths) !== null && _b !== void 0 ? _b : [];
|
|
40
|
+
let added = 0;
|
|
41
|
+
let removed = 0;
|
|
42
|
+
let derived = 0;
|
|
43
|
+
let lost = 0;
|
|
44
|
+
const lines = raw.map((line) => {
|
|
45
|
+
// `lost` only ever describes something being removed. `derived` can land
|
|
46
|
+
// on either side, because "this value is a guess" is a claim about the
|
|
47
|
+
// value, not about the direction it is travelling: a migration adds a
|
|
48
|
+
// guessed field going up, and a reconciliation against an authoritative
|
|
49
|
+
// record *removes* the guessed one it had been carrying.
|
|
50
|
+
const tag = line.kind === 'del' && covers(lossyPaths, line.path)
|
|
51
|
+
? 'lost'
|
|
52
|
+
: line.kind !== 'same' && covers(derivedPaths, line.path)
|
|
53
|
+
? 'derived'
|
|
54
|
+
: undefined;
|
|
55
|
+
if (line.kind === 'add')
|
|
56
|
+
added++;
|
|
57
|
+
if (line.kind === 'del')
|
|
58
|
+
removed++;
|
|
59
|
+
if (tag === 'derived')
|
|
60
|
+
derived++;
|
|
61
|
+
if (tag === 'lost')
|
|
62
|
+
lost++;
|
|
63
|
+
return tag ? Object.assign(Object.assign({}, line), { tag }) : line;
|
|
64
|
+
});
|
|
65
|
+
return { lines, stats: { added, removed, derived, lost } };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* True when `path` is one of the tagged paths, or sits inside one.
|
|
69
|
+
*
|
|
70
|
+
* Deliberately one-directional. Tagging a parent because one of its children
|
|
71
|
+
* is lossy reads as a lie: when `author` is promoted from `{ name, email }`
|
|
72
|
+
* to a bare string, `author.email` is genuinely lost but `author` itself
|
|
73
|
+
* survives — marking the whole object "cannot be carried" tells the reader
|
|
74
|
+
* the opposite of what happened. A subtree that really is dropped whole
|
|
75
|
+
* arrives with the parent path in the list, and every line under it is then
|
|
76
|
+
* tagged by the `startsWith` case.
|
|
77
|
+
*/
|
|
78
|
+
function covers(paths, path) {
|
|
79
|
+
const line = normalizePath(path);
|
|
80
|
+
return paths.some((raw) => {
|
|
81
|
+
const tagged = normalizePath(raw);
|
|
82
|
+
// A read of a *list* reports paths against the list
|
|
83
|
+
// (`[].liquidity.hqlaPct`) while a diff often shows one element of it.
|
|
84
|
+
// Try the path as given and with that leading hop removed, so one result
|
|
85
|
+
// annotates either view without the caller rewriting its own paths.
|
|
86
|
+
const candidates = tagged.startsWith('[].')
|
|
87
|
+
? [tagged, tagged.slice(3)]
|
|
88
|
+
: [tagged];
|
|
89
|
+
return candidates.some((p) => p === line || line.startsWith(`${p}.`));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Array indices collapse to `[]` on both sides before matching, because the
|
|
94
|
+
* two sides count differently on purpose: a result says "every holding loses
|
|
95
|
+
* its liquidityTier" (`holdings[].liquidityTier`) while a diff line is about
|
|
96
|
+
* one specific holding (`holdings[3].liquidityTier`). Same claim, and only
|
|
97
|
+
* one of them can be written per element.
|
|
98
|
+
*/
|
|
99
|
+
export function normalizePath(path) {
|
|
100
|
+
return path.replace(/\[\d+\]/g, '[]');
|
|
101
|
+
}
|
|
102
|
+
// --- walking ---------------------------------------------------------------
|
|
103
|
+
function isPlainObject(v) {
|
|
104
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
105
|
+
}
|
|
106
|
+
function format(value) {
|
|
107
|
+
return typeof value === 'string' ? JSON.stringify(value) : String(value);
|
|
108
|
+
}
|
|
109
|
+
function label(key) {
|
|
110
|
+
return key === null ? '' : `${JSON.stringify(key)}: `;
|
|
111
|
+
}
|
|
112
|
+
function child(path, key) {
|
|
113
|
+
return path ? `${path}.${key}` : key;
|
|
114
|
+
}
|
|
115
|
+
/** Emits an entire value as one-sided lines — a wholly added or removed key. */
|
|
116
|
+
function emit(kind, key, value, path, indent, last, out) {
|
|
117
|
+
const comma = last ? '' : ',';
|
|
118
|
+
if (isPlainObject(value)) {
|
|
119
|
+
const keys = Object.keys(value);
|
|
120
|
+
out.push({ kind, indent, text: `${label(key)}{`, path });
|
|
121
|
+
keys.forEach((k, i) => emit(kind, k, value[k], child(path, k), indent + 1, i === keys.length - 1, out));
|
|
122
|
+
out.push({ kind, indent, text: `}${comma}`, path });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (Array.isArray(value)) {
|
|
126
|
+
out.push({ kind, indent, text: `${label(key)}[`, path });
|
|
127
|
+
value.forEach((v, i) => emit(kind, null, v, `${path}[${i}]`, indent + 1, i === value.length - 1, out));
|
|
128
|
+
out.push({ kind, indent, text: `]${comma}`, path });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
out.push({ kind, indent, text: `${label(key)}${format(value)}${comma}`, path });
|
|
132
|
+
}
|
|
133
|
+
function emitSame(key, value, path, indent, last, out) {
|
|
134
|
+
const comma = last ? '' : ',';
|
|
135
|
+
if (isPlainObject(value)) {
|
|
136
|
+
const keys = Object.keys(value);
|
|
137
|
+
out.push({ kind: 'same', indent, text: `${label(key)}{`, path });
|
|
138
|
+
keys.forEach((k, i) => emitSame(k, value[k], child(path, k), indent + 1, i === keys.length - 1, out));
|
|
139
|
+
out.push({ kind: 'same', indent, text: `}${comma}`, path });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (Array.isArray(value)) {
|
|
143
|
+
out.push({ kind: 'same', indent, text: `${label(key)}[`, path });
|
|
144
|
+
value.forEach((v, i) => emitSame(null, v, `${path}[${i}]`, indent + 1, i === value.length - 1, out));
|
|
145
|
+
out.push({ kind: 'same', indent, text: `]${comma}`, path });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
out.push({ kind: 'same', indent, text: `${label(key)}${format(value)}${comma}`, path });
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Walks both values in parallel, pairing by key rather than by line number.
|
|
152
|
+
*
|
|
153
|
+
* `undefined` marks "absent on this side", which is safe because JSON has no
|
|
154
|
+
* undefined — a key that exists with an undefined value did not survive
|
|
155
|
+
* serialization in the first place.
|
|
156
|
+
*/
|
|
157
|
+
function walk(key, before, after, path, indent, last, out) {
|
|
158
|
+
const comma = last ? '' : ',';
|
|
159
|
+
if (before === undefined && after === undefined)
|
|
160
|
+
return;
|
|
161
|
+
if (before === undefined) {
|
|
162
|
+
emit('add', key, after, path, indent, last, out);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (after === undefined) {
|
|
166
|
+
emit('del', key, before, path, indent, last, out);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (isPlainObject(before) && isPlainObject(after)) {
|
|
170
|
+
// Before's key order first, then keys only after has — an unchanged
|
|
171
|
+
// record reads in its original order, and additions land where they were
|
|
172
|
+
// introduced rather than being alphabetised into the middle of it.
|
|
173
|
+
const keys = [
|
|
174
|
+
...Object.keys(before),
|
|
175
|
+
...Object.keys(after).filter((k) => !(k in before)),
|
|
176
|
+
];
|
|
177
|
+
out.push({ kind: 'same', indent, text: `${label(key)}{`, path });
|
|
178
|
+
keys.forEach((k, i) => walk(k, before[k], after[k], child(path, k), indent + 1, i === keys.length - 1, out));
|
|
179
|
+
out.push({ kind: 'same', indent, text: `}${comma}`, path });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
183
|
+
const length = Math.max(before.length, after.length);
|
|
184
|
+
out.push({ kind: 'same', indent, text: `${label(key)}[`, path });
|
|
185
|
+
for (let i = 0; i < length; i++) {
|
|
186
|
+
walk(null, before[i], after[i], `${path}[${i}]`, indent + 1, i === length - 1, out);
|
|
187
|
+
}
|
|
188
|
+
out.push({ kind: 'same', indent, text: `]${comma}`, path });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (JSON.stringify(before) === JSON.stringify(after)) {
|
|
192
|
+
// Unchanged, but possibly a whole subtree that moved wholesale, so print
|
|
193
|
+
// it rather than collapsing it to one line.
|
|
194
|
+
emitSame(key, after, path, indent, last, out);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
// Both sides describe the same key, so they share its position: a replaced
|
|
198
|
+
// final key must not sprout a trailing comma on the removed line only.
|
|
199
|
+
emit('del', key, before, path, indent, last, out);
|
|
200
|
+
emit('add', key, after, path, indent, last, out);
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=payload-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-diff.js","sourceRoot":"","sources":["../../../../../libs/studio/src/lib/payload-diff.ts"],"names":[],"mappings":"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"}
|