ts-proto 1.171.0 → 1.173.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
@@ -796,6 +796,14 @@ type OneOfCase<T, K extends OneOfCases<T>> = T extends {
796
796
  }
797
797
  ? T[U]
798
798
  : never;
799
+
800
+ /** Extracts the specific type of a value type from a oneOf field */
801
+ export type OneOfValue<T, K extends OneOfCases<T>> = T extends {
802
+ $case: K;
803
+ [key: string]: unknown;
804
+ }
805
+ ? T
806
+ : never;
799
807
  ```
800
808
 
801
809
  # Default values and unset fields
@@ -0,0 +1,8 @@
1
+ import { Options } from "./options";
2
+ /** Converts `key` to TS/JS camel-case idiom, unless overridden not to. */
3
+ export declare function maybeSnakeToCamel(key: string, options: Pick<Options, "snakeToCamel">): string;
4
+ export declare function snakeToCamel(s: string): string;
5
+ export declare function camelToSnake(s: string): string;
6
+ export declare function capitalize(s: string): string;
7
+ export declare function uncapitalize(s: string): string;
8
+ export declare function camelCaseGrpc(s: string): string;
@@ -0,0 +1,19 @@
1
+ import { TypeMap } from "./types";
2
+ import { Utils } from "./main";
3
+ import { Options } from "./options";
4
+ import { FileDescriptorProto } from "ts-proto-descriptors";
5
+ /** Provides a parameter object for passing around the various context/config data. */
6
+ export interface BaseContext {
7
+ options: Options;
8
+ typeMap: TypeMap;
9
+ utils: Utils;
10
+ }
11
+ export interface Context extends BaseContext {
12
+ currentFile: FileContext;
13
+ }
14
+ export interface FileContext {
15
+ isProto3Syntax: boolean;
16
+ }
17
+ export declare function createFileContext(file: FileDescriptorProto): {
18
+ isProto3Syntax: boolean;
19
+ };
@@ -0,0 +1,4 @@
1
+ import { Context } from "./context";
2
+ import { Code } from "ts-poet";
3
+ export declare function generateEncoder(ctx: Context, typeName: string): Code;
4
+ export declare function generateDecoder(ctx: Context, typeName: string): Code;
@@ -0,0 +1,19 @@
1
+ import { Code } from "ts-poet";
2
+ import { EnumDescriptorProto, EnumValueDescriptorProto } from "ts-proto-descriptors";
3
+ import SourceInfo from "./sourceInfo";
4
+ import { Context } from "./context";
5
+ type UnrecognizedEnum = {
6
+ present: false;
7
+ } | {
8
+ present: true;
9
+ name: string;
10
+ };
11
+ export declare function generateEnum(ctx: Context, fullName: string, enumDesc: EnumDescriptorProto, sourceInfo: SourceInfo): Code;
12
+ /** Generates a function with a big switch statement to decode JSON -> our enum. */
13
+ export declare function generateEnumFromJson(ctx: Context, fullName: string, enumDesc: EnumDescriptorProto, unrecognizedEnum: UnrecognizedEnum): Code;
14
+ /** Generates a function with a big switch statement to encode our enum -> JSON. */
15
+ export declare function generateEnumToJson(ctx: Context, fullName: string, enumDesc: EnumDescriptorProto, unrecognizedEnum: UnrecognizedEnum): Code;
16
+ /** Generates a function with a big switch statement to encode our string enum -> int value. */
17
+ export declare function generateEnumToNumber(ctx: Context, fullName: string, enumDesc: EnumDescriptorProto, unrecognizedEnum: UnrecognizedEnum): Code;
18
+ export declare function getMemberName(ctx: Context, enumDesc: EnumDescriptorProto, valueDesc: EnumValueDescriptorProto): string;
19
+ export {};
@@ -0,0 +1,6 @@
1
+ import { Code } from "ts-poet";
2
+ import { Utils } from "./main";
3
+ /** Creates a function to transform a message Source to a Uint8Array Source. */
4
+ export declare function generateEncodeTransform(utils: Utils, fullName: string): Code;
5
+ /** Creates a function to transform a Uint8Array Source to a message Source. */
6
+ export declare function generateDecodeTransform(utils: Utils, fullName: string): Code;
@@ -0,0 +1,8 @@
1
+ import { Code } from "ts-poet";
2
+ import { FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
3
+ import { Context } from "./context";
4
+ import SourceInfo from "./sourceInfo";
5
+ /**
6
+ * Generates a framework-agnostic service descriptor.
7
+ */
8
+ export declare function generateGenericServiceDefinition(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo, serviceDesc: ServiceDescriptorProto): Code;
@@ -0,0 +1,9 @@
1
+ import { Code } from "ts-poet";
2
+ import { FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
3
+ import { Context } from "./context";
4
+ import SourceInfo from "./sourceInfo";
5
+ /**
6
+ * Generates a service definition and server / client stubs for the
7
+ * `@grpc/grpc-js` library.
8
+ */
9
+ export declare function generateGrpcJsService(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo, serviceDesc: ServiceDescriptorProto): Code;
@@ -0,0 +1,17 @@
1
+ import { MethodDescriptorProto, FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
2
+ import { Code } from "ts-poet";
3
+ import { Context } from "./context";
4
+ /** Generates a client that uses the `@improbable-web/grpc-web` library. */
5
+ export declare function generateGrpcClientImpl(ctx: Context, _fileDesc: FileDescriptorProto, serviceDesc: ServiceDescriptorProto): Code;
6
+ /** Creates the service descriptor that grpc-web needs at runtime. */
7
+ export declare function generateGrpcServiceDesc(fileDesc: FileDescriptorProto, serviceDesc: ServiceDescriptorProto): Code;
8
+ /**
9
+ * Creates the method descriptor that grpc-web needs at runtime to make `unary` calls.
10
+ *
11
+ * Note that we take a few liberties in the implementation give we don't 100% match
12
+ * what grpc-web's existing output is, but it works out; see comments in the method
13
+ * implementation.
14
+ */
15
+ export declare function generateGrpcMethodDesc(ctx: Context, serviceDesc: ServiceDescriptorProto, methodDesc: MethodDescriptorProto): Code;
16
+ /** Adds misc top-level definitions for grpc-web functionality. */
17
+ export declare function addGrpcWebMisc(ctx: Context, hasStreamingMethods: boolean): Code;
@@ -0,0 +1,7 @@
1
+ import { FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
2
+ import { Code } from "ts-poet";
3
+ import SourceInfo from "./sourceInfo";
4
+ import { Context } from "./context";
5
+ export declare function generateNestjsServiceController(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo, serviceDesc: ServiceDescriptorProto): Code;
6
+ export declare function generateNestjsServiceClient(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo, serviceDesc: ServiceDescriptorProto): Code;
7
+ export declare function generateNestjsGrpcServiceMethodsDecorator(ctx: Context, serviceDesc: ServiceDescriptorProto): Code;
@@ -0,0 +1,8 @@
1
+ import { Code } from "ts-poet";
2
+ import { FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
3
+ import { Context } from "./context";
4
+ import SourceInfo from "./sourceInfo";
5
+ /**
6
+ * Generates server / client stubs for `nice-grpc` library.
7
+ */
8
+ export declare function generateNiceGrpcService(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo, serviceDesc: ServiceDescriptorProto): Code;
@@ -0,0 +1,31 @@
1
+ import { FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
2
+ import { Code } from "ts-poet";
3
+ import SourceInfo from "./sourceInfo";
4
+ import { Context } from "./context";
5
+ /**
6
+ * Generates an interface for `serviceDesc`.
7
+ *
8
+ * Some RPC frameworks (i.e. Twirp) can use the same interface, i.e.
9
+ * `getFoo(req): Promise<res>` for the client-side and server-side,
10
+ * which is the intent for this interface.
11
+ *
12
+ * Other RPC frameworks (i.e. NestJS) that need different client-side
13
+ * vs. server-side code/interfaces are handled separately.
14
+ */
15
+ export declare function generateService(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo, serviceDesc: ServiceDescriptorProto): Code;
16
+ export declare function generateServiceClientImpl(ctx: Context, fileDesc: FileDescriptorProto, serviceDesc: ServiceDescriptorProto): Code;
17
+ /**
18
+ * Creates an `Rpc.request(service, method, data)` abstraction.
19
+ *
20
+ * This lets clients pass in their own request-promise-ish client.
21
+ *
22
+ * This also requires clientStreamingRequest, serverStreamingRequest and
23
+ * bidirectionalStreamingRequest methods if any of the RPCs is streaming.
24
+ *
25
+ * We don't export this because if a project uses multiple `*.proto` files,
26
+ * we don't want our the barrel imports in `index.ts` to have multiple `Rpc`
27
+ * types.
28
+ */
29
+ export declare function generateRpcType(ctx: Context, hasStreamingMethods: boolean): Code;
30
+ export declare function generateDataLoadersType(): Code;
31
+ export declare function generateDataLoaderOptionsType(): Code;
@@ -0,0 +1,36 @@
1
+ import { Context } from "./context";
2
+ import { Code } from "ts-poet";
3
+ export type StructFieldNames = {
4
+ nullValue: string;
5
+ numberValue: string;
6
+ stringValue: string;
7
+ boolValue: string;
8
+ structValue: string;
9
+ listValue: string;
10
+ };
11
+ /** Whether we need to generate `.wrap` and `.unwrap` methods for the given type. */
12
+ export declare function isWrapperType(fullProtoTypeName: string): boolean;
13
+ /**
14
+ * Converts ts-proto's idiomatic Struct/Value/ListValue representation to the proto messages.
15
+ *
16
+ * We do this deeply b/c NestJS does not invoke wrappers recursively.
17
+ */
18
+ export declare function generateWrapDeep(ctx: Context, fullProtoTypeName: string, fieldNames: StructFieldNames): Code[];
19
+ /**
20
+ * Converts proto's Struct/Value?listValue messages to ts-proto's idiomatic representation.
21
+ *
22
+ * We do this deeply b/c NestJS does not invoke wrappers recursively.
23
+ */
24
+ export declare function generateUnwrapDeep(ctx: Context, fullProtoTypeName: string, fieldNames: StructFieldNames): Code[];
25
+ /**
26
+ * Converts ts-proto's idiomatic Struct/Value/ListValue representation to the proto messages.
27
+ *
28
+ * We do this shallow's b/c ts-proto's encode methods handle the recursion.
29
+ */
30
+ export declare function generateWrapShallow(ctx: Context, fullProtoTypeName: string, fieldNames: StructFieldNames): Code[];
31
+ /**
32
+ * Converts proto's Struct/Value?listValue messages to ts-proto's idiomatic representation.
33
+ *
34
+ * We do this shallowly b/c ts-proto's decode methods handle recursion.
35
+ */
36
+ export declare function generateUnwrapShallow(ctx: Context, fullProtoTypeName: string, fieldNames: StructFieldNames): Code[];
@@ -0,0 +1,3 @@
1
+ import { Code } from "ts-poet";
2
+ import { BaseContext } from "./context";
3
+ export declare function generateTypeRegistry(ctx: BaseContext): Code;
@@ -0,0 +1 @@
1
+ export { DateOption, EnvOption, JsonTimestampOption, LongOption, OneofOption, Options, ServiceOption } from "./options";
package/build/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceOption = exports.OneofOption = exports.LongOption = exports.JsonTimestampOption = exports.EnvOption = exports.DateOption = void 0;
4
+ var options_1 = require("./options");
5
+ Object.defineProperty(exports, "DateOption", { enumerable: true, get: function () { return options_1.DateOption; } });
6
+ Object.defineProperty(exports, "EnvOption", { enumerable: true, get: function () { return options_1.EnvOption; } });
7
+ Object.defineProperty(exports, "JsonTimestampOption", { enumerable: true, get: function () { return options_1.JsonTimestampOption; } });
8
+ Object.defineProperty(exports, "LongOption", { enumerable: true, get: function () { return options_1.LongOption; } });
9
+ Object.defineProperty(exports, "OneofOption", { enumerable: true, get: function () { return options_1.OneofOption; } });
10
+ Object.defineProperty(exports, "ServiceOption", { enumerable: true, get: function () { return options_1.ServiceOption; } });
@@ -0,0 +1,54 @@
1
+ import { Code } from "ts-poet";
2
+ import { ConditionalOutput } from "ts-poet/build/ConditionalOutput";
3
+ import { FileDescriptorProto } from "ts-proto-descriptors";
4
+ import { Context } from "./context";
5
+ import { Options } from "./options";
6
+ export declare function generateFile(ctx: Context, fileDesc: FileDescriptorProto): [string, Code];
7
+ export type Utils = ReturnType<typeof makeDeepPartial> & ReturnType<typeof makeObjectIdMethods> & ReturnType<typeof makeTimestampMethods> & ReturnType<typeof makeByteUtils> & ReturnType<typeof makeLongUtils> & ReturnType<typeof makeComparisonUtils> & ReturnType<typeof makeNiceGrpcServerStreamingMethodResult> & ReturnType<typeof makeGrpcWebErrorClass> & ReturnType<typeof makeExtensionClass> & ReturnType<typeof makeAssertionUtils>;
8
+ /** These are runtime utility methods used by the generated code. */
9
+ export declare function makeUtils(options: Options): Utils;
10
+ declare function makeLongUtils(options: Options, bytes: ReturnType<typeof makeByteUtils>): {
11
+ numberToLong: ConditionalOutput;
12
+ longToNumber: ConditionalOutput;
13
+ longToString: ConditionalOutput;
14
+ longToBigint: ConditionalOutput;
15
+ Long: ConditionalOutput;
16
+ };
17
+ declare function makeByteUtils(options: Options): {
18
+ globalThis: ConditionalOutput;
19
+ bytesFromBase64: ConditionalOutput;
20
+ base64FromBytes: ConditionalOutput;
21
+ };
22
+ declare function makeDeepPartial(options: Options, longs: ReturnType<typeof makeLongUtils>): {
23
+ Builtin: ConditionalOutput;
24
+ DeepPartial: ConditionalOutput;
25
+ Exact: ConditionalOutput;
26
+ };
27
+ declare function makeObjectIdMethods(): {
28
+ fromJsonObjectId: ConditionalOutput;
29
+ fromProtoObjectId: ConditionalOutput;
30
+ toProtoObjectId: ConditionalOutput;
31
+ };
32
+ declare function makeTimestampMethods(options: Options, longs: ReturnType<typeof makeLongUtils>, bytes: ReturnType<typeof makeByteUtils>): {
33
+ toTimestamp: ConditionalOutput;
34
+ fromTimestamp: ConditionalOutput;
35
+ fromJsonTimestamp: ConditionalOutput;
36
+ };
37
+ declare function makeComparisonUtils(): {
38
+ isObject: ConditionalOutput;
39
+ isSet: ConditionalOutput;
40
+ };
41
+ declare function makeNiceGrpcServerStreamingMethodResult(options: Options): {
42
+ NiceGrpcServerStreamingMethodResult: ConditionalOutput;
43
+ };
44
+ declare function makeGrpcWebErrorClass(bytes: ReturnType<typeof makeByteUtils>): {
45
+ GrpcWebError: ConditionalOutput;
46
+ };
47
+ declare function makeExtensionClass(options: Options): {
48
+ Extension: ConditionalOutput;
49
+ };
50
+ declare function makeAssertionUtils(bytes: ReturnType<typeof makeByteUtils>): {
51
+ fail: ConditionalOutput;
52
+ };
53
+ export declare const contextTypeVar = "Context extends DataLoaders";
54
+ export {};
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) {
@@ -0,0 +1,102 @@
1
+ import { ToStringOpts } from "ts-poet/build/Code";
2
+ export declare enum LongOption {
3
+ NUMBER = "number",
4
+ LONG = "long",
5
+ STRING = "string",
6
+ BIGINT = "bigint"
7
+ }
8
+ export declare enum DateOption {
9
+ DATE = "date",
10
+ STRING = "string",
11
+ STRING_NANO = "string-nano",
12
+ TIMESTAMP = "timestamp"
13
+ }
14
+ export declare enum JsonTimestampOption {
15
+ RFC3339 = "rfc3339",
16
+ RAW = "raw"
17
+ }
18
+ export declare enum EnvOption {
19
+ NODE = "node",
20
+ BROWSER = "browser",
21
+ BOTH = "both"
22
+ }
23
+ export declare enum OneofOption {
24
+ PROPERTIES = "properties",
25
+ UNIONS = "unions"
26
+ }
27
+ export declare enum ServiceOption {
28
+ GRPC = "grpc-js",
29
+ NICE_GRPC = "nice-grpc",
30
+ GENERIC = "generic-definitions",
31
+ DEFAULT = "default",
32
+ NONE = "none"
33
+ }
34
+ export type Options = {
35
+ context: boolean;
36
+ snakeToCamel: Array<"json" | "keys">;
37
+ forceLong: LongOption;
38
+ useJsTypeOverride: boolean;
39
+ globalThisPolyfill: boolean;
40
+ useOptionals: boolean | "none" | "deprecatedOnly" | "messages" | "all";
41
+ emitDefaultValues: Array<"json-methods">;
42
+ useDate: DateOption;
43
+ useJsonTimestamp: JsonTimestampOption;
44
+ useMongoObjectId: boolean;
45
+ oneof: OneofOption;
46
+ esModuleInterop: boolean;
47
+ fileSuffix: string;
48
+ importSuffix: string;
49
+ outputEncodeMethods: true | false | "encode-only" | "decode-only" | "encode-no-creation";
50
+ outputJsonMethods: true | false | "to-only" | "from-only";
51
+ outputPartialMethods: boolean;
52
+ outputTypeAnnotations: boolean | "static-only" | "optional";
53
+ outputTypeRegistry: boolean;
54
+ stringEnums: boolean;
55
+ constEnums: boolean;
56
+ removeEnumPrefix: boolean;
57
+ enumsAsLiterals: boolean;
58
+ outputClientImpl: boolean | "grpc-web";
59
+ outputServices: ServiceOption[];
60
+ addGrpcMetadata: boolean;
61
+ metadataType: string | undefined;
62
+ addNestjsRestParameter: boolean;
63
+ returnObservable: boolean;
64
+ lowerCaseServiceMethods: boolean;
65
+ nestJs: boolean;
66
+ env: EnvOption;
67
+ unrecognizedEnum: boolean;
68
+ unrecognizedEnumName: string;
69
+ unrecognizedEnumValue: number;
70
+ exportCommonSymbols: boolean;
71
+ outputSchema: boolean;
72
+ onlyTypes: boolean;
73
+ emitImportedFiles: boolean;
74
+ useAbortSignal: boolean;
75
+ useExactTypes: boolean;
76
+ useAsyncIterable: boolean;
77
+ unknownFields: boolean;
78
+ usePrototypeForDefaults: boolean;
79
+ useJsonName: boolean;
80
+ useJsonWireFormat: boolean;
81
+ useNumericEnumForJson: boolean;
82
+ initializeFieldsAsUndefined: boolean;
83
+ useMapType: boolean;
84
+ useReadonlyTypes: boolean;
85
+ useSnakeTypeName: boolean;
86
+ outputExtensions: boolean;
87
+ outputIndex: boolean;
88
+ M: {
89
+ [from: string]: string;
90
+ };
91
+ rpcBeforeRequest: boolean;
92
+ rpcAfterResponse: boolean;
93
+ rpcErrorHandler: boolean;
94
+ comments: boolean;
95
+ disableProto2Optionals: boolean;
96
+ disableProto2DefaultValues: boolean;
97
+ useNullAsOptional: boolean;
98
+ };
99
+ export declare function defaultOptions(): Options;
100
+ export declare function optionsFromParameter(parameter: string | undefined): Options;
101
+ export declare function getTsPoetOpts(options: Options): ToStringOpts;
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,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { FileDescriptorProto } from "ts-proto-descriptors";
2
+ import { Code } from "ts-poet";
3
+ import { Context } from "./context";
4
+ import SourceInfo from "./sourceInfo";
5
+ export declare function generateSchema(ctx: Context, fileDesc: FileDescriptorProto, sourceInfo: SourceInfo): Code[];
@@ -0,0 +1,78 @@
1
+ import { FileDescriptorProto } from "ts-proto-descriptors";
2
+ /** This type is expecting a value from the Fields constant. */
3
+ export type FieldID = number;
4
+ /**
5
+ * The field values here represent the proto field IDs associated with the types
6
+ * (file,message,enum,service).
7
+ *
8
+ * For more information read the comments for SourceCodeInfo declared in
9
+ * google's 'descriptor.proto' file, see:
10
+ * https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto#L730
11
+ */
12
+ export declare const Fields: {
13
+ file: {
14
+ syntax: number;
15
+ message_type: number;
16
+ enum_type: number;
17
+ service: number;
18
+ extension: number;
19
+ };
20
+ message: {
21
+ field: number;
22
+ nested_type: number;
23
+ enum_type: number;
24
+ oneof_decl: number;
25
+ };
26
+ enum: {
27
+ value: number;
28
+ };
29
+ service: {
30
+ method: number;
31
+ };
32
+ };
33
+ /**
34
+ * This type is simply an interface on the SourceCodeInfo.Location message.
35
+ */
36
+ export interface SourceDescription {
37
+ readonly span: number[];
38
+ readonly leadingComments: string;
39
+ readonly trailingComments: string;
40
+ readonly leadingDetachedComments: string[];
41
+ }
42
+ /**
43
+ * Mapping from a string of dotted notation `path` parts to efficiently
44
+ * lookup the related source information.
45
+ */
46
+ export type SourceInfoMap = {
47
+ [key: string]: SourceDescription;
48
+ };
49
+ /**
50
+ * This class provides direct lookup and navigation through the type
51
+ * system by the use of lookup/open to access the source info for types
52
+ * defined in a protocol buffer.
53
+ */
54
+ export default class SourceInfo implements SourceDescription {
55
+ private readonly sourceCode;
56
+ private readonly selfDescription;
57
+ /** Returns an empty SourceInfo */
58
+ static empty(): SourceInfo;
59
+ /**
60
+ * Creates the SourceInfo from the FileDescriptorProto given to you
61
+ * by the protoc compiler. It indexes file.sourceCodeInfo by dotted
62
+ * path notation and returns the root SourceInfo.
63
+ */
64
+ static fromDescriptor(file: FileDescriptorProto): SourceInfo;
65
+ private constructor();
66
+ /** Returns the code span [start line, start column, end line] */
67
+ get span(): number[];
68
+ /** Leading consecutive comment lines prior to the current element */
69
+ get leadingComments(): string;
70
+ /** Documentation is unclear about what exactly this is */
71
+ get trailingComments(): string;
72
+ /** Detached comments are those preceeding but separated by a blank non-comment line */
73
+ get leadingDetachedComments(): string[];
74
+ /** Return the source info for the field id and index specficied */
75
+ lookup(type: FieldID, index?: number): SourceDescription;
76
+ /** Returns a new SourceInfo class representing the field id and index specficied */
77
+ open(type: FieldID, index: number): SourceInfo;
78
+ }
@@ -0,0 +1,105 @@
1
+ import { CodeGeneratorRequest, DescriptorProto, EnumDescriptorProto, FieldDescriptorProto, FieldDescriptorProto_Type, FileDescriptorProto, MessageOptions, MethodDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
2
+ import { Code, Import } from "ts-poet";
3
+ import { Options } from "./options";
4
+ import { Context } from "./context";
5
+ /** Based on https://github.com/dcodeIO/protobuf.js/blob/master/src/types.js#L37. */
6
+ export declare function basicWireType(type: FieldDescriptorProto_Type): number;
7
+ export declare function basicLongWireType(type: FieldDescriptorProto_Type): number | undefined;
8
+ /** Returns the type name without any repeated/required/etc. labels. */
9
+ export declare function basicTypeName(ctx: Context, field: FieldDescriptorProto, typeOptions?: {
10
+ keepValueType?: boolean;
11
+ }): Code;
12
+ /** Returns the Reader method for the primitive's read/write call. */
13
+ export declare function toReaderCall(field: FieldDescriptorProto): string;
14
+ export declare function packedType(type: FieldDescriptorProto_Type): number | undefined;
15
+ export declare function getFieldOptionsJsType(field: FieldDescriptorProto, options: Options): FieldDescriptorProto_Type | undefined;
16
+ export declare function defaultValue(ctx: Context, field: FieldDescriptorProto): any;
17
+ /** Creates code that checks that the field is not the default value. Supports scalars and enums. */
18
+ export declare function notDefaultCheck(ctx: Context, field: FieldDescriptorProto, messageOptions: MessageOptions | undefined, place: string): Code;
19
+ /** A map of proto type name, e.g. `foo.Message.Inner`, to module/class name, e.g. `foo`, `Message_Inner`. */
20
+ export type TypeMap = Map<string, [string, string, DescriptorProto | EnumDescriptorProto]>;
21
+ /** Scans all of the proto files in `request` and builds a map of proto typeName -> TS module/name. */
22
+ export declare function createTypeMap(request: CodeGeneratorRequest, options: Options): TypeMap;
23
+ /** A "Scalar Value Type" as defined in https://developers.google.com/protocol-buffers/docs/proto3#scalar */
24
+ export declare function isScalar(field: FieldDescriptorProto): boolean;
25
+ export declare function isOptionalProperty(field: FieldDescriptorProto, messageOptions: MessageOptions | undefined, options: Options, isProto3Syntax: boolean): boolean;
26
+ /** This includes all scalars, enums and the [groups type](https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/DescriptorProtos.FieldDescriptorProto.Type.html#TYPE_GROUP) */
27
+ export declare function isPrimitive(field: FieldDescriptorProto): boolean;
28
+ export declare function isBytes(field: FieldDescriptorProto): boolean;
29
+ export declare function isMessage(field: FieldDescriptorProto): boolean;
30
+ export declare function isEnum(field: FieldDescriptorProto): boolean;
31
+ export declare function isWithinOneOf(field: FieldDescriptorProto): boolean;
32
+ export declare function isWithinOneOfThatShouldBeUnion(options: Options, field: FieldDescriptorProto): boolean;
33
+ export declare function isRepeated(field: FieldDescriptorProto): boolean;
34
+ export declare function isLong(field: FieldDescriptorProto): boolean;
35
+ export declare function isWholeNumber(field: FieldDescriptorProto): boolean;
36
+ export declare function isMapType(ctx: Context, messageDesc: DescriptorProto, field: FieldDescriptorProto): boolean;
37
+ export declare function isObjectId(field: FieldDescriptorProto): boolean;
38
+ export declare function isTimestamp(field: FieldDescriptorProto): boolean;
39
+ export declare function isValueType(ctx: Context, field: FieldDescriptorProto): boolean;
40
+ export declare function isAnyValueType(field: FieldDescriptorProto): boolean;
41
+ export declare function isAnyValueTypeName(typeName: string): boolean;
42
+ export declare function isBytesValueType(field: FieldDescriptorProto): boolean;
43
+ export declare function isFieldMaskType(field: FieldDescriptorProto): boolean;
44
+ export declare function isFieldMaskTypeName(typeName: string): boolean;
45
+ export declare function isListValueType(field: FieldDescriptorProto): boolean;
46
+ export declare function isListValueTypeName(typeName: string): boolean;
47
+ export declare function isStructType(field: FieldDescriptorProto): boolean;
48
+ export declare function isStructTypeName(typeName: string): boolean;
49
+ export declare function isLongValueType(field: FieldDescriptorProto): boolean;
50
+ export declare function isEmptyType(typeName: string): boolean;
51
+ export declare function valueTypeName(ctx: Context, typeName: string): Code | undefined;
52
+ export declare function wrapperTypeName(typeName: string): string | undefined;
53
+ /** Maps `.some_proto_namespace.Message` to a TypeName. */
54
+ export declare function messageToTypeName(ctx: Context, protoType: string, typeOptions?: {
55
+ keepValueType?: boolean;
56
+ repeated?: boolean;
57
+ }): Code;
58
+ export declare function getEnumMethod(ctx: Context, enumProtoType: string, methodSuffix: string): Import;
59
+ /** Return the TypeName for any field (primitive/message/etc.) as exposed in the interface. */
60
+ export declare function toTypeName(ctx: Context, messageDesc: DescriptorProto | undefined, field: FieldDescriptorProto, ensureOptional?: boolean): Code;
61
+ /**
62
+ * For a protobuf map field, if the generated code should use the javascript Map type.
63
+ *
64
+ * If the type of a protobuf map key corresponds to the Long type, we always use the Map type. This avoids generating
65
+ * invalid code such as below (using Long as key of a javascript object):
66
+ *
67
+ * export interface Foo {
68
+ * bar: { [key: Long]: Long }
69
+ * }
70
+ *
71
+ * See https://github.com/stephenh/ts-proto/issues/708 for more details.
72
+ */
73
+ export declare function shouldGenerateJSMapType(ctx: Context, message: DescriptorProto, field: FieldDescriptorProto): boolean;
74
+ export declare function detectMapType(ctx: Context, messageDesc: DescriptorProto, fieldDesc: FieldDescriptorProto): {
75
+ messageDesc: DescriptorProto;
76
+ keyField: FieldDescriptorProto;
77
+ keyType: Code;
78
+ valueField: FieldDescriptorProto;
79
+ valueType: Code;
80
+ } | undefined;
81
+ export declare function rawRequestType(ctx: Context, methodDesc: MethodDescriptorProto, typeOptions?: {
82
+ keepValueType?: boolean;
83
+ repeated?: boolean;
84
+ }): Code;
85
+ export declare function observableType(ctx: Context, asType?: boolean): Code;
86
+ export declare function requestType(ctx: Context, methodDesc: MethodDescriptorProto, partial?: boolean): Code;
87
+ export declare function responseType(ctx: Context, methodDesc: MethodDescriptorProto, typeOptions?: {
88
+ keepValueType?: boolean;
89
+ repeated?: boolean;
90
+ }): Code;
91
+ export declare function responsePromise(ctx: Context, methodDesc: MethodDescriptorProto): Code;
92
+ export declare function responseObservable(ctx: Context, methodDesc: MethodDescriptorProto): Code;
93
+ export declare function responsePromiseOrObservable(ctx: Context, methodDesc: MethodDescriptorProto): Code;
94
+ export interface BatchMethod {
95
+ methodDesc: MethodDescriptorProto;
96
+ uniqueIdentifier: string;
97
+ singleMethodName: string;
98
+ inputFieldName: string;
99
+ inputType: Code;
100
+ outputFieldName: string;
101
+ outputType: Code;
102
+ mapType: boolean;
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;
@@ -0,0 +1,80 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { Code, Import } from "ts-poet";
4
+ import { CodeGeneratorRequest, FieldDescriptorProto, FileDescriptorProto, MethodDescriptorProto, MethodOptions } from "ts-proto-descriptors";
5
+ import ReadStream = NodeJS.ReadStream;
6
+ import { SourceDescription } from "./sourceInfo";
7
+ import { Options } from "./options";
8
+ export declare function protoFilesToGenerate(request: CodeGeneratorRequest): FileDescriptorProto[];
9
+ export declare function generateIndexFiles(files: FileDescriptorProto[], options: Options): [string, Code][];
10
+ export declare function readToBuffer(stream: ReadStream): Promise<Buffer>;
11
+ export declare function fail(message: string): never;
12
+ export declare function singular(name: string): string;
13
+ export declare function lowerFirst(name: string): string;
14
+ export declare function upperFirst(name: string): string;
15
+ /** Removes potentially harmful characters from comments and pushes it into chunks. */
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
+ export declare function maybePrefixPackage(fileDesc: FileDescriptorProto, rest: string): string;
19
+ /**
20
+ * Asserts that an object is an instance of a certain class
21
+ * @param obj The object to check
22
+ * @param constructor The constructor of the class to check
23
+ */
24
+ export declare function assertInstanceOf<T>(obj: unknown, constructor: {
25
+ new (...args: any[]): T;
26
+ }): asserts obj is T;
27
+ /**
28
+ * A MethodDescriptorProto subclass that adds formatted properties
29
+ */
30
+ export declare class FormattedMethodDescriptor implements MethodDescriptorProto {
31
+ name: string;
32
+ inputType: string;
33
+ outputType: string;
34
+ options: MethodOptions | undefined;
35
+ clientStreaming: boolean;
36
+ serverStreaming: boolean;
37
+ private original;
38
+ private ctxOptions;
39
+ /**
40
+ * The name of this method with formatting applied according to the `Options` object passed to the constructor.
41
+ * Automatically updates to any changes to the `Options` or `name` of this object
42
+ */
43
+ get formattedName(): string;
44
+ constructor(src: MethodDescriptorProto, options: Options);
45
+ /**
46
+ * Retrieve the source `MethodDescriptorProto` used to construct this object
47
+ * @returns The source `MethodDescriptorProto` used to construct this object
48
+ */
49
+ getSource(): MethodDescriptorProto;
50
+ /**
51
+ * Applies formatting rules to a gRPC method name.
52
+ * @param methodName The original method name
53
+ * @param options The options object containing rules to apply
54
+ * @returns The formatted method name
55
+ */
56
+ static formatName(methodName: string, options: Options): string;
57
+ }
58
+ export declare function getFieldJsonName(field: Pick<FieldDescriptorProto, "name" | "jsonName">, options: Pick<Options, "snakeToCamel" | "useJsonName">): string;
59
+ export declare function getFieldName(field: Pick<FieldDescriptorProto, "name" | "jsonName">, options: Pick<Options, "snakeToCamel" | "useJsonName">): string;
60
+ /** Returns `bar` or `"bar"` if `propertyName` isn't a safe property name. */
61
+ export declare function safeAccessor(propertyName: string): string;
62
+ /**
63
+ * Returns a snippet for reading an object's property, such as `foo.bar`, or `foo['bar']` if the property name contains unusual characters.
64
+ * For simplicity, we don't match the ECMA 5/6 rules for valid identifiers exactly, and return array syntax liberally.
65
+ * @param objectName
66
+ * @param propertyName
67
+ * @param optional
68
+ */
69
+ export declare function getPropertyAccessor(objectName: string, propertyName: string, optional?: boolean): string;
70
+ export declare function impFile(options: Options, spec: string): Import;
71
+ export declare function impProto(options: Options, module: string, type: string): Import;
72
+ export declare function tryCatchBlock(tryBlock: Code | string, handleErrorBlock: Code | string): Code;
73
+ export declare function arrowFunction(params: string, body: Code | string, isOneLine?: boolean): Code;
74
+ export declare function nullOrUndefined(options: Pick<Options, "useNullAsOptional">, hasProto3Optional?: boolean): string;
75
+ export declare function maybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string, prefix?: string): string;
76
+ export declare function maybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string, prefix?: string): string;
77
+ export declare function withOrMaybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
78
+ export declare function withOrMaybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
79
+ export declare function withAndMaybeCheckIsNotNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
80
+ export declare function withAndMaybeCheckIsNull(options: Pick<Options, "useNullAsOptional">, typeName: string): string;
@@ -0,0 +1,8 @@
1
+ import { DescriptorProto, EnumDescriptorProto, FileDescriptorProto, ServiceDescriptorProto } from "ts-proto-descriptors";
2
+ import SourceInfo from "./sourceInfo";
3
+ import { Options } from "./options";
4
+ type MessageVisitor = (fullName: string, desc: DescriptorProto, sourceInfo: SourceInfo, fullProtoTypeName: string) => void;
5
+ type EnumVisitor = (fullName: string, desc: EnumDescriptorProto, sourceInfo: SourceInfo, fullProtoTypeName: string) => void;
6
+ export declare function visit(proto: FileDescriptorProto | DescriptorProto, sourceInfo: SourceInfo, messageFn: MessageVisitor, options: Options, enumFn?: EnumVisitor, tsPrefix?: string, protoPrefix?: string): void;
7
+ export declare function visitServices(proto: FileDescriptorProto, sourceInfo: SourceInfo, serviceFn: (desc: ServiceDescriptorProto, sourceInfo: SourceInfo) => void): void;
8
+ export {};
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.171.0",
3
+ "version": "1.173.0",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",
7
7
  "bin": {
8
8
  "protoc-gen-ts_proto": "./protoc-gen-ts_proto"
9
9
  },
10
+ "types": "build/index.d.ts",
10
11
  "scripts": {
11
12
  "build": "yarn tsc",
12
13
  "build:test": "yarn proto2bin && yarn proto2pbjs && yarn bin2ts",
@@ -61,7 +62,7 @@
61
62
  "rxjs": "^7.8.1",
62
63
  "semantic-release": "^21.0.7",
63
64
  "ts-jest": "^29.1.1",
64
- "tsx": "^3.12.7",
65
+ "tsx": "^3.14.0",
65
66
  "typescript": "^5.1.6",
66
67
  "uglify-js": "^3.17.4"
67
68
  },