Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into replace-protobuf.js
Browse files Browse the repository at this point in the history
  • Loading branch information
timostamm committed Aug 12, 2024
2 parents 7ef0c73 + 76243a8 commit 0231877
Show file tree
Hide file tree
Showing 39 changed files with 3,338 additions and 89 deletions.
Binary file removed .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ build/
/integration/*/pbjs.d.ts
coverage/
yarn-error.log
.DS_Store

# Yarn
.pnp.*
Expand Down
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
## [1.181.1](https://github.com/stephenh/ts-proto/compare/v1.181.0...v1.181.1) (2024-07-13)


### Bug Fixes

* Incorrect message names in the generated code for repeated fields ([#1073](https://github.com/stephenh/ts-proto/issues/1073)) ([8a95d8e](https://github.com/stephenh/ts-proto/commit/8a95d8e0983a38e604b6990461e726db566ff311)), closes [#1072](https://github.com/stephenh/ts-proto/issues/1072)

# [1.181.0](https://github.com/stephenh/ts-proto/compare/v1.180.0...v1.181.0) (2024-07-01)


### Features

* added the "typePrefix" and "typeSuffix" options. ([#1069](https://github.com/stephenh/ts-proto/issues/1069)) ([ab515cd](https://github.com/stephenh/ts-proto/commit/ab515cda322baeb94c7588117e4bb5bee6281874)), closes [#1033](https://github.com/stephenh/ts-proto/issues/1033)

# [1.180.0](https://github.com/stephenh/ts-proto/compare/v1.179.0...v1.180.0) (2024-06-15)


### Features

* oneof=unions-value to use the same field name for oneof cases ([#1062](https://github.com/stephenh/ts-proto/issues/1062)) ([7493090](https://github.com/stephenh/ts-proto/commit/74930908cc8e5292577a793b7ae06c3721225ac3)), closes [#1060](https://github.com/stephenh/ts-proto/issues/1060)

# [1.179.0](https://github.com/stephenh/ts-proto/compare/v1.178.0...v1.179.0) (2024-06-15)


### Features

* bigIntLiteral option for using BigInt literals ([#1063](https://github.com/stephenh/ts-proto/issues/1063)) ([b89fbcb](https://github.com/stephenh/ts-proto/commit/b89fbcb1f99ccfcd1f06551286c2459e44a3bac2)), closes [#928](https://github.com/stephenh/ts-proto/issues/928) [#932](https://github.com/stephenh/ts-proto/issues/932)

# [1.178.0](https://github.com/stephenh/ts-proto/compare/v1.177.0...v1.178.0) (2024-06-07)


Expand Down
58 changes: 50 additions & 8 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -551,8 +551,14 @@ Generated code will be placed in the Gradle build directory.
- With `--ts_proto_opt=comments=false`, comments won't be copied from the proto files to the generated code.
- With `--ts_proto_opt=bigIntLiteral=false`, the generated code will use `BigInt("0")` instead of `0n` for BigInt literals. BigInt literals aren't supported by TypeScript when the "target" compiler option set to something older than "ES2020".
- With `--ts_proto_opt=useNullAsOptional=true`, `undefined` values will be converted to `null`, and if you use `optional` label in your `.proto` file, the field will have `undefined` type as well. for example:
- With `--ts_proto_opt=typePrefix=MyPrefix`, the generated interfaces, enums, and factories will have a prefix of `MyPrefix` in their names.
- With `--ts_proto_opt=typeSuffix=MySuffix`, the generated interfaces, enums, and factories will have a suffix of `MySuffix` in their names.
```protobuf
message ProfileInfo {
int32 id = 1;
Expand Down Expand Up @@ -603,7 +609,7 @@ export interface User {
}
```
- With `--ts_proto_opt=noDefaultsForOptionals=true`, `undefined` primitive values will not be defaulted as per the protobuf spec. Additionally unlike the standard behavior, when a field is set to it's standard default value, it *will* be encoded allowing it to be sent over the wire and distinguished from undefined values. For example if a message does not set a boolean value, ordinarily this would be defaulted to `false` which is different to it being undefined.
- With `--ts_proto_opt=noDefaultsForOptionals=true`, `undefined` primitive values will not be defaulted as per the protobuf spec. Additionally unlike the standard behavior, when a field is set to it's standard default value, it *will* be encoded allowing it to be sent over the wire and distinguished from undefined values. For example if a message does not set a boolean value, ordinarily this would be defaulted to `false` which is different to it being undefined.
This option allows the library to act in a compatible way with the [Wire implementation](https://square.github.io/wire/) maintained and used by Square/Block. Note: this option should only be used in combination with other client/server code generated using Wire or ts-proto with this option enabled.
Expand Down Expand Up @@ -752,7 +758,7 @@ ts-protoc --ts_proto_out=./output -I=./protos ./protoc/*.proto
# Todo
- Support the string-based encoding of duration in `fromJSON`/`toJSON`
- Make `oneof=unions` the default behavior in 2.0
- Make `oneof=unions-value` the default behavior in 2.0
- Probably change `forceLong` default in 2.0, should default to `forceLong=long`
- Make `esModuleInterop=true` the default in 2.0
Expand All @@ -770,23 +776,33 @@ Will generate a `Foo` type with two fields: `field_a: string | undefined;` and `
With this output, you'll have to check both `if object.field_a` and `if object.field_b`, and if you set one, you'll have to remember to unset the other.
Instead, we recommend using the `oneof=unions` option, which will change the output to be an Abstract Data Type/ADT like:
Instead, we recommend using the `oneof=unions-value` option, which will change the output to be an Algebraic Data Type/ADT like:
```typescript
interface YourMessage {
eitherField?: { $case: "field_a"; field_a: string } | { $case: "field_b"; field_b: string };
eitherField?: { $case: "field_a"; value: string } | { $case: "field_b"; value: string };
}
```
As this will automatically enforce only one of `field_a` or `field_b` "being set" at a time, because the values are stored in the `eitherField` field that can only have a single value at a time.
(Note that `eitherField` is optional b/c `oneof` in Protobuf means "at most one field" is set, and does not mean one of the fields _must_ be set.)
In ts-proto's currently-unscheduled 2.x release, `oneof=unions` will become the default behavior.
In ts-proto's currently-unscheduled 2.x release, `oneof=unions-value` will become the default behavior.
There is also a `oneof=unions` option, which generates a union where the field names are included in each option:
```typescript
interface YourMessage {
eitherField?: { $case: "field_a"; field_a: string } | { $case: "field_b"; field_b: string };
}
```
This is no longer recommended as it can be difficult to write code and types to handle multiple oneof options:
## OneOf Type Helpers
The following helper types may make it easier to work with the types generated from `oneof=unions`:
The following helper types may make it easier to work with the types generated from `oneof=unions`, though they are generally not needed if you use `oneof=unions-value`:
```ts
/** Extracts all the case names from a oneOf field. */
Expand All @@ -797,19 +813,45 @@ type OneOfValues<T> = T extends { $case: infer U extends string; [key: string]:

/** Extracts the specific type of a oneOf case based on its field name */
type OneOfCase<T, K extends OneOfCases<T>> = T extends {
$case: K;
[key: string]: unknown;
}
? T
: never;

/** Extracts the specific type of a value type from a oneOf field */
type OneOfValue<T, K extends OneOfCases<T>> = T extends {
$case: infer U extends K;
[key: string]: unknown;
}
? T[U]
: never;
```
/** Extracts the specific type of a value type from a oneOf field */
export type OneOfValue<T, K extends OneOfCases<T>> = T extends {
For comparison, the equivalents for `oneof=unions-value`:
```ts
/** Extracts all the case names from a oneOf field. */
type OneOfCases<T> = T['$case'];

/** Extracts a union of all the value types from a oneOf field */
type OneOfValues<T> = T['value'];

/** Extracts the specific type of a oneOf case based on its field name */
type OneOfCase<T, K extends OneOfCases<T>> = T extends {
$case: K;
[key: string]: unknown;
}
? T
: never;

/** Extracts the specific type of a value type from a oneOf field */
type OneOfValue<T, K extends OneOfCases<T>> = T extends {
$case: infer U extends K;
value: unknown;
}
? T[U]
: never;
```
# Default values and unset fields
Expand Down
17 changes: 17 additions & 0 deletions integration/affixes/affixes.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
syntax = "proto3";

package affixes;

message AwesomeMessage {
message Inner {
}
}

enum AwesomeEnum {
AWESOME_ENUM_AWESOME = 0;
AWESOME_ENUM_COOL = 1;
AWESOME_ENUM_JUST_OKAY = 2;
}

service AwesomeService {
}
171 changes: 171 additions & 0 deletions integration/affixes/affixes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// source: affixes.proto

/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";

export const protobufPackage = "affixes";

export enum PrefixAwesomeEnumSuffix {
AWESOME_ENUM_AWESOME = 0,
AWESOME_ENUM_COOL = 1,
AWESOME_ENUM_JUST_OKAY = 2,
UNRECOGNIZED = -1,
}

export function prefixAwesomeEnumSuffixFromJSON(object: any): PrefixAwesomeEnumSuffix {
switch (object) {
case 0:
case "AWESOME_ENUM_AWESOME":
return PrefixAwesomeEnumSuffix.AWESOME_ENUM_AWESOME;
case 1:
case "AWESOME_ENUM_COOL":
return PrefixAwesomeEnumSuffix.AWESOME_ENUM_COOL;
case 2:
case "AWESOME_ENUM_JUST_OKAY":
return PrefixAwesomeEnumSuffix.AWESOME_ENUM_JUST_OKAY;
case -1:
case "UNRECOGNIZED":
default:
return PrefixAwesomeEnumSuffix.UNRECOGNIZED;
}
}

export function prefixAwesomeEnumSuffixToJSON(object: PrefixAwesomeEnumSuffix): string {
switch (object) {
case PrefixAwesomeEnumSuffix.AWESOME_ENUM_AWESOME:
return "AWESOME_ENUM_AWESOME";
case PrefixAwesomeEnumSuffix.AWESOME_ENUM_COOL:
return "AWESOME_ENUM_COOL";
case PrefixAwesomeEnumSuffix.AWESOME_ENUM_JUST_OKAY:
return "AWESOME_ENUM_JUST_OKAY";
case PrefixAwesomeEnumSuffix.UNRECOGNIZED:
default:
return "UNRECOGNIZED";
}
}

export interface PrefixAwesomeMessageSuffix {
}

export interface PrefixAwesomeMessage_InnerSuffix {
}

function createBasePrefixAwesomeMessageSuffix(): PrefixAwesomeMessageSuffix {
return {};
}

export const PrefixAwesomeMessageSuffix = {
encode(_: PrefixAwesomeMessageSuffix, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
return writer;
},

decode(input: BinaryReader | Uint8Array, length?: number): PrefixAwesomeMessageSuffix {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBasePrefixAwesomeMessageSuffix();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},

fromJSON(_: any): PrefixAwesomeMessageSuffix {
return {};
},

toJSON(_: PrefixAwesomeMessageSuffix): unknown {
const obj: any = {};
return obj;
},

create<I extends Exact<DeepPartial<PrefixAwesomeMessageSuffix>, I>>(base?: I): PrefixAwesomeMessageSuffix {
return PrefixAwesomeMessageSuffix.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<PrefixAwesomeMessageSuffix>, I>>(_: I): PrefixAwesomeMessageSuffix {
const message = createBasePrefixAwesomeMessageSuffix();
return message;
},
};

function createBasePrefixAwesomeMessage_InnerSuffix(): PrefixAwesomeMessage_InnerSuffix {
return {};
}

export const PrefixAwesomeMessage_InnerSuffix = {
encode(_: PrefixAwesomeMessage_InnerSuffix, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
return writer;
},

decode(input: BinaryReader | Uint8Array, length?: number): PrefixAwesomeMessage_InnerSuffix {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBasePrefixAwesomeMessage_InnerSuffix();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},

fromJSON(_: any): PrefixAwesomeMessage_InnerSuffix {
return {};
},

toJSON(_: PrefixAwesomeMessage_InnerSuffix): unknown {
const obj: any = {};
return obj;
},

create<I extends Exact<DeepPartial<PrefixAwesomeMessage_InnerSuffix>, I>>(
base?: I,
): PrefixAwesomeMessage_InnerSuffix {
return PrefixAwesomeMessage_InnerSuffix.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<PrefixAwesomeMessage_InnerSuffix>, I>>(
_: I,
): PrefixAwesomeMessage_InnerSuffix {
const message = createBasePrefixAwesomeMessage_InnerSuffix();
return message;
},
};

export interface AwesomeService {
}

export const AwesomeServiceServiceName = "affixes.AwesomeService";
export class AwesomeServiceClientImpl implements AwesomeService {
private readonly rpc: Rpc;
private readonly service: string;
constructor(rpc: Rpc, opts?: { service?: string }) {
this.service = opts?.service || AwesomeServiceServiceName;
this.rpc = rpc;
}
}

interface Rpc {
request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
}

type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;

export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
1 change: 1 addition & 0 deletions integration/affixes/parameters.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
typePrefix=Prefix,typeSuffix=Suffix
2 changes: 1 addition & 1 deletion integration/extension-import/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es2018",
"target": "es2020",
"lib": ["es2018"],
"module": "commonjs",
"strict": true,
Expand Down
Loading

0 comments on commit 0231877

Please sign in to comment.