@archie/devtools 0.0.21 → 0.0.23
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 +6 -0
- package/dist/client/client.d.mts +3 -1
- package/dist/client/client.d.ts +3 -1
- package/dist/client/client.js +289 -142
- package/dist/client/client.mjs +252 -104
- package/dist/index.d.mts +182 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +343 -47
- package/dist/index.mjs +343 -47
- package/dist/inspector.standalone.js +145 -6
- package/package.json +2 -3
package/dist/index.d.mts
CHANGED
|
@@ -10,9 +10,44 @@ import { types, PluginObj } from '@babel/core';
|
|
|
10
10
|
*
|
|
11
11
|
* The injected prop contains:
|
|
12
12
|
* nodeId, file, line, col, componentName, staticProps, movable, parentNodeId
|
|
13
|
+
* + (ARCH-883 F1) slot, propBindings, propOwner
|
|
13
14
|
*
|
|
14
15
|
* At runtime the Fiber bridge reads `memoizedProps.__editorMeta` to resolve
|
|
15
16
|
* element identity without any DOM attributes.
|
|
17
|
+
*
|
|
18
|
+
* ARCH-883 F1 (SDD §2.3/§2.6) adds three compile-time-only things:
|
|
19
|
+
*
|
|
20
|
+
* 1. `propBindings` — which of this node's rendered expressions trace back to
|
|
21
|
+
* a prop of the enclosing component, and whether that trace is safe enough
|
|
22
|
+
* to OFFER as an edit. It never decides what code to write; the write goes
|
|
23
|
+
* through the existing server write-paths. Anything the resolver is not
|
|
24
|
+
* certain about degrades to a GAP, never to a wrong binding.
|
|
25
|
+
* 2. `data-kit-slot` consumption — the curated slot label is lifted into the
|
|
26
|
+
* meta and the ATTRIBUTE IS STRIPPED, so it never reaches the DOM. The
|
|
27
|
+
* plugin treats the string as opaque; validating it against the canonical
|
|
28
|
+
* vocabulary (kit-runtime's `slot-vocabulary` export) belongs to the
|
|
29
|
+
* consumer. devtools deliberately takes no dependency on kit-runtime.
|
|
30
|
+
* 3. `movable: false` for kit-origin nodes — reordering inside a kit template
|
|
31
|
+
* affects N usages, a permanent non-objective (PRD §1.3).
|
|
32
|
+
*
|
|
33
|
+
* `parentNodeId` stays INTRA-FILE by construction (it only ever walks JSX
|
|
34
|
+
* ancestors within the file being transformed), so it never links a kit template
|
|
35
|
+
* node to a screen usage; per SDD §2.3 it must not be used across that seam.
|
|
36
|
+
* See the type docs in `types/editor-meta.ts`.
|
|
37
|
+
*
|
|
38
|
+
* ARCH-883 P0-1: the prop value is emitted as a ZERO-ARG ARROW FUNCTION that
|
|
39
|
+
* returns the meta object literal — `__editorMeta={() => ({...})}` — NOT the
|
|
40
|
+
* object literal directly. React serializes unknown OBJECT-valued props on
|
|
41
|
+
* host elements into the DOM (`__editorMeta="[object Object]"` on every
|
|
42
|
+
* published prototype page — a live production bug, proven by an executed
|
|
43
|
+
* SSR test in `src/client/dnd/design-mode/__tests__/editor-meta-react-behavior.test.ts`).
|
|
44
|
+
* Function- and symbol-valued unknown props are silently dropped by React in
|
|
45
|
+
* SSR, hydration, and client render — never written to the DOM — while
|
|
46
|
+
* remaining fully readable on `fiber.memoizedProps.__editorMeta` via a call.
|
|
47
|
+
* Every reader in the Fiber bridge (`fiber-bridge.ts`, `useElementScanner.ts`,
|
|
48
|
+
* `inspector.standalone.js`) invokes the value when it is a function and
|
|
49
|
+
* tolerates a raw object when it is not, so bundles built before this change
|
|
50
|
+
* keep resolving correctly until they are rebuilt.
|
|
16
51
|
*/
|
|
17
52
|
|
|
18
53
|
interface EditorMetaPluginOptions {
|
|
@@ -22,11 +57,157 @@ interface EditorMetaPluginOptions {
|
|
|
22
57
|
instrumentImported?: boolean;
|
|
23
58
|
/** Include exact host source refs for runtime DOM lookup. */
|
|
24
59
|
includeHostSourceRef?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Where the transformed sources come from (ARCH-883 F1).
|
|
62
|
+
*
|
|
63
|
+
* - `'screen'` (default) — per-project `screens/<slug>.jsx`. Reorder is a real
|
|
64
|
+
* operation there, so `movable` keeps its structural meaning.
|
|
65
|
+
* - `'kit'` — the shared kit component library (the `vendor.editor.js` babel
|
|
66
|
+
* pre-pass over the kit's `.gen/` sources, SDD §2.1). Every node emits
|
|
67
|
+
* `movable: false`: one template backs N usages across N projects, so
|
|
68
|
+
* reordering it is a permanent non-objective (PRD §1.3).
|
|
69
|
+
*
|
|
70
|
+
* Independently of this flag, a slot-carrying node is kit-origin by definition
|
|
71
|
+
* and also emits `movable: false`.
|
|
72
|
+
*/
|
|
73
|
+
origin?: 'screen' | 'kit';
|
|
25
74
|
}
|
|
26
75
|
declare function babelPluginEditorMeta({ types: t }: {
|
|
27
76
|
types: typeof types;
|
|
28
77
|
}, opts?: EditorMetaPluginOptions): PluginObj;
|
|
29
78
|
|
|
79
|
+
/**
|
|
80
|
+
* A link between a rendered JSX expression and a prop of the component whose
|
|
81
|
+
* template contains it (ARCH-883 F1, SDD §2.3).
|
|
82
|
+
*
|
|
83
|
+
* `propBindings` decides what UI the editor may OFFER — never what code gets
|
|
84
|
+
* written. The server resolves the actual write through the existing
|
|
85
|
+
* `rebuild-screen` / `screen-slice` / `update-shell` paths.
|
|
86
|
+
*
|
|
87
|
+
* ROUTABILITY IS AN ALLOWLIST with THREE conditions, both required:
|
|
88
|
+
*
|
|
89
|
+
* const routable =
|
|
90
|
+
* (b.kind === 'direct' || b.kind === 'derived') &&
|
|
91
|
+
* usageValueIsStringLiteralOrAbsent(usage, b.prop) && // consumer-side
|
|
92
|
+
* propOwnerMatchesUsageComponent(meta, usage); // consumer-side
|
|
93
|
+
*
|
|
94
|
+
* Everything else is a gap: a `kind: 'formatted'` entry (prop-reachable but not
|
|
95
|
+
* safely routable) or no entry at all for that target. A resolver false positive
|
|
96
|
+
* must always degrade to a gap, never to a wrong binding.
|
|
97
|
+
*
|
|
98
|
+
* THE USAGE-VALUE LAW APPLIES TO BOTH ROUTABLE KINDS, not only to `derived`.
|
|
99
|
+
* The plugin sees the kit template, never the usage site, so it cannot enforce
|
|
100
|
+
* it — the consumer must, for `direct` too. Real-corpus evidence for why: on the
|
|
101
|
+
* kit, `direct` outnumbers `derived` ~26:1, and a `direct` binding whose usage
|
|
102
|
+
* value is a computed object (`config={{…}}`, `widgets={list}`) is exactly as
|
|
103
|
+
* unwritable as a `derived` one. Scoping the law to `derived` would leave the
|
|
104
|
+
* overwhelming majority of bindings unguarded.
|
|
105
|
+
*
|
|
106
|
+
* Attributes that are machine contracts rather than content (`on*` handlers,
|
|
107
|
+
* `data-*` — including the durable `data-agent-id` key — and structural ones like
|
|
108
|
+
* `id`/`htmlFor`/`name`/`type`/`role`/`slot`) are downgraded to `formatted` by the
|
|
109
|
+
* PRODUCER, because no usage value could make them a text edit. The consumer does
|
|
110
|
+
* not need to re-derive that list; it only needs the allowlist above.
|
|
111
|
+
*/
|
|
112
|
+
interface PropBinding {
|
|
113
|
+
/**
|
|
114
|
+
* Where the bound expression renders: the element's children, or an attribute.
|
|
115
|
+
*
|
|
116
|
+
* Parse `attr:` by splitting on the FIRST colon only — namespaced JSX attributes
|
|
117
|
+
* keep their own colon (`attr:xlink:href` is the attribute `xlink:href`). A
|
|
118
|
+
* naive `split(':')[1]` silently truncates those.
|
|
119
|
+
*/
|
|
120
|
+
target: 'children' | `attr:${string}`;
|
|
121
|
+
/**
|
|
122
|
+
* Prop name on the OWNING component — the one named by `EditorMeta.propOwner`,
|
|
123
|
+
* NOT necessarily the component at the usage site. The consumer MUST verify
|
|
124
|
+
* `propOwner` against the usage component it resolved from the fiber chain and
|
|
125
|
+
* treat a mismatch as a gap.
|
|
126
|
+
*/
|
|
127
|
+
prop: string;
|
|
128
|
+
/**
|
|
129
|
+
* Routing verdict.
|
|
130
|
+
*
|
|
131
|
+
* - `direct` — the expression is a bare identifier that is a prop of the
|
|
132
|
+
* owning component (`{headline}`). Routable.
|
|
133
|
+
* - `derived` — the expression's root is a SINGLE prop identifier carrying a
|
|
134
|
+
* string-literal fallback, reached directly or through one
|
|
135
|
+
* local-const hop (`{title}` where `const title = headline || '…'`).
|
|
136
|
+
* Subject to the same consumer-side usage-value law as `direct`
|
|
137
|
+
* (see above) — being `derived` is not a stricter licence, just a
|
|
138
|
+
* longer trace.
|
|
139
|
+
* - `formatted`— prop-reachable but NOT routable: member expressions, ternaries,
|
|
140
|
+
* template literals, calls (`{brand.slice(0, 1)}`), more than one
|
|
141
|
+
* prop identifier, or an expression among mixed children. This is
|
|
142
|
+
* the explicit gap marker; `prop` on it is telemetry only.
|
|
143
|
+
*/
|
|
144
|
+
kind: 'direct' | 'derived' | 'formatted';
|
|
145
|
+
}
|
|
146
|
+
/** Metadata injected into every JSX element by babel-plugin-editor-meta. */
|
|
147
|
+
interface EditorMeta {
|
|
148
|
+
/** Stable identifier: "file:line:col:componentName" */
|
|
149
|
+
nodeId: string;
|
|
150
|
+
/** Relative file path from project root. */
|
|
151
|
+
file: string;
|
|
152
|
+
line: number;
|
|
153
|
+
col: number;
|
|
154
|
+
/** PascalCase component name or lowercase HTML tag. */
|
|
155
|
+
componentName: string;
|
|
156
|
+
/** Safely serializable literal prop values. Dynamic expressions are "__dynamic__". */
|
|
157
|
+
staticProps: Record<string, unknown> | null;
|
|
158
|
+
/**
|
|
159
|
+
* Whether the JSX node is in a reorderable position (2+ siblings).
|
|
160
|
+
*
|
|
161
|
+
* ARCH-883 F1: forced to `false` for every kit-origin node (slot-carrying
|
|
162
|
+
* nodes, and everything emitted with `origin: 'kit'`). Reordering inside a kit
|
|
163
|
+
* template affects N usages across N projects — a permanent non-objective per
|
|
164
|
+
* the PRD (§1.3), not a missing feature.
|
|
165
|
+
*/
|
|
166
|
+
movable: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* nodeId of the enclosing JSX parent element, or null for top-level.
|
|
169
|
+
*
|
|
170
|
+
* INTRA-FILE BY CONSTRUCTION: the plugin only walks JSX ancestors inside the
|
|
171
|
+
* file it is transforming, so this never links a kit template node to a screen
|
|
172
|
+
* usage. Per SDD §2.3 it must NOT be used across the kit↔screen seam — the
|
|
173
|
+
* editor tree there is derived from the fiber chain, and projection from the
|
|
174
|
+
* DOM. The root node of a kit template emits `null` here.
|
|
175
|
+
*/
|
|
176
|
+
parentNodeId: string | null;
|
|
177
|
+
/**
|
|
178
|
+
* Curated kit slot label, e.g. `"AuthFrame/aside/headline"` (SDD §2.6).
|
|
179
|
+
*
|
|
180
|
+
* Consumed from a `data-kit-slot` attribute at compile time; the attribute is
|
|
181
|
+
* STRIPPED from the output and never reaches the DOM — it travels on the fiber.
|
|
182
|
+
* A UI/telemetry label, NEVER a persisted key.
|
|
183
|
+
*
|
|
184
|
+
* The plugin treats any well-formed slot string as OPAQUE (non-empty, `/`
|
|
185
|
+
* separated, ≤4 segments). Validating it against the canonical vocabulary
|
|
186
|
+
* (`slot-vocabulary`, published by kit-runtime) is the consumer's job — devtools
|
|
187
|
+
* deliberately takes no dependency on kit-runtime.
|
|
188
|
+
*
|
|
189
|
+
* Absent (`undefined`) on nodes with no slot and on bundles built before F1.
|
|
190
|
+
*/
|
|
191
|
+
slot?: string | null;
|
|
192
|
+
/**
|
|
193
|
+
* Prop bindings for this node's rendered expressions (SDD §2.3).
|
|
194
|
+
*
|
|
195
|
+
* Emitted only when non-empty — read it as `meta.propBindings ?? []`. Absent on
|
|
196
|
+
* bundles built before ARCH-883 F1.
|
|
197
|
+
*/
|
|
198
|
+
propBindings?: PropBinding[];
|
|
199
|
+
/**
|
|
200
|
+
* Name of the component whose props `PropBinding.prop` refers to — the nearest
|
|
201
|
+
* enclosing, module-level component function that destructures its props.
|
|
202
|
+
*
|
|
203
|
+
* Emitted only alongside `propBindings`. The consumer MUST check it against the
|
|
204
|
+
* usage component before offering an edit: a kit-internal helper component
|
|
205
|
+
* (`function TableRow({ row })`) yields bindings in ITS prop namespace, which is
|
|
206
|
+
* not the usage's, and routing those would write the wrong prop. Mismatch = gap.
|
|
207
|
+
*/
|
|
208
|
+
propOwner?: string | null;
|
|
209
|
+
}
|
|
210
|
+
|
|
30
211
|
interface ArchieDevToolsOptions {
|
|
31
212
|
/**
|
|
32
213
|
* Enable debug logging.
|
|
@@ -61,4 +242,4 @@ interface ArchieDevToolsPlugin {
|
|
|
61
242
|
}
|
|
62
243
|
declare function archieDevTools(options?: ArchieDevToolsOptions): ArchieDevToolsPlugin;
|
|
63
244
|
|
|
64
|
-
export { type EditorMetaPluginOptions, archieDevTools, babelPluginEditorMeta };
|
|
245
|
+
export { type EditorMeta, type EditorMetaPluginOptions, type PropBinding, archieDevTools, babelPluginEditorMeta };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,9 +10,44 @@ import { types, PluginObj } from '@babel/core';
|
|
|
10
10
|
*
|
|
11
11
|
* The injected prop contains:
|
|
12
12
|
* nodeId, file, line, col, componentName, staticProps, movable, parentNodeId
|
|
13
|
+
* + (ARCH-883 F1) slot, propBindings, propOwner
|
|
13
14
|
*
|
|
14
15
|
* At runtime the Fiber bridge reads `memoizedProps.__editorMeta` to resolve
|
|
15
16
|
* element identity without any DOM attributes.
|
|
17
|
+
*
|
|
18
|
+
* ARCH-883 F1 (SDD §2.3/§2.6) adds three compile-time-only things:
|
|
19
|
+
*
|
|
20
|
+
* 1. `propBindings` — which of this node's rendered expressions trace back to
|
|
21
|
+
* a prop of the enclosing component, and whether that trace is safe enough
|
|
22
|
+
* to OFFER as an edit. It never decides what code to write; the write goes
|
|
23
|
+
* through the existing server write-paths. Anything the resolver is not
|
|
24
|
+
* certain about degrades to a GAP, never to a wrong binding.
|
|
25
|
+
* 2. `data-kit-slot` consumption — the curated slot label is lifted into the
|
|
26
|
+
* meta and the ATTRIBUTE IS STRIPPED, so it never reaches the DOM. The
|
|
27
|
+
* plugin treats the string as opaque; validating it against the canonical
|
|
28
|
+
* vocabulary (kit-runtime's `slot-vocabulary` export) belongs to the
|
|
29
|
+
* consumer. devtools deliberately takes no dependency on kit-runtime.
|
|
30
|
+
* 3. `movable: false` for kit-origin nodes — reordering inside a kit template
|
|
31
|
+
* affects N usages, a permanent non-objective (PRD §1.3).
|
|
32
|
+
*
|
|
33
|
+
* `parentNodeId` stays INTRA-FILE by construction (it only ever walks JSX
|
|
34
|
+
* ancestors within the file being transformed), so it never links a kit template
|
|
35
|
+
* node to a screen usage; per SDD §2.3 it must not be used across that seam.
|
|
36
|
+
* See the type docs in `types/editor-meta.ts`.
|
|
37
|
+
*
|
|
38
|
+
* ARCH-883 P0-1: the prop value is emitted as a ZERO-ARG ARROW FUNCTION that
|
|
39
|
+
* returns the meta object literal — `__editorMeta={() => ({...})}` — NOT the
|
|
40
|
+
* object literal directly. React serializes unknown OBJECT-valued props on
|
|
41
|
+
* host elements into the DOM (`__editorMeta="[object Object]"` on every
|
|
42
|
+
* published prototype page — a live production bug, proven by an executed
|
|
43
|
+
* SSR test in `src/client/dnd/design-mode/__tests__/editor-meta-react-behavior.test.ts`).
|
|
44
|
+
* Function- and symbol-valued unknown props are silently dropped by React in
|
|
45
|
+
* SSR, hydration, and client render — never written to the DOM — while
|
|
46
|
+
* remaining fully readable on `fiber.memoizedProps.__editorMeta` via a call.
|
|
47
|
+
* Every reader in the Fiber bridge (`fiber-bridge.ts`, `useElementScanner.ts`,
|
|
48
|
+
* `inspector.standalone.js`) invokes the value when it is a function and
|
|
49
|
+
* tolerates a raw object when it is not, so bundles built before this change
|
|
50
|
+
* keep resolving correctly until they are rebuilt.
|
|
16
51
|
*/
|
|
17
52
|
|
|
18
53
|
interface EditorMetaPluginOptions {
|
|
@@ -22,11 +57,157 @@ interface EditorMetaPluginOptions {
|
|
|
22
57
|
instrumentImported?: boolean;
|
|
23
58
|
/** Include exact host source refs for runtime DOM lookup. */
|
|
24
59
|
includeHostSourceRef?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Where the transformed sources come from (ARCH-883 F1).
|
|
62
|
+
*
|
|
63
|
+
* - `'screen'` (default) — per-project `screens/<slug>.jsx`. Reorder is a real
|
|
64
|
+
* operation there, so `movable` keeps its structural meaning.
|
|
65
|
+
* - `'kit'` — the shared kit component library (the `vendor.editor.js` babel
|
|
66
|
+
* pre-pass over the kit's `.gen/` sources, SDD §2.1). Every node emits
|
|
67
|
+
* `movable: false`: one template backs N usages across N projects, so
|
|
68
|
+
* reordering it is a permanent non-objective (PRD §1.3).
|
|
69
|
+
*
|
|
70
|
+
* Independently of this flag, a slot-carrying node is kit-origin by definition
|
|
71
|
+
* and also emits `movable: false`.
|
|
72
|
+
*/
|
|
73
|
+
origin?: 'screen' | 'kit';
|
|
25
74
|
}
|
|
26
75
|
declare function babelPluginEditorMeta({ types: t }: {
|
|
27
76
|
types: typeof types;
|
|
28
77
|
}, opts?: EditorMetaPluginOptions): PluginObj;
|
|
29
78
|
|
|
79
|
+
/**
|
|
80
|
+
* A link between a rendered JSX expression and a prop of the component whose
|
|
81
|
+
* template contains it (ARCH-883 F1, SDD §2.3).
|
|
82
|
+
*
|
|
83
|
+
* `propBindings` decides what UI the editor may OFFER — never what code gets
|
|
84
|
+
* written. The server resolves the actual write through the existing
|
|
85
|
+
* `rebuild-screen` / `screen-slice` / `update-shell` paths.
|
|
86
|
+
*
|
|
87
|
+
* ROUTABILITY IS AN ALLOWLIST with THREE conditions, both required:
|
|
88
|
+
*
|
|
89
|
+
* const routable =
|
|
90
|
+
* (b.kind === 'direct' || b.kind === 'derived') &&
|
|
91
|
+
* usageValueIsStringLiteralOrAbsent(usage, b.prop) && // consumer-side
|
|
92
|
+
* propOwnerMatchesUsageComponent(meta, usage); // consumer-side
|
|
93
|
+
*
|
|
94
|
+
* Everything else is a gap: a `kind: 'formatted'` entry (prop-reachable but not
|
|
95
|
+
* safely routable) or no entry at all for that target. A resolver false positive
|
|
96
|
+
* must always degrade to a gap, never to a wrong binding.
|
|
97
|
+
*
|
|
98
|
+
* THE USAGE-VALUE LAW APPLIES TO BOTH ROUTABLE KINDS, not only to `derived`.
|
|
99
|
+
* The plugin sees the kit template, never the usage site, so it cannot enforce
|
|
100
|
+
* it — the consumer must, for `direct` too. Real-corpus evidence for why: on the
|
|
101
|
+
* kit, `direct` outnumbers `derived` ~26:1, and a `direct` binding whose usage
|
|
102
|
+
* value is a computed object (`config={{…}}`, `widgets={list}`) is exactly as
|
|
103
|
+
* unwritable as a `derived` one. Scoping the law to `derived` would leave the
|
|
104
|
+
* overwhelming majority of bindings unguarded.
|
|
105
|
+
*
|
|
106
|
+
* Attributes that are machine contracts rather than content (`on*` handlers,
|
|
107
|
+
* `data-*` — including the durable `data-agent-id` key — and structural ones like
|
|
108
|
+
* `id`/`htmlFor`/`name`/`type`/`role`/`slot`) are downgraded to `formatted` by the
|
|
109
|
+
* PRODUCER, because no usage value could make them a text edit. The consumer does
|
|
110
|
+
* not need to re-derive that list; it only needs the allowlist above.
|
|
111
|
+
*/
|
|
112
|
+
interface PropBinding {
|
|
113
|
+
/**
|
|
114
|
+
* Where the bound expression renders: the element's children, or an attribute.
|
|
115
|
+
*
|
|
116
|
+
* Parse `attr:` by splitting on the FIRST colon only — namespaced JSX attributes
|
|
117
|
+
* keep their own colon (`attr:xlink:href` is the attribute `xlink:href`). A
|
|
118
|
+
* naive `split(':')[1]` silently truncates those.
|
|
119
|
+
*/
|
|
120
|
+
target: 'children' | `attr:${string}`;
|
|
121
|
+
/**
|
|
122
|
+
* Prop name on the OWNING component — the one named by `EditorMeta.propOwner`,
|
|
123
|
+
* NOT necessarily the component at the usage site. The consumer MUST verify
|
|
124
|
+
* `propOwner` against the usage component it resolved from the fiber chain and
|
|
125
|
+
* treat a mismatch as a gap.
|
|
126
|
+
*/
|
|
127
|
+
prop: string;
|
|
128
|
+
/**
|
|
129
|
+
* Routing verdict.
|
|
130
|
+
*
|
|
131
|
+
* - `direct` — the expression is a bare identifier that is a prop of the
|
|
132
|
+
* owning component (`{headline}`). Routable.
|
|
133
|
+
* - `derived` — the expression's root is a SINGLE prop identifier carrying a
|
|
134
|
+
* string-literal fallback, reached directly or through one
|
|
135
|
+
* local-const hop (`{title}` where `const title = headline || '…'`).
|
|
136
|
+
* Subject to the same consumer-side usage-value law as `direct`
|
|
137
|
+
* (see above) — being `derived` is not a stricter licence, just a
|
|
138
|
+
* longer trace.
|
|
139
|
+
* - `formatted`— prop-reachable but NOT routable: member expressions, ternaries,
|
|
140
|
+
* template literals, calls (`{brand.slice(0, 1)}`), more than one
|
|
141
|
+
* prop identifier, or an expression among mixed children. This is
|
|
142
|
+
* the explicit gap marker; `prop` on it is telemetry only.
|
|
143
|
+
*/
|
|
144
|
+
kind: 'direct' | 'derived' | 'formatted';
|
|
145
|
+
}
|
|
146
|
+
/** Metadata injected into every JSX element by babel-plugin-editor-meta. */
|
|
147
|
+
interface EditorMeta {
|
|
148
|
+
/** Stable identifier: "file:line:col:componentName" */
|
|
149
|
+
nodeId: string;
|
|
150
|
+
/** Relative file path from project root. */
|
|
151
|
+
file: string;
|
|
152
|
+
line: number;
|
|
153
|
+
col: number;
|
|
154
|
+
/** PascalCase component name or lowercase HTML tag. */
|
|
155
|
+
componentName: string;
|
|
156
|
+
/** Safely serializable literal prop values. Dynamic expressions are "__dynamic__". */
|
|
157
|
+
staticProps: Record<string, unknown> | null;
|
|
158
|
+
/**
|
|
159
|
+
* Whether the JSX node is in a reorderable position (2+ siblings).
|
|
160
|
+
*
|
|
161
|
+
* ARCH-883 F1: forced to `false` for every kit-origin node (slot-carrying
|
|
162
|
+
* nodes, and everything emitted with `origin: 'kit'`). Reordering inside a kit
|
|
163
|
+
* template affects N usages across N projects — a permanent non-objective per
|
|
164
|
+
* the PRD (§1.3), not a missing feature.
|
|
165
|
+
*/
|
|
166
|
+
movable: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* nodeId of the enclosing JSX parent element, or null for top-level.
|
|
169
|
+
*
|
|
170
|
+
* INTRA-FILE BY CONSTRUCTION: the plugin only walks JSX ancestors inside the
|
|
171
|
+
* file it is transforming, so this never links a kit template node to a screen
|
|
172
|
+
* usage. Per SDD §2.3 it must NOT be used across the kit↔screen seam — the
|
|
173
|
+
* editor tree there is derived from the fiber chain, and projection from the
|
|
174
|
+
* DOM. The root node of a kit template emits `null` here.
|
|
175
|
+
*/
|
|
176
|
+
parentNodeId: string | null;
|
|
177
|
+
/**
|
|
178
|
+
* Curated kit slot label, e.g. `"AuthFrame/aside/headline"` (SDD §2.6).
|
|
179
|
+
*
|
|
180
|
+
* Consumed from a `data-kit-slot` attribute at compile time; the attribute is
|
|
181
|
+
* STRIPPED from the output and never reaches the DOM — it travels on the fiber.
|
|
182
|
+
* A UI/telemetry label, NEVER a persisted key.
|
|
183
|
+
*
|
|
184
|
+
* The plugin treats any well-formed slot string as OPAQUE (non-empty, `/`
|
|
185
|
+
* separated, ≤4 segments). Validating it against the canonical vocabulary
|
|
186
|
+
* (`slot-vocabulary`, published by kit-runtime) is the consumer's job — devtools
|
|
187
|
+
* deliberately takes no dependency on kit-runtime.
|
|
188
|
+
*
|
|
189
|
+
* Absent (`undefined`) on nodes with no slot and on bundles built before F1.
|
|
190
|
+
*/
|
|
191
|
+
slot?: string | null;
|
|
192
|
+
/**
|
|
193
|
+
* Prop bindings for this node's rendered expressions (SDD §2.3).
|
|
194
|
+
*
|
|
195
|
+
* Emitted only when non-empty — read it as `meta.propBindings ?? []`. Absent on
|
|
196
|
+
* bundles built before ARCH-883 F1.
|
|
197
|
+
*/
|
|
198
|
+
propBindings?: PropBinding[];
|
|
199
|
+
/**
|
|
200
|
+
* Name of the component whose props `PropBinding.prop` refers to — the nearest
|
|
201
|
+
* enclosing, module-level component function that destructures its props.
|
|
202
|
+
*
|
|
203
|
+
* Emitted only alongside `propBindings`. The consumer MUST check it against the
|
|
204
|
+
* usage component before offering an edit: a kit-internal helper component
|
|
205
|
+
* (`function TableRow({ row })`) yields bindings in ITS prop namespace, which is
|
|
206
|
+
* not the usage's, and routing those would write the wrong prop. Mismatch = gap.
|
|
207
|
+
*/
|
|
208
|
+
propOwner?: string | null;
|
|
209
|
+
}
|
|
210
|
+
|
|
30
211
|
interface ArchieDevToolsOptions {
|
|
31
212
|
/**
|
|
32
213
|
* Enable debug logging.
|
|
@@ -61,4 +242,4 @@ interface ArchieDevToolsPlugin {
|
|
|
61
242
|
}
|
|
62
243
|
declare function archieDevTools(options?: ArchieDevToolsOptions): ArchieDevToolsPlugin;
|
|
63
244
|
|
|
64
|
-
export { type EditorMetaPluginOptions, archieDevTools, babelPluginEditorMeta };
|
|
245
|
+
export { type EditorMeta, type EditorMetaPluginOptions, type PropBinding, archieDevTools, babelPluginEditorMeta };
|