Skip to content

Commit 2a80474

Browse files
committed
refine serviceImplement
add docs
1 parent f6adc99 commit 2a80474

File tree

10 files changed

+231
-46
lines changed

10 files changed

+231
-46
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ See [LCD Clients](#lcd-clients) for more info.
335335
| `rpcClients.scoped` | will generate factory of scoped RPC Clients | `undefined` |
336336
| `rpcClients.scopedIsExclusive` | will allow both scoped bundles and all RPC Clients | `true` |
337337
| `rpcClients.enabledServices` | which services to enable | [`Msg`,`Query`,`Service`] |
338+
| `rpcClients.instantOps` | will generate instant rpc operations in the file `service-ops.ts` under root folder, which contains customized classes having selected rpc methods | `undefined` |
339+
| `rpcClients.serviceImplement` | assign implement type of rpc methods, `Query` or `Tx`, by setting patterns under service types. | `undefined` |
338340

339341
See [RPC Clients](#rpc-clients) for more info.
340342

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,57 @@
1-
import { traverse } from '@cosmology/proto-parser'
2-
import { getNestedProto } from '@cosmology/utils'
3-
import { defaultTelescopeOptions, ProtoService } from '@cosmology/types';
4-
import { expectCode, getTestProtoStore, printCode } from '../../../../../test-utils';
5-
import { GenericParseContext } from '../../../../encoding';
6-
import { createRpcInterface, createRpcClientClass, createRpcClientInterface } from './rpc';
1+
import { traverse } from "@cosmology/proto-parser";
2+
import { getNestedProto } from "@cosmology/utils";
3+
import { defaultTelescopeOptions, ProtoService } from "@cosmology/types";
4+
import {
5+
expectCode,
6+
getTestProtoStore,
7+
printCode,
8+
} from "../../../../../test-utils";
9+
import { GenericParseContext } from "../../../../encoding";
10+
import {
11+
createRpcInterface,
12+
createRpcClientClass,
13+
createRpcClientInterface,
14+
} from "./rpc";
715
const store = getTestProtoStore();
816
store.traverseAll();
917

10-
it('RPC Msg Client but Query implement', () => {
11-
const ref = store.findProto('cosmos/bank/v1beta1/tx.proto');
12-
const res = traverse(store, ref);
13-
const service: ProtoService = getNestedProto(res).Msg;
14-
const context = new GenericParseContext(ref, store, defaultTelescopeOptions);
15-
expectCode(createRpcClientInterface(context, service))
16-
expectCode(createRpcClientClass(context, service))
17-
expectCode(createRpcInterface(context, service))
18+
it("RPC Msg Client but Query implement", () => {
19+
const ref = store.findProto("cosmos/bank/v1beta1/tx.proto");
20+
const res = traverse(store, ref);
21+
const service: ProtoService = getNestedProto(res).Msg;
22+
const context = new GenericParseContext(ref, store, defaultTelescopeOptions);
23+
expectCode(createRpcClientInterface(context, service));
24+
expectCode(createRpcClientClass(context, service));
25+
expectCode(createRpcInterface(context, service));
1826
});
1927

20-
it('RPC Msg implement Client', () => {
21-
const ref = store.findProto('cosmos/bank/v1beta1/tx.proto');
28+
it("RPC Msg implement Client", () => {
29+
const ref = store.findProto("cosmos/bank/v1beta1/tx.proto");
2230
const res = traverse(store, ref);
2331
const service: ProtoService = getNestedProto(res).Msg;
2432
const context = new GenericParseContext(ref, store, defaultTelescopeOptions);
2533
context.options.rpcClients!.serviceImplement = {
26-
"Msg": "Tx"
27-
}
28-
expectCode(createRpcClientInterface(context, service))
29-
expectCode(createRpcClientClass(context, service))
34+
Msg: {
35+
type: "Tx",
36+
},
37+
};
38+
expectCode(createRpcClientInterface(context, service));
39+
expectCode(createRpcClientClass(context, service));
3040
});
3141

32-
it('RPC Msg Query mixed implement Client', () => {
33-
const ref = store.findProto('cosmos/bank/v1beta1/tx.proto');
42+
it("RPC Msg Query mixed implement Client", () => {
43+
const ref = store.findProto("cosmos/bank/v1beta1/tx.proto");
3444
const res = traverse(store, ref);
3545
const service: ProtoService = getNestedProto(res).Msg;
3646
const context = new GenericParseContext(ref, store, defaultTelescopeOptions);
3747
context.options.rpcClients!.serviceImplement = {
38-
"multiSend": "Tx"
39-
}
40-
expectCode(createRpcClientInterface(context, service))
41-
expectCode(createRpcClientClass(context, service))
48+
Msg: {
49+
include: {
50+
patterns: ["**.multiSend"],
51+
},
52+
type: "Tx",
53+
},
54+
};
55+
expectCode(createRpcClientInterface(context, service));
56+
expectCode(createRpcClientClass(context, service));
4257
});

packages/ast/src/clients/rpc/class/tendermint/rpc.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,12 @@ export const createRpcClientInterface = (
529529
.map((key) => {
530530
const methodName = camelRpcMethods ? camel(key) : key;
531531

532-
const implementType = getServiceImplement(service.name, methodName, serviceImplement);
532+
const implementType = getServiceImplement(
533+
service.name,
534+
context.ref.proto.package,
535+
methodName,
536+
serviceImplement
537+
);
533538

534539
const method = service.methods[key];
535540

@@ -611,7 +616,12 @@ export const createRpcClientClass = (
611616
.map(key => {
612617
const name = camelRpcMethods ? camel(key) : key;
613618

614-
const implementType = getServiceImplement(service.name, name, serviceImplement);
619+
const implementType = getServiceImplement(
620+
service.name,
621+
context.ref.proto.package,
622+
name,
623+
serviceImplement
624+
);
615625

616626
const method = service.methods[key];
617627
switch (implementType) {

packages/telescope/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ See [LCD Clients](#lcd-clients) for more info.
335335
| `rpcClients.scoped` | will generate factory of scoped RPC Clients | `undefined` |
336336
| `rpcClients.scopedIsExclusive` | will allow both scoped bundles and all RPC Clients | `true` |
337337
| `rpcClients.enabledServices` | which services to enable | [`Msg`,`Query`,`Service`] |
338+
| `rpcClients.instantOps` | will generate instant rpc operations in the file `service-ops.ts` under root folder, which contains customized classes having selected rpc methods | `undefined` |
339+
| `rpcClients.serviceImplement` | assign implement type of rpc methods, `Query` or `Tx`, by setting patterns under service types. | `undefined` |
338340

339341
See [RPC Clients](#rpc-clients) for more info.
340342

packages/telescope/__tests__/telescope-instant-rpc.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const options: TelescopeOptions = {
7575
useExact: false,
7676
timestamp: "date",
7777
duration: "duration",
78-
useTelescopeGeneratedType: true
78+
useTelescopeGeneratedType: true,
7979
},
8080
},
8181

@@ -152,7 +152,9 @@ const options: TelescopeOptions = {
152152
},
153153
],
154154
serviceImplement: {
155-
"Msg": "Tx"
155+
Msg: {
156+
type: "Tx",
157+
},
156158
},
157159
enabledServices: [
158160
"Msg",
@@ -171,7 +173,11 @@ const options: TelescopeOptions = {
171173
{
172174
className: "CosmosAuthAccount",
173175
include: {
174-
patterns: ["cosmos.auth.**.*account*", "cosmos.auth.**.*Account*", "cosmos.gov.v1beta1.**"],
176+
patterns: [
177+
"cosmos.auth.**.*account*",
178+
"cosmos.auth.**.*Account*",
179+
"cosmos.gov.v1beta1.**",
180+
],
175181
},
176182
nameMapping: {
177183
All: {
@@ -180,7 +186,7 @@ const options: TelescopeOptions = {
180186
Tx: {
181187
txDeposit: "cosmos.gov.v1beta1.deposit",
182188
txVote: "cosmos.gov.v1beta1.vote",
183-
}
189+
},
184190
},
185191
},
186192
],

packages/types/src/telescope.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,21 @@ interface TelescopeOpts {
170170
scopedIsExclusive?: boolean;
171171
bundle?: boolean;
172172
serviceImplement?: {
173-
[ key: 'Msg' |
174-
'Query' |
175-
'Service' |
176-
'ReflectionService' |
177-
'ABCIApplication' |
178-
string ]: 'Query' | 'Tx' | string
179-
},
173+
[
174+
key:
175+
| "Msg"
176+
| "Query"
177+
| "Service"
178+
| "ReflectionService"
179+
| "ABCIApplication"
180+
| string
181+
]: {
182+
include?: {
183+
patterns?: string[];
184+
};
185+
type: "Query" | "Tx" | string;
186+
};
187+
};
180188
enabledServices?: (
181189
'Msg' |
182190
'Query' |

packages/types/types/telescope.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,12 @@ interface TelescopeOpts {
142142
scopedIsExclusive?: boolean;
143143
bundle?: boolean;
144144
serviceImplement?: {
145-
[key: 'Msg' | 'Query' | 'Service' | 'ReflectionService' | 'ABCIApplication' | string]: 'Query' | 'Tx' | string;
145+
[key: "Msg" | "Query" | "Service" | "ReflectionService" | "ABCIApplication" | string]: {
146+
include?: {
147+
patterns?: string[];
148+
};
149+
type: "Query" | "Tx" | string;
150+
};
146151
};
147152
enabledServices?: ('Msg' | 'Query' | 'Service' | 'ReflectionService' | 'ABCIApplication' | string)[];
148153
scoped?: {
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { getServiceImplement } from "..";
2+
3+
it("returns undefined with no serviceImplement", () => {
4+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance");
5+
6+
expect(result).toBeUndefined();
7+
});
8+
9+
it("returns Tx with no include in Msg", () => {
10+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance", {
11+
Msg: {
12+
type: "Tx",
13+
},
14+
});
15+
16+
expect(result).toBe("Tx");
17+
});
18+
19+
it("returns Tx with no pattern in Msg", () => {
20+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance", {
21+
Msg: {
22+
include: {},
23+
type: "Tx",
24+
},
25+
});
26+
27+
expect(result).toBe("Tx");
28+
});
29+
30+
it("returns Tx with empty pattern in Msg", () => {
31+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance", {
32+
Msg: {
33+
include: {
34+
patterns: [],
35+
},
36+
type: "Tx",
37+
},
38+
});
39+
40+
expect(result).toBe("Tx");
41+
});
42+
43+
it("returns Tx with ** pattern in Msg", () => {
44+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance", {
45+
Msg: {
46+
include: {
47+
patterns: ["**"],
48+
},
49+
type: "Tx",
50+
},
51+
});
52+
53+
expect(result).toBe("Tx");
54+
});
55+
56+
it("returns Tx with **.bala* pattern in Msg", () => {
57+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance", {
58+
Msg: {
59+
include: {
60+
patterns: ["**.bala*"],
61+
},
62+
type: "Tx",
63+
},
64+
});
65+
66+
expect(result).toBe("Tx");
67+
});
68+
69+
it("returns undefined with **.bara* pattern in Msg", () => {
70+
const result = getServiceImplement("Msg", "cosmos.bank.v1beta1", "balance", {
71+
Msg: {
72+
include: {
73+
patterns: ["**.bara*"],
74+
},
75+
type: "Tx",
76+
},
77+
});
78+
79+
expect(result).toBeUndefined();
80+
});
81+
82+
it("returns undefined with Query **.bala* pattern in Msg", () => {
83+
const result = getServiceImplement("Query", "cosmos.bank.v1beta1", "balance", {
84+
Msg: {
85+
include: {
86+
patterns: ["**.bala*"],
87+
},
88+
type: "Tx",
89+
},
90+
});
91+
92+
expect(result).toBeUndefined();
93+
});

packages/utils/src/utils.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import minimatch from "minimatch";
12
import {
23
TelescopeOptions,
34
TelescopeOption,
@@ -103,6 +104,10 @@ export const buildImports = (imports: ImportUsage[]) => {
103104
});
104105
};
105106

107+
// https://github.com/isaacs/minimatch/blob/main/src/index.ts#L61
108+
// Optimized checking for the most common glob patterns.
109+
const globPattern = /\*+([^+@!?\*\[\(]*)/;
110+
106111
export const getServiceImplement = (
107112
serviceName:
108113
| "Msg"
@@ -111,12 +116,46 @@ export const getServiceImplement = (
111116
| "ReflectionService"
112117
| "ABCIApplication"
113118
| string,
119+
packagePath: string,
114120
methodName: string,
115121
serviceImplement?: {
116-
[key: 'Msg' | 'Query' | 'Service' | 'ReflectionService' | 'ABCIApplication' | string]: 'Query' | 'Tx' | string;
122+
[
123+
key:
124+
| "Msg"
125+
| "Query"
126+
| "Service"
127+
| "ReflectionService"
128+
| "ABCIApplication"
129+
| string
130+
]: {
131+
include?: {
132+
patterns?: string[];
133+
};
134+
type: "Query" | "Tx" | string;
135+
};
117136
}
118137
) => {
119-
return serviceImplement
120-
? serviceImplement[serviceName] ?? serviceImplement[methodName]
121-
: undefined;
138+
if (serviceImplement) {
139+
const implement = serviceImplement[serviceName];
140+
if (implement) {
141+
const methodNameWithPkg = `${packagePath}.${methodName}`;
142+
143+
const isMatching =
144+
!implement.include?.patterns?.length ||
145+
implement.include.patterns.some((pattern) => {
146+
if (!globPattern.test(pattern)) {
147+
return methodNameWithPkg === pattern;
148+
}
149+
return minimatch(methodNameWithPkg, pattern);
150+
});
151+
152+
if (isMatching) {
153+
return implement.type;
154+
} else {
155+
return undefined;
156+
}
157+
}
158+
}
159+
160+
return undefined;
122161
};

packages/utils/types/utils.d.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ export declare const buildImports: (imports: ImportUsage[]) => {
2626
value: string;
2727
};
2828
}[];
29-
export declare const getServiceImplement: (serviceName: "Msg" | "Query" | "Service" | "ReflectionService" | "ABCIApplication" | string, methodName: string, serviceImplement?: {
30-
[key: string]: string;
29+
export declare const getServiceImplement: (serviceName: "Msg" | "Query" | "Service" | "ReflectionService" | "ABCIApplication" | string, packagePath: string, methodName: string, serviceImplement?: {
30+
[key: string]: {
31+
include?: {
32+
patterns?: string[];
33+
};
34+
type: "Query" | "Tx" | string;
35+
};
3136
}) => string;

0 commit comments

Comments
 (0)