Skip to content

Commit

Permalink
cleanup JSON patch
Browse files Browse the repository at this point in the history
  • Loading branch information
pyramation committed Jun 13, 2024
1 parent df44cc1 commit f761921
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 51 deletions.
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ The following blockchain libraries (generated by Telescope) are available via np
- [Amino Encoding](#amino-encoding)
- [Prototypes Options](#prototypes-options)
- [Prototypes Methods](#prototypes-methods)
- [Enums Methods](#enums-options)
- [LCD Client Options](#lcd-client-options)
- [RPC Client Options](#rpc-client-options)
- [Stargate Client Options](#stargate-client-options)
Expand Down Expand Up @@ -79,6 +80,7 @@ The following blockchain libraries (generated by Telescope) are available via np
- [RPC Client Classes](#rpc-client-classes)
- [Instant RPC Methods](#instant-rpc-methods)
- [Manually registering types](#manually-registering-types)
- [JSON Patch Protos](#json-patch-protos)
- [CosmWasm](#cosmwasm)
- [Dependencies](#dependencies)
- [Troubleshooting](#troubleshooting)
Expand Down Expand Up @@ -314,6 +316,7 @@ telescope({
| `prototypes.addTypeUrlToObjects` | add typeUrl field to generated Decoders | `true` |
| `prototypes.enableRegistryLoader` | generate Registry loader to *.registry.ts files | `true` |
| `prototypes.enableMessageComposer` | generate MessageComposer to *.registry.ts files | `true` |
| `prototypes.patch` | An object mapping filenames to an array of `Operation` to be applied as patches to proto files during generation. See [JSON Patch Protos](#json-patch-protos) | `undefined`|

### Prototypes Methods

Expand All @@ -327,6 +330,13 @@ telescope({
| `prototypes.methods.fromSDK` | boolean to enable `fromSDK` method on proto objects | `false` |
| `prototypes.methods.toSDK` | boolean to enable `toSDK` method on proto objects | `false` |

### Enums Options

| option | description | defaults |
| ------------------------------------- | --------------------------------------------------------------- | ---------- |
| `enums.useCustomNames` | Enables the usage of custom names for enums if specified through proto options or annotations, allowing for more descriptive or project-specific naming conventions. | `false` |


### LCD Client Options

| option | description | defaults |
Expand Down Expand Up @@ -986,6 +996,51 @@ export const getCustomSigningClient = async ({ rpcEndpoint, signer }: { rpcEndpo
};
```

## JSON Patch Protos

The `prototypes.patch` configuration within the options object allows for dynamic modifications to protobuf definitions during code generation. This feature is designed to apply specific changes to proto files without altering the original source. By using JSON Patch operations such as `replace` and `add`, developers can customize the generated output to better fit project requirements when upstream SDK PRs are lagging or not in production.

Patches are specified as arrays of `Operation`s, where each operation is defined by:
- `op`: The operation type (`add` or `replace`).
- `path`: The JSON path to the target field, optionally prefixed with `@` to denote paths derived automatically from the package name, simplifying navigation within the proto file's structure.
- `value`: The new value to be set at the target location specified by the path.

Here is how these patches can be defined within the prototypes configuration:

```json
{
"prototypes": {
"patch": {
"cosmwasm/wasm/v1/types.proto": [
{
"op": "replace",
"path": "@/AccessType/valuesOptions/ACCESS_TYPE_UNSPECIFIED/(gogoproto.enumvalue_customname)",
"value": "UnspecifiedAccess"
},
{
"op": "replace",
"path": "@/AccessType/valuesOptions/ACCESS_TYPE_NOBODY/(gogoproto.enumvalue_customname)",
"value": "NobodyAccess"
},
{
"op": "add",
"path": "@/AccessType/values/ACCESS_TYPE_SUPER_FUN",
"value": 4
},
{
"op": "add",
"path": "@/AccessType/valuesOptions/ACCESS_TYPE_SUPER_FUN",
"value": {
"(gogoproto.enumvalue_customname)": "SuperFunAccessType"
}
}
]
}
}
}
```


## CosmWasm

Generate TypeScript SDKs for your CosmWasm smart contracts by using the `cosmwasm` option on `TelescopeOptions`. The `cosmwasm` option is actually a direct reference to the `TSBuilderInput` object, for the most up-to-date documentation, visit [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen).
Expand Down
6 changes: 2 additions & 4 deletions packages/ast/src/encoding/proto/proto.json.patch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
} from "./enums";
import {
getNestedProto,
convertProtoPathToNestedJSONPath as convert,
convertPackageNameToNestedJSONPath as convertPackage
} from "@cosmology/utils";
import { ProtoParseContext } from "@cosmology/ast";
Expand All @@ -14,15 +13,14 @@ import {
getTestProtoStore
} from "../../../test-utils";

const p = convert('cosmwasm/wasm/v1/types.proto');
const cp = convertPackage('cosmwasm.wasm.v1');
const store = getTestProtoStore({
prototypes: {
patch: {
'cosmwasm/wasm/v1/types.proto': [
{ op: 'replace', path: '~/AccessType/valuesOptions/ACCESS_TYPE_NOBODY/(gogoproto.enumvalue_customname)', value: 'NobodyAccess' },
{ op: 'replace', path: '@/AccessType/valuesOptions/ACCESS_TYPE_NOBODY/(gogoproto.enumvalue_customname)', value: 'NobodyAccess' },
{ op: 'replace', path: '@/AccessType/valuesOptions/ACCESS_TYPE_UNSPECIFIED/(gogoproto.enumvalue_customname)', value: 'UnspecifiedAccess' },
{ op: 'replace', path: p + '/AccessType/valuesOptions/ACCESS_TYPE_EVERYBODY/(gogoproto.enumvalue_customname)', value: 'EverybodyAccess' },
{ op: 'replace', path: cp + '/AccessType/valuesOptions/ACCESS_TYPE_EVERYBODY/(gogoproto.enumvalue_customname)', value: 'EverybodyAccess' },
{ op: 'replace', path: cp + '/AccessType/valuesOptions/ACCESS_TYPE_ONLY_ADDRESS/(gogoproto.enumvalue_customname)', value: 'OnlyAddressAccess' },
{
op: "add",
Expand Down
5 changes: 1 addition & 4 deletions packages/parser/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import google_struct from './native/struct';
import google_wrappers from './native/wrappers';
import { ProtoResolver } from './resolver';
import { applyPatch } from 'fast-json-patch';
import { convertProtoPathToNestedJSONPath, convertPackageNameToNestedJSONPath } from '@cosmology/utils';
import { convertPackageNameToNestedJSONPath } from '@cosmology/utils';

const GOOGLE_PROTOS = [
['google/protobuf/any.proto', google_any],
Expand Down Expand Up @@ -109,9 +109,6 @@ export class ProtoStore implements IProtoStore {
const ops = this.options.prototypes.patch[filename] ?? [];
try {
const result = applyPatch(protoJson, ops.map(op => {
if (op.path.startsWith('~')) {
op.path = convertProtoPathToNestedJSONPath(filename) + op.path.substring(1);
}
if (op.path.startsWith('@')) {
op.path = convertPackageNameToNestedJSONPath(protoJson.package) + op.path.substring(1);
}
Expand Down
55 changes: 55 additions & 0 deletions packages/telescope/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ The following blockchain libraries (generated by Telescope) are available via np
- [Amino Encoding](#amino-encoding)
- [Prototypes Options](#prototypes-options)
- [Prototypes Methods](#prototypes-methods)
- [Enums Methods](#enums-options)
- [LCD Client Options](#lcd-client-options)
- [RPC Client Options](#rpc-client-options)
- [Stargate Client Options](#stargate-client-options)
Expand Down Expand Up @@ -79,6 +80,7 @@ The following blockchain libraries (generated by Telescope) are available via np
- [RPC Client Classes](#rpc-client-classes)
- [Instant RPC Methods](#instant-rpc-methods)
- [Manually registering types](#manually-registering-types)
- [JSON Patch Protos](#json-patch-protos)
- [CosmWasm](#cosmwasm)
- [Dependencies](#dependencies)
- [Troubleshooting](#troubleshooting)
Expand Down Expand Up @@ -314,6 +316,7 @@ telescope({
| `prototypes.addTypeUrlToObjects` | add typeUrl field to generated Decoders | `true` |
| `prototypes.enableRegistryLoader` | generate Registry loader to *.registry.ts files | `true` |
| `prototypes.enableMessageComposer` | generate MessageComposer to *.registry.ts files | `true` |
| `prototypes.patch` | An object mapping filenames to an array of `Operation` to be applied as patches to proto files during generation. See [JSON Patch Protos](#json-patch-protos) | `undefined`|

### Prototypes Methods

Expand All @@ -327,6 +330,13 @@ telescope({
| `prototypes.methods.fromSDK` | boolean to enable `fromSDK` method on proto objects | `false` |
| `prototypes.methods.toSDK` | boolean to enable `toSDK` method on proto objects | `false` |

### Enums Options

| option | description | defaults |
| ------------------------------------- | --------------------------------------------------------------- | ---------- |
| `enums.useCustomNames` | Enables the usage of custom names for enums if specified through proto options or annotations, allowing for more descriptive or project-specific naming conventions. | `false` |


### LCD Client Options

| option | description | defaults |
Expand Down Expand Up @@ -986,6 +996,51 @@ export const getCustomSigningClient = async ({ rpcEndpoint, signer }: { rpcEndpo
};
```

## JSON Patch Protos

The `prototypes.patch` configuration within the options object allows for dynamic modifications to protobuf definitions during code generation. This feature is designed to apply specific changes to proto files without altering the original source. By using JSON Patch operations such as `replace` and `add`, developers can customize the generated output to better fit project requirements when upstream SDK PRs are lagging or not in production.

Patches are specified as arrays of `Operation`s, where each operation is defined by:
- `op`: The operation type (`add` or `replace`).
- `path`: The JSON path to the target field, optionally prefixed with `@` to denote paths derived automatically from the package name, simplifying navigation within the proto file's structure.
- `value`: The new value to be set at the target location specified by the path.

Here is how these patches can be defined within the prototypes configuration:

```json
{
"prototypes": {
"patch": {
"cosmwasm/wasm/v1/types.proto": [
{
"op": "replace",
"path": "@/AccessType/valuesOptions/ACCESS_TYPE_UNSPECIFIED/(gogoproto.enumvalue_customname)",
"value": "UnspecifiedAccess"
},
{
"op": "replace",
"path": "@/AccessType/valuesOptions/ACCESS_TYPE_NOBODY/(gogoproto.enumvalue_customname)",
"value": "NobodyAccess"
},
{
"op": "add",
"path": "@/AccessType/values/ACCESS_TYPE_SUPER_FUN",
"value": 4
},
{
"op": "add",
"path": "@/AccessType/valuesOptions/ACCESS_TYPE_SUPER_FUN",
"value": {
"(gogoproto.enumvalue_customname)": "SuperFunAccessType"
}
}
]
}
}
}
```


## CosmWasm

Generate TypeScript SDKs for your CosmWasm smart contracts by using the `cosmwasm` option on `TelescopeOptions`. The `cosmwasm` option is actually a direct reference to the `TSBuilderInput` object, for the most up-to-date documentation, visit [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen).
Expand Down
43 changes: 0 additions & 43 deletions packages/utils/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,49 +227,6 @@ function excludePackageFromTraversal(pkg: string, traversal: string[]) {
return traversal.join('_').replace(connectedPkg, '');
}


/**
* Converts a protobuf package path into a deeply nested JSON path format suitable for
* hierarchical representations. This function is ideal for adapting proto package paths
* to structured configurations or mappings in JSON.
*
* @param protoPath The protobuf package path as a string, typically formatted as
* a directory-like structure such as "cosmwasm/wasm/v1/types.proto".
* The "types.proto" or any file name with '.proto' is excluded from
* the conversion.
*
* Example input:
* - "cosmwasm/wasm/v1/types.proto"
*
* @returns A string representing the deeply nested JSON path. The function constructs this
* by starting with "/root/nested" and appending "/nested/{part}" for each segment
* of the original path.
*
* Example output for "cosmwasm/wasm/v1/types.proto":
* - "/root/nested/cosmwasm/nested/wasm/nested/v1"
*
* Usage:
* const jsonNestedPath = convertProtoPathToNestedJSONPath("cosmwasm/wasm/v1/types.proto");
* console.log(jsonNestedPath); // Outputs: "/root/nested/cosmwasm/nested/wasm/nested/v1/nested"
*/
export function convertProtoPathToNestedJSONPath(protoPath: string): string {
// Split the path to isolate components, ignoring any '.proto' file specification
const parts = protoPath.split('/');
if (parts[parts.length - 1].includes('.proto')) {
parts.pop();
}

// Start with the base path
let jsonPath = '/root/nested';

// Append '/nested/{part}' for each path segment
parts.forEach(part => {
jsonPath += `/${part}/nested`;
});

return jsonPath;
}

/**
* Converts a dot-separated package name into a deeply nested JSON path format suitable for
* hierarchical representations. This function is ideal for adapting package names like those
Expand Down

0 comments on commit f761921

Please sign in to comment.