Skip to content

Commit 6c8010f

Browse files
committed
Migrate from deprecated rawprotoparse to rawproto
1 parent 90d8f33 commit 6c8010f

4 files changed

Lines changed: 256 additions & 12 deletions

File tree

custom-typings/rawproto.d.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
declare module 'rawproto' {
2+
/**
3+
* RawProto class for parsing raw protobuf binary data without a schema.
4+
* Migrated from deprecated rawprotoparse package.
5+
*/
6+
export class RawProto {
7+
constructor(data: Uint8Array | ArrayBuffer | Buffer | number[]);
8+
9+
/**
10+
* Convert the parsed protobuf data to a JavaScript object.
11+
* @param queryMap - Optional query map for field name/type mapping
12+
* @param prefix - Field name prefix (default: 'f')
13+
* @param nameMap - Optional name map
14+
* @param typeMap - Optional type map
15+
*/
16+
toJS(
17+
queryMap?: Record<string, string>,
18+
prefix?: string,
19+
nameMap?: Record<string, string>,
20+
typeMap?: Record<string, string>
21+
): Record<string, any>;
22+
23+
/**
24+
* Generate a .proto schema file from the parsed data.
25+
*/
26+
toProto(
27+
queryMap?: Record<string, string>,
28+
prefix?: string,
29+
nameMap?: Record<string, string>,
30+
typeMap?: Record<string, string>,
31+
messageName?: string
32+
): string;
33+
34+
/**
35+
* Query specific fields using path:type format.
36+
*/
37+
query(...queries: string[]): any[];
38+
39+
/**
40+
* Sub-messages indexed by field number.
41+
*/
42+
sub: Record<string, RawProto[]>;
43+
44+
/**
45+
* Field counts.
46+
*/
47+
fields: Record<number, number>;
48+
49+
/**
50+
* The value as a string, if it looks like a string.
51+
*/
52+
string?: string;
53+
54+
/**
55+
* The value as an integer.
56+
*/
57+
int?: number;
58+
59+
/**
60+
* The value as a float.
61+
*/
62+
float?: number;
63+
64+
/**
65+
* The value as a boolean.
66+
*/
67+
bool?: boolean;
68+
69+
/**
70+
* The raw bytes.
71+
*/
72+
bytes?: Buffer;
73+
74+
/**
75+
* Whether the value is likely a string.
76+
*/
77+
likelyString?: boolean;
78+
}
79+
80+
export default RawProto;
81+
}

package-lock.json

Lines changed: 59 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
"posthog-js": "^1.57.2",
120120
"qrcode.react": "^4.2.0",
121121
"randexp": "^0.5.3",
122-
"rawprotoparse": "^0.0.9",
122+
"rawproto": "^1.0.3",
123123
"react": "^18.2.0",
124124
"react-autosuggest": "^10.0.4",
125125
"react-beautiful-dnd": "^13.1.1",

src/util/protobuf.ts

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,107 @@
1-
import parseRawProto from 'rawprotoparse';
1+
/// <reference path="../../custom-typings/rawproto.d.ts" />
2+
import RawProto from 'rawproto';
23
import { gunzipSync, inflateSync } from 'zlib';
34

45
import { Headers } from '../types';
56
import { getHeaderValue } from '../model/http/headers';
67

8+
/**
9+
* Recursively converts a RawProto tree to a simple JS object.
10+
* This mirrors the output format of the deprecated rawprotoparse package.
11+
*
12+
* The old rawprotoparse returned:
13+
* - Single values directly: { "1": "Hello World" }
14+
* - Nested messages as objects: { "1": { "2": "value" } }
15+
* - Buffers for binary data
16+
*
17+
* @param protoNode - A RawProto node to convert
18+
* @returns A plain JavaScript object with field numbers as keys
19+
*/
20+
function convertRawProtoToObject(protoNode: RawProto): Record<string, any> {
21+
const result: Record<string, any> = {};
22+
23+
if (!protoNode.sub) {
24+
return result;
25+
}
26+
27+
for (const fieldNum of Object.keys(protoNode.sub)) {
28+
const fields = protoNode.sub[fieldNum];
29+
30+
if (fields.length === 1) {
31+
const field = fields[0];
32+
33+
let handled = false;
34+
35+
// Try string first
36+
if (field.likelyString !== undefined ? field.likelyString : false) {
37+
try {
38+
const str = field.string;
39+
if (str !== undefined) {
40+
result[fieldNum] = str;
41+
handled = true;
42+
}
43+
} catch (e) {}
44+
}
45+
46+
if (handled) continue;
47+
48+
// Check if it's a sub-message (has its own sub fields)
49+
if (field.sub && Object.keys(field.sub).length > 0) {
50+
result[fieldNum] = convertRawProtoToObject(field);
51+
continue;
52+
}
53+
54+
// Try int for varint types
55+
try {
56+
const num = field.int;
57+
if (num !== undefined && typeof num === 'number' && Number.isSafeInteger(num)) {
58+
result[fieldNum] = num;
59+
continue;
60+
}
61+
} catch (e) {}
62+
63+
// Fall back to bytes
64+
try {
65+
const bytes = field.bytes;
66+
if (bytes !== undefined) {
67+
result[fieldNum] = Buffer.from(bytes);
68+
continue;
69+
}
70+
} catch (e) {}
71+
72+
result[fieldNum] = null;
73+
} else {
74+
// Multiple values - create an array
75+
result[fieldNum] = fields.map((field: any) => {
76+
if (field.likelyString !== undefined ? field.likelyString : false) {
77+
try {
78+
const str = field.string;
79+
if (str !== undefined) return str;
80+
} catch (e) {}
81+
}
82+
83+
if (field.sub && Object.keys(field.sub).length > 0) {
84+
return convertRawProtoToObject(field);
85+
}
86+
87+
try {
88+
const num = field.int;
89+
if (num !== undefined && typeof num === 'number' && Number.isSafeInteger(num)) return num;
90+
} catch (e) {}
91+
92+
try {
93+
const bytes = field.bytes;
94+
if (bytes !== undefined) return Buffer.from(bytes);
95+
} catch (e) {}
96+
97+
return null;
98+
});
99+
}
100+
}
101+
102+
return result;
103+
}
104+
7105
export function isProbablyProtobuf(input: Uint8Array) {
8106
// Protobuf data starts with a varint, consisting of a
9107
// field number in [1, 2^29[ and a field type in [0, 5]*.
@@ -36,7 +134,22 @@ export function isProbablyProtobuf(input: Uint8Array) {
36134
[0, 1, 2, 5].includes(fieldType);
37135
}
38136

39-
export const parseRawProtobuf = parseRawProto;
137+
/**
138+
* Parse raw protobuf binary data into a JavaScript object.
139+
* This is a wrapper around rawproto that maintains backward compatibility
140+
* with the old rawprotoparse API.
141+
*
142+
* @param input - The protobuf binary data to parse
143+
* @param _options - Options object (for backward compatibility, currently unused)
144+
* @returns Parsed protobuf data as a JavaScript object
145+
*/
146+
export function parseRawProtobuf(
147+
input: Uint8Array | Buffer,
148+
_options?: { prefix?: string }
149+
): any {
150+
const rawProto = new RawProto(input);
151+
return convertRawProtoToObject(rawProto);
152+
}
40153

41154
// GRPC message structure:
42155
// Ref: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md

0 commit comments

Comments
 (0)