Hallo allerseits! Lassen Sie uns ein wenig über die Datenvalidierung sprechen. Was ist kompliziert und warum sollte es beispielsweise in einem in Typoskript geschriebenen Projekt überhaupt benötigt werden? Typoskript steuert ziemlich gut alles, es bleibt die maximale Benutzereingabe zu überprüfen. Das heißt, ein Dutzend Stammgäste in das Projekt zu werfen und alles, so scheint es, kann das Thema schließen, aber ... Weit davon entfernt, immer und im Falle des Webs fast nie, befindet sich das gesamte Projekt in einer einzigen Codebasis und verwendet dieselben Typen. An der Kreuzung solcher Codebasen entstehen Situationen, in denen das Warten nicht der Realität entspricht und das Typoskript hier kein Assistent mehr ist. Einige Beispiele:
- Der Client-Teil der Anwendung empfängt Daten von der API und validiert sie. Erstens kann sich die API plötzlich und manchmal ohne vorherige Ankündigung ändern, und zweitens wissen die "Server-Leute" selbst manchmal nicht, was ihre API tun kann, zum Beispiel in einem bestimmten Bereich, anstatt eines garantierten Arrays, selbst wenn es leer ist, kann der Vollmond
null
. Bei der Beschreibung der Daten auf dem Client scheinen Programmierer zu bestimmen, mit was der Client zu arbeiten weiß. Wenn etwas schief geht, ist es viel angenehmer, sofort eine Meldung in der Konsole über die Ursache des Problems zu sehen, als einen unverständlichen Fehler zu erkennen, der bereits in der Ansichtsebene aufgetreten ist (und es ist gut, wenn es sofort bemerkt wird). Auch jetzt gibt es bereits Lösungen ( 1 , 2 ), mit denen Typen vom Server zum Client übertragen werden können. Ich habe es noch nicht versucht, aber es ist durchaus möglich, dass dies die Zukunft ist. - Die umgekehrte Situation ist, wenn der Server die gesendeten Parameter überprüft, um die Verarbeitung der Anforderung sofort zu beenden, wenn sie nicht den erwarteten entsprechen. Ich denke, es sind keine Details erforderlich, warum dies wichtig ist.
- Die Validierung von Daten vor dem Speichern in der Datenbank ist ebenfalls nicht überflüssig. Zum Beispiel können Sie sehen, wie es in einem meiner Motorräder organisiert ist: MaraquiaORM # Validation .
Ich denke, die Beispiele sind ziemlich überzeugend und jetzt gibt es kein Gefühl, dass Sie mit einfachen Stammgästen umgehen können, da es nicht nur um Benutzereingaben geht, sondern um die Validierung komplexer, normalerweise auf mehreren Datenebenen verschachtelter Daten. Hier wird bereits eine spezielle Bibliothek benötigt. Und natürlich gibt es! Es kommt einfach so vor, dass ich in den letzten 10 Jahren jedes Mal, wenn ich ein neues Projekt starte, versuche, eine andere solche Bibliothek darin zu verwenden und sie an meine Bedürfnisse anzupassen. Und jedes Mal, wenn etwas schief geht, führt dies manchmal dazu, dass die Testperson mitten in der aktiven Entwicklung ausgetauscht wird. Ich werde nicht über alle Optionen sprechen, die ich studiert habe, sondern nur über die im aktuellen Projekt getesteten.
Typprüfung
Github
Kleine und recht praktische Bibliothek. Die Schaltung wird als String beschrieben. Mit mehrzeiligen Zeichenfolgen können Sie ziemlich komplexe Strukturen beschreiben:
`{ ID: String, creator: { fname: String | Null, mname: String | Null, lname: String | Null, email: [String] } | Undefined, sender: Maybe { name: String, email: String }, type: Number, subject: String, ... }`
Es gibt ziemlich schwerwiegende Nachteile:
- Die IDE hilft in keiner Weise bei einer Reihe von Schemata, was besonders beim Wechsel zu Typoskript ärgerlich war.
- Fast nutzlose Fehlermeldungen. Ich habe diese Bibliothek seit mehr als einem Jahr nicht mehr benutzt und vielleicht hat sich etwas geändert (nach dem Code zu urteilen, nein). Nachrichten hatten den Stil "Erwartete Zeichenfolge, null erhalten". Stellen Sie sich nun vor, Sie haben eine Reihe von Teilen für 200 Objekte, von denen jedes Felder mit Zeichenfolgen enthält, und in nur einem Objekt ist eines der Felder gebrochen. Wie finde ich dieses Feld? Alle 200 Artikel anzeigen? Ich habe so oft gelitten und es hat
mein Leben wirklich gebrochen und den Eindruck der Bibliothek ruiniert. Normalerweise möchte ich nicht wissen, was dort erwartet und empfangen wurde, aber ich möchte das Datenschema öffnen und das darin benötigte Feld und dasselbe in den Daten selbst finden. Mit anderen Worten, in der Fehlermeldung ist es wichtig, den Schlüsselpfad an der richtigen Stelle in den Daten / im Schema zu haben, und was dort erwartet wurde und überhaupt angekommen ist, kann weggelassen werden. - Natürlich eine Kleinigkeit, aber die Einrückung im obigen Beispiel verschwindet nicht, wenn der Code komprimiert wird.
Joi
Github
Browserversion : joi-browser
Wahrscheinlich die bekannteste Bibliothek zu diesem Thema mit einer Reihe von Funktionen und einer endlosen API. Zuerst habe ich es auf dem Server benutzt und es hat sich perfekt gezeigt. Irgendwann habe ich beschlossen, es durch eine type-check
auf dem Client zu ersetzen. Zu diesem Zeitpunkt hatte ich fast keine Kontrolle über die Größe des Bundles, es gab einfach keine Probleme damit. Aber im Laufe des Jahres ist es schnell gewachsen und im mobilen Internet war der erste Anwendungsdownload überhaupt nicht bequem. Es wurde beschlossen, ein verzögertes Laden von Komponenten zu organisieren. Der Webpack-Bundle-Analyzer- Bericht zeigte eine Reihe von Riesen im Bundle, und alle gingen problemlos zu den vom Webpack erstellten Blöcken. Alle außer Joi
. Viele Komponenten kommunizieren mit dem Server und alle Serverantworten werden validiert. Das heißt, es ist nicht sinnvoll, Joi
in eine Art Block zu stecken. Es wird einfach immer direkt nach dem Hauptblock geladen. Irgendwann sah das Hauptbündel so aus: tyts . Natürlich entstand ein anhaltender Wunsch, etwas dagegen zu unternehmen. Ich wollte die gleiche praktische Bibliothek, aber viel weniger.
Ja
Github
In der Readme-Version versprechen sie ungefähr das gleiche Joi
, aber in der für das Frontend geeigneten Größe. Tatsächlich ist es nur etwa zweimal kleiner, Yup
war immer noch die größte Bibliothek im Hauptpaket. Darüber hinaus traten zusätzliche Nachteile auf:
- Die Standardbibliothek überspringt alle
undefined
. Ständig .required()
schreiben .required()
nicht sehr angenehm, und ich mag es besser, wenn anfangs alles unmöglich ist und wo es erlaubt ist. Joi
hat eine Option presence: 'required'
, um dieses Verhalten zu konfigurieren. Ich habe eine Anfrage mit der höllischen Nummer 666 erstellt , aber bisher schweigen die Autoren. - Es gibt keine Möglichkeit, die Werte eines Objekts zu überprüfen, da alle Schlüssel zulässig sind.
Joi
verwendet dazu object.pattern , wobei das erste Argument eine beliebige Zeichenfolge akzeptiert . Wahrscheinlich wäre es immer noch möglich, irgendwie herauszukommen, und die Autoren können das erste Minus korrigieren, aber angesichts der Größe wollte ich nicht warten oder etwas selbst bearbeiten.
Ow
Github
Der nächste Bewerber erwies sich schließlich als sehr klein, und er ließ ihn nicht ständig schreiben ()
wo Sie darauf verzichten können. Sie können beispielsweise einen Validator schreiben, der eine Zeichenfolge zulässt oder wie folgt undefined
:
let optionalStringValidator = ow.optional.string; ow(optionalStringValidator, '1');
Großartig! Was ist mit null
? Beim Umblättern der gesamten Dokumentation fand ich die folgende Methode:
ow.any(ow.optional.string, ow.null);
Oh Horror! Als ich versuchte, einen Teil der Validierung im Projekt neu zu schreiben, habe ich mir beim Tippen fast die Finger gebrochen. Ich habe ow.nullable
Problem mit dem Hinzufügen von ow.nullable
, das hier gesendet wurde . Kurz gesagt, sie sagen, dass null
nicht benötigt wird. Die dort angegebenen Argumente sind auch in Anbetracht der ersten Zeile in ihrer Readme-Datei völlig ausreichend:
Funktionsargumentvalidierung für Menschen
Das heißt, diese Bibliothek dient zum Überprüfen der Werte, die als Argumente für die Funktion dienen. Anscheinend haben sie nicht wirklich mit riesigen verschachtelten Strukturen vom Server gerechnet.
Weitere Studien und Verwendungsversuche ergaben mehrere weitere Funktionen, die wiederum durch dieselbe Zeile in der Readme-Datei gut erklärt wurden, aber nicht sehr gut zu mir passten. Dies ist eigentlich eine ziemlich gute Bibliothek, nur für ein paar andere Zwecke.
Hier hatte ich es schon satt aufzugeben und beschloss, meine Bibliothek mit Blackjack und Jungfrauen zu schreiben. Ja, ja, ich bin mit dem nächsten Fahrrad wieder bei dir :). Treffen:
Omyumyum
Einige Beispiele:
import om from 'omyumyum'; const isOptionalNumber = om.number.or.undefined; isOptionalNumber('1');
.or
kann beliebig .or
verwendet werden, indem Sie die Optionen erweitern:
om.number.or.string.or.null.or.undefined;
In diesem Fall wird ständig eine fast gewöhnliche Funktion generiert, die jedes Argument boolean
und einen boolean
zurückgibt.
Wenn die Funktion einen Fehler auslösen soll, wenn der Test fehlschlägt:
om(om.number, '1');
Oder mit Curry:
const isNumberOrThrow = om(om.number); isNumberOrThrow('1')
Die resultierende Funktion ist nicht ganz normal, da sie zusätzliche Methoden enthält. .or
bereits angezeigt, ein Teil der Methoden hängt vom ausgewählten Typ ab (siehe API ). Beispielsweise kann eine Zeichenfolge mit einem regulären Ausdruck erweitert werden:
const isNonEmptyString = om.string.pattern(/\S/);
Und für das Objekt können Sie seine Form angeben:
const isUserData = om.object.shape({ name: om.string, age: om.number.or.vacuum
Der versprochene Schlüsselweg zum Problempunkt:
om(om.array.of(om.object.shape({ name: om.string })), [{ name: '' }, { name: null }]);
Wenn die integrierten Funktionen nicht ausreichen, können Sie immer .custom(validator: (value: any) => boolean)
:
const isEmailOrPhone = om.custom(require('is-email')).or.custom(require('is-phone')); isEmailOrPhone('test@test.test');
Auf Lager ist auch die erwartete .and
verwendet, um Typen zu kombinieren und zu verbessern:
const isNonZeroString = om.string.and.custom(str => str.length > 0);
.and
hat Vorrang vor .or
, aber da .custom()
den Validator mit genau der Form akzeptiert, die von der Bibliothek erstellt wurde, kann dies umgangen werden:
Sie können zuvor erstellte Validatoren weiter verbessern. Die alten verderben überhaupt nicht. Versuchen isUserData
die zuvor erstellten isUserData
zu verbessern:
const isImprovedUserData = isUserData.and.object.shape({ friends: om.array.of(isUserData).or.vacuum }); isImprovedUserData({ name: '', age: 20, friends: [{ name: '', age: 18 }] });
Nun, blieb .not
:
const isNotVacuum = om.not.null.and.not.undefined;
Weitere verfügbare Methoden finden Sie in der Bibliotheks- API .
Vorteile der Bibliothek:
- Lakonische Syntax mit
.or
, .or
, .or
und einem Minimum an Klammern. In Kombination mit dem Autocomplete-Typoskript wird das Set zum Vergnügen. - Winziges Gewicht sogar im Vergleich zu
Ow
(fast 10-mal weniger (minify + gzip)) und im Vergleich zu Joi
Bibliothek wie eine Feder neben einem Berg. - Schöner Name :)
Nachteile der Bibliothek:
- Weniger Typen und ihre Modifikatoren. Und es ist unwahrscheinlich, dass es noch viel mehr geben wird. Alle drei am Anfang des Artikels angegebenen Verwendungsszenarien (etwas über Junctions und Codebasen) setzen die Übertragung von Klartextdaten voraus, in den meisten Fällen handelt es sich um JSON. Das heißt, meiner Meinung nach sollte eine solche Bibliothek die in JSON möglichen Typen sowie
undefined
und einige häufig verwendete Typen unterstützen. Aus irgendeinem Grund ist derselbe Ow
mit Unterstützung für alle Arten von typisierten Arrays und anderem Unsinn vollgestopft. Ich finde das überflüssig. - Kann keine Daten wie
Joi
konvertieren. Ich denke, Joi
ist auch ziemlich schlecht darin. Zumindest habe ich nicht genug von seinen Fähigkeiten und mache bei Bedarf Transformationen mit völlig anderen Werkzeugen. Vielleicht ist dies eine weitere Entwicklungsrichtung für omyumyum
.
Das ist alles! Wenn Ihnen der Artikel gefallen hat, abonnieren Sie den Kanal und viel Glück)).