Skip to content

Commit 2be1556

Browse files
authored
Merge pull request #542 from open-rpc/fix/notifications
Fix/notifications
2 parents c635be0 + 6d3167b commit 2be1556

File tree

6 files changed

+164
-37
lines changed

6 files changed

+164
-37
lines changed

src/go.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ const getParamsTyping = (method: MethodObject): string => {
2222

2323
const getMethodTyping = (method: MethodObject): string => {
2424
const mResult = method.result as ContentDescriptorObject;
25-
const mutableSchema = (mResult.schema === true || mResult.schema === false) ? mResult.schema : { ...mResult.schema };
26-
const resultName = languageSafeName(getTitle(titleizer(mutableSchema)));
27-
2825
const methodAliasName = getMethodAliasName(method);
29-
3026
const params = getParamsTyping(method);
3127

28+
if(mResult === undefined) {
29+
return `\t${methodAliasName}(${params}) error`;
30+
}
31+
32+
const mutableSchema = (mResult.schema === true || mResult.schema === false) ? mResult.schema : { ...mResult.schema };
33+
const resultName = languageSafeName(getTitle(titleizer(mutableSchema)));
34+
3235
return `\t${methodAliasName}(${params}) (${resultName}, error)`;
3336
};
3437

src/index.test.ts

Lines changed: 104 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,22 @@ const getTestOpenRPCDocument = () => ({
3838
},
3939
},
4040
},
41+
{
42+
name: "notificationTest",
43+
params: [
44+
{
45+
name: "notificationParamName",
46+
required: true,
47+
schema: {
48+
description: "a really cool notificationTest",
49+
title: "notificationTestParam",
50+
type: "number",
51+
},
52+
},
53+
],
54+
}
4155
],
42-
openrpc: "1.0.0",
56+
openrpc: "1.3.2",
4357
} as OpenRPC);
4458

4559
const expectedNipTipTypescript = [
@@ -49,10 +63,16 @@ const expectedNipTipTypescript = [
4963
" *",
5064
" */",
5165
"export type Niptip = number;",
66+
"/**",
67+
" *",
68+
" * a really cool notificationTest",
69+
" *",
70+
" */",
5271
].join("\n");
5372
const expectedSkeepadeepTypescript = "export type Skeepadeep = number;";
5473
const expectedReepadoopTypescript = "export type NumberHo1ClIqD = number;";
5574
const expectedRipSlipTypescript = [
75+
"export type NotificationTestParam = number;",
5676
"export interface Ripslip {",
5777
" reepadoop?: NumberHo1ClIqD;",
5878
" skeepadeep?: Skeepadeep;",
@@ -62,6 +82,7 @@ const expectedRipSlipTypescript = [
6282
"}",
6383
].join("\n");
6484
const expectedJibberTypescript = "export type Jibber = (jibberNiptip: Niptip) => Promise<Ripslip>;";
85+
const expectedNotificationTestTypescript = "export type NotificationTest = (notificationParamName: NotificationTestParam) => Promise<void>;";
6586
const expectedTypescript = [
6687
expectedReepadoopTypescript,
6788
expectedSkeepadeepTypescript,
@@ -74,8 +95,9 @@ const expectedTypescript = [
7495
" * Generated! Represents an alias to any of the provided schemas",
7596
" *",
7697
" */",
77-
"export type AnyOfNiptipRipslip = Niptip | Ripslip;",
98+
"export type AnyOfNiptipNotificationTestParamRipslip = Niptip | NotificationTestParam | Ripslip;",
7899
expectedJibberTypescript,
100+
expectedNotificationTestTypescript,
79101
].join("\n");
80102

81103
const expectedNipTipRust = "";
@@ -95,6 +117,11 @@ const expectedRipSlipRust = [
95117
"/// a really cool niptip",
96118
"///",
97119
"pub type Niptip = f64;",
120+
"/// NotificationTestParam",
121+
"///",
122+
"/// a really cool notificationTest",
123+
"///",
124+
"pub type NotificationTestParam = f64;",
98125
"#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Builder, Default)]",
99126
"#[builder(setter(strip_option), default)]",
100127
"#[serde(default)]",
@@ -111,18 +138,21 @@ const expectedRipSlipRust = [
111138
].join("\n");
112139

113140
const expectedJibberRust = "pub fn Jibber(&mut self, jibberNiptip: Niptip) -> RpcRequest<Ripslip>;";
141+
const expectedNotificationTestRust = "pub fn NotificationTest(&mut self, notificationParamName: NotificationTestParam) -> RpcRequest<void>;";
114142
const expectedRust = [
115143
expectedRipSlipRust,
116144
"#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]",
117145
"#[serde(untagged)]",
118-
"pub enum AnyOfNiptipRipslip {",
146+
"pub enum AnyOfNiptipNotificationTestParamRipslip {",
119147
" Niptip(Niptip),",
148+
" NotificationTestParam(NotificationTestParam),",
120149
" Ripslip(Ripslip),",
121150
"}",
122151
expectedJibberRust,
152+
expectedNotificationTestRust,
123153
].join("\n");
124154

125-
const expectedNipTipGo = ["// a really cool niptip", "type Niptip float64"].join("\n");
155+
const expectedNipTipGo = ["// a really cool niptip", "type Niptip float64", "// a really cool notificationTest", "type NotificationTestParam float64"].join("\n");
126156
const expectedSkeepadeepGo = "type Skeepadeep int64";
127157
const expectedReepadoopGo = "type NumberHo1ClIqD float64";
128158
const expectedRipSlipGo = [
@@ -136,17 +166,23 @@ const expectedRipSlipGo = [
136166
const expectedJibberGo = [
137167
"type Jipperjobber interface {",
138168
"\tJibber(jibberNiptip Niptip) (Ripslip, error)",
169+
"\tNotificationTest(notificationParamName NotificationTestParam) error",
139170
"}",
140171
].join("\n");
141172

142173
const expectedExtraGo = [
143-
"func (a *AnyOfNiptipRipslip) UnmarshalJSON(bytes []byte) error {",
174+
"func (a *AnyOfNiptipNotificationTestParamRipslip) UnmarshalJSON(bytes []byte) error {",
144175
"\tvar ok bool",
145176
"\tvar myNiptip Niptip",
146177
"\tif err := json.Unmarshal(bytes, &myNiptip); err == nil {",
147178
"\t\tok = true",
148179
"\t\ta.Niptip = &myNiptip",
149180
"\t}",
181+
"\tvar myNotificationTestParam NotificationTestParam",
182+
"\tif err := json.Unmarshal(bytes, &myNotificationTestParam); err == nil {",
183+
"\t\tok = true",
184+
"\t\ta.NotificationTestParam = &myNotificationTestParam",
185+
"\t}",
150186
"\tvar myRipslip Ripslip",
151187
"\tif err := json.Unmarshal(bytes, &myRipslip); err == nil {",
152188
"\t\tok = true",
@@ -157,11 +193,14 @@ const expectedExtraGo = [
157193
"\t}",
158194
"\treturn errors.New(\"failed to unmarshal any of the object properties\")",
159195
"}",
160-
"func (o AnyOfNiptipRipslip) MarshalJSON() ([]byte, error) {",
196+
"func (o AnyOfNiptipNotificationTestParamRipslip) MarshalJSON() ([]byte, error) {",
161197
"\tout := []interface{}{}",
162198
"\tif o.Niptip != nil {",
163199
"\t\tout = append(out, o.Niptip)",
164200
"\t}",
201+
"\tif o.NotificationTestParam != nil {",
202+
"\t\tout = append(out, o.NotificationTestParam)",
203+
"\t}",
165204
"\tif o.Ripslip != nil {",
166205
"\t\tout = append(out, o.Ripslip)",
167206
"\t}",
@@ -178,9 +217,10 @@ const expectedGo = [
178217
expectedNipTipGo,
179218
expectedRipSlipGo,
180219
"// Generated! Represents an alias to any of the provided schemas",
181-
"type AnyOfNiptipRipslip struct {",
182-
"\tNiptip *Niptip",
183-
"\tRipslip *Ripslip",
220+
"type AnyOfNiptipNotificationTestParamRipslip struct {",
221+
"\tNiptip *Niptip",
222+
"\tNotificationTestParam *NotificationTestParam",
223+
"\tRipslip *Ripslip",
184224
"}",
185225
expectedExtraGo,
186226
expectedJibberGo
@@ -251,6 +291,51 @@ describe("MethodTypings", () => {
251291
params: ["Niptip"],
252292
result: "Ripslip",
253293
});
294+
295+
expect(
296+
methodTypings.getTypingNames(
297+
"typescript",
298+
(getTestOpenRPCDocument().methods as MethodObject[])[1],
299+
),
300+
).toEqual({
301+
method: "NotificationTest",
302+
params: ["NotificationTestParam"],
303+
result: "Promise<void>",
304+
});
305+
306+
expect(
307+
methodTypings.getTypingNames(
308+
"rust",
309+
(getTestOpenRPCDocument().methods as MethodObject[])[1],
310+
),
311+
).toEqual({
312+
method: "NotificationTest",
313+
params: ["NotificationTestParam"],
314+
result: "RpcRequest<void>",
315+
});
316+
317+
318+
expect(
319+
methodTypings.getTypingNames(
320+
"go",
321+
(getTestOpenRPCDocument().methods as MethodObject[])[1],
322+
),
323+
).toEqual({
324+
method: "NotificationTest",
325+
params: ["NotificationTestParam"],
326+
result: "void",
327+
});
328+
329+
expect(
330+
methodTypings.getTypingNames(
331+
"python",
332+
(getTestOpenRPCDocument().methods as MethodObject[])[1],
333+
),
334+
).toEqual({
335+
method: "NotificationTest",
336+
params: ["NotificationTestParam"],
337+
result: "None",
338+
});
254339
});
255340

256341
it("prefixes names with 'any' when they aren't recognized json schemas", () => {
@@ -274,15 +359,16 @@ describe("MethodTypings", () => {
274359

275360
it("returns a ParamTypings for a method", () => {
276361
const methodTypings = new MethodTypings(getTestOpenRPCDocument());
362+
277363

278364
expect(methodTypings.getParamsTypings("typescript"))
279-
.toEqual("jibberNiptip: Niptip");
365+
.toEqual("jibberNiptip: Niptip\nnotificationParamName: NotificationTestParam");
280366

281367
expect(methodTypings.getParamsTypings("rust"))
282-
.toEqual("jibberNiptip: Niptip");
368+
.toEqual("jibberNiptip: Niptip\nnotificationParamName: NotificationTestParam");
283369

284370
expect(methodTypings.getParamsTypings("go"))
285-
.toEqual("jibberNiptip Niptip");
371+
.toEqual("jibberNiptip Niptip\nnotificationParamName NotificationTestParam");
286372

287373
expect(methodTypings.getParamsTypings("python"))
288374
.toEqual("");
@@ -319,25 +405,22 @@ describe("MethodTypings", () => {
319405
const methodTypings = new MethodTypings(getTestOpenRPCDocument());
320406

321407
expect(methodTypings.getMethodTypings("typescript"))
322-
.toEqual("export type Jibber = (jibberNiptip: Niptip) => Promise<Ripslip>;");
408+
.toEqual([expectedJibberTypescript, expectedNotificationTestTypescript].join("\n"));
323409

324410
expect(methodTypings.getMethodTypings("rust"))
325-
.toEqual("pub fn Jibber(&mut self, jibberNiptip: Niptip) -> RpcRequest<Ripslip>;");
411+
.toEqual([expectedJibberRust, expectedNotificationTestRust].join("\n"));
326412

327413
expect(methodTypings.getMethodTypings("go"))
328-
.toEqual([
329-
"type Jipperjobber interface {",
330-
"\tJibber(jibberNiptip Niptip) (Ripslip, error)",
331-
"}",
332-
].join("\n"));
414+
.toEqual(expectedJibberGo);
333415

334416
expect(methodTypings.getMethodTypings("python"))
335-
.toEqual("");
417+
.toEqual(""+"\n"+"");
336418
});
337419

338420
it("works when there are no params", () => {
339421
const copytestOpenRPCDocument = getTestOpenRPCDocument();
340422
(copytestOpenRPCDocument.methods[0] as MethodObject).params = [];
423+
copytestOpenRPCDocument.methods = [copytestOpenRPCDocument.methods[0]];
341424
const methodTypings = new MethodTypings(copytestOpenRPCDocument);
342425

343426
expect(methodTypings.getMethodTypings("typescript"))
@@ -366,7 +449,7 @@ describe("MethodTypings", () => {
366449
expect(methodTypings.toString("typescript", {
367450
includeMethodAliasTypings: true,
368451
includeSchemaTypings: false,
369-
})).toBe(expectedJibberTypescript);
452+
})).toBe([expectedJibberTypescript, expectedNotificationTestTypescript].join("\n"));
370453
});
371454

372455
it("returns a string of typings for all languages", () => {

src/index.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ const generators: Generators = {
2424
typescript,
2525
};
2626

27+
const languageAliases: { [key in OpenRPCTypingsSupportedLanguages]: OpenRPCTypingsSupportedLanguages } = {
28+
"ts": "typescript",
29+
"rs": "rust",
30+
"golang": "go",
31+
"py": "python",
32+
"rust": "rust",
33+
"typescript": "typescript",
34+
"go": "go",
35+
"python": "python",
36+
};
37+
2738
export type OpenRPCTypingsSupportedLanguages = "rust" | "rs" | "typescript" | "ts" | "go" | "golang" | "py" | "python";
2839

2940
interface OpenRPCTypings {
@@ -95,11 +106,34 @@ export default class MethodTypings {
95106
return generators[language].getParamsTyping(method, joinString);
96107
}
97108

109+
public getEmptyResultType(language: OpenRPCTypingsSupportedLanguages): string {
110+
const standardizedLanguage = languageAliases[language];
111+
switch(standardizedLanguage) {
112+
case "typescript":
113+
return "Promise<void>";
114+
115+
case "rust":
116+
return "RpcRequest<void>";
117+
118+
case "go":
119+
return "void";
120+
121+
case "python":
122+
return "None";
123+
124+
/* istanbul ignore next */
125+
default:
126+
/* istanbul ignore next */
127+
throw new Error(`Cannot resolve empty result type for unknown language: ${language}`);
128+
}
129+
}
130+
98131
public getTypingNames(
99132
language: OpenRPCTypingsSupportedLanguages,
100133
method: MethodObject,
101134
): OpenRPCMethodTypingNames {
102-
const gen = generators[language];
135+
const standardizedLanguage = languageAliases[language];
136+
const gen = generators[standardizedLanguage];
103137

104138
const defaultedMethod = (this.openrpcDocument.methods as MethodObject[]).find(({ name }) => name === method.name) as MethodObject;
105139

@@ -109,7 +143,7 @@ export default class MethodTypings {
109143
return {
110144
method: gen.getMethodAliasName(defaultedMethod),
111145
params: methodParams.map(({ schema }) => languageSafeName(getTitle(titleizer(schema)))),
112-
result: languageSafeName(getTitle(titleizer(methodResult.schema))),
146+
result: methodResult ? languageSafeName(getTitle(titleizer(methodResult.schema))) : this.getEmptyResultType(standardizedLanguage),
113147
};
114148
}
115149

@@ -126,7 +160,7 @@ export default class MethodTypings {
126160
options: OpenRPCTypingsToStringOptions = this.toStringOptionsDefaults,
127161
): string {
128162

129-
const typings = [];
163+
const typings: string[] = [];
130164
if (options.includeSchemaTypings) {
131165
typings.push(this.getSchemaTypings(language));
132166
}

src/rust.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ const getParamsTyping = (method: MethodObject) => {
2323

2424
const getMethodTyping = (method: MethodObject) => {
2525
const mResult = method.result as ContentDescriptorObject;
26-
const mutableSchema = (mResult.schema === true || mResult.schema === false) ? mResult.schema : { ...mResult.schema };
27-
const resultName = getTitle(titleizer(mutableSchema));
28-
const result = `RpcRequest<${languageSafeName(resultName)}>`;
26+
let result = `RpcRequest<void>`;
27+
28+
if(mResult !== undefined) {
29+
const mutableSchema = (mResult.schema === true || mResult.schema === false) ? mResult.schema : { ...mResult.schema };
30+
const resultName = getTitle(titleizer(mutableSchema));
31+
result = `RpcRequest<${languageSafeName(resultName)}>`;
32+
}
2933

3034
const methodAliasName = getMethodAliasName(method);
3135
const params = getParamsTyping(method);

src/typescript.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ const getParamsTyping = (method: MethodObject, joinString?: string): string => {
2424
};
2525

2626
const getMethodTyping: GetParamsTyping = (method: MethodObject): string => {
27-
const result = method.result as ContentDescriptorObject;
28-
const mutableSchema = (result.schema === true || result.schema === false) ? result.schema : { ...result.schema };
29-
const resultName = getTitle(titleizer(mutableSchema));
30-
const resultTypeName = `Promise<${languageSafeName(resultName)}>`;
31-
3227
const methodAliasName = getMethodAliasName(method);
3328
const params = getParamsTyping(method);
29+
const result = method.result as ContentDescriptorObject;
30+
let resultTypeName = "Promise<void>";
31+
32+
if(result !== undefined) {
33+
const mutableSchema = (result.schema === true || result.schema === false) ? result.schema : { ...result.schema };
34+
const resultName = getTitle(titleizer(mutableSchema));
35+
resultTypeName = `Promise<${languageSafeName(resultName)}>`;
36+
}
3437

3538
return `export type ${methodAliasName} = (${params}) => ${resultTypeName};`;
3639
};

0 commit comments

Comments
 (0)