ts-proto 1.172.0 → 1.174.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/README.markdown CHANGED
@@ -305,6 +305,8 @@ Generated code will be placed in the Gradle build directory.
305
305
 
306
306
  The default behavior is `forceLong=number`, which will internally still use the `long` library to encode/decode values on the wire (so you will still see a `util.Long = Long` line in your output), but will convert the `long` values to `number` automatically for you. Note that a runtime error is thrown if, while doing this conversion, a 64-bit value is larger than can be correctly stored as a `number`.
307
307
 
308
+ - With `--ts_proto_opt=useJsTypeOverride`, 64-bit numbers will be ouput as the [FieldOption.JSType](https://protobuf.dev/reference/java/api-docs/com/google/protobuf/DescriptorProtos.FieldOptions.JSType) specified on the field. This takes precendence over the `forceLong` option provided.
309
+
308
310
  - With `--ts_proto_opt=esModuleInterop=true` changes output to be `esModuleInterop` compliant.
309
311
 
310
312
  Specifically the `Long` imports will be generated as `import Long from 'long'` instead of `import * as Long from 'long'`.
@@ -796,6 +798,14 @@ type OneOfCase<T, K extends OneOfCases<T>> = T extends {
796
798
  }
797
799
  ? T[U]
798
800
  : never;
801
+
802
+ /** Extracts the specific type of a value type from a oneOf field */
803
+ export type OneOfValue<T, K extends OneOfCases<T>> = T extends {
804
+ $case: K;
805
+ [key: string]: unknown;
806
+ }
807
+ ? T
808
+ : never;
799
809
  ```
800
810
 
801
811
  # Default values and unset fields
package/build/main.js CHANGED
@@ -794,7 +794,17 @@ function getDecodeReadSnippet(ctx, field) {
794
794
  }
795
795
  }
796
796
  else if ((0, types_1.basicLongWireType)(field.type) !== undefined) {
797
- if (options.forceLong === options_1.LongOption.LONG) {
797
+ if ((0, types_1.isJsTypeFieldOption)(options, field)) {
798
+ switch (field.options.jstype) {
799
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER:
800
+ readSnippet = (0, ts_poet_1.code) `${utils.longToNumber}(${readSnippet} as Long)`;
801
+ break;
802
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING:
803
+ readSnippet = (0, ts_poet_1.code) `${utils.longToString}(${readSnippet} as Long)`;
804
+ break;
805
+ }
806
+ }
807
+ else if (options.forceLong === options_1.LongOption.LONG) {
798
808
  readSnippet = (0, ts_poet_1.code) `${readSnippet} as Long`;
799
809
  }
800
810
  else if (options.forceLong === options_1.LongOption.STRING) {
@@ -1038,13 +1048,13 @@ function getEncodeWriteSnippet(ctx, field) {
1038
1048
  case "int64":
1039
1049
  case "sint64":
1040
1050
  case "sfixed64":
1041
- return (place) => (0, ts_poet_1.code) `if (BigInt.asIntN(64, ${place}) !== ${place}) {
1051
+ return (place, placeAlt) => (0, ts_poet_1.code) `if (BigInt.asIntN(64, ${place}) !== ${placeAlt !== null && placeAlt !== void 0 ? placeAlt : place}) {
1042
1052
  throw new ${utils.globalThis}.Error('value provided for field ${place} of type ${fieldType} too large');
1043
1053
  }
1044
1054
  writer.uint32(${tag}).${(0, types_1.toReaderCall)(field)}(${place}.toString())`;
1045
1055
  case "uint64":
1046
1056
  case "fixed64":
1047
- return (place) => (0, ts_poet_1.code) `if (BigInt.asUintN(64, ${place}) !== ${place}) {
1057
+ return (place, placeAlt) => (0, ts_poet_1.code) `if (BigInt.asUintN(64, ${place}) !== ${placeAlt !== null && placeAlt !== void 0 ? placeAlt : place}) {
1048
1058
  throw new ${utils.globalThis}.Error('value provided for field ${place} of type ${fieldType} too large');
1049
1059
  }
1050
1060
  writer.uint32(${tag}).${(0, types_1.toReaderCall)(field)}(${place}.toString())`;
@@ -1277,9 +1287,13 @@ function generateEncode(ctx, fullName, messageDesc) {
1277
1287
  `);
1278
1288
  }
1279
1289
  else if ((0, types_1.isScalar)(field) || (0, types_1.isEnum)(field)) {
1290
+ const isJsType = (0, types_1.isScalar)(field) && (0, types_1.isJsTypeFieldOption)(options, field);
1291
+ const body = isJsType && options.forceLong === options_1.LongOption.BIGINT
1292
+ ? writeSnippet(`BigInt(${messageProperty})`)
1293
+ : writeSnippet(`${messageProperty}`);
1280
1294
  chunks.push((0, ts_poet_1.code) `
1281
1295
  if (${(0, types_1.notDefaultCheck)(ctx, field, messageDesc.options, `${messageProperty}`)}) {
1282
- ${writeSnippet(`${messageProperty}`)};
1296
+ ${body};
1283
1297
  }
1284
1298
  `);
1285
1299
  }
@@ -1566,6 +1580,7 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1566
1580
  const jsonPropertyOptional = (0, utils_1.getPropertyAccessor)("object", jsonName, true);
1567
1581
  // get code that extracts value from incoming object
1568
1582
  const readSnippet = (from) => {
1583
+ var _a;
1569
1584
  if ((0, types_1.isEnum)(field)) {
1570
1585
  const fromJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "FromJSON");
1571
1586
  return (0, ts_poet_1.code) `${fromJson}(${from})`;
@@ -1580,6 +1595,11 @@ function generateFromJson(ctx, fullName, fullTypeName, messageDesc) {
1580
1595
  return (0, ts_poet_1.code) `${utils.bytesFromBase64}(${from})`;
1581
1596
  }
1582
1597
  }
1598
+ else if ((0, types_1.isLong)(field) && (0, types_1.isJsTypeFieldOption)(options, field)) {
1599
+ const fieldType = (_a = (0, types_1.getFieldOptionsJsType)(field, ctx.options)) !== null && _a !== void 0 ? _a : field.type;
1600
+ const cstr = (0, case_1.capitalize)((0, types_1.basicTypeName)(ctx, { ...field, type: fieldType }, { keepValueType: true }).toCodeString([]));
1601
+ return (0, ts_poet_1.code) `${utils.globalThis}.${cstr}(${from})`;
1602
+ }
1583
1603
  else if ((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.LONG) {
1584
1604
  const cstr = (0, case_1.capitalize)((0, types_1.basicTypeName)(ctx, field, { keepValueType: true }).toCodeString([]));
1585
1605
  return (0, ts_poet_1.code) `${cstr}.fromValue(${from})`;
@@ -1812,6 +1832,7 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1812
1832
  const jsonProperty = (0, utils_1.getPropertyAccessor)("obj", jsonName);
1813
1833
  const messageProperty = (0, utils_1.getPropertyAccessor)("message", fieldName);
1814
1834
  const readSnippet = (from) => {
1835
+ var _a;
1815
1836
  if ((0, types_1.isEnum)(field)) {
1816
1837
  const toJson = (0, types_1.getEnumMethod)(ctx, field.typeName, "ToJSON");
1817
1838
  return (0, ts_poet_1.code) `${toJson}(${from})`;
@@ -1889,6 +1910,14 @@ function generateToJson(ctx, fullName, fullProtobufTypeName, messageDesc) {
1889
1910
  else if ((0, types_1.isBytes)(field)) {
1890
1911
  return (0, ts_poet_1.code) `${utils.base64FromBytes}(${from})`;
1891
1912
  }
1913
+ else if ((0, types_1.isLong)(field) && (0, types_1.isJsTypeFieldOption)(options, field)) {
1914
+ const fieldType = (_a = (0, types_1.getFieldOptionsJsType)(field, ctx.options)) !== null && _a !== void 0 ? _a : field.type;
1915
+ if (!fieldType) {
1916
+ return (0, ts_poet_1.code) `${from}`;
1917
+ }
1918
+ const cstr = (0, case_1.capitalize)((0, types_1.basicTypeName)(ctx, { ...field, type: fieldType }, { keepValueType: true }).toCodeString([]));
1919
+ return (0, ts_poet_1.code) `${utils.globalThis}.${cstr}(${from})`;
1920
+ }
1892
1921
  else if ((0, types_1.isLong)(field) && options.forceLong === options_1.LongOption.LONG) {
1893
1922
  return (0, ts_poet_1.code) `(${from} || ${(0, types_1.defaultValue)(ctx, field)}).toString()`;
1894
1923
  }
@@ -2007,7 +2036,9 @@ function generateFromPartial(ctx, fullName, messageDesc) {
2007
2036
  const messageProperty = (0, utils_1.getPropertyAccessor)("message", fieldName);
2008
2037
  const objectProperty = (0, utils_1.getPropertyAccessor)("object", fieldName);
2009
2038
  const readSnippet = (from) => {
2010
- if (((0, types_1.isLong)(field) || (0, types_1.isLongValueType)(field)) && options.forceLong === options_1.LongOption.LONG) {
2039
+ if (((0, types_1.isLong)(field) || (0, types_1.isLongValueType)(field)) &&
2040
+ options.forceLong === options_1.LongOption.LONG &&
2041
+ !(0, types_1.isJsTypeFieldOption)(options, field)) {
2011
2042
  return (0, ts_poet_1.code) `Long.fromValue(${from})`;
2012
2043
  }
2013
2044
  else if ((0, types_1.isObjectId)(field) && options.useMongoObjectId) {
@@ -35,6 +35,7 @@ export type Options = {
35
35
  context: boolean;
36
36
  snakeToCamel: Array<"json" | "keys">;
37
37
  forceLong: LongOption;
38
+ useJsTypeOverride: boolean;
38
39
  globalThisPolyfill: boolean;
39
40
  useOptionals: boolean | "none" | "deprecatedOnly" | "messages" | "all";
40
41
  emitDefaultValues: Array<"json-methods">;
@@ -97,5 +98,5 @@ export type Options = {
97
98
  };
98
99
  export declare function defaultOptions(): Options;
99
100
  export declare function optionsFromParameter(parameter: string | undefined): Options;
100
- export declare function getTsPoetOpts(options: Options): ToStringOpts;
101
+ export declare function getTsPoetOpts(options: Options, tsProtoVersion: string, protocVersion: string, fileName?: string): ToStringOpts;
101
102
  export declare function addTypeToMessages(options: Options): boolean;
package/build/options.js CHANGED
@@ -46,6 +46,7 @@ function defaultOptions() {
46
46
  emitDefaultValues: [],
47
47
  globalThisPolyfill: false,
48
48
  forceLong: LongOption.NUMBER,
49
+ useJsTypeOverride: false,
49
50
  useOptionals: "none",
50
51
  useDate: DateOption.DATE,
51
52
  useJsonTimestamp: JsonTimestampOption.RFC3339,
@@ -244,11 +245,20 @@ function parseParameter(parameter) {
244
245
  function parseParamValue(value) {
245
246
  return value === "true" ? true : value === "false" ? false : value;
246
247
  }
247
- function getTsPoetOpts(options) {
248
+ function getTsPoetOpts(options, tsProtoVersion, protocVersion, fileName) {
248
249
  const { importSuffix, esModuleInterop } = options;
249
250
  const pbjs = "protobufjs/minimal" + importSuffix;
250
251
  return {
251
- prefix: `/* eslint-disable */`,
252
+ // Comment block at the top of every source file, since these comments require specific
253
+ // syntax incompatible with ts-poet, we will hard-code the string and prepend to the
254
+ // generator output.
255
+ prefix: `// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
256
+ // versions:
257
+ // protoc-gen-ts_proto ${tsProtoVersion}
258
+ // protoc ${protocVersion}
259
+ ${fileName ? `// source: ${fileName}` : ""}
260
+
261
+ /* eslint-disable */`,
252
262
  dprintOptions: { preferSingleLine: true, lineWidth: 120 },
253
263
  forceRequireImport: esModuleInterop ? [] : ["long"],
254
264
  forceDefaultImport: esModuleInterop ? [pbjs] : [],
package/build/plugin.js CHANGED
@@ -14,6 +14,7 @@ async function main() {
14
14
  // const json = JSON.parse(stdin.toString());
15
15
  // const request = CodeGeneratorRequest.fromObject(json);
16
16
  const request = ts_proto_descriptors_1.CodeGeneratorRequest.decode(stdin);
17
+ const { protocVersion, tsProtoVersion } = await (0, utils_1.getVersions)(request);
17
18
  const options = (0, options_1.optionsFromParameter)(request.parameter);
18
19
  const typeMap = (0, types_1.createTypeMap)(request, options);
19
20
  const utils = (0, main_1.makeUtils)(options);
@@ -42,7 +43,7 @@ async function main() {
42
43
  }
43
44
  const files = await Promise.all(filesToGenerate.map(async (file) => {
44
45
  const [path, code] = (0, main_1.generateFile)({ ...ctx, currentFile: (0, context_1.createFileContext)(file) }, file);
45
- const content = code.toString({ ...(0, options_1.getTsPoetOpts)(options), path });
46
+ const content = code.toString({ ...(0, options_1.getTsPoetOpts)(options, tsProtoVersion, protocVersion, file.name), path });
46
47
  return { name: path, content };
47
48
  }));
48
49
  if (options.outputTypeRegistry) {
@@ -50,12 +51,12 @@ async function main() {
50
51
  const ctx = { options, typeMap, utils };
51
52
  const path = "typeRegistry.ts";
52
53
  const code = (0, generate_type_registry_1.generateTypeRegistry)(ctx);
53
- const content = code.toString({ ...(0, options_1.getTsPoetOpts)(options), path });
54
+ const content = code.toString({ ...(0, options_1.getTsPoetOpts)(options, tsProtoVersion, protocVersion), path });
54
55
  files.push({ name: path, content });
55
56
  }
56
57
  if (options.outputIndex) {
57
58
  for (const [path, code] of (0, utils_1.generateIndexFiles)(filesToGenerate, options)) {
58
- const content = code.toString({ ...(0, options_1.getTsPoetOpts)(options), path });
59
+ const content = code.toString({ ...(0, options_1.getTsPoetOpts)(options, tsProtoVersion, protocVersion), path });
59
60
  files.push({ name: path, content });
60
61
  }
61
62
  }
package/build/types.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare function basicTypeName(ctx: Context, field: FieldDescriptorProto,
12
12
  /** Returns the Reader method for the primitive's read/write call. */
13
13
  export declare function toReaderCall(field: FieldDescriptorProto): string;
14
14
  export declare function packedType(type: FieldDescriptorProto_Type): number | undefined;
15
+ export declare function getFieldOptionsJsType(field: FieldDescriptorProto, options: Options): FieldDescriptorProto_Type | undefined;
15
16
  export declare function defaultValue(ctx: Context, field: FieldDescriptorProto): any;
16
17
  /** Creates code that checks that the field is not the default value. Supports scalars and enums. */
17
18
  export declare function notDefaultCheck(ctx: Context, field: FieldDescriptorProto, messageOptions: MessageOptions | undefined, place: string): Code;
@@ -101,3 +102,4 @@ export interface BatchMethod {
101
102
  mapType: boolean;
102
103
  }
103
104
  export declare function detectBatchMethod(ctx: Context, fileDesc: FileDescriptorProto, serviceDesc: ServiceDescriptorProto, methodDesc: MethodDescriptorProto): BatchMethod | undefined;
105
+ export declare function isJsTypeFieldOption(options: Options, field: FieldDescriptorProto): boolean;
package/build/types.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.detectBatchMethod = exports.responsePromiseOrObservable = exports.responseObservable = exports.responsePromise = exports.responseType = exports.requestType = exports.observableType = exports.rawRequestType = exports.detectMapType = exports.shouldGenerateJSMapType = exports.toTypeName = exports.getEnumMethod = exports.messageToTypeName = exports.wrapperTypeName = exports.valueTypeName = exports.isEmptyType = exports.isLongValueType = exports.isStructTypeName = exports.isStructType = exports.isListValueTypeName = exports.isListValueType = exports.isFieldMaskTypeName = exports.isFieldMaskType = exports.isBytesValueType = exports.isAnyValueTypeName = exports.isAnyValueType = exports.isValueType = exports.isTimestamp = exports.isObjectId = exports.isMapType = exports.isWholeNumber = exports.isLong = exports.isRepeated = exports.isWithinOneOfThatShouldBeUnion = exports.isWithinOneOf = exports.isEnum = exports.isMessage = exports.isBytes = exports.isPrimitive = exports.isOptionalProperty = exports.isScalar = exports.createTypeMap = exports.notDefaultCheck = exports.defaultValue = exports.packedType = exports.toReaderCall = exports.basicTypeName = exports.basicLongWireType = exports.basicWireType = void 0;
3
+ exports.detectBatchMethod = exports.responsePromiseOrObservable = exports.responseObservable = exports.responsePromise = exports.responseType = exports.requestType = exports.observableType = exports.rawRequestType = exports.detectMapType = exports.shouldGenerateJSMapType = exports.toTypeName = exports.getEnumMethod = exports.messageToTypeName = exports.wrapperTypeName = exports.valueTypeName = exports.isEmptyType = exports.isLongValueType = exports.isStructTypeName = exports.isStructType = exports.isListValueTypeName = exports.isListValueType = exports.isFieldMaskTypeName = exports.isFieldMaskType = exports.isBytesValueType = exports.isAnyValueTypeName = exports.isAnyValueType = exports.isValueType = exports.isTimestamp = exports.isObjectId = exports.isMapType = exports.isWholeNumber = exports.isLong = exports.isRepeated = exports.isWithinOneOfThatShouldBeUnion = exports.isWithinOneOf = exports.isEnum = exports.isMessage = exports.isBytes = exports.isPrimitive = exports.isOptionalProperty = exports.isScalar = exports.createTypeMap = exports.notDefaultCheck = exports.defaultValue = exports.getFieldOptionsJsType = exports.packedType = exports.toReaderCall = exports.basicTypeName = exports.basicLongWireType = exports.basicWireType = void 0;
4
+ exports.isJsTypeFieldOption = void 0;
4
5
  const ts_proto_descriptors_1 = require("ts-proto-descriptors");
5
6
  const ts_poet_1 = require("ts-poet");
6
7
  const options_1 = require("./options");
@@ -60,8 +61,10 @@ function basicLongWireType(type) {
60
61
  exports.basicLongWireType = basicLongWireType;
61
62
  /** Returns the type name without any repeated/required/etc. labels. */
62
63
  function basicTypeName(ctx, field, typeOptions = {}) {
64
+ var _a, _b;
63
65
  const { options } = ctx;
64
- switch (field.type) {
66
+ const fieldType = (_a = getFieldOptionsJsType(field, ctx.options)) !== null && _a !== void 0 ? _a : field.type;
67
+ switch (fieldType) {
65
68
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_DOUBLE:
66
69
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FLOAT:
67
70
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_INT32:
@@ -75,8 +78,10 @@ function basicTypeName(ctx, field, typeOptions = {}) {
75
78
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SINT64:
76
79
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FIXED64:
77
80
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED64:
78
- // this handles 2^53, Long is only needed for 2^64; this is effectively pbjs's forceNumber
79
- return longTypeName(ctx);
81
+ return isJsTypeFieldOption(options, field)
82
+ ? (_b = jsTypeName(field)) !== null && _b !== void 0 ? _b : longTypeName(ctx)
83
+ : // this handles 2^53, Long is only needed for 2^64; this is effectively pbjs's forceNumber
84
+ longTypeName(ctx);
80
85
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_BOOL:
81
86
  return (0, ts_poet_1.code) `boolean`;
82
87
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_STRING:
@@ -164,10 +169,28 @@ function packedType(type) {
164
169
  }
165
170
  }
166
171
  exports.packedType = packedType;
172
+ function getFieldOptionsJsType(field, options) {
173
+ var _a;
174
+ if (!options.useJsTypeOverride || ((_a = field.options) === null || _a === void 0 ? void 0 : _a.jstype) === undefined) {
175
+ return;
176
+ }
177
+ switch (field.options.jstype) {
178
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING:
179
+ return ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_STRING;
180
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER:
181
+ return ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_INT64;
182
+ // In the case of JS_NORMAL, we don't want to override the type, so we return
183
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_NORMAL:
184
+ // In the case of UNRECOGNIZED, we assume default behavior and we don't want to override the type, so we return
185
+ case ts_proto_descriptors_1.FieldOptions_JSType.UNRECOGNIZED:
186
+ return;
187
+ }
188
+ }
189
+ exports.getFieldOptionsJsType = getFieldOptionsJsType;
167
190
  function defaultValue(ctx, field) {
168
191
  const { typeMap, options, utils, currentFile } = ctx;
169
192
  const useDefaultValue = !currentFile.isProto3Syntax && !options.disableProto2DefaultValues && field.defaultValue;
170
- const numbericDefaultVal = useDefaultValue ? field.defaultValue : 0;
193
+ const numericDefaultVal = useDefaultValue ? field.defaultValue : 0;
171
194
  switch (field.type) {
172
195
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_DOUBLE:
173
196
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FLOAT:
@@ -176,7 +199,7 @@ function defaultValue(ctx, field) {
176
199
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SINT32:
177
200
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FIXED32:
178
201
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED32:
179
- return numbericDefaultVal;
202
+ return numericDefaultVal;
180
203
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_ENUM:
181
204
  // proto3 enforces enums starting at 0, however proto2 does not, so we have
182
205
  // to probe and see if zero is an allowed value. If it's not, pick the first one.
@@ -193,34 +216,33 @@ function defaultValue(ctx, field) {
193
216
  else {
194
217
  return defaultEnum.number;
195
218
  }
219
+ case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_INT64:
196
220
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_UINT64:
197
221
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FIXED64:
198
- if (options.forceLong === options_1.LongOption.LONG) {
199
- return (0, ts_poet_1.code) `${utils.Long}.${useDefaultValue ? "fromNumber" : "UZERO"}${useDefaultValue ? `(${numbericDefaultVal})` : ""}`;
200
- }
201
- else if (options.forceLong === options_1.LongOption.STRING) {
202
- return `"${numbericDefaultVal}"`;
203
- }
204
- else if (options.forceLong === options_1.LongOption.BIGINT) {
205
- return `BigInt("${numbericDefaultVal}")`;
206
- }
207
- else {
208
- return numbericDefaultVal;
209
- }
210
- case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_INT64:
211
222
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SINT64:
212
223
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED64:
224
+ if (isJsTypeFieldOption(options, field)) {
225
+ switch (field.options.jstype) {
226
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING:
227
+ return `"${numericDefaultVal}"`;
228
+ case ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER:
229
+ return numericDefaultVal;
230
+ }
231
+ }
213
232
  if (options.forceLong === options_1.LongOption.LONG) {
214
- return (0, ts_poet_1.code) `${utils.Long}.${useDefaultValue ? "fromNumber" : "ZERO"}${useDefaultValue ? `(${numbericDefaultVal})` : ""}`;
233
+ const value = field.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_UINT64 || field.type === ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_FIXED64
234
+ ? "UZERO"
235
+ : "ZERO";
236
+ return (0, ts_poet_1.code) `${utils.Long}.${useDefaultValue ? "fromNumber" : value}${useDefaultValue ? `(${numericDefaultVal})` : ""}`;
215
237
  }
216
238
  else if (options.forceLong === options_1.LongOption.STRING) {
217
- return `"${numbericDefaultVal}"`;
239
+ return `"${numericDefaultVal}"`;
218
240
  }
219
241
  else if (options.forceLong === options_1.LongOption.BIGINT) {
220
- return `BigInt("${numbericDefaultVal}")`;
242
+ return `BigInt("${numericDefaultVal}")`;
221
243
  }
222
244
  else {
223
- return numbericDefaultVal;
245
+ return numericDefaultVal;
224
246
  }
225
247
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_BOOL:
226
248
  return useDefaultValue ? field.defaultValue : false;
@@ -278,7 +300,7 @@ function notDefaultCheck(ctx, field, messageOptions, place) {
278
300
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_INT64:
279
301
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SINT64:
280
302
  case ts_proto_descriptors_1.FieldDescriptorProto_Type.TYPE_SFIXED64:
281
- if (options.forceLong === options_1.LongOption.LONG) {
303
+ if (options.forceLong === options_1.LongOption.LONG && !isJsTypeFieldOption(options, field)) {
282
304
  return (0, ts_poet_1.code) `${maybeNotUndefinedAnd} !${place}.equals(${defaultValue(ctx, field)})`;
283
305
  }
284
306
  else {
@@ -541,6 +563,15 @@ function longTypeName(ctx) {
541
563
  return (0, ts_poet_1.code) `number`;
542
564
  }
543
565
  }
566
+ function jsTypeName(field) {
567
+ var _a, _b;
568
+ if (((_a = field.options) === null || _a === void 0 ? void 0 : _a.jstype) === ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING) {
569
+ return (0, ts_poet_1.code) `string`;
570
+ }
571
+ else if (((_b = field.options) === null || _b === void 0 ? void 0 : _b.jstype) === ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER) {
572
+ return (0, ts_poet_1.code) `number`;
573
+ }
574
+ }
544
575
  /** Maps `.some_proto_namespace.Message` to a TypeName. */
545
576
  function messageToTypeName(ctx, protoType, typeOptions = {}) {
546
577
  var _a;
@@ -584,13 +615,15 @@ function getEnumMethod(ctx, enumProtoType, methodSuffix) {
584
615
  exports.getEnumMethod = getEnumMethod;
585
616
  /** Return the TypeName for any field (primitive/message/etc.) as exposed in the interface. */
586
617
  function toTypeName(ctx, messageDesc, field, ensureOptional = false) {
618
+ var _a;
587
619
  function finalize(type, isOptional) {
588
620
  if (isOptional) {
589
621
  return (0, ts_poet_1.code) `${type} | ${(0, utils_1.nullOrUndefined)(ctx.options, field.proto3Optional)}`;
590
622
  }
591
623
  return type;
592
624
  }
593
- let type = basicTypeName(ctx, field, { keepValueType: false });
625
+ const fieldType = (_a = getFieldOptionsJsType(field, ctx.options)) !== null && _a !== void 0 ? _a : field.type;
626
+ const type = basicTypeName(ctx, { ...field, type: fieldType }, { keepValueType: false });
594
627
  if (isRepeated(field)) {
595
628
  const mapType = messageDesc ? detectMapType(ctx, messageDesc, field) : false;
596
629
  if (mapType) {
@@ -756,3 +789,9 @@ exports.detectBatchMethod = detectBatchMethod;
756
789
  function hasSingleRepeatedField(messageDesc) {
757
790
  return messageDesc.field.length == 1 && messageDesc.field[0].label === ts_proto_descriptors_1.FieldDescriptorProto_Label.LABEL_REPEATED;
758
791
  }
792
+ function isJsTypeFieldOption(options, field) {
793
+ var _a, _b;
794
+ return (options.useJsTypeOverride &&
795
+ (((_a = field.options) === null || _a === void 0 ? void 0 : _a.jstype) === ts_proto_descriptors_1.FieldOptions_JSType.JS_NUMBER || ((_b = field.options) === null || _b === void 0 ? void 0 : _b.jstype) === ts_proto_descriptors_1.FieldOptions_JSType.JS_STRING));
796
+ }
797
+ exports.isJsTypeFieldOption = isJsTypeFieldOption;
package/build/utils.d.ts CHANGED
@@ -14,7 +14,6 @@ export declare function lowerFirst(name: string): string;
14
14
  export declare function upperFirst(name: string): string;
15
15
  /** Removes potentially harmful characters from comments and pushes it into chunks. */
16
16
  export declare function maybeAddComment(options: Pick<Options, "comments">, desc: Partial<Pick<SourceDescription, "leadingComments" | "trailingComments">>, chunks: Code[], deprecated?: boolean, prefix?: string): void;
17
- export declare function prefixDisableLinter(spec: string): string;
18
17
  export declare function maybePrefixPackage(fileDesc: FileDescriptorProto, rest: string): string;
19
18
  /**
20
19
  * Asserts that an object is an instance of a certain class
@@ -78,3 +77,7 @@ export declare function withOrMaybeCheckIsNotNull(options: Pick<Options, "useNul
78
77
  export declare function withOrMaybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
79
78
  export declare function withAndMaybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
80
79
  export declare function withAndMaybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
80
+ export declare function getVersions(request: CodeGeneratorRequest): Promise<{
81
+ protocVersion: string;
82
+ tsProtoVersion: string;
83
+ }>;
package/build/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.withAndMaybeCheckIsNull = exports.withAndMaybeCheckIsNotNull = exports.withOrMaybeCheckIsNull = exports.withOrMaybeCheckIsNotNull = exports.maybeCheckIsNull = exports.maybeCheckIsNotNull = exports.nullOrUndefined = exports.arrowFunction = exports.tryCatchBlock = exports.impProto = exports.impFile = exports.getPropertyAccessor = exports.safeAccessor = exports.getFieldName = exports.getFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.generateIndexFiles = exports.protoFilesToGenerate = void 0;
3
+ exports.getVersions = exports.withAndMaybeCheckIsNull = exports.withAndMaybeCheckIsNotNull = exports.withOrMaybeCheckIsNull = exports.withOrMaybeCheckIsNotNull = exports.maybeCheckIsNull = exports.maybeCheckIsNotNull = exports.nullOrUndefined = exports.arrowFunction = exports.tryCatchBlock = exports.impProto = exports.impFile = exports.getPropertyAccessor = exports.safeAccessor = exports.getFieldName = exports.getFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.generateIndexFiles = exports.protoFilesToGenerate = void 0;
4
4
  const path = require("path");
5
5
  const ts_poet_1 = require("ts-poet");
6
6
  const options_1 = require("./options");
@@ -116,13 +116,6 @@ function maybeAddComment(options, desc, chunks, deprecated, prefix = "") {
116
116
  }
117
117
  }
118
118
  exports.maybeAddComment = maybeAddComment;
119
- // Comment block at the top of every source file, since these comments require specific
120
- // syntax incompatible with ts-poet, we will hard-code the string and prepend to the
121
- // generator output.
122
- function prefixDisableLinter(spec) {
123
- return `/* eslint-disable */\n${spec}`;
124
- }
125
- exports.prefixDisableLinter = prefixDisableLinter;
126
119
  function maybePrefixPackage(fileDesc, rest) {
127
120
  const prefix = fileDesc.package === "" ? "" : `${fileDesc.package}.`;
128
121
  return `${prefix}${rest}`;
@@ -289,3 +282,19 @@ function withAndMaybeCheckIsNull(options, typeName) {
289
282
  return maybeCheckIsNotNull(options, typeName, "&&");
290
283
  }
291
284
  exports.withAndMaybeCheckIsNull = withAndMaybeCheckIsNull;
285
+ async function getVersions(request) {
286
+ var _a;
287
+ let protocVersion = "unknown";
288
+ if (request.compilerVersion) {
289
+ const { major, minor, patch } = request.compilerVersion;
290
+ protocVersion = `v${major}.${minor}.${patch}`;
291
+ }
292
+ const path = "../package.json";
293
+ const packageJson = await Promise.resolve(`${path}`).then(s => require(s));
294
+ const tsProtoVersion = `v${(_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.version) !== null && _a !== void 0 ? _a : "unknown"}`;
295
+ return {
296
+ protocVersion,
297
+ tsProtoVersion,
298
+ };
299
+ }
300
+ exports.getVersions = getVersions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.172.0",
3
+ "version": "1.174.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",
@@ -62,7 +62,7 @@
62
62
  "rxjs": "^7.8.1",
63
63
  "semantic-release": "^21.0.7",
64
64
  "ts-jest": "^29.1.1",
65
- "tsx": "^3.12.7",
65
+ "tsx": "^3.14.0",
66
66
  "typescript": "^5.1.6",
67
67
  "uglify-js": "^3.17.4"
68
68
  },