@reynsu/nativelens-event-protocol 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 ADDED
@@ -0,0 +1,55 @@
1
+ # @reynsu/nativelens-event-protocol
2
+
3
+ Canonical `RunEvent` discriminated union + Zod schemas for the nativelens event bus.
4
+
5
+ Published under `@reynsu/` because the `@nativelens` npm scope is not (yet) claimed as an org. Inside the nativelens monorepo this package is still referenced as `@nativelens/event-protocol` (workspace dep); the swap to the published name is a follow-up PR.
6
+
7
+ This package owns the wire shape that flows between probe ↔ harness ↔ runner ↔ dashboard. It is the single source of truth — consumers cast their internal types into this protocol at boundaries and trust the typed `RunEvent` thereafter.
8
+
9
+ ## Why a separate repo
10
+
11
+ Per ADR-0002, the protocol used to live as a local mirror inside the `nativelens` monorepo (`packages/event-protocol/`). Extracting it here lets:
12
+
13
+ - `nativelens` consume a published, version-pinned dep instead of a `workspace:*` symlink.
14
+ - `reactlens` migrate to this protocol once its own event surface aligns (currently `src/runner/events.ts` in that repo).
15
+ - Both consumers evolve independently against a contract that bumps semver explicitly.
16
+
17
+ ## Wire shape (v0.1.0)
18
+
19
+ `RunEvent` is a discriminated union over `type`:
20
+
21
+ | Variant | Direction | Purpose |
22
+ |---|---|---|
23
+ | `hello` | probe → harness, runner → harness | Role announcement at connection time |
24
+ | `step:set` | runner → probe | Mark the current `(testId, stepId)` |
25
+ | `step:ack` | probe → runner | Confirm `(testId, stepId)` was applied |
26
+ | `snapshot` | probe → harness | Component tree + testID map for one commit |
27
+ | `test:end` | runner → harness | End of a test, flush boundary |
28
+ | `a11y:violation` | runner → harness | One violation reported by the walker |
29
+ | `hmr:start` / `hmr:end` | probe → harness | Metro hot-reload boundaries; harness silences snapshot persistence between them |
30
+
31
+ Every variant has a `make*` builder and is in `parseRunEvent` for fail-soft inbound decoding.
32
+
33
+ ## Usage
34
+
35
+ ```ts
36
+ import { parseRunEvent, makeSnapshot, type RunEvent } from '@reynsu/nativelens-event-protocol';
37
+
38
+ const event = parseRunEvent(rawJsonLine);
39
+ if (event?.type === 'snapshot') {
40
+ // typed access to tree, testIdIndex, etc.
41
+ }
42
+ ```
43
+
44
+ ## Versioning
45
+
46
+ Pre-1.0: minor bumps may include breaking wire changes; pin to the exact minor in dependents. Post-1.0: strict semver per the wire contract.
47
+
48
+ ## Development
49
+
50
+ ```bash
51
+ pnpm install
52
+ pnpm test
53
+ pnpm typecheck
54
+ pnpm build
55
+ ```
@@ -0,0 +1,250 @@
1
+ import { z } from 'zod';
2
+ export declare const SerializedNodeKind: z.ZodEnum<["host", "function", "class", "memo", "forwardRef", "other"]>;
3
+ export type SerializedNodeKind = z.infer<typeof SerializedNodeKind>;
4
+ export type SerializedNode = {
5
+ fiberId: number;
6
+ name: string;
7
+ kind: SerializedNodeKind;
8
+ props: Record<string, unknown>;
9
+ hooks: unknown[];
10
+ children: SerializedNode[];
11
+ };
12
+ export declare const SerializedNodeSchema: z.ZodType<SerializedNode>;
13
+ export type TestIdIndex = Record<string, number>;
14
+ export declare const TestIdIndexSchema: z.ZodType<TestIdIndex>;
15
+ export declare const StepSetSchema: z.ZodObject<{
16
+ type: z.ZodLiteral<"step:set">;
17
+ testId: z.ZodString;
18
+ stepId: z.ZodString;
19
+ }, "strip", z.ZodTypeAny, {
20
+ type: "step:set";
21
+ testId: string;
22
+ stepId: string;
23
+ }, {
24
+ type: "step:set";
25
+ testId: string;
26
+ stepId: string;
27
+ }>;
28
+ export type StepSet = z.infer<typeof StepSetSchema>;
29
+ export declare function makeStepSet(testId: string, stepId: string): StepSet;
30
+ export declare const StepAckSchema: z.ZodObject<{
31
+ type: z.ZodLiteral<"step:ack">;
32
+ testId: z.ZodString;
33
+ stepId: z.ZodString;
34
+ }, "strip", z.ZodTypeAny, {
35
+ type: "step:ack";
36
+ testId: string;
37
+ stepId: string;
38
+ }, {
39
+ type: "step:ack";
40
+ testId: string;
41
+ stepId: string;
42
+ }>;
43
+ export type StepAck = z.infer<typeof StepAckSchema>;
44
+ export declare function makeStepAck(testId: string, stepId: string): StepAck;
45
+ export declare const HelloRole: z.ZodEnum<["probe", "runner"]>;
46
+ export type HelloRole = z.infer<typeof HelloRole>;
47
+ export declare const HelloSchema: z.ZodObject<{
48
+ type: z.ZodLiteral<"hello">;
49
+ role: z.ZodEnum<["probe", "runner"]>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ type: "hello";
52
+ role: "probe" | "runner";
53
+ }, {
54
+ type: "hello";
55
+ role: "probe" | "runner";
56
+ }>;
57
+ export type Hello = z.infer<typeof HelloSchema>;
58
+ export declare function makeHello(role: HelloRole): Hello;
59
+ export declare const TestEndSchema: z.ZodObject<{
60
+ type: z.ZodLiteral<"test:end">;
61
+ testId: z.ZodString;
62
+ }, "strip", z.ZodTypeAny, {
63
+ type: "test:end";
64
+ testId: string;
65
+ }, {
66
+ type: "test:end";
67
+ testId: string;
68
+ }>;
69
+ export type TestEnd = z.infer<typeof TestEndSchema>;
70
+ export declare function makeTestEnd(testId: string): TestEnd;
71
+ export declare const SnapshotSchema: z.ZodObject<{
72
+ type: z.ZodLiteral<"snapshot">;
73
+ commit: z.ZodNumber;
74
+ testId: z.ZodString;
75
+ stepId: z.ZodString;
76
+ ts: z.ZodNumber;
77
+ tree: z.ZodType<SerializedNode, z.ZodTypeDef, SerializedNode>;
78
+ testIdIndex: z.ZodType<TestIdIndex, z.ZodTypeDef, TestIdIndex>;
79
+ }, "strip", z.ZodTypeAny, {
80
+ type: "snapshot";
81
+ testId: string;
82
+ stepId: string;
83
+ commit: number;
84
+ ts: number;
85
+ tree: SerializedNode;
86
+ testIdIndex: TestIdIndex;
87
+ }, {
88
+ type: "snapshot";
89
+ testId: string;
90
+ stepId: string;
91
+ commit: number;
92
+ ts: number;
93
+ tree: SerializedNode;
94
+ testIdIndex: TestIdIndex;
95
+ }>;
96
+ export type Snapshot = z.infer<typeof SnapshotSchema>;
97
+ export declare function makeSnapshot(payload: Omit<Snapshot, 'type'>): Snapshot;
98
+ export declare const A11yImpactSchema: z.ZodEnum<["minor", "moderate", "serious", "critical"]>;
99
+ export type A11yImpact = z.infer<typeof A11yImpactSchema>;
100
+ export declare const A11yViolationSchema: z.ZodObject<{
101
+ type: z.ZodLiteral<"a11y:violation">;
102
+ ruleId: z.ZodString;
103
+ impact: z.ZodEnum<["minor", "moderate", "serious", "critical"]>;
104
+ description: z.ZodString;
105
+ help: z.ZodString;
106
+ helpUrl: z.ZodOptional<z.ZodString>;
107
+ targets: z.ZodArray<z.ZodString, "many">;
108
+ }, "strip", z.ZodTypeAny, {
109
+ type: "a11y:violation";
110
+ ruleId: string;
111
+ impact: "minor" | "moderate" | "serious" | "critical";
112
+ description: string;
113
+ help: string;
114
+ targets: string[];
115
+ helpUrl?: string | undefined;
116
+ }, {
117
+ type: "a11y:violation";
118
+ ruleId: string;
119
+ impact: "minor" | "moderate" | "serious" | "critical";
120
+ description: string;
121
+ help: string;
122
+ targets: string[];
123
+ helpUrl?: string | undefined;
124
+ }>;
125
+ export type A11yViolation = z.infer<typeof A11yViolationSchema>;
126
+ export declare function makeA11yViolation(payload: Omit<A11yViolation, 'type'>): A11yViolation;
127
+ export declare const HmrStartSchema: z.ZodObject<{
128
+ type: z.ZodLiteral<"hmr:start">;
129
+ }, "strip", z.ZodTypeAny, {
130
+ type: "hmr:start";
131
+ }, {
132
+ type: "hmr:start";
133
+ }>;
134
+ export type HmrStart = z.infer<typeof HmrStartSchema>;
135
+ export declare function makeHmrStart(): HmrStart;
136
+ export declare const HmrEndSchema: z.ZodObject<{
137
+ type: z.ZodLiteral<"hmr:end">;
138
+ }, "strip", z.ZodTypeAny, {
139
+ type: "hmr:end";
140
+ }, {
141
+ type: "hmr:end";
142
+ }>;
143
+ export type HmrEnd = z.infer<typeof HmrEndSchema>;
144
+ export declare function makeHmrEnd(): HmrEnd;
145
+ export declare const RunEventSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
146
+ type: z.ZodLiteral<"step:set">;
147
+ testId: z.ZodString;
148
+ stepId: z.ZodString;
149
+ }, "strip", z.ZodTypeAny, {
150
+ type: "step:set";
151
+ testId: string;
152
+ stepId: string;
153
+ }, {
154
+ type: "step:set";
155
+ testId: string;
156
+ stepId: string;
157
+ }>, z.ZodObject<{
158
+ type: z.ZodLiteral<"step:ack">;
159
+ testId: z.ZodString;
160
+ stepId: z.ZodString;
161
+ }, "strip", z.ZodTypeAny, {
162
+ type: "step:ack";
163
+ testId: string;
164
+ stepId: string;
165
+ }, {
166
+ type: "step:ack";
167
+ testId: string;
168
+ stepId: string;
169
+ }>, z.ZodObject<{
170
+ type: z.ZodLiteral<"hello">;
171
+ role: z.ZodEnum<["probe", "runner"]>;
172
+ }, "strip", z.ZodTypeAny, {
173
+ type: "hello";
174
+ role: "probe" | "runner";
175
+ }, {
176
+ type: "hello";
177
+ role: "probe" | "runner";
178
+ }>, z.ZodObject<{
179
+ type: z.ZodLiteral<"snapshot">;
180
+ commit: z.ZodNumber;
181
+ testId: z.ZodString;
182
+ stepId: z.ZodString;
183
+ ts: z.ZodNumber;
184
+ tree: z.ZodType<SerializedNode, z.ZodTypeDef, SerializedNode>;
185
+ testIdIndex: z.ZodType<TestIdIndex, z.ZodTypeDef, TestIdIndex>;
186
+ }, "strip", z.ZodTypeAny, {
187
+ type: "snapshot";
188
+ testId: string;
189
+ stepId: string;
190
+ commit: number;
191
+ ts: number;
192
+ tree: SerializedNode;
193
+ testIdIndex: TestIdIndex;
194
+ }, {
195
+ type: "snapshot";
196
+ testId: string;
197
+ stepId: string;
198
+ commit: number;
199
+ ts: number;
200
+ tree: SerializedNode;
201
+ testIdIndex: TestIdIndex;
202
+ }>, z.ZodObject<{
203
+ type: z.ZodLiteral<"test:end">;
204
+ testId: z.ZodString;
205
+ }, "strip", z.ZodTypeAny, {
206
+ type: "test:end";
207
+ testId: string;
208
+ }, {
209
+ type: "test:end";
210
+ testId: string;
211
+ }>, z.ZodObject<{
212
+ type: z.ZodLiteral<"a11y:violation">;
213
+ ruleId: z.ZodString;
214
+ impact: z.ZodEnum<["minor", "moderate", "serious", "critical"]>;
215
+ description: z.ZodString;
216
+ help: z.ZodString;
217
+ helpUrl: z.ZodOptional<z.ZodString>;
218
+ targets: z.ZodArray<z.ZodString, "many">;
219
+ }, "strip", z.ZodTypeAny, {
220
+ type: "a11y:violation";
221
+ ruleId: string;
222
+ impact: "minor" | "moderate" | "serious" | "critical";
223
+ description: string;
224
+ help: string;
225
+ targets: string[];
226
+ helpUrl?: string | undefined;
227
+ }, {
228
+ type: "a11y:violation";
229
+ ruleId: string;
230
+ impact: "minor" | "moderate" | "serious" | "critical";
231
+ description: string;
232
+ help: string;
233
+ targets: string[];
234
+ helpUrl?: string | undefined;
235
+ }>, z.ZodObject<{
236
+ type: z.ZodLiteral<"hmr:start">;
237
+ }, "strip", z.ZodTypeAny, {
238
+ type: "hmr:start";
239
+ }, {
240
+ type: "hmr:start";
241
+ }>, z.ZodObject<{
242
+ type: z.ZodLiteral<"hmr:end">;
243
+ }, "strip", z.ZodTypeAny, {
244
+ type: "hmr:end";
245
+ }, {
246
+ type: "hmr:end";
247
+ }>]>;
248
+ export type RunEvent = z.infer<typeof RunEventSchema>;
249
+ export declare function parseRunEvent(raw: string): RunEvent | undefined;
250
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,kBAAkB,yEAO7B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAS1D,CAAC;AAKF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAoC,CAAC;AAQ1F,eAAO,MAAM,aAAa;;;;;;;;;;;;EAIxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;EAIxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,eAAO,MAAM,SAAS,gCAA8B,CAAC;AACrD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD,eAAO,MAAM,WAAW;;;;;;;;;EAGtB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAEhD;AAED,eAAO,MAAM,aAAa;;;;;;;;;EAGxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;EAQzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,wBAAgB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,QAAQ,CAEtE;AAID,eAAO,MAAM,gBAAgB,yDAAuD,CAAC;AACrF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;EAS9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,aAAa,CAErF;AAKD,eAAO,MAAM,cAAc;;;;;;EAA6C,CAAC;AACzE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,wBAAgB,YAAY,IAAI,QAAQ,CAEvC;AAED,eAAO,MAAM,YAAY;;;;;;EAA2C,CAAC;AACrE,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IASzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAS/D"}
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ // @nativelens/event-protocol
2
+ // Local mirror of the eventual @reactlens/event-protocol package (ADR 0002).
3
+ // Schemas + canonical types for events flowing on the bus.
4
+ import { z } from 'zod';
5
+ // --- Component snapshot ---
6
+ export const SerializedNodeKind = z.enum([
7
+ 'host',
8
+ 'function',
9
+ 'class',
10
+ 'memo',
11
+ 'forwardRef',
12
+ 'other',
13
+ ]);
14
+ export const SerializedNodeSchema = z.lazy(() => z.object({
15
+ fiberId: z.number(),
16
+ name: z.string(),
17
+ kind: SerializedNodeKind,
18
+ props: z.record(z.string(), z.unknown()),
19
+ hooks: z.array(z.unknown()),
20
+ children: z.array(SerializedNodeSchema),
21
+ }));
22
+ export const TestIdIndexSchema = z.record(z.string(), z.number());
23
+ // --- RunEvent: discriminated union of every event on the wire ---
24
+ //
25
+ // Each variant ships with a zod schema, a builder, and is included in
26
+ // `parseRunEvent` for inbound decoding. Adding a new variant means: extend
27
+ // the union below, add a builder, and add the schema to the discriminator.
28
+ export const StepSetSchema = z.object({
29
+ type: z.literal('step:set'),
30
+ testId: z.string(),
31
+ stepId: z.string(),
32
+ });
33
+ export function makeStepSet(testId, stepId) {
34
+ return { type: 'step:set', testId, stepId };
35
+ }
36
+ export const StepAckSchema = z.object({
37
+ type: z.literal('step:ack'),
38
+ testId: z.string(),
39
+ stepId: z.string(),
40
+ });
41
+ export function makeStepAck(testId, stepId) {
42
+ return { type: 'step:ack', testId, stepId };
43
+ }
44
+ export const HelloRole = z.enum(['probe', 'runner']);
45
+ export const HelloSchema = z.object({
46
+ type: z.literal('hello'),
47
+ role: HelloRole,
48
+ });
49
+ export function makeHello(role) {
50
+ return { type: 'hello', role };
51
+ }
52
+ export const TestEndSchema = z.object({
53
+ type: z.literal('test:end'),
54
+ testId: z.string(),
55
+ });
56
+ export function makeTestEnd(testId) {
57
+ return { type: 'test:end', testId };
58
+ }
59
+ export const SnapshotSchema = z.object({
60
+ type: z.literal('snapshot'),
61
+ commit: z.number(),
62
+ testId: z.string(),
63
+ stepId: z.string(),
64
+ ts: z.number(),
65
+ tree: SerializedNodeSchema,
66
+ testIdIndex: TestIdIndexSchema,
67
+ });
68
+ export function makeSnapshot(payload) {
69
+ return { type: 'snapshot', ...payload };
70
+ }
71
+ // `a11y:violation` carries over from reactlens unchanged (ADR 0005 §Event protocol).
72
+ // The walker emits a Violation[]; the runner adapter sends one event per violation.
73
+ export const A11yImpactSchema = z.enum(['minor', 'moderate', 'serious', 'critical']);
74
+ export const A11yViolationSchema = z.object({
75
+ type: z.literal('a11y:violation'),
76
+ ruleId: z.string(),
77
+ impact: A11yImpactSchema,
78
+ description: z.string(),
79
+ help: z.string(),
80
+ helpUrl: z.string().optional(),
81
+ // testIDs of the affected elements (resolved via testIdIndex on the dashboard).
82
+ targets: z.array(z.string()),
83
+ });
84
+ export function makeA11yViolation(payload) {
85
+ return { type: 'a11y:violation', ...payload };
86
+ }
87
+ // HMR coordination events (P12, ADR pending) — signal Metro hot-reload
88
+ // boundaries to the harness so snapshots emitted during a hot reload can be
89
+ // discarded rather than mistaken for end-of-action commits.
90
+ export const HmrStartSchema = z.object({ type: z.literal('hmr:start') });
91
+ export function makeHmrStart() {
92
+ return { type: 'hmr:start' };
93
+ }
94
+ export const HmrEndSchema = z.object({ type: z.literal('hmr:end') });
95
+ export function makeHmrEnd() {
96
+ return { type: 'hmr:end' };
97
+ }
98
+ export const RunEventSchema = z.discriminatedUnion('type', [
99
+ StepSetSchema,
100
+ StepAckSchema,
101
+ HelloSchema,
102
+ SnapshotSchema,
103
+ TestEndSchema,
104
+ A11yViolationSchema,
105
+ HmrStartSchema,
106
+ HmrEndSchema,
107
+ ]);
108
+ export function parseRunEvent(raw) {
109
+ let candidate;
110
+ try {
111
+ candidate = JSON.parse(raw);
112
+ }
113
+ catch {
114
+ return undefined;
115
+ }
116
+ const result = RunEventSchema.safeParse(candidate);
117
+ return result.success ? result.data : undefined;
118
+ }
119
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@reynsu/nativelens-event-protocol",
3
+ "version": "0.1.1",
4
+ "description": "Canonical RunEvent union + Zod schemas for the nativelens event bus. Consumed by @nativelens/* packages and by reactlens once it migrates per ADR-0002.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "files": [
8
+ "dist",
9
+ "src",
10
+ "!src/**/*.test.ts"
11
+ ],
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.build.json",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "typecheck": "tsc --noEmit",
25
+ "prepublishOnly": "npm run typecheck && npm test && npm run build"
26
+ },
27
+ "dependencies": {
28
+ "zod": "^3.23.8"
29
+ },
30
+ "devDependencies": {
31
+ "typescript": "~5.9.2",
32
+ "vitest": "^2.1.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/reynsu/nativelens-protocol.git"
40
+ },
41
+ "pnpm": {
42
+ "onlyBuiltDependencies": ["esbuild"]
43
+ }
44
+ }
package/src/index.ts ADDED
@@ -0,0 +1,171 @@
1
+ // @nativelens/event-protocol
2
+ // Local mirror of the eventual @reactlens/event-protocol package (ADR 0002).
3
+ // Schemas + canonical types for events flowing on the bus.
4
+
5
+ import { z } from 'zod';
6
+
7
+ // --- Component snapshot ---
8
+
9
+ export const SerializedNodeKind = z.enum([
10
+ 'host',
11
+ 'function',
12
+ 'class',
13
+ 'memo',
14
+ 'forwardRef',
15
+ 'other',
16
+ ]);
17
+ export type SerializedNodeKind = z.infer<typeof SerializedNodeKind>;
18
+
19
+ export type SerializedNode = {
20
+ fiberId: number;
21
+ name: string;
22
+ kind: SerializedNodeKind;
23
+ props: Record<string, unknown>;
24
+ hooks: unknown[];
25
+ children: SerializedNode[];
26
+ };
27
+
28
+ export const SerializedNodeSchema: z.ZodType<SerializedNode> = z.lazy(() =>
29
+ z.object({
30
+ fiberId: z.number(),
31
+ name: z.string(),
32
+ kind: SerializedNodeKind,
33
+ props: z.record(z.string(), z.unknown()),
34
+ hooks: z.array(z.unknown()),
35
+ children: z.array(SerializedNodeSchema),
36
+ }),
37
+ );
38
+
39
+ // testID → fiberId map shipped alongside the tree on `component:snapshot`.
40
+ // Last-write-wins on duplicate testIDs; the probe emits a warning when a
41
+ // collision happens so users surface ambiguous locators.
42
+ export type TestIdIndex = Record<string, number>;
43
+
44
+ export const TestIdIndexSchema: z.ZodType<TestIdIndex> = z.record(z.string(), z.number());
45
+
46
+ // --- RunEvent: discriminated union of every event on the wire ---
47
+ //
48
+ // Each variant ships with a zod schema, a builder, and is included in
49
+ // `parseRunEvent` for inbound decoding. Adding a new variant means: extend
50
+ // the union below, add a builder, and add the schema to the discriminator.
51
+
52
+ export const StepSetSchema = z.object({
53
+ type: z.literal('step:set'),
54
+ testId: z.string(),
55
+ stepId: z.string(),
56
+ });
57
+ export type StepSet = z.infer<typeof StepSetSchema>;
58
+
59
+ export function makeStepSet(testId: string, stepId: string): StepSet {
60
+ return { type: 'step:set', testId, stepId };
61
+ }
62
+
63
+ export const StepAckSchema = z.object({
64
+ type: z.literal('step:ack'),
65
+ testId: z.string(),
66
+ stepId: z.string(),
67
+ });
68
+ export type StepAck = z.infer<typeof StepAckSchema>;
69
+
70
+ export function makeStepAck(testId: string, stepId: string): StepAck {
71
+ return { type: 'step:ack', testId, stepId };
72
+ }
73
+
74
+ export const HelloRole = z.enum(['probe', 'runner']);
75
+ export type HelloRole = z.infer<typeof HelloRole>;
76
+
77
+ export const HelloSchema = z.object({
78
+ type: z.literal('hello'),
79
+ role: HelloRole,
80
+ });
81
+ export type Hello = z.infer<typeof HelloSchema>;
82
+
83
+ export function makeHello(role: HelloRole): Hello {
84
+ return { type: 'hello', role };
85
+ }
86
+
87
+ export const TestEndSchema = z.object({
88
+ type: z.literal('test:end'),
89
+ testId: z.string(),
90
+ });
91
+ export type TestEnd = z.infer<typeof TestEndSchema>;
92
+
93
+ export function makeTestEnd(testId: string): TestEnd {
94
+ return { type: 'test:end', testId };
95
+ }
96
+
97
+ export const SnapshotSchema = z.object({
98
+ type: z.literal('snapshot'),
99
+ commit: z.number(),
100
+ testId: z.string(),
101
+ stepId: z.string(),
102
+ ts: z.number(),
103
+ tree: SerializedNodeSchema,
104
+ testIdIndex: TestIdIndexSchema,
105
+ });
106
+ export type Snapshot = z.infer<typeof SnapshotSchema>;
107
+
108
+ export function makeSnapshot(payload: Omit<Snapshot, 'type'>): Snapshot {
109
+ return { type: 'snapshot', ...payload };
110
+ }
111
+
112
+ // `a11y:violation` carries over from reactlens unchanged (ADR 0005 §Event protocol).
113
+ // The walker emits a Violation[]; the runner adapter sends one event per violation.
114
+ export const A11yImpactSchema = z.enum(['minor', 'moderate', 'serious', 'critical']);
115
+ export type A11yImpact = z.infer<typeof A11yImpactSchema>;
116
+
117
+ export const A11yViolationSchema = z.object({
118
+ type: z.literal('a11y:violation'),
119
+ ruleId: z.string(),
120
+ impact: A11yImpactSchema,
121
+ description: z.string(),
122
+ help: z.string(),
123
+ helpUrl: z.string().optional(),
124
+ // testIDs of the affected elements (resolved via testIdIndex on the dashboard).
125
+ targets: z.array(z.string()),
126
+ });
127
+ export type A11yViolation = z.infer<typeof A11yViolationSchema>;
128
+
129
+ export function makeA11yViolation(payload: Omit<A11yViolation, 'type'>): A11yViolation {
130
+ return { type: 'a11y:violation', ...payload };
131
+ }
132
+
133
+ // HMR coordination events (P12, ADR pending) — signal Metro hot-reload
134
+ // boundaries to the harness so snapshots emitted during a hot reload can be
135
+ // discarded rather than mistaken for end-of-action commits.
136
+ export const HmrStartSchema = z.object({ type: z.literal('hmr:start') });
137
+ export type HmrStart = z.infer<typeof HmrStartSchema>;
138
+
139
+ export function makeHmrStart(): HmrStart {
140
+ return { type: 'hmr:start' };
141
+ }
142
+
143
+ export const HmrEndSchema = z.object({ type: z.literal('hmr:end') });
144
+ export type HmrEnd = z.infer<typeof HmrEndSchema>;
145
+
146
+ export function makeHmrEnd(): HmrEnd {
147
+ return { type: 'hmr:end' };
148
+ }
149
+
150
+ export const RunEventSchema = z.discriminatedUnion('type', [
151
+ StepSetSchema,
152
+ StepAckSchema,
153
+ HelloSchema,
154
+ SnapshotSchema,
155
+ TestEndSchema,
156
+ A11yViolationSchema,
157
+ HmrStartSchema,
158
+ HmrEndSchema,
159
+ ]);
160
+ export type RunEvent = z.infer<typeof RunEventSchema>;
161
+
162
+ export function parseRunEvent(raw: string): RunEvent | undefined {
163
+ let candidate: unknown;
164
+ try {
165
+ candidate = JSON.parse(raw);
166
+ } catch {
167
+ return undefined;
168
+ }
169
+ const result = RunEventSchema.safeParse(candidate);
170
+ return result.success ? result.data : undefined;
171
+ }