GitHub pflegt eine der größten OpenAPI-Beschreibungen, die überhaupt veröffentlicht werden, und gibt sie unter der MIT-Lizenz frei. sgcOpenAPI liefert keine handgeschriebene GitHub-Komponente mit, sondern einen Generator. Ein einziger Kommandozeilenaufruf über api.github.com.json erzeugt eine einzige Pascal-Unit mit 1.225 Methoden, einer typisierten Response-Klasse für jede davon und einer Funktion GetOpenAPIClient, die dir einen fertigen Client liefert.
Auf einen Blick
GitHub + sgcOpenAPI
Die Zahlen weiter unten sind nicht geschätzt, sondern gemessen: der Generator lief über die aktuelle Beschreibung und das Ergebnis wurde kompiliert.
Quell-Spezifikation
descriptions/api.github.com/api.github.com.json in github/rest-api-description, deklariert als OpenAPI 3.0.3. Ein Konvertierungsschritt ist nicht nötig.
Was dabei herauskommt
Aus 813 Pfaden werden 1.225 Methoden und 1.134 Response-Klassen, dazu 3.250 Modellklassen, in einer einzigen Unit von rund 274.000 Zeilen.
Authentifizierung
Generiere mit -a 2 und setze zur Laufzeit Authentication.Token.BearerToken. Das deckt einen Personal Access Token genauso ab wie einen Installation Token.
Kompiliert sauber
Die generierte Unit baut sauber unter RAD Studio 12 für Win32, mit nichts im Bibliothekspfad außer dem Source-Ordner von sgcOpenAPI.
Schritt 1
Den Generator ausführen
GitHub veröffentlicht mehrere Spielarten derselben Beschreibung. api.github.com.json beschreibt den gehosteten Dienst, ghes-3.x.json beschreibt GitHub Enterprise Server. Generiere aus derjenigen, auf die du zielst.
> sgcOpenAPI.exe -i "api.github.com.json" -o "github.pas" -a 2
File successfully created github.pas
-i nimmt eine lokale Datei oder eine URL und akzeptiert JSON wie YAML. -o ist die zu schreibende Pascal-Unit, und die Unit wird nach dieser Datei benannt. -a 2 wählt die Token-Authentifizierung, jede generierte Methode sendet also Authorization: Bearer. Dieselbe ausführbare Datei ist ein GUI-Assistent, wenn du sie ohne Parameter startest, und sie endet mit 0 bei Erfolg, mit 5 bei einer fehlerhaften Eingabedatei, mit 6 bei einer fehlerhaften Ausgabedatei und mit 7, wenn sich das Dokument nicht in ein gültiges OpenAPI-3-Dokument überführen lässt.
Nimm die generierte .pas ins Projekt auf und trag sie in eine uses-Klausel ein. Es gibt keine Komponente zu installieren, denn sgcOpenAPI registriert keine und liefert kein Design-Time-Package mit.
Schritt 2
Deine Repositories auflisten
GitHub schreibt seine Operation-IDs mit Schrägstrichen und Bindestrichen, etwa repos/list-for-authenticated-user. Diese Zeichen dürfen in einem Pascal-Bezeichner nicht vorkommen, der Generator entfernt sie also, und die Methode heißt am Ende reposlistforauthenticateduser.
Ein Endpunkt, der ein Array zurückgibt, bekommt eine Antwort, deren Successful ein TsgcOpenAPIArray-Nachfahre mit typisiertem Items ist, hier TArray<TsgcOpenAPI_repository_Class>. Die Basis-URL stammt aus dem servers-Eintrag, der generierte Konstruktor setzt also bereits https://api.github.com. Die Paginierung wird nicht vor dir versteckt: aPer_page und aPage sind gewöhnliche Argumente, und du läufst selbst über die Seiten.
Wenn dich die kleingeschriebenen Namen stören, generiere mit -m 1, dann werden die Methoden nach der Zusammenfassung der Operation benannt, oder mit -m 2, dann nach dem Endpunkt.
Schritt 3
Ein Issue anlegen und Pull Requests auflisten
Pfadparameter kommen als führende Argumente an, in der Reihenfolge, in der das Dokument sie deklariert. Der Request-Body kommt als String an, aus dem Grund, der weiter unten steht.
var
oIssue: TsgcOpenAPI_issuescreate_Response;
oPulls: TsgcOpenAPI_pullslist_Response;
begin
oIssue := GetOpenAPIClient.issuescreate('octocat', 'Hello-World',
'{"title":"Memory leak in the HTTP/2 reader",' +
'"body":"Repro steps: ...","labels":["bug","http2"]}');
tryif oIssue.IsSuccessful then
memoLog.Lines.Add('filed issue #' +
IntToStr(oIssue.Successful.Number) + ' ' + oIssue.Successful.Html_url)
else
memoLog.Lines.Add(oIssue.Error422._message);
finally
oIssue.Free;
end;
oPulls := GetOpenAPIClient.pullslist('octocat', 'Hello-World',
'open', 'updated');
try
memoLog.Lines.Add(IntToStr(oPulls.ResponseCode));
finally
oPulls.Free;
end;
end;
Jede Response-Klasse trägt Successful plus eine Eigenschaft pro Statuscode, den das Dokument deklariert. Error304, Error401, Error403 und Error422 stehen also zum Auslesen bereit, wenn der Aufruf fehlschlägt. Ein Status, den GitHub mit einem benannten Schema beschreibt, wird zu einer Klasse, und einer, den GitHub mit gar nichts beschreibt, wird zu einem einfachen String. Die Fehler-Eigenschaft wird bei Bedarf erzeugt, ist also nie nil, und du prüfst IsSuccessful statt das Objekt zu testen.
Der Unterstrich in _message ist kein Tippfehler. message ist eines der 68 reservierten Pascal-Wörter, die der Generator maskiert, ein Schemafeld mit diesem Namen kommt also mit führendem Unterstrich an. Dasselbe passiert mit type, object, default, index und dem Rest der Liste, die alle irgendwo in GitHubs Schemas vorkommen.
Was du bekommst
Was die generierte Unit enthält
Die Unit spiegelt die Beschreibung. Nichts wird kuratiert, alles was GitHub dokumentiert ist also da, und alles was GitHub auslässt fehlt.
Jede dokumentierte Operation
1.225 Methoden, für Repositories und Contents, Issues und Pull Requests, Actions und Check Runs, Packages, Organisationen und Teams, GitHub Apps, Code Scanning und den Rest der Oberfläche.
Eine Response-Klasse pro Methode
Jede stammt von TsgcOpenAPIResponse ab und erbt IsSuccessful, das bei 200 bis 299 wahr ist, dazu ResponseCode und ResponseError.
3.250 Modellklassen
TsgcOpenAPI_repository_Class, TsgcOpenAPI_issue_Class, TsgcOpenAPI_basic_error_Class, TsgcOpenAPI_validation_error_Class und jedes andere Schema aus dem components-Abschnitt.
Tags als Kommentare
GitHubs Tags werden als Kommentare ausgegeben, die die Methoden innerhalb der einen Client-Klasse gruppieren. Zu eigenen Klassen werden sie nicht, alles hängt also an GetOpenAPIClient.
Die Dokumentation aus der Spezifikation
GitHubs eigene Beschreibungen kommen als Pascal-Kommentare über jeder Methode und jeder Eigenschaft an, die IDE zeigt sie also genau dort, wo du sie verwendest.
Enterprise Server ebenfalls
Die ghes-3.x-Beschreibungen generieren genauso. Halte eine generierte Unit pro Ziel vor, wenn du mit beiden sprichst.
Bevor du loslegst
Vier Dinge, die du wissen solltest
Alle vier stammen aus einem echten Generierungslauf über die aktuelle Beschreibung.
Die Unit ist sehr groß
Rund 274.000 Zeilen und 12 MB, die größte der öffentlichen Spezifikationen, die wir hier generieren. Das Kompilieren dauert unter zwei Sekunden, aber der Editor der IDE wird bei einer Datei dieser Größe langsam. -x lässt Operationen weg, die du als "VERB endpoint" aufführst, und -p entfernt danach die Klassen, die keine verbliebene Operation mehr nutzt.
Die meisten Request-Bodies sind Strings
343 Operationen deklarieren einen application/json-Body, aber fast alle beschreiben ihn als anonymes Inline-Objekt statt als benanntes Schema. Ein Inline-Objekt hat keinen Namen, den eine Klasse tragen könnte, der Parameter lautet deshalb const aBody: string und du baust das JSON selbst. Die wenigen, die ein benanntes Schema referenzieren, bekommen sehr wohl eine typisierte Klasse.
273 Warnungen, und sie lohnen die Lektüre
Die meisten betreffen Composition ohne Discriminator-Mapping, wobei die generierte Klasse ein Member pro Zweig trägt. Ein paar melden ein $ref, das im Dokument nicht auflösbar ist, und ein paar melden eine Operation mit zwei Erfolgsstatus, von denen nur einer generiert wird. Der Generator sagt welcher, statt still zu wählen.
Rate Limits und App-Tokens liegen bei dir
Der generierte Client ist ein getreuer HTTP-Client und nicht mehr. Er cacht keine ETag-Werte, wiederholt nichts bei 403 und erneuert keinen Installation Token einer GitHub App. Lies ResponseCode aus, setze über OnBeforeRequest einen Conditional-Request-Header, und erzeuge Installation Tokens mit den apps-Methoden, die die Unit bereits enthält.
Verwandte Lektüre
Aus dem Blog
OpenAPI-Delphi-Parser
Wie der Parser reale Spezifikationen handhabt, einschließlich der Composition-Keywords hinter den meisten Warnungen.
sgcOpenAPI liefert den Parser, den Codegenerator, den OpenAPI-Server und fertige SDKs für Amazon, Azure, Google und Microsoft mit. Ein Produkt, drei Stufen, nach Arbeitsplatz statt nach Funktionsumfang bepreist.