0
# Reflection System
1
2
Complete runtime reflection API for working with protobuf types, services, and schemas. Provides programmatic access to all protobuf constructs with full type information and manipulation capabilities.
3
4
## Capabilities
5
6
### Root Namespace
7
8
Root namespace containing all loaded protobuf definitions, serving as the entry point for type lookup and schema management.
9
10
```javascript { .api }
11
class Root extends Namespace {
12
/**
13
* Constructs a new root namespace
14
* @param options - Root options
15
*/
16
constructor(options?: object);
17
18
/**
19
* Creates root from JSON descriptor
20
* @param json - JSON descriptor object
21
* @param root - Optional root to populate
22
* @returns Root instance
23
*/
24
static fromJSON(json: object, root?: Root): Root;
25
26
/**
27
* Deferred fields for cross-references
28
*/
29
deferred: Field[];
30
31
/**
32
* Loads proto files into this root
33
* @param filename - File path(s) to load
34
* @param callback - Callback receiving error and root
35
* @returns This root instance
36
*/
37
load(filename: string | string[], callback: LoadCallback): Root;
38
39
/**
40
* Synchronously loads proto files into this root
41
* @param filename - File path(s) to load
42
* @returns This root instance
43
*/
44
loadSync(filename: string | string[]): Root;
45
}
46
```
47
48
**Usage Examples:**
49
50
```javascript
51
const protobuf = require("protobufjs");
52
53
// Create new root
54
const root = new protobuf.Root();
55
56
// Load definitions
57
root.load("schema.proto", function(err, loadedRoot) {
58
// Look up message types
59
const UserMessage = root.lookupType("package.User");
60
const UserService = root.lookupService("package.UserService");
61
});
62
63
// Create from JSON descriptor
64
const jsonDescriptor = { /* JSON schema */ };
65
const root = protobuf.Root.fromJSON(jsonDescriptor);
66
```
67
68
### Type Reflection
69
70
Message type reflection providing complete schema information and instance operations.
71
72
```javascript { .api }
73
class Type extends Namespace {
74
/**
75
* Constructs a new message type
76
* @param name - Type name
77
* @param options - Type options
78
*/
79
constructor(name: string, options?: object);
80
81
/**
82
* Creates type from JSON descriptor
83
* @param name - Type name
84
* @param json - JSON descriptor
85
* @returns Type instance
86
*/
87
static fromJSON(name: string, json: object): Type;
88
89
/**
90
* Field definitions by field id
91
*/
92
fields: { [id: number]: Field };
93
94
/**
95
* OneOf definitions by name
96
*/
97
oneofs: { [name: string]: OneOf };
98
99
/**
100
* Extension field ranges
101
*/
102
extensions: number[][];
103
104
/**
105
* Reserved field ids and names
106
*/
107
reserved: Array<number[] | string[]>;
108
109
/**
110
* Array of all fields
111
*/
112
fieldsArray: Field[];
113
114
/**
115
* Array of all oneofs
116
*/
117
oneofsArray: OneOf[];
118
119
/**
120
* Message constructor function
121
*/
122
ctor: Message;
123
124
/**
125
* Creates message instance from properties
126
* @param properties - Property values
127
* @returns Message instance
128
*/
129
create(properties?: object): Message;
130
131
/**
132
* Encodes message to writer
133
* @param message - Message instance or plain object
134
* @param writer - Writer to encode to
135
* @returns Writer instance
136
*/
137
encode(message: Message | object, writer?: Writer): Writer;
138
139
/**
140
* Decodes message from reader
141
* @param reader - Reader or buffer to decode from
142
* @param length - Message length if known
143
* @returns Decoded message instance
144
*/
145
decode(reader: Reader | Uint8Array, length?: number): Message;
146
147
/**
148
* Verifies message properties
149
* @param message - Message properties to verify
150
* @returns Error message or null if valid
151
*/
152
verify(message: object): string | null;
153
154
/**
155
* Creates message from plain object
156
* @param object - Plain object with message data
157
* @returns Message instance
158
*/
159
fromObject(object: object): Message;
160
161
/**
162
* Converts message to plain object
163
* @param message - Message instance
164
* @param options - Conversion options
165
* @returns Plain object representation
166
*/
167
toObject(message: Message, options?: IConversionOptions): object;
168
}
169
```
170
171
**Usage Examples:**
172
173
```javascript
174
// Get type from root
175
const MessageType = root.lookupType("package.MessageType");
176
177
// Inspect type properties
178
console.log("Fields:", MessageType.fieldsArray.map(f => f.name));
179
console.log("OneOfs:", MessageType.oneofsArray.map(o => o.name));
180
181
// Create and manipulate messages
182
const message = MessageType.create({ field1: "value", field2: 42 });
183
const encoded = MessageType.encode(message).finish();
184
const decoded = MessageType.decode(encoded);
185
```
186
187
### Field Reflection
188
189
Field definitions within message types, including detailed type information and options.
190
191
```javascript { .api }
192
class Field extends FieldBase {
193
/**
194
* Constructs a new message field
195
* @param name - Field name
196
* @param id - Field id
197
* @param type - Field type
198
* @param rule - Field rule (optional, required, repeated)
199
* @param extend - Extended type if extension field
200
* @param options - Field options
201
*/
202
constructor(name: string, id: number, type: string, rule?: string, extend?: string, options?: object);
203
204
/**
205
* Field rule (optional, required, repeated)
206
*/
207
rule: string;
208
209
/**
210
* Field type name
211
*/
212
type: string;
213
214
/**
215
* Unique field id
216
*/
217
id: number;
218
219
/**
220
* Whether field is a map
221
*/
222
map: boolean;
223
224
/**
225
* Whether field is repeated
226
*/
227
repeated: boolean;
228
229
/**
230
* Whether field is required
231
*/
232
required: boolean;
233
234
/**
235
* Whether field is optional
236
*/
237
optional: boolean;
238
239
/**
240
* OneOf this field belongs to
241
*/
242
partOf: OneOf | null;
243
244
/**
245
* Default value for field type
246
*/
247
typeDefault: any;
248
249
/**
250
* Explicit default value
251
*/
252
defaultValue: any;
253
254
/**
255
* Resolved type reference
256
*/
257
resolvedType: Type | Enum | null;
258
}
259
```
260
261
**Usage Examples:**
262
263
```javascript
264
const MessageType = root.lookupType("package.Message");
265
266
// Inspect fields
267
MessageType.fieldsArray.forEach(field => {
268
console.log(`Field: ${field.name} (${field.type}) id=${field.id}`);
269
console.log(` Rule: ${field.rule}`);
270
console.log(` Required: ${field.required}`);
271
console.log(` Default: ${field.defaultValue}`);
272
273
if (field.resolvedType) {
274
console.log(` Resolved Type: ${field.resolvedType.name}`);
275
}
276
});
277
```
278
279
### Enum Reflection
280
281
Enumeration type reflection with value definitions and metadata.
282
283
```javascript { .api }
284
class Enum extends ReflectionObject {
285
/**
286
* Constructs a new enum
287
* @param name - Enum name
288
* @param values - Enum values
289
* @param options - Enum options
290
*/
291
constructor(name: string, values?: object, options?: object);
292
293
/**
294
* Creates enum from JSON descriptor
295
* @param name - Enum name
296
* @param json - JSON descriptor
297
* @returns Enum instance
298
*/
299
static fromJSON(name: string, json: object): Enum;
300
301
/**
302
* Enum values by name
303
*/
304
values: { [name: string]: number };
305
306
/**
307
* Enum values by id
308
*/
309
valuesById: { [id: number]: string };
310
311
/**
312
* Value comments by name
313
*/
314
comments: { [name: string]: string };
315
316
/**
317
* Adds enum value
318
* @param name - Value name
319
* @param id - Value id
320
* @param comment - Optional comment
321
* @returns This enum
322
*/
323
add(name: string, id: number, comment?: string): Enum;
324
325
/**
326
* Removes enum value
327
* @param name - Value name
328
* @returns This enum
329
*/
330
remove(name: string): Enum;
331
}
332
```
333
334
**Usage Examples:**
335
336
```javascript
337
const StatusEnum = root.lookupEnum("package.Status");
338
339
// Inspect enum values
340
Object.keys(StatusEnum.values).forEach(name => {
341
const id = StatusEnum.values[name];
342
console.log(`${name} = ${id}`);
343
});
344
345
// Use enum values
346
const message = MessageType.create({
347
status: StatusEnum.values.ACTIVE
348
});
349
```
350
351
### Service Reflection
352
353
Service definition reflection for RPC services and their methods.
354
355
```javascript { .api }
356
class Service extends Namespace {
357
/**
358
* Constructs a new service
359
* @param name - Service name
360
* @param options - Service options
361
*/
362
constructor(name: string, options?: object);
363
364
/**
365
* Creates service from JSON descriptor
366
* @param name - Service name
367
* @param json - JSON descriptor
368
* @returns Service instance
369
*/
370
static fromJSON(name: string, json: object): Service;
371
372
/**
373
* Service methods by name
374
*/
375
methods: { [name: string]: Method };
376
377
/**
378
* Array of all methods
379
*/
380
methodsArray: Method[];
381
382
/**
383
* Creates RPC service instance
384
* @param rpcImpl - RPC implementation
385
* @param requestDelimited - Whether requests are delimited
386
* @param responseDelimited - Whether responses are delimited
387
* @returns Service instance
388
*/
389
create(rpcImpl: RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): rpc.Service;
390
}
391
```
392
393
### Method Reflection
394
395
RPC method definitions within services.
396
397
```javascript { .api }
398
class Method extends ReflectionObject {
399
/**
400
* Constructs a new method
401
* @param name - Method name
402
* @param type - Method type (typically "rpc")
403
* @param requestType - Request type name
404
* @param responseType - Response type name
405
* @param requestStream - Whether request is streaming
406
* @param responseStream - Whether response is streaming
407
* @param options - Method options
408
*/
409
constructor(name: string, type: string, requestType: string, responseType: string,
410
requestStream?: boolean, responseStream?: boolean, options?: object);
411
412
/**
413
* Method type (typically "rpc")
414
*/
415
type: string;
416
417
/**
418
* Request type name
419
*/
420
requestType: string;
421
422
/**
423
* Response type name
424
*/
425
responseType: string;
426
427
/**
428
* Whether request is streaming
429
*/
430
requestStream: boolean;
431
432
/**
433
* Whether response is streaming
434
*/
435
responseStream: boolean;
436
437
/**
438
* Resolved request type
439
*/
440
resolvedRequestType: Type | null;
441
442
/**
443
* Resolved response type
444
*/
445
resolvedResponseType: Type | null;
446
}
447
```
448
449
### Namespace Operations
450
451
Base namespace operations for organizing and looking up protobuf definitions.
452
453
```javascript { .api }
454
class Namespace extends NamespaceBase {
455
/**
456
* Nested objects array (fields, types, services, etc.)
457
*/
458
nestedArray: ReflectionObject[];
459
460
/**
461
* Nested objects by name
462
*/
463
nested: { [name: string]: ReflectionObject };
464
465
/**
466
* Adds nested object to namespace
467
* @param object - Object to add
468
* @returns This namespace
469
*/
470
add(object: ReflectionObject): Namespace;
471
472
/**
473
* Removes nested object from namespace
474
* @param object - Object to remove
475
* @returns This namespace
476
*/
477
remove(object: ReflectionObject): Namespace;
478
479
/**
480
* Gets nested object by name
481
* @param name - Object name
482
* @returns Found object or null
483
*/
484
get(name: string): ReflectionObject | null;
485
486
/**
487
* Looks up nested object by path
488
* @param path - Dot-separated path
489
* @param filterTypes - Types to filter for
490
* @param parentAlreadyChecked - Whether parent was already checked
491
* @returns Found object or null
492
*/
493
lookup(path: string | string[], filterTypes?: any, parentAlreadyChecked?: boolean): ReflectionObject | null;
494
495
/**
496
* Looks up message type by path
497
* @param path - Dot-separated path
498
* @returns Found type or null
499
*/
500
lookupType(path: string | string[]): Type | null;
501
502
/**
503
* Looks up service by path
504
* @param path - Dot-separated path
505
* @returns Found service or null
506
*/
507
lookupService(path: string | string[]): Service | null;
508
509
/**
510
* Looks up enum by path
511
* @param path - Dot-separated path
512
* @returns Found enum or null
513
*/
514
lookupEnum(path: string | string[]): Enum | null;
515
516
/**
517
* Looks up type or enum by path
518
* @param path - Dot-separated path
519
* @returns Found type or enum or null
520
*/
521
lookupTypeOrEnum(path: string | string[]): Type | Enum | null;
522
}
523
```
524
525
**Usage Examples:**
526
527
```javascript
528
// Namespace traversal
529
const root = protobuf.Root.fromJSON(jsonDescriptor);
530
531
// Look up by absolute path
532
const UserType = root.lookupType("com.example.User");
533
const UserService = root.lookupService("com.example.UserService");
534
const StatusEnum = root.lookupEnum("com.example.Status");
535
536
// Iterate namespace contents
537
function printNamespace(ns, indent = "") {
538
ns.nestedArray.forEach(obj => {
539
console.log(indent + obj.name + " (" + obj.constructor.name + ")");
540
if (obj instanceof protobuf.Namespace) {
541
printNamespace(obj, indent + " ");
542
}
543
});
544
}
545
546
printNamespace(root);
547
```
548
549
## Types
550
551
```javascript { .api }
552
interface LoadCallback {
553
(error: Error | null, root?: Root): void;
554
}
555
556
interface IConversionOptions {
557
longs?: typeof String | typeof Number | typeof Long;
558
enums?: typeof String;
559
bytes?: typeof Array | typeof String;
560
defaults?: boolean;
561
arrays?: boolean;
562
objects?: boolean;
563
oneofs?: boolean;
564
}
565
566
interface RPCImpl {
567
(method: Method, requestData: Uint8Array, callback: RPCImplCallback): void;
568
}
569
570
interface RPCImplCallback {
571
(error: Error | null, response?: Uint8Array): void;
572
}
573
```