Skip to content

Commit

Permalink
patch enums, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pyramation committed Jun 13, 2024
1 parent 9e5099d commit df44cc1
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ exports[`createProtoEnumFromJSON 1`] = `
case "AccessTypeUnspecified":
return AccessType.ACCESS_TYPE_UNSPECIFIED;
case 1:
case "NobodyAccess":
case "AccessTypeNobody":
return AccessType.ACCESS_TYPE_NOBODY;
case 2:
case "AccessTypeOnlyAddress":
return AccessType.ACCESS_TYPE_ONLY_ADDRESS;
case 3:
case "EverybodyAccess":
case "AccessTypeEverybody":
return AccessType.ACCESS_TYPE_EVERYBODY;
case -1:
case "UNRECOGNIZED":
Expand All @@ -44,11 +44,11 @@ exports[`createProtoEnumToJSON 1`] = `
case AccessType.ACCESS_TYPE_UNSPECIFIED:
return "AccessTypeUnspecified";
case AccessType.ACCESS_TYPE_NOBODY:
return "NobodyAccess";
return "AccessTypeNobody";
case AccessType.ACCESS_TYPE_ONLY_ADDRESS:
return "AccessTypeOnlyAddress";
case AccessType.ACCESS_TYPE_EVERYBODY:
return "EverybodyAccess";
return "AccessTypeEverybody";
case AccessType.UNRECOGNIZED:
default:
return "UNRECOGNIZED";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`createProtoEnum 1`] = `
"/** AccessType permission types */
export enum NullValue {
/** ACCESS_TYPE_UNSPECIFIED - AccessTypeUnspecified placeholder for empty value */
ACCESS_TYPE_UNSPECIFIED = 0,
/** ACCESS_TYPE_NOBODY - AccessTypeNobody forbidden */
ACCESS_TYPE_NOBODY = 1,
/** ACCESS_TYPE_ONLY_ADDRESS - AccessTypeOnlyAddress restricted to an address */
ACCESS_TYPE_ONLY_ADDRESS = 2,
/** ACCESS_TYPE_EVERYBODY - AccessTypeEverybody unrestricted */
ACCESS_TYPE_EVERYBODY = 3,
ACCESS_TYPE_SUPER_FUN = 4,
UNRECOGNIZED = -1,
}"
`;

exports[`createProtoEnumFromJSON 1`] = `
"export function accessTypeFromJSON(object: any): AccessType {
switch (object) {
case 0:
case "UnspecifiedAccess":
return AccessType.ACCESS_TYPE_UNSPECIFIED;
case 1:
case "NobodyAccess":
return AccessType.ACCESS_TYPE_NOBODY;
case 2:
case "OnlyAddressAccess":
return AccessType.ACCESS_TYPE_ONLY_ADDRESS;
case 3:
case "EverybodyAccess":
return AccessType.ACCESS_TYPE_EVERYBODY;
case 4:
case "SuperFunAccessType":
return AccessType.ACCESS_TYPE_SUPER_FUN;
case -1:
case "UNRECOGNIZED":
default:
return AccessType.UNRECOGNIZED;
}
}"
`;

exports[`createProtoEnumToJSON 1`] = `
"export function accessTypeToJSON(object: AccessType): string {
switch (object) {
case AccessType.ACCESS_TYPE_UNSPECIFIED:
return "UnspecifiedAccess";
case AccessType.ACCESS_TYPE_NOBODY:
return "NobodyAccess";
case AccessType.ACCESS_TYPE_ONLY_ADDRESS:
return "OnlyAddressAccess";
case AccessType.ACCESS_TYPE_EVERYBODY:
return "EverybodyAccess";
case AccessType.ACCESS_TYPE_SUPER_FUN:
return "SuperFunAccessType";
case AccessType.UNRECOGNIZED:
default:
return "UNRECOGNIZED";
}
}"
`;
13 changes: 3 additions & 10 deletions packages/ast/src/encoding/proto/proto.enum.custom.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,16 @@ import {
createProtoEnumFromJSON,
createProtoEnumToJSON,
} from "./enums";
import { getNestedProto, convertProtoPathToNestedJSONPath as convert } from "@cosmology/utils";
import {
getNestedProto
} from "@cosmology/utils";
import { ProtoParseContext } from "@cosmology/ast";
import {
expectCode,
getTestProtoStore
} from "../../../test-utils";

const p = convert('cosmwasm/wasm/v1/types.proto');
const store = getTestProtoStore({
prototypes: {
patch: {
'cosmwasm/wasm/v1/types.proto': [
{ op: 'replace', path: p + '/AccessType/valuesOptions/ACCESS_TYPE_NOBODY/(gogoproto.enumvalue_customname)', value: 'NobodyAccess' },
{ op: 'replace', path: p + '/AccessType/valuesOptions/ACCESS_TYPE_EVERYBODY/(gogoproto.enumvalue_customname)', value: 'EverybodyAccess' },
]
}
},
enums: {
useCustomNames: true
}
Expand Down
82 changes: 82 additions & 0 deletions packages/ast/src/encoding/proto/proto.json.patch.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
createProtoEnum,
createProtoEnumFromJSON,
createProtoEnumToJSON,
} from "./enums";
import {
getNestedProto,
convertProtoPathToNestedJSONPath as convert,
convertPackageNameToNestedJSONPath as convertPackage
} from "@cosmology/utils";
import { ProtoParseContext } from "@cosmology/ast";
import {
expectCode,
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_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_ONLY_ADDRESS/(gogoproto.enumvalue_customname)', value: 'OnlyAddressAccess' },
{
op: "add",
path: "/root/nested/cosmwasm/nested/wasm/nested/v1/nested/AccessType/values/ACCESS_TYPE_SUPER_FUN",
value: 4
},
{
op: "add",
path: "/root/nested/cosmwasm/nested/wasm/nested/v1/nested/AccessType/valuesOptions/ACCESS_TYPE_SUPER_FUN",
value: {
"(gogoproto.enumvalue_customname)": "SuperFunAccessType"
}
}
]
}
},
enums: {
useCustomNames: true
}
});
store.traverseAll();

it("createProtoEnum", async () => {
const ref = store.findProto('cosmwasm/wasm/v1/types.proto');
const context = new ProtoParseContext(ref, store, store.options);
expectCode(
createProtoEnum(
context,
"NullValue",
getNestedProto(ref.traversed).AccessType
)
);
});

it("createProtoEnumFromJSON", async () => {
const ref = store.findProto('cosmwasm/wasm/v1/types.proto');
const context = new ProtoParseContext(ref, store, store.options);
expectCode(
createProtoEnumFromJSON(
context,
"AccessType",
getNestedProto(ref.traversed).AccessType
)
);
});

it("createProtoEnumToJSON", async () => {
const ref = store.findProto('cosmwasm/wasm/v1/types.proto');
const context = new ProtoParseContext(ref, store, store.options);
expectCode(
createProtoEnumToJSON(
context,
"AccessType",
getNestedProto(ref.traversed).AccessType
)
);
});
24 changes: 19 additions & 5 deletions packages/parser/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { sync as glob } from 'glob';
import { parse } from '@cosmology/protobufjs';
import { readFileSync } from 'fs';
import { join, resolve as pathResolve } from 'path';
import { ALLOWED_RPC_SERVICES, ProtoDep, ProtoField, ProtoRef, ProtoServiceMethod, ProtoType, TelescopeOptions, ENUM_PROTO2_DEFAULT, ENUM_PROTO3_DEFAULT } from '@cosmology/types';
import { ProtoDep, ProtoRef, ProtoServiceMethod, TelescopeOptions, ENUM_PROTO2_DEFAULT, ENUM_PROTO3_DEFAULT } from '@cosmology/types';
import { createTypeUrlTypeMap, getNestedProto, getPackageAndNestedFromStr, isRefIncluded, isRefExcluded } from './';
import { parseFullyTraversedProtoImports, symbolsToImportNames, traverse } from './traverse';
import { lookupAny, lookupAnyFromImports } from './lookup';
Expand All @@ -17,7 +17,8 @@ import google_field_mask from './native/field_mask';
import google_struct from './native/struct';
import google_wrappers from './native/wrappers';
import { ProtoResolver } from './resolver';
import { applyOperation, applyPatch } from 'fast-json-patch';
import { applyPatch } from 'fast-json-patch';
import { convertProtoPathToNestedJSONPath, convertPackageNameToNestedJSONPath } from '@cosmology/utils';

const GOOGLE_PROTOS = [
['google/protobuf/any.proto', google_any],
Expand Down Expand Up @@ -105,9 +106,22 @@ export class ProtoStore implements IProtoStore {
try {
let protoJson = parseProto(content, this.options.prototypes.parser);
if (this.options.prototypes.patch && this.options.prototypes.patch[filename]) {
const ops = this.options.prototypes.patch[filename];
const result = applyPatch(protoJson, ops);
protoJson = result.newDocument;
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);
}
return op;
}));
protoJson = result.newDocument;
} catch (e2) {
console.error('JSON Patch error on proto: ' + filename);
}

}
return {
absolute,
Expand Down
34 changes: 34 additions & 0 deletions packages/utils/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,37 @@ export function convertProtoPathToNestedJSONPath(protoPath: string): string {

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
* used in Protobuf or similar systems to structured configurations or mappings in JSON.
*
* @param packageName The dot-separated package name as a string, typically formatted as
* a namespace structure such as "cosmwasm.wasm.v1".
*
* Example input:
* - "cosmwasm.wasm.v1"
*
* @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 package name. This mimics a directory path structure in a JSON tree, where
* each package level is further nested within its parent.
*
* Example output for "cosmwasm.wasm.v1":
* - "/root/nested/cosmwasm/nested/wasm/nested/v1"
*
* Usage:
* const jsonNestedPath = convertPackageNameToNestedJSONPath("cosmwasm.wasm.v1");
* console.log(jsonNestedPath); // Outputs: "/root/nested/cosmwasm/nested/wasm/nested/v1/nested"
*/
export function convertPackageNameToNestedJSONPath(packageName: string): string {
const parts = packageName.split('.');

let jsonPath = '/root/nested';
parts.forEach(part => {
jsonPath += `/${part}/nested`;
});

return jsonPath;
}
24 changes: 24 additions & 0 deletions packages/utils/types/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,27 @@ export declare const getTypeNameByEnumObj: (field: any, pkg: string, traversal:
* console.log(jsonNestedPath); // Outputs: "/root/nested/cosmwasm/nested/wasm/nested/v1/nested"
*/
export declare function convertProtoPathToNestedJSONPath(protoPath: string): string;
/**
* 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
* used in Protobuf or similar systems to structured configurations or mappings in JSON.
*
* @param packageName The dot-separated package name as a string, typically formatted as
* a namespace structure such as "cosmwasm.wasm.v1".
*
* Example input:
* - "cosmwasm.wasm.v1"
*
* @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 package name. This mimics a directory path structure in a JSON tree, where
* each package level is further nested within its parent.
*
* Example output for "cosmwasm.wasm.v1":
* - "/root/nested/cosmwasm/nested/wasm/nested/v1"
*
* Usage:
* const jsonNestedPath = convertPackageNameToNestedJSONPath("cosmwasm.wasm.v1");
* console.log(jsonNestedPath); // Outputs: "/root/nested/cosmwasm/nested/wasm/nested/v1/nested"
*/
export declare function convertPackageNameToNestedJSONPath(packageName: string): string;

0 comments on commit df44cc1

Please sign in to comment.