openapi2pas.pp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. {
  2. This file is part of the Free Component Library
  3. Copyright (c) 2024 by Michael Van Canneyt [email protected]
  4. Open API to pascal code generator
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. program openapi2pas;
  12. {$mode objfpc}{$H+}
  13. uses
  14. Classes,
  15. SysUtils,
  16. CustApp,
  17. fpjson,
  18. fpyaml.parser,
  19. fpyaml.data,
  20. fpyaml.json,
  21. fpopenapi.objects,
  22. fpopenapi.reader,
  23. fpopenapi.codegen;
  24. type
  25. { TGenDTOApplication }
  26. TGenDTOApplication = class(TCustomApplication)
  27. private
  28. FInputIsYAML : Boolean;
  29. FQuiet : Boolean;
  30. FCodeGen : TOpenAPICodeGen;
  31. FServiceMapFile,
  32. FUUIDMapFile : String;
  33. procedure ReadYAML(const aInputFile: string; aApi: TOpenAPI);
  34. protected
  35. Procedure DoLog(EventType : TEventType; const Msg : String); override;
  36. procedure DoRun; override;
  37. procedure ReadOpenAPi(const aInputFile: string; aApi: TOpenAPI);
  38. procedure WriteAPI(aApi: TOpenAPI; const aOutputFile: String);
  39. procedure WriteConfig(const aFileName: string);
  40. public
  41. constructor Create(TheOwner: TComponent); override;
  42. destructor Destroy; override;
  43. procedure Usage(const aMessage : string); virtual;
  44. end;
  45. { TGenDTOApplication }
  46. procedure TGenDTOApplication.WriteAPI(aApi: TOpenAPI; const aOutputFile : String) ;
  47. begin
  48. FCodeGen.OnLog:=@DoLog;
  49. FCodeGen.BaseOutputFileName:=aOutputFile;
  50. FCodeGen.API:=aAPI;
  51. if (FUUIDMapFile<>'') and FileExists(FUUIDMapFile) then
  52. FCodeGen.UUIDMap.LoadFromFile(FUUIDMapFile);
  53. if (FServiceMapFile<>'') then
  54. FCodeGen.ServiceMap.LoadFromFile(FServiceMapFile);
  55. FCodeGen.Execute;
  56. if FUUIDMapFile<>'' then
  57. FCodeGen.UUIDMap.SavetoFile(FUUIDMapFile);
  58. end;
  59. procedure TGenDTOApplication.ReadYAML(const aInputFile : string; aApi: TOpenAPI);
  60. var
  61. lParser : TYAMLParser;
  62. lYAML : TYAMLStream;
  63. lJSON : TJSONData;
  64. lJSONString : TJSONStringType;
  65. lReader : TOpenAPIReader;
  66. begin
  67. lYAML:=Nil;
  68. lParser:=TYAMLParser.Create(aInputFile);
  69. try
  70. lYAML:=lParser.Parse;
  71. finally
  72. lParser.Free;
  73. end;
  74. lJSON:=Nil;
  75. try
  76. lJSON:=YAMLtoJSON(lYAML);
  77. lJSONString:=lJSON.FormatJSON();
  78. finally
  79. lJSON.Free;
  80. end;
  81. lReader:=TOpenAPIReader.Create(Self);
  82. try
  83. lReader.ReadFromString(aAPI,lJSONString);
  84. finally
  85. lReader.Free;
  86. end;
  87. end;
  88. procedure TGenDTOApplication.ReadOpenAPi(const aInputFile : string; aApi: TOpenAPI);
  89. var
  90. lReader : TOpenAPIReader;
  91. begin
  92. lReader:=TOpenAPIReader.Create(Self);
  93. try
  94. lReader.ReadFromFile(aAPI,aInputFile);
  95. finally
  96. lReader.Free;
  97. end;
  98. end;
  99. procedure TGenDTOApplication.DoLog(EventType: TEventType; const Msg: String);
  100. begin
  101. if FQuiet then
  102. exit;
  103. Writeln(EventType,' : ',Msg);
  104. end;
  105. procedure TGenDTOApplication.WriteConfig(const aFileName : string);
  106. var
  107. lDir : String;
  108. begin
  109. lDir:=ExtractFilePath(aFileName);
  110. if lDir<>'' then
  111. If not ForceDirectories(lDir) then
  112. begin
  113. Writeln(StdErr,'Failed to create directory ',lDir);
  114. Exit;
  115. end;
  116. Log(etInfo,'Writing config file to %s',[aFileName]);
  117. FCodegen.SaveConfig(aFileName);
  118. end;
  119. procedure TGenDTOApplication.DoRun;
  120. const
  121. shortOpts = 'hi:o:dequ:s:varcC:bnw:y';
  122. LongOpts : Array of string = ('help','input:','output:','delphi','uuid-map:','quiet','service-map','verbose-header','enumerated','async','server','client','config:','abstract','no-implementation','write-config:','yaml');
  123. var
  124. lAPI : TOpenAPI;
  125. lConfig, lOutputFile,lInputFile, ErrorMsg : String;
  126. begin
  127. Terminate;
  128. ErrorMsg:=CheckOptions(ShortOPts,LongOpts);
  129. if (ErrorMsg<>'') or HasOption('h','help') then
  130. begin
  131. Usage(ErrorMsg);
  132. Exit;
  133. end;
  134. lConfig:=GetOptionValue('C','config');
  135. if (lConfig<>'') then
  136. FCodeGen.LoadConfig(lConfig);
  137. FCodeGen.DelphiCode:=HasOption('d','delphi');
  138. FCodeGen.VerboseHeader:=HasOption('v','verbose-header');
  139. FCodeGen.UseEnums:=HasOption('e','enumerated');
  140. FCodeGen.AsyncService:=HasOption('a','async');
  141. lInputFile:=GetOptionValue('i','input');
  142. lOutputFile:=GetOptionValue('o','output');
  143. FUUIDMapFile:=GetOptionValue('u','uuid-map');
  144. FServiceMapFile:=GetOptionValue('s','service-map');
  145. FCodeGen.GenerateServer:=HasOption('r','server');
  146. FCodeGen.GenerateClient:=HasOption('c','client');
  147. FCodeGen.AbstractServiceCalls:=HasOption('b','abstract');
  148. FCodeGen.SkipServerServiceImplementationModule:=HasOption('n','no-implementation');
  149. FInputIsYAML:=HasOption('y','yaml') or TYAMLParser.IsYamlFileName(lInputFile);
  150. FQuiet:=HasOption('q','quiet');
  151. if HasOption('w','write-config') then
  152. WriteConfig(GetOptionValue('w','write-config'))
  153. else
  154. begin
  155. if lInputFile='' then
  156. begin
  157. Usage('No input file specified.');
  158. Exit;
  159. end;
  160. if lOutputFile='' then
  161. lOutputFile:=ChangeFileExt(lInputFile,'');
  162. lAPI:=TOpenAPI.Create;
  163. try
  164. if FInputIsYAML then
  165. ReadYAML(lInputFile,lAPI)
  166. else
  167. ReadOpenAPi(lInputFile,lAPI);
  168. WriteApi(lApi,lOutputFile);
  169. finally
  170. lApi.Free;
  171. end;
  172. end;
  173. end;
  174. constructor TGenDTOApplication.Create(TheOwner: TComponent);
  175. begin
  176. inherited Create(TheOwner);
  177. ExceptionExitCode:=1;
  178. StopOnException:=True;
  179. FCodeGen:=TOpenAPICodeGen.Create(Self);
  180. end;
  181. destructor TGenDTOApplication.Destroy;
  182. begin
  183. FreeAndNil(FCodeGen);
  184. inherited Destroy;
  185. end;
  186. procedure TGenDTOApplication.Usage(const aMessage: string);
  187. begin
  188. if aMessage<>'' then
  189. Writeln('Error : ',aMessage);
  190. writeln('Usage: ', ExtractFileName(ExeName), ' [options]');
  191. Writeln('Where options is one or more of:');
  192. Writeln('-a --async Generate asynchronous service calls.');
  193. Writeln('-b --abstract Split server in abstract handler and implementation modules (and units).');
  194. Writeln('-c --client Generate client-side service.');
  195. Writeln('-C --config=FILE Read config file with converter settings.');
  196. Writeln('-d --delphi Generate delphi code for DTO/Serializer/Service definitions.');
  197. Writeln('-e --enumerated Use enumerateds (default is to keep strings).');
  198. Writeln('-h --help This message.');
  199. Writeln('-i --input=FILE OpenAPI JSON File to use. Required.');
  200. Writeln('-n --no-implementation Skip generation of server service module (only useful when -b is used).');
  201. Writeln('-o --output=FILE Base filename for output.');
  202. Writeln('-q --quiet Be less verbose.');
  203. Writeln('-r --server Generate a HTTP server module.');
  204. Writeln('-s --service-map=FILE Read service and method name mapping from file.');
  205. Writeln('-u --uuid-map=FILE Read (and write) a file with UUIDs for interfaces.');
  206. Writeln('-v --verbose-header Add OpenAPI description to unit header.');
  207. Writeln('-w --write-config=FILE Write a configuration file with current settings and exit.');
  208. ExitCode:=Ord(aMessage<>'');
  209. end;
  210. var
  211. Application: TGenDTOApplication;
  212. begin
  213. Application:=TGenDTOApplication.Create(nil);
  214. Application.Title:='Generate DTO Application';
  215. Application.Run;
  216. Application.Free;
  217. end.