@aptre/protobuf-es-lite 0.1.0

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/dist/util.js ADDED
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ // Copyright 2024 Aperture Robotics, LLC.
3
+ // Copyright 2021-2024 Buf Technologies, Inc.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.getFieldZeroValueExpression = exports.getFieldDefaultValueExpression = exports.getFieldTypeInfo = void 0;
18
+ const protobuf_1 = require("@bufbuild/protobuf");
19
+ const ecmascript_1 = require("@bufbuild/protoplugin/ecmascript");
20
+ function getFieldTypeInfo(field) {
21
+ const typing = [];
22
+ let typingInferrableFromZeroValue;
23
+ let optional = false;
24
+ switch (field.fieldKind) {
25
+ case "scalar":
26
+ typing.push(scalarTypeScriptType(field.scalar, field.longType));
27
+ optional =
28
+ field.optional ||
29
+ field.proto.label === protobuf_1.FieldDescriptorProto_Label.REQUIRED;
30
+ typingInferrableFromZeroValue = true;
31
+ break;
32
+ case "message": {
33
+ const baseType = protobuf_1.codegenInfo.getUnwrappedFieldType(field);
34
+ if (baseType !== undefined) {
35
+ typing.push(scalarTypeScriptType(baseType, protobuf_1.LongType.BIGINT));
36
+ }
37
+ else {
38
+ typing.push({
39
+ kind: "es_ref_message",
40
+ type: field.message,
41
+ typeOnly: true,
42
+ });
43
+ }
44
+ optional = true;
45
+ typingInferrableFromZeroValue = true;
46
+ break;
47
+ }
48
+ case "enum":
49
+ typing.push({
50
+ kind: "es_ref_enum",
51
+ type: field.enum,
52
+ typeOnly: true,
53
+ });
54
+ optional =
55
+ field.optional ||
56
+ field.proto.label === protobuf_1.FieldDescriptorProto_Label.REQUIRED;
57
+ typingInferrableFromZeroValue = true;
58
+ break;
59
+ case "map": {
60
+ let keyType;
61
+ switch (field.mapKey) {
62
+ case protobuf_1.ScalarType.INT32:
63
+ case protobuf_1.ScalarType.FIXED32:
64
+ case protobuf_1.ScalarType.UINT32:
65
+ case protobuf_1.ScalarType.SFIXED32:
66
+ case protobuf_1.ScalarType.SINT32:
67
+ keyType = "number";
68
+ break;
69
+ default:
70
+ keyType = "string";
71
+ break;
72
+ }
73
+ let valueType;
74
+ switch (field.mapValue.kind) {
75
+ case "scalar":
76
+ valueType = scalarTypeScriptType(field.mapValue.scalar, protobuf_1.LongType.BIGINT);
77
+ break;
78
+ case "message":
79
+ valueType = {
80
+ kind: "es_ref_message",
81
+ type: field.mapValue.message,
82
+ typeOnly: true,
83
+ };
84
+ break;
85
+ case "enum":
86
+ valueType = {
87
+ kind: "es_ref_enum",
88
+ type: field.mapValue.enum,
89
+ typeOnly: true,
90
+ };
91
+ break;
92
+ }
93
+ typing.push("{ [key: ", keyType, "]: ", valueType, " }");
94
+ typingInferrableFromZeroValue = false;
95
+ optional = false;
96
+ break;
97
+ }
98
+ }
99
+ if (field.repeated) {
100
+ typing.push("[]");
101
+ optional = false;
102
+ typingInferrableFromZeroValue = false;
103
+ }
104
+ return { typing, optional, typingInferrableFromZeroValue };
105
+ }
106
+ exports.getFieldTypeInfo = getFieldTypeInfo;
107
+ /**
108
+ * Return a printable expression for the default value of a field.
109
+ * Only applicable for singular scalar and enum fields.
110
+ */
111
+ function getFieldDefaultValueExpression(field, enumAs = "enum_value_as_is") {
112
+ if (field.repeated) {
113
+ return undefined;
114
+ }
115
+ if (field.fieldKind !== "enum" && field.fieldKind !== "scalar") {
116
+ return undefined;
117
+ }
118
+ const defaultValue = field.getDefaultValue();
119
+ if (defaultValue === undefined) {
120
+ return undefined;
121
+ }
122
+ switch (field.fieldKind) {
123
+ case "enum": {
124
+ const enumValue = field.enum.values.find((value) => value.number === defaultValue);
125
+ if (enumValue === undefined) {
126
+ throw new Error(`invalid enum default value: ${String(defaultValue)} for ${enumValue}`);
127
+ }
128
+ return literalEnumValue(enumValue, enumAs);
129
+ }
130
+ case "scalar":
131
+ return literalScalarValue(defaultValue, field);
132
+ }
133
+ }
134
+ exports.getFieldDefaultValueExpression = getFieldDefaultValueExpression;
135
+ /**
136
+ * Return a printable expression for the zero value of a field.
137
+ *
138
+ * Returns either:
139
+ * - empty array literal for repeated fields
140
+ * - empty object literal for maps
141
+ * - undefined for message fields
142
+ * - an enums first value
143
+ * - scalar zero value
144
+ */
145
+ function getFieldZeroValueExpression(field, enumAs = "enum_value_as_is") {
146
+ if (field.repeated) {
147
+ return "[]";
148
+ }
149
+ switch (field.fieldKind) {
150
+ case "message":
151
+ return undefined;
152
+ case "map":
153
+ return "{}";
154
+ case "enum": {
155
+ // In proto3, the first enum value must be zero.
156
+ // In proto2, protobuf-go returns the first value as the default.
157
+ if (field.enum.values.length < 1) {
158
+ throw new Error("invalid enum: missing at least one value");
159
+ }
160
+ const zeroValue = field.enum.values[0];
161
+ return literalEnumValue(zeroValue, enumAs);
162
+ }
163
+ case "scalar": {
164
+ const defaultValue = protobuf_1.codegenInfo.scalarZeroValue(field.scalar, field.longType);
165
+ return literalScalarValue(defaultValue, field);
166
+ }
167
+ }
168
+ }
169
+ exports.getFieldZeroValueExpression = getFieldZeroValueExpression;
170
+ function literalScalarValue(value, field) {
171
+ switch (field.scalar) {
172
+ case protobuf_1.ScalarType.DOUBLE:
173
+ case protobuf_1.ScalarType.FLOAT:
174
+ case protobuf_1.ScalarType.INT32:
175
+ case protobuf_1.ScalarType.FIXED32:
176
+ case protobuf_1.ScalarType.UINT32:
177
+ case protobuf_1.ScalarType.SFIXED32:
178
+ case protobuf_1.ScalarType.SINT32:
179
+ if (typeof value != "number") {
180
+ throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
181
+ }
182
+ return value;
183
+ case protobuf_1.ScalarType.BOOL:
184
+ if (typeof value != "boolean") {
185
+ throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
186
+ }
187
+ return value;
188
+ case protobuf_1.ScalarType.STRING:
189
+ if (typeof value != "string") {
190
+ throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
191
+ }
192
+ return { kind: "es_string", value };
193
+ case protobuf_1.ScalarType.BYTES:
194
+ if (!(value instanceof Uint8Array)) {
195
+ throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
196
+ }
197
+ return value;
198
+ case protobuf_1.ScalarType.INT64:
199
+ case protobuf_1.ScalarType.SINT64:
200
+ case protobuf_1.ScalarType.SFIXED64:
201
+ case protobuf_1.ScalarType.UINT64:
202
+ case protobuf_1.ScalarType.FIXED64:
203
+ if (typeof value != "bigint" && typeof value != "string") {
204
+ throw new Error(`Unexpected value for ${protobuf_1.ScalarType[field.scalar]} ${field.toString()}: ${String(value)}`);
205
+ }
206
+ return {
207
+ kind: "es_proto_int64",
208
+ type: field.scalar,
209
+ longType: field.longType,
210
+ value,
211
+ };
212
+ }
213
+ }
214
+ function literalEnumValue(value, enumAs) {
215
+ switch (enumAs) {
216
+ case "enum_value_as_is":
217
+ return [
218
+ { kind: "es_ref_enum", type: value.parent, typeOnly: false },
219
+ ".",
220
+ (0, ecmascript_1.localName)(value),
221
+ ];
222
+ case "enum_value_as_integer":
223
+ return [
224
+ value.number,
225
+ " /* ",
226
+ value.parent.typeName,
227
+ ".",
228
+ value.name,
229
+ " */",
230
+ ];
231
+ case "enum_value_as_cast_integer":
232
+ return [
233
+ value.number,
234
+ " as ",
235
+ { kind: "es_ref_enum", type: value.parent, typeOnly: true },
236
+ ".",
237
+ (0, ecmascript_1.localName)(value),
238
+ ];
239
+ }
240
+ }
241
+ function scalarTypeScriptType(type, longType) {
242
+ switch (type) {
243
+ case protobuf_1.ScalarType.STRING:
244
+ return "string";
245
+ case protobuf_1.ScalarType.BOOL:
246
+ return "boolean";
247
+ case protobuf_1.ScalarType.UINT64:
248
+ case protobuf_1.ScalarType.SFIXED64:
249
+ case protobuf_1.ScalarType.FIXED64:
250
+ case protobuf_1.ScalarType.SINT64:
251
+ case protobuf_1.ScalarType.INT64:
252
+ if (longType === protobuf_1.LongType.STRING) {
253
+ return "string";
254
+ }
255
+ return "bigint";
256
+ case protobuf_1.ScalarType.BYTES:
257
+ return "Uint8Array";
258
+ default:
259
+ return "number";
260
+ }
261
+ }
@@ -0,0 +1,30 @@
1
+ syntax = "proto3";
2
+ package example;
3
+
4
+ import "google/protobuf/timestamp.proto";
5
+
6
+ // Echoer service returns the given message.
7
+ service Echoer {
8
+ // Echo returns the given message.
9
+ rpc Echo(EchoMsg) returns (EchoMsg);
10
+ // EchoServerStream is an example of a server -> client one-way stream.
11
+ rpc EchoServerStream(EchoMsg) returns (stream EchoMsg);
12
+ // EchoClientStream is an example of client->server one-way stream.
13
+ rpc EchoClientStream(stream EchoMsg) returns (EchoMsg);
14
+ // EchoBidiStream is an example of a two-way stream.
15
+ rpc EchoBidiStream(stream EchoMsg) returns (stream EchoMsg);
16
+ }
17
+
18
+ // ExampleEnum is an example enumeration.
19
+ enum ExampleEnum {
20
+ UNKNOWN = 0;
21
+ FIRST = 1;
22
+ SECOND = 2;
23
+ }
24
+
25
+ // EchoMsg is the message body for Echo.
26
+ message EchoMsg {
27
+ string body = 1;
28
+ google.protobuf.Timestamp ts = 2;
29
+ ExampleEnum example_enum = 3;
30
+ }
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@aptre/protobuf-es-lite",
3
+ "description": "Lightweight Protobuf codegen for TypeScript and JavaScript.",
4
+ "version": "0.1.0",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "url": "git+ssh://git@github.com/aperturerobotics/protobuf-es-lite.git"
8
+ },
9
+ "files": [
10
+ ".ignore",
11
+ "LICENSE",
12
+ "README.md",
13
+ "bin/protoc-gen-es-lite",
14
+ "example/example.proto",
15
+ "example/example.pb.ts",
16
+ "tsconfig.base.json",
17
+ "tsconfig.json",
18
+ "dist"
19
+ ],
20
+ "bin": {
21
+ "protoc-gen-es-lite": "bin/protoc-gen-es-lite"
22
+ },
23
+ "main": "./dist/index.js",
24
+ "exports": {
25
+ ".": {
26
+ "import": "./dist/index.js",
27
+ "require": "./dist/index.js"
28
+ }
29
+ },
30
+ "engines": {
31
+ "node": ">=14"
32
+ },
33
+ "scripts": {
34
+ "clean": "rimraf ./dist",
35
+ "build": "npm run clean && tsc --project tsconfig.json --outDir ./dist",
36
+ "typecheck": "tsc --noEmit --project tsconfig.json --outDir ./dist",
37
+ "example": "npm run build && protoc --plugin=./bin/protoc-gen-es-lite --es-lite_out=. --es-lite_opt target=ts --es-lite_opt ts_nocheck=false ./example/example.proto",
38
+ "format": "prettier --write './src/**/(*.ts|*.tsx|*.html|*.css|*.scss)'"
39
+ },
40
+ "preferUnplugged": true,
41
+ "dependencies": {
42
+ "@bufbuild/protobuf": "^1.9.0",
43
+ "@bufbuild/protoplugin": "1.9.0"
44
+ },
45
+ "peerDependencies": {
46
+ "@bufbuild/protobuf": "1.9.0"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "@bufbuild/protobuf": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "devDependencies": {
54
+ "prettier": "^3.2.5",
55
+ "rimraf": "^5.0.5",
56
+ "typescript": "^5.4.5"
57
+ }
58
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "esModuleInterop": false,
5
+ "forceConsistentCasingInFileNames": true,
6
+ "strict": true,
7
+ "noImplicitAny": true,
8
+ "strictNullChecks": true,
9
+ "strictFunctionTypes": true,
10
+ "strictBindCallApply": true,
11
+ "strictPropertyInitialization": true,
12
+ "noImplicitThis": true,
13
+ "useUnknownInCatchVariables": true,
14
+ "noUnusedLocals": true,
15
+ "noImplicitReturns": true,
16
+ "noFallthroughCasesInSwitch": true,
17
+ "noImplicitOverride": true,
18
+ "moduleResolution": "Node16",
19
+ "module": "Node16",
20
+ "verbatimModuleSyntax": true,
21
+ "skipLibCheck": false
22
+ }
23
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "files": ["src/protoc-gen-es-lite-plugin.ts", "src/index.ts"],
3
+ "extends": "./tsconfig.base.json",
4
+ "compilerOptions": {
5
+ "resolveJsonModule": true,
6
+ "verbatimModuleSyntax": false,
7
+ "module": "CommonJS",
8
+ "moduleResolution": "Node10"
9
+ }
10
+ }