Skip to content

Commit dae506d

Browse files
committed
feat(ipc-codegen): human-authored JSONC schema format
Add a friendly JSONC schema front-end to schema_visitor.ts that lowers a single per-service object (service/aliases/types/error/commands with shorthand string type refs) to the positional named_union form the generators already consume, so the four generators are untouched and the produced CompiledSchema is identical. The type prefix and method-prefix stripping fold into the 'service' field, retiring --prefix/--strip-method-prefix and detectPrefix for friendly schemas. aliases support bin32 (nominal) and scalar synonyms (e.g. MerkleTreeId = u32). Convert the echo example schema to schema.jsonc and update its bootstraps; remove the schema_reflection_test (it asserted the old positional shape). Add scripts/convert_schema.ts, a one-shot positional->friendly converter used to migrate the remaining service schemas. Goldens unchanged; full echo test matrix (golden x4, UDS 4x4, SHM, ts_package) passes.
1 parent 993c25a commit dae506d

21 files changed

Lines changed: 634 additions & 736 deletions

ipc-codegen/SCHEMA_SPEC.md

Lines changed: 160 additions & 190 deletions
Large diffs are not rendered by default.

ipc-codegen/bootstrap.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ function test_cmds {
5555
echo "$prefix $script golden ts"
5656
echo "$prefix $script golden cpp"
5757
echo "$prefix $script golden zig"
58-
echo "$prefix ipc-codegen/echo_example/cpp/build/bin/schema_reflection_test --schema ipc-codegen/echo_example/schema/schema.json"
5958
echo "$prefix ipc-codegen/echo_example/ts_package/test.sh uds"
6059
echo "$prefix ipc-codegen/echo_example/ts_package/test.sh shm"
6160

ipc-codegen/echo_example/cpp/CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,5 @@ add_executable(echo_client
4848
)
4949
target_link_libraries(echo_client PRIVATE echo_common ipc_runtime)
5050

51-
add_executable(schema_reflection_test src/schema_reflection_test.cpp)
52-
target_link_libraries(schema_reflection_test PRIVATE echo_common)
53-
5451
add_executable(golden_test src/golden_test.cpp)
5552
target_link_libraries(golden_test PRIVATE echo_common)

ipc-codegen/echo_example/cpp/bootstrap.sh

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ CODEGEN="$(cd "$DIR/../.." && pwd)"
66
NODE="node --experimental-strip-types --experimental-transform-types --no-warnings"
77

88
$NODE "$CODEGEN/src/generate.ts" \
9-
--schema "$DIR/../schema/schema.json" \
9+
--schema "$DIR/../schema/schema.jsonc" \
1010
--lang cpp \
1111
--server \
1212
--client \
13-
--strip-method-prefix \
1413
--out "$DIR/src/generated" \
15-
--prefix Echo \
1614
--cpp-namespace echo
1715

1816
cmake -S "$DIR" -B "$DIR/build"
19-
cmake --build "$DIR/build" --target echo_server echo_client schema_reflection_test golden_test
17+
cmake --build "$DIR/build" --target echo_server echo_client golden_test

ipc-codegen/echo_example/cpp/src/schema_reflection_test.cpp

Lines changed: 0 additions & 79 deletions
This file was deleted.

ipc-codegen/echo_example/rust/bootstrap.sh

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ CODEGEN="$(cd "$DIR/../.." && pwd)"
66
NODE="node --experimental-strip-types --experimental-transform-types --no-warnings"
77

88
$NODE "$CODEGEN/src/generate.ts" \
9-
--schema "$DIR/../schema/schema.json" \
9+
--schema "$DIR/../schema/schema.jsonc" \
1010
--lang rust \
1111
--server \
1212
--client \
13-
--strip-method-prefix \
1413
--uds \
1514
--ffi \
16-
--out "$DIR/src/generated" \
17-
--prefix Echo
15+
--out "$DIR/src/generated"
1816

1917
(cd "$DIR" && cargo build --locked --quiet)
2018
# Compile-check the generated FFI backend (not linked into the binaries).

ipc-codegen/echo_example/schema/schema.json

Lines changed: 0 additions & 118 deletions
This file was deleted.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// echo.schema.jsonc — the entire echo service, human-authored.
2+
{
3+
"service": "Echo",
4+
5+
// Named byte aliases (nominal 32-byte types). Only bin32 today.
6+
"aliases": {
7+
"Fr": "bin32"
8+
},
9+
10+
// Shared struct types, referenced by name from commands.
11+
"types": {
12+
"EchoInner": {
13+
"values": "bytes[]",
14+
"flag": "bool?"
15+
}
16+
},
17+
18+
// Error variant shared by every command.
19+
"error": { "message": "string" },
20+
21+
// command -> { request, response }. Names are unprefixed; generated type
22+
// names get the service prefix (EchoBytes), method names do not (bytes).
23+
"commands": {
24+
"Bytes": { "request": { "data": "bytes" },
25+
"response": { "data": "bytes" } },
26+
27+
"Fields": { "request": { "a": "u32", "b": "u64", "name": "string" },
28+
"response": { "a": "u32", "b": "u64", "name": "string" } },
29+
30+
"Nested": { "request": { "inner": "EchoInner" },
31+
"response": { "inner": "EchoInner" } },
32+
33+
"Aliases": { "request": { "treeId": "u32", "hash": "Fr",
34+
"maybeHash": "Fr?", "hashes": "Fr[]" },
35+
"response": { "treeId": "u32", "hash": "Fr",
36+
"maybeHash": "Fr?", "hashes": "Fr[]" } },
37+
38+
"Blobs": { "request": { "maybeData": "bytes?", "parts": "bytes[2]" },
39+
"response": { "maybeData": "bytes?", "parts": "bytes[2]" } },
40+
41+
"Fail": { "request": { "message": "string" },
42+
"response": {} }
43+
}
44+
}

ipc-codegen/echo_example/ts/bootstrap.sh

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ REPO_ROOT="$(cd "$CODEGEN/.." && pwd)"
77
NODE="node --experimental-strip-types --experimental-transform-types --no-warnings"
88

99
$NODE "$CODEGEN/src/generate.ts" \
10-
--schema "$DIR/../schema/schema.json" \
10+
--schema "$DIR/../schema/schema.jsonc" \
1111
--lang ts \
1212
--server \
1313
--client \
14-
--out "$DIR/src/generated" \
15-
--prefix Echo
14+
--out "$DIR/src/generated"
1615

1716
(cd "$REPO_ROOT/ipc-runtime" && ./bootstrap.sh)
1817
(cd "$REPO_ROOT/ipc-runtime/ts" && yarn install --immutable && yarn build)

ipc-codegen/echo_example/ts/src/echo_client.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ async function run() {
5858

5959
// Test 1: EchoBytes
6060
const testData = Uint8Array.from([0xde, 0xad, 0xbe, 0xef, 0x42]);
61-
const resp1 = await api.echoBytes({ data: testData });
61+
const resp1 = await api.bytes({ data: testData });
6262
assertBytes(resp1.data, testData, "EchoBytes data");
6363
console.error("echo_client(ts): EchoBytes OK");
6464

6565
// Test 2: EchoFields
66-
const resp2 = await api.echoFields({
66+
const resp2 = await api.fields({
6767
a: 42,
6868
b: 999999,
6969
name: "hello wire compat",
@@ -78,7 +78,7 @@ async function run() {
7878
values: [Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5])],
7979
flag: true,
8080
};
81-
const resp3 = await api.echoNested({ inner });
81+
const resp3 = await api.nested({ inner });
8282
assertEqual(resp3.inner.flag, true, "EchoNested flag");
8383
assertEqual(resp3.inner.values.length, 2, "EchoNested values length");
8484
assertBytes(resp3.inner.values[0]!, inner.values[0]!, "EchoNested values[0]");
@@ -87,7 +87,7 @@ async function run() {
8787
// Test 4: EchoAliases
8888
const hash = testHash(0x10);
8989
const second = testHash(0x40);
90-
const resp4 = await api.echoAliases({
90+
const resp4 = await api.aliases({
9191
treeId: 7,
9292
hash,
9393
maybeHash: second,
@@ -102,7 +102,7 @@ async function run() {
102102
console.error("echo_client(ts): EchoAliases OK");
103103

104104
// Test 5: EchoAliases with maybeHash absent (optional over live IPC)
105-
const resp5 = await api.echoAliases({
105+
const resp5 = await api.aliases({
106106
treeId: 7,
107107
hash,
108108
maybeHash: null,
@@ -113,20 +113,20 @@ async function run() {
113113

114114
// Test 6: EchoFields with b > 2^32 (uint64 wire encoding over live IPC)
115115
const big = Number.MAX_SAFE_INTEGER;
116-
const resp6 = await api.echoFields({ a: 42, b: big, name: "big" });
116+
const resp6 = await api.fields({ a: 42, b: big, name: "big" });
117117
assertEqual(resp6.b, big, "EchoFields u64");
118118
// Values past 2^53 must throw client-side rather than silently lose precision.
119119
let threw = false;
120120
try {
121-
await api.echoFields({ a: 42, b: 2 ** 60, name: "too big" });
121+
await api.fields({ a: 42, b: 2 ** 60, name: "too big" });
122122
} catch {
123123
threw = true;
124124
}
125125
assertEqual(threw, true, "EchoFields u64 guard");
126126
console.error("echo_client(ts): EchoFields u64 OK");
127127

128128
// Test 7: EchoBlobs — optional bytes Some/None and fixed [bytes; 2]
129-
const resp7 = await api.echoBlobs({
129+
const resp7 = await api.blobs({
130130
maybeData: Uint8Array.from([0xaa, 0xbb]),
131131
parts: [Uint8Array.from([1, 2, 3]), Uint8Array.from([4])],
132132
});
@@ -141,7 +141,7 @@ async function run() {
141141
"EchoBlobs parts[0]",
142142
);
143143
assertBytes(resp7.parts[1]!, Uint8Array.from([4]), "EchoBlobs parts[1]");
144-
const resp7b = await api.echoBlobs({
144+
const resp7b = await api.blobs({
145145
maybeData: null,
146146
parts: [Uint8Array.from([]), Uint8Array.from([9])],
147147
});
@@ -151,7 +151,7 @@ async function run() {
151151
// Test 8: EchoFail — server error surfaces with its message
152152
let failMessage = "";
153153
try {
154-
await api.echoFail({ message: "deliberate failure" });
154+
await api.fail({ message: "deliberate failure" });
155155
} catch (e: any) {
156156
failMessage = e.message;
157157
}

0 commit comments

Comments
 (0)