├── .gitignore ├── LICENSE ├── demo01-Github ├── Form.Main.dfm ├── Form.Main.pas ├── Github_GraphQL_Demo.dpr └── clear_project.bat └── src └── GraphQL.Base.pas /.gitignore: -------------------------------------------------------------------------------- 1 | # ########## OS X hidden file index data 2 | 3 | .DS_Store 4 | 5 | # ########## VS Code configuration file 6 | 7 | .vscode/settings.json 8 | 9 | # ########## Windows console batch file 10 | 11 | OpenConsole.bat 12 | 13 | # ########## Secure include file 14 | 15 | Secure*.inc 16 | 17 | # ########## Delphi project file 18 | # (*.dproj) Delphi Project file 19 | # (*.cbproj) C++Builder Project file 20 | 21 | *.dproj 22 | 23 | # ########## Resource file 24 | # (*.rc, *.res) Compiled and uncompiled resource files 25 | # *.rc 26 | 27 | *.res 28 | 29 | # ########## Delphi binary files 30 | # (*.dll) A dynamically linked library file 31 | # (*.exe) Windows executable file 32 | # (*.bpl) Package shared library file 33 | # (*.bpi) Package import library file 34 | # (*.dcp) Delphi Compiled Package file 35 | # (*.drc) Delphi resource string file 36 | # (*.map) Map debug file 37 | # (*.dres) Delphi compiled resource file. (Used when you add to a project RESOURCE such as an icon or image.) 38 | # (*.dcu) Delphi Compiled Unit file 39 | # (*.lib) static library file OR import library for the Win32/Win64 40 | # (*.ocx) OLE Control eXtension 41 | # (*.rsm) Used for remote debugging. (Include remote debug symbols option.) 42 | # (*.dylib) Dynamic library (.dll) or package (.bpl) compiled for the OS X 43 | # (*.tds) Remote debugger TDS debug file. 44 | # (*.tlb) Type library 45 | 46 | *.exe 47 | *.dll 48 | *.bpl 49 | *.bpi 50 | *.dcp 51 | *.drc 52 | *.map 53 | *.dres 54 | *.tds 55 | *.dcu 56 | *.lib 57 | *.ocx 58 | *.rsm 59 | *.tds 60 | *.tlb 61 | 62 | # ########## Android / iOS / OS X binary files 63 | # (*.apk) Android application package file. 64 | # (*.so) Unix-like systems shared libraries (OS X and Linux) 65 | # (*.a) Static library file (ELF-format) produced by Clang 66 | 67 | *.so 68 | *.apk 69 | *.a 70 | 71 | # ########## IDE files 72 | # (*.cfg) Project configuration file used for command-line compiles 73 | # (*.ddp): Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 74 | # (*.vlb): Visual LiveBindings file. Added in Delphi XE2. 75 | # (*.deployproj): Deployment Manager configuration file for your project. Added in Delphi XE2. 76 | 77 | *.cfg 78 | *.ddp 79 | *.vlb 80 | *.deployproj 81 | 82 | 83 | # ########## Other IDE files 84 | # Delphi local files (user-specific info) 85 | 86 | *.local 87 | *.identcache 88 | *.projdata 89 | *.tvsconfig 90 | *.dsk 91 | *.otares 92 | 93 | # ########## Delphi history and backups 94 | # (__history) History folder 95 | # (__recovery) Recovery folder 96 | # (*.~*) Local versions history file 97 | 98 | __history/ 99 | __recovery/ 100 | *.~* 101 | 102 | # ########## Castalia statistics file. Castalia add in Delphi XE7 103 | 104 | *.stat 105 | 106 | # ########## C++Builder 107 | # (*.obj) C++ Object File 108 | # (*.pch) C++ Precompiled Header File 109 | # (*.o) C++ object file or compiled translation unit. 110 | # (*.pch) C++ precompiled header file. 111 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Bogdan Polak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /demo01-Github/Form.Main.dfm: -------------------------------------------------------------------------------- 1 | object Form1: TForm1 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form1' 5 | ClientHeight = 369 6 | ClientWidth = 484 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | OnCreate = FormCreate 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object GroupBox1: TGroupBox 18 | AlignWithMargins = True 19 | Left = 3 20 | Top = 3 21 | Width = 185 22 | Height = 363 23 | Align = alLeft 24 | Caption = 'GroupBox1' 25 | TabOrder = 0 26 | object Button1: TButton 27 | AlignWithMargins = True 28 | Left = 5 29 | Top = 18 30 | Width = 175 31 | Height = 25 32 | Action = actQueryUser 33 | Align = alTop 34 | TabOrder = 0 35 | end 36 | object Button2: TButton 37 | AlignWithMargins = True 38 | Left = 5 39 | Top = 49 40 | Width = 175 41 | Height = 25 42 | Action = actQueryRepoList 43 | Align = alTop 44 | TabOrder = 1 45 | end 46 | object Button3: TButton 47 | AlignWithMargins = True 48 | Left = 5 49 | Top = 80 50 | Width = 175 51 | Height = 25 52 | Action = actGetIssuesList 53 | Align = alTop 54 | TabOrder = 2 55 | end 56 | end 57 | object Memo1: TMemo 58 | AlignWithMargins = True 59 | Left = 264 60 | Top = 87 61 | Width = 185 62 | Height = 89 63 | BevelKind = bkFlat 64 | BorderStyle = bsNone 65 | Font.Charset = DEFAULT_CHARSET 66 | Font.Color = clWindowText 67 | Font.Height = -12 68 | Font.Name = 'Consolas' 69 | Font.Style = [] 70 | Lines.Strings = ( 71 | 'Memo1') 72 | ParentFont = False 73 | ScrollBars = ssVertical 74 | TabOrder = 1 75 | end 76 | object ActionList1: TActionList 77 | Left = 216 78 | Top = 8 79 | object actQueryUser: TAction 80 | Caption = 'actQueryUser' 81 | OnExecute = actQueryUserExecute 82 | end 83 | object actQueryRepoList: TAction 84 | Caption = 'actQueryRepos' 85 | OnExecute = actQueryRepoListExecute 86 | end 87 | object actGetIssuesList: TAction 88 | Caption = 'actGetIssuesList' 89 | OnExecute = actGetIssuesListExecute 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /demo01-Github/Form.Main.pas: -------------------------------------------------------------------------------- 1 | unit Form.Main; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, 7 | System.SysUtils, System.Variants, System.Classes, System.Actions, 8 | Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ActnList, 9 | Vcl.StdCtrls, 10 | GraphQL.Base; 11 | 12 | type 13 | TForm1 = class(TForm) 14 | Button1: TButton; 15 | GroupBox1: TGroupBox; 16 | ActionList1: TActionList; 17 | actQueryUser: TAction; 18 | actQueryRepoList: TAction; 19 | actGetIssuesList: TAction; 20 | Memo1: TMemo; 21 | Button2: TButton; 22 | Button3: TButton; 23 | procedure FormCreate(Sender: TObject); 24 | procedure actQueryUserExecute(Sender: TObject); 25 | procedure actQueryRepoListExecute(Sender: TObject); 26 | procedure actGetIssuesListExecute(Sender: TObject); 27 | private 28 | GraphQL: TGraphQL; 29 | procedure DoCallGitHubAPI(const GraphQLQuery: string; 30 | GraphQLVariables: string = ''); 31 | public 32 | end; 33 | 34 | var 35 | Form1: TForm1; 36 | 37 | implementation 38 | 39 | {$R *.dfm} 40 | 41 | uses 42 | System.JSON; 43 | 44 | {$INCLUDE SecureConsts.inc} 45 | 46 | const 47 | // ------------------------------------------------------------------------ 48 | // README: 49 | // 50 | // * GitHub account is required to run this demo 51 | // * Remove $INCLUDE SecureConsts.inc 52 | // * Enter your personal access token 53 | // 54 | // More info: 55 | // https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ 56 | // 57 | GITHUB_AccessToken = GitHub_Secure_AccessToken; 58 | 59 | procedure TForm1.DoCallGitHubAPI(const GraphQLQuery: string; 60 | GraphQLVariables: string = ''); 61 | var 62 | jsVariables: TJSONObject; 63 | AResponse: string; 64 | begin 65 | GraphQL.URL := 'https://api.github.com/graphql'; 66 | GraphQL.Authorization := 'bearer ' + GITHUB_AccessToken; 67 | if GraphQLVariables = '' then 68 | AResponse := GraphQL.CallQuery(GraphQLQuery) 69 | else 70 | begin 71 | jsVariables := TJSONObject.ParseJSONValue(GraphQLVariables) as TJSONObject; 72 | AResponse := GraphQL.CallQuery(GraphQLQuery, jsVariables); 73 | jsVariables.Free; 74 | end; 75 | // --- 76 | Memo1.Lines.Add('----------------------'); 77 | Memo1.Lines.Add(AResponse); 78 | end; 79 | 80 | procedure TForm1.FormCreate(Sender: TObject); 81 | begin 82 | GraphQL := TGraphQL.Create(Self); 83 | Memo1.Align := alClient; 84 | Memo1.Clear; 85 | end; 86 | 87 | procedure TForm1.actQueryUserExecute(Sender: TObject); 88 | var 89 | Query: string; 90 | begin 91 | Query := 'query { viewer { login } }'; 92 | DoCallGitHubAPI(Query); 93 | end; 94 | 95 | procedure TForm1.actQueryRepoListExecute(Sender: TObject); 96 | var 97 | Query: string; 98 | Variables: string; 99 | begin 100 | Query := 'query ($maxRepos:Int!) { ' + sGraphNewLine + 101 | 'viewer { name repositories(last: $maxRepos) { nodes {name} } } ' + 102 | sGraphNewLine + ' }'; 103 | Variables := '{"maxRepos":12}'; 104 | DoCallGitHubAPI(Query, Variables); 105 | end; 106 | 107 | procedure TForm1.actGetIssuesListExecute(Sender: TObject); 108 | var 109 | Query: string; 110 | begin 111 | Query := 'query GetIssuesFromDelphiDataproxy {' + 112 | ' repository (owner:\"bogdanpolak\", name:\"delphi-dataproxy\") { ' + 113 | sGraphNewLine + 114 | ' issues(first:100) { totalCount nodes{ title url createdAt } }' + 115 | sGraphNewLine + ' } }'; 116 | DoCallGitHubAPI(Query); 117 | end; 118 | 119 | end. 120 | -------------------------------------------------------------------------------- /demo01-Github/Github_GraphQL_Demo.dpr: -------------------------------------------------------------------------------- 1 | program Github_GraphQL_Demo; 2 | 3 | uses 4 | Vcl.Forms, 5 | Form.Main in 'Form.Main.pas' {Form1}, 6 | GraphQL.Base in '..\src\GraphQL.Base.pas'; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.MainFormOnTaskbar := True; 13 | Application.CreateForm(TForm1, Form1); 14 | Application.Run; 15 | end. 16 | -------------------------------------------------------------------------------- /demo01-Github/clear_project.bat: -------------------------------------------------------------------------------- 1 | rmdir /Q /S __history 2 | rmdir /Q /S Win32 3 | rmdir /Q /S .svn 4 | rmdir /Q /S __recovery 5 | 6 | del *.identcache 7 | del *.dproj.local 8 | del desktop.ini 9 | del *.stat 10 | 11 | del *.dcu 12 | del *.exe 13 | del *.dll 14 | -------------------------------------------------------------------------------- /src/GraphQL.Base.pas: -------------------------------------------------------------------------------- 1 | unit GraphQL.Base; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | System.JSON; 8 | 9 | const 10 | sGraphNewLine = '\n'; 11 | 12 | type 13 | TGraphQL = class(TComponent) 14 | private 15 | FURL: string; 16 | FAuthorization: string; 17 | procedure SetURL(const Value: string); 18 | procedure SetAuthorization(const Value: string); 19 | public 20 | function CallQuery(const Query: string; Variables: TJSONObject = nil) 21 | : string; overload; 22 | function CallQuery(const Query: string; const Variables: String) 23 | : string; overload; 24 | property URL: string read FURL write SetURL; 25 | property Authorization: string read FAuthorization write SetAuthorization; 26 | end; 27 | 28 | implementation 29 | 30 | uses 31 | System.SysUtils, 32 | System.NetConsts, 33 | System.Net.HttpClient, 34 | System.Net.URLClient; 35 | 36 | function TGraphQL.CallQuery(const Query: string; 37 | Variables: TJSONObject = nil): string; 38 | var 39 | ARequest: string; 40 | HttpClient: THTTPClient; 41 | ST: TStream; 42 | Response: IHTTPResponse; 43 | begin 44 | // TODO: Validate URL and Authorization properties; 45 | if Variables = nil then 46 | ARequest := '{"query": "' + Query + '" }' 47 | else 48 | ARequest := '{"query": "' + Query + '",' + '"variables": ' + 49 | Variables.ToString + ' }'; 50 | HttpClient := THTTPClient.Create; 51 | try 52 | HttpClient.ContentType := 'application/json'; 53 | // Request.CharSet := 'utf-8' 54 | // HttpClient.Accept := CONTENTTYPE_APPLICATION_JSON; 55 | ST := TStringStream.Create(ARequest); 56 | try 57 | if Authorization = '' then 58 | Response := HttpClient.Post(URL, ST, nil, nil) 59 | else 60 | Response := HttpClient.Post(URL, ST, nil, 61 | TNetHeaders.Create(TNameValuePair.Create('Authorization', 62 | Authorization))); 63 | Result := Response.ContentAsString; 64 | finally 65 | ST.Free; 66 | end; 67 | finally 68 | HttpClient.Free; 69 | end; 70 | end; 71 | 72 | function TGraphQL.CallQuery(const Query: string; 73 | const Variables: String): string; 74 | begin 75 | raise Exception.Create('Not implemented yet'); 76 | end; 77 | 78 | procedure TGraphQL.SetAuthorization(const Value: string); 79 | begin 80 | FAuthorization := Value; 81 | end; 82 | 83 | procedure TGraphQL.SetURL(const Value: string); 84 | begin 85 | FURL := Value; 86 | end; 87 | 88 | end. 89 | --------------------------------------------------------------------------------