diff --git a/src/index.test.ts b/src/index.test.ts index cc988009..e393e7ca 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -38,9 +38,11 @@ const expectedRipSlipTypescript = [ " [k: string]: any;", "}", ].join("\n"); +const expectedJibberTypescript = "export type TJibber = (niptip: TNiptip): Promise;"; const expectedTypescript = [ expectedNipTipTypescript, expectedRipSlipTypescript, + expectedJibberTypescript, ].join("\n"); const expectedNipTipRust = ""; @@ -69,7 +71,9 @@ const expectedRipSlipRust = [ " reepadoop: Option,", "}", ].join("\n"); -const expectedRust = expectedRipSlipRust; + +const expectedJibberRust = "pub fn jibber(&mut self, niptip: Niptip) -> RpcRequest;"; +const expectedRust = [expectedRipSlipRust, expectedJibberRust].join("\n"); describe("MethodTypings", () => { @@ -85,184 +89,98 @@ describe("MethodTypings", () => { expect(methodTypings).toBeInstanceOf(MethodTypings); }); - describe("getTypeDefinitionsForMethod", () => { + describe("getMethodTypings", () => { it("throws if types not generated yet", () => { const methodTypings = new MethodTypings(testOpenRPCDocument); - expect(() => methodTypings.getTypeDefinitionsForMethod(testOpenRPCDocument.methods[0], "typescript")).toThrow(); - }); - - describe("typscript", () => { - - it("returns a string of typings for a method", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getTypeDefinitionsForMethod(testOpenRPCDocument.methods[0], "typescript")) - .toBe(expectedTypescript); - }); - - }); - - describe("rust", () => { - - it("returns a string of typings where the typeNames are unique", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getTypeDefinitionsForMethod(testOpenRPCDocument.methods[0], "rust")).toBe(expectedRust); - }); - + expect(() => methodTypings.getMethodTypings(testOpenRPCDocument.methods[0], "typescript")).toThrow(); }); - }); - - describe("getTypingsForMethod", () => { - - it("throws if types not generated yet", () => { + it("returns a string of typings for a method", async () => { const methodTypings = new MethodTypings(testOpenRPCDocument); - expect(() => methodTypings.getTypingsForMethod(testOpenRPCDocument.methods[0], "typescript")).toThrow(); - }); - - describe("typscript", () => { - - it("returns a string of typings for a method", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getTypingsForMethod(testOpenRPCDocument.methods[0], "typescript")).toEqual({ - methodAliasName: "TJibber", - params: [ - { - typeId: "jibber/0", - typeName: "TNiptip", - typing: expectedNipTipTypescript, - }, - ], - result: { - typeId: "jibber/result", - typeName: "IRipslip", - typing: expectedRipSlipTypescript, + await methodTypings.generateTypings(); + + expect(methodTypings.getMethodTypings(testOpenRPCDocument.methods[0], "typescript")).toEqual({ + methodAliasName: "TJibber", + methodTyping: "export type TJibber = (niptip: TNiptip): Promise;", + params: [ + { + typeId: "jibber/0", + typeName: "TNiptip", + typing: expectedNipTipTypescript, }, - }); + ], + result: { + typeId: "jibber/result", + typeName: "IRipslip", + typing: expectedRipSlipTypescript, + }, }); - }); - - describe("rust", () => { - - it("returns a string of typings where the typeNames are unique", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getTypingsForMethod(testOpenRPCDocument.methods[0], "rust")).toEqual({ - methodAliasName: "Jibber", - params: [ - { - typeId: "jibber/0", - typeName: "Niptip", - typing: expectedNipTipRust, - }, - ], - result: { - typeId: "jibber/result", - typeName: "Ripslip", - typing: expectedRipSlipRust, + expect(methodTypings.getMethodTypings(testOpenRPCDocument.methods[0], "rust")).toEqual({ + methodAliasName: "Jibber", + methodTyping: "pub fn jibber(&mut self, niptip: Niptip) -> RpcRequest;", + params: [ + { + typeId: "jibber/0", + typeName: "Niptip", + typing: expectedNipTipRust, }, - }); + ], + result: { + typeId: "jibber/result", + typeName: "Ripslip", + typing: expectedRipSlipRust, + }, }); - }); - }); - describe("getAllUniqueTypings", () => { + describe("toString", () => { it("throws if types not generated yet", () => { const methodTypings = new MethodTypings(testOpenRPCDocument); - expect(() => methodTypings.getAllUniqueTypings("typescript")).toThrow(); - }); - - describe("typscript", () => { - - it("returns a string of typings where the typeNames are unique", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getAllUniqueTypings("typescript")).toBe(expectedTypescript); - }); - + expect(() => methodTypings.toString("typescript")).toThrow(); }); - describe("rust", () => { - - it("returns a string of typings where the typeNames are unique", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getAllUniqueTypings("rust")).toBe(expectedRust); - }); + it("returns a string of typings where the typeNames are unique", async () => { + const methodTypings = new MethodTypings(testOpenRPCDocument); + await methodTypings.generateTypings(); + expect(methodTypings.toString("typescript")).toBe(expectedTypescript); + expect(methodTypings.toString("rust")).toBe(expectedRust); }); }); - describe("getMethodTypeAlias", () => { + describe("getMethodAliasTyping", () => { it("throws if types not generated yet", async () => { const methodTypings = new MethodTypings(testOpenRPCDocument); - expect(() => methodTypings.getMethodTypeAlias(testOpenRPCDocument.methods[0], "typescript")).toThrow(); + expect(() => methodTypings.getMethodAliasTyping(testOpenRPCDocument.methods[0], "typescript")).toThrow(); }); - describe("typescript", () => { - - it("returns the function signature for a method", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getMethodTypeAlias(testOpenRPCDocument.methods[0], "typescript")) - .toBe("export type TJibber = (niptip: TNiptip): Promise;"); - }); - - it("works when there are no params", async () => { - const copytestOpenRPCDocument = cloneDeep(testOpenRPCDocument); - copytestOpenRPCDocument.methods[0].params = []; - const methodTypings = new MethodTypings(copytestOpenRPCDocument); - await methodTypings.generateTypings(); + it("returns the function signature for a method", async () => { + const methodTypings = new MethodTypings(testOpenRPCDocument); + await methodTypings.generateTypings(); - expect(methodTypings.getMethodTypeAlias(copytestOpenRPCDocument.methods[0], "typescript")) - .toBe("export type TJibber = (): Promise;"); - }); + expect(methodTypings.getMethodAliasTyping(testOpenRPCDocument.methods[0], "typescript")) + .toBe("export type TJibber = (niptip: TNiptip): Promise;"); + expect(methodTypings.getMethodAliasTyping(testOpenRPCDocument.methods[0], "rust")) + .toBe("pub fn jibber(&mut self, niptip: Niptip) -> RpcRequest;"); }); - describe("rust", () => { + it("works when there are no params", async () => { + const copytestOpenRPCDocument = cloneDeep(testOpenRPCDocument); + copytestOpenRPCDocument.methods[0].params = []; + const methodTypings = new MethodTypings(copytestOpenRPCDocument); + await methodTypings.generateTypings(); - it("does the same as getFunctionSignature", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); + expect(methodTypings.getMethodAliasTyping(copytestOpenRPCDocument.methods[0], "typescript")) + .toBe("export type TJibber = (): Promise;"); - expect(methodTypings.getMethodTypeAlias(testOpenRPCDocument.methods[0], "rust")) - .toBe(methodTypings.getMethodTypeAlias(testOpenRPCDocument.methods[0], "rust")); - }); - - it("returns the function signature for a method", async () => { - const methodTypings = new MethodTypings(testOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getMethodTypeAlias(testOpenRPCDocument.methods[0], "rust")) - .toBe("pub fn jibber(&mut self, niptip: Niptip) -> RpcRequest;"); - }); - - it("works when there are no params", async () => { - const copytestOpenRPCDocument = cloneDeep(testOpenRPCDocument); - copytestOpenRPCDocument.methods[0].params = []; - - const methodTypings = new MethodTypings(copytestOpenRPCDocument); - await methodTypings.generateTypings(); - - expect(methodTypings.getMethodTypeAlias(copytestOpenRPCDocument.methods[0], "rust")) - .toBe("pub fn jibber(&mut self) -> RpcRequest;"); - }); + expect(methodTypings.getMethodAliasTyping(copytestOpenRPCDocument.methods[0], "rust")) + .toBe("pub fn jibber(&mut self) -> RpcRequest;"); }); }); @@ -339,8 +257,7 @@ describe("MethodTypings", () => { const methodTypings = new MethodTypings(copytestOpenRPCDocument); await methodTypings.generateTypings(); - const typings = methodTypings.getAllUniqueTypings("rust"); - expect(methodTypings.getAllUniqueTypings("rust")) + expect(methodTypings.toString("rust", { includeContentDescriptorTypings: true, includeMethodAliasTypings: false })) .toBe([ "pub type Ripslip2 = String;", "#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]", diff --git a/src/index.ts b/src/index.ts index b59dabb3..12d3d9e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,15 +24,30 @@ interface ITypingMapByLanguage { export interface IMethodTypings { methodAliasName: string; + methodTyping: string; params: IContentDescriptorTyping[]; result: IContentDescriptorTyping; } +export interface IToStringOptions { + includeMethodAliasTypings?: boolean; + includeContentDescriptorTypings?: boolean; +} + +const toStringOptionsDefaults = { + includeContentDescriptorTypings: true, + includeMethodAliasTypings: true, +}; + /** * A class to handle all the tasks relating to types for the OpenRPC Document. */ export default class MethodTypings { private typingMapByLanguage: ITypingMapByLanguage = {}; + private toStringOptionsDefaults: IToStringOptions = { + includeContentDescriptorTypings: true, + includeMethodAliasTypings: true, + }; constructor(private openrpcDocument: OpenRPC) { } @@ -50,81 +65,73 @@ export default class MethodTypings { } /** - * Gives you all the [[IMethodTypings]] for a given method. + * A method that returns all the method type aliases as a string, useful to directly inserting into code. * - * @param method The method you need typing for. - * @param langeuage The langauge you want the signature to be in. + * @param language The langauge you want the signature to be in. * - * @returns the typings for the method. + * @returns A string containing all the typings. * */ - public getTypingsForMethod(method: MethodObject, language: TLanguages): IMethodTypings { + public getAllContentDescriptorTypings(language: TLanguages): string { if (Object.keys(this.typingMapByLanguage).length === 0) { throw new Error("typings have not yet been generated. Please run generateTypings first."); } - const typingsMap = this.typingMapByLanguage[language]; - - const typings = values(typingsMap); - const typingsForMethod = filter(typings, ({ typeId }) => _.startsWith(typeId, method.name)); - const paramsAndResult = partition(typingsForMethod, ({ typeId }) => typeId.includes("result")); - const methodTypings = zipObject(["result", "params"], paramsAndResult); - - return { - methodAliasName: generators[language].getMethodAliasName(method), - params: methodTypings.params, - result: methodTypings.result[0], - }; + return this.typingsToString(_.values(this.typingMapByLanguage[language])); } /** - * Gives you all the [[IContentDescriptorTyping.typings]] needed for a particular method. + * A method that returns all the types as a string, useful to directly inserting into code. * - * @param method The method you need the types for. * @param langeuage The langauge you want the signature to be in. * - * @returns A string containing all the typings joined together. + * @returns A string containing all the typings. * */ - public getTypeDefinitionsForMethod(method: MethodObject, language: TLanguages): string { + public getAllMethodAliasTypings(language: TLanguages): string { if (Object.keys(this.typingMapByLanguage).length === 0) { throw new Error("typings have not yet been generated. Please run generateTypings first."); } - const typings = _.chain(this.getTypingsForMethod(method, language)) - .values() - .flatten() - .value() as IContentDescriptorTyping[]; + const generatorForLang = generators[language]; + const typingsMapForLang = this.typingMapByLanguage[language]; - return this.typingsToString(typings); + return _.chain(this.openrpcDocument.methods) + .map((method) => generatorForLang.getMethodTypeAlias(method, typingsMapForLang)) + .join("\n") + .value(); } /** - * A method that returns all the types as a string, useful to directly inserting into code. + * A configurable way to output the typings into a string. * - * @param langeuage The langauge you want the signature to be in. - * - * @returns A string containing all the typings + * @param language The language you want the typings to be + * @param options include or filter particular parts of the output. * + * @returns a multi-line string containing the types in the language specified. */ - public getAllUniqueTypings(language: TLanguages): string { + public toString(language: TLanguages, options: IToStringOptions = this.toStringOptionsDefaults): string { if (Object.keys(this.typingMapByLanguage).length === 0) { throw new Error("typings have not yet been generated. Please run generateTypings first."); } - const typings = _.chain(this.typingMapByLanguage[language]) - .values() - .uniqBy("typeName") - .value() as IContentDescriptorTyping[]; + const typings = []; + if (options.includeContentDescriptorTypings) { + typings.push(this.getAllContentDescriptorTypings(language)); + } + + if (options.includeMethodAliasTypings) { + typings.push(this.getAllMethodAliasTypings(language)); + } - return this.typingsToString(typings); + return typings.join("\n"); } /** * A method that returns a type alias for a given method * * @param method The OpenRPC Method that you want a signature for. - * @param langeuage The langauge you want the signature to be in. + * @param language The langauge you want the signature to be in. * * @returns A string containing a type alias for a function signature of * the same signature as the passed in method. @@ -136,12 +143,11 @@ export default class MethodTypings { * const additionMethod = examples.simpleMath.examples * .find((method) => method.name === "addition"); * const additionFunctionTypeAlias = openrpcTypings.getMethodTypeAlias(additionMethod, "typescript"); - * fs.writeFileSync("./simpleMathAddition.ts", additionFunctionTypeAlias); - * const { TAddition } = require("./simpleMathAddition"); + * // "export TAddition = (a: number, b: number) => number" * ``` * */ - public getMethodTypeAlias(method: MethodObject, language: TLanguages): string { + public getMethodAliasTyping(method: MethodObject, language: TLanguages): string { if (Object.keys(this.typingMapByLanguage).length === 0) { throw new Error("typings have not yet been generated. Please run generateTypings first."); } @@ -152,6 +158,37 @@ export default class MethodTypings { return sig; } + /** + * Gives you all the [[IMethodTypings]] for a given method. + * + * @param method The method you need typing for. + * @param language The langauge you want the signature to be in. + * + * @returns the typings for the method. + * + */ + public getMethodTypings(method: MethodObject, language: TLanguages): IMethodTypings { + if (Object.keys(this.typingMapByLanguage).length === 0) { + throw new Error("typings have not yet been generated. Please run generateTypings first."); + } + + const typingsMap = this.typingMapByLanguage[language]; + + const typings = values(typingsMap); + const typingsForMethod = filter(typings, ({ typeId }) => _.startsWith(typeId, method.name)); + const paramsAndResult = partition(typingsForMethod, ({ typeId }) => typeId.includes("result")); + const methodTypings = zipObject(["result", "params"], paramsAndResult); + + const generatorForLanguage = generators[language]; + + return { + methodAliasName: generatorForLanguage.getMethodAliasName(method), + methodTyping: generatorForLanguage.getMethodTypeAlias(method, typingsMap), + params: methodTypings.params, + result: methodTypings.result[0], + }; + } + private typingsToString(typings: IContentDescriptorTyping[]): string { const compacted = _.chain(typings) .map("typing")