@dxos/codec-protobuf 2.33.9-dev.7d11f506 → 2.33.9-dev.8e92e630

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.
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2021 DXOS.org
3
+ //
4
+
5
+ import * as protobuf from 'protobufjs';
6
+
7
+ export const encodeProtobuf = (root: protobuf.Root): string => JSON.stringify(root.toJSON());
8
+
9
+ export const decodeProtobuf = (json: string): protobuf.Root => protobuf.Root.fromJSON(JSON.parse(json));
package/src/index.ts CHANGED
@@ -5,7 +5,9 @@
5
5
  export * from './buffer-patch';
6
6
  export * from './codec';
7
7
  export * from './common';
8
+ export * from './encoding';
8
9
  export * from './interface';
10
+ export * from './mapping';
9
11
  export * from './sanitizer';
10
12
  export * from './schema';
11
13
  export * from './service';
package/src/mapping.ts CHANGED
@@ -2,6 +2,9 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
+ import assert from 'node:assert';
6
+ import protobufjs from 'protobufjs';
7
+
5
8
  import { Substitutions } from './common';
6
9
 
7
10
  export type MapingDescriptors = Partial<Record<string, (value: any, ...extraArgs: any) => any>>
@@ -23,3 +26,60 @@ export const createMappingDescriptors = (substitutions: Substitutions): Bidirect
23
26
  decode
24
27
  };
25
28
  };
29
+
30
+ export type FieldMapper = (value: any, typeName: string) => Promise<any>;
31
+
32
+ export const mapMessage = async (type: protobufjs.Type, mapper: FieldMapper, obj: any) => {
33
+ const res: any = {};
34
+ for (const field of type.fieldsArray) {
35
+ if (!(field.name in obj)) {
36
+ continue;
37
+ }
38
+ res[field.name] = await mapField(field, mapper, obj[field.name]);
39
+ }
40
+
41
+ return res;
42
+ };
43
+
44
+ const mapField = async (field: protobufjs.Field, mapper: FieldMapper, value: any) => {
45
+ if (!field.required && (value === null || value === undefined)) {
46
+ return value;
47
+ } else if (field.repeated) {
48
+ return await Promise.all(value.map((value: any) => mapScalarField(field, mapper, value)));
49
+ } else if (field.map) {
50
+ assert(field instanceof protobufjs.MapField);
51
+ return await asyncObjectMap((value) => mapScalarField(field, mapper, value), value);
52
+ } else {
53
+ return mapScalarField(field, mapper, value);
54
+ }
55
+ };
56
+
57
+ const mapScalarField = async (field: protobufjs.Field, mapper: FieldMapper, value: any) => {
58
+ if (!field.resolved) {
59
+ field.resolve();
60
+ }
61
+
62
+ const typeName = field.resolvedType?.fullName.slice(1); // Name of the protobuf message type if the field type is not primitive.
63
+ if (typeName) {
64
+ return await mapper(value, typeName);
65
+ }
66
+
67
+ if (field.resolvedType && field.resolvedType instanceof protobufjs.Type) {
68
+ return await mapMessage(field.resolvedType, mapper, value);
69
+ }
70
+
71
+ return value;
72
+ };
73
+
74
+ const asyncObjectMap = async <K extends keyof any, T, U>(
75
+ map: (value: T, key: K) => Promise<U>,
76
+ record: Record<K, T>
77
+ ): Promise<Record<K, U>> => {
78
+ const res: Record<K, U> = {} as any;
79
+
80
+ await Promise.all(Object.entries(record).map(async ([key, value]) => {
81
+ res[key as keyof typeof res] = await map(value as T, key as K);
82
+ }));
83
+
84
+ return res;
85
+ };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
  import * as pb from 'protobufjs';
7
7
 
8
8
  import { MapingDescriptors } from '../mapping';
@@ -33,7 +33,6 @@ const createMessageMapperCached = (type: pb.Type, substitutions: MapingDescripto
33
33
  }
34
34
  };
35
35
 
36
- // TODO(dmaretskyi): Support maps.
37
36
  if (field.repeated) {
38
37
  c`res.${field.name} = obj.${field.name}.map(item => `;
39
38
  genMapScalar('item');
@@ -52,6 +51,11 @@ const createMessageMapperCached = (type: pb.Type, substitutions: MapingDescripto
52
51
  c`;`;
53
52
  }
54
53
  } c`}`;
54
+ if (!field.getOption('proto3_optional') && !field.repeated && !field.map && !field.partOf) {
55
+ c`else {`; {
56
+ c`${ref(throwMissingFieldError)}('${field.name}', '${field.parent!.fullName.slice(1)}')`;
57
+ } c`}`;
58
+ }
55
59
  }
56
60
  c`return res;`;
57
61
  });
@@ -59,3 +63,7 @@ const createMessageMapperCached = (type: pb.Type, substitutions: MapingDescripto
59
63
 
60
64
  return cache[type.fullName];
61
65
  };
66
+
67
+ const throwMissingFieldError = (fieldName: string, typeName: string) => {
68
+ throw new Error(`Missing field: ${fieldName} on ${typeName}`);
69
+ };
package/src/service.ts CHANGED
@@ -2,15 +2,15 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
5
+ import assert from 'node:assert';
6
6
  import pb from 'protobufjs';
7
7
 
8
8
  import type { Schema } from './schema';
9
9
  import { Stream } from './stream';
10
10
 
11
11
  export interface Any {
12
- 'type_url'?: string;
13
- value?: Uint8Array;
12
+ 'type_url': string;
13
+ value: Uint8Array;
14
14
  }
15
15
 
16
16
  export interface ServiceBackend {
package/src/stream.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'assert';
6
5
  import debug from 'debug';
6
+ import assert from 'node:assert';
7
7
 
8
8
  const log = debug('dxos:codec-protobuf:stream');
9
9