Bezpieczne API typowe z Zod i OpenAPI w jednym kontrakcie
Waliduj żądania na poziomie brzegowym i generuj dokumentację OpenAPI na podstawie tych samych schematów, aby dokumentacja nigdy się nie zmieniała.
To przewodnictwo odbudowuje funkcjonalną ścieżkę dla: tworzenia bezpiecznej pod względem typów API Express przy użyciu Zod i OpenAPI. Skupia się na umowach, sprawdzaniach oraz kodzie, który można bez problemu dodać do repozytorium, nie musząc zgadywać intencji twórcy. Aby uzyskać ogólny obraz, należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Lepiej używać małych, testowalnych jednostek niż rozbudowanych skryptów. Gdy dany krok zawiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.
Idea
Aby zrealizować tę ideę, należy przed zmianą kodu określić dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nazwij poszczególne elementy, zdefiniuj kryteria sukcesu i odrzuć ciche, częściowe ukończenie zadania. Weryfikuj na granicach za pomocą schematów, które jednocześnie generują dokumentację. Jedno źródło prawdy zapobiega rozbieżnościom pomiędzy OpenAPI a obsługującymi je elementami.
const CreateUserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
api.post("/users", {
body: CreateUserSchema,
response: {
201: UserSchema,
},
handler: async (req) => {
const user = await createUser(req.body);
return {
status: 201,
body: user,
};
},
});
Dlaczego tworzyć kolejną bibliotekę Express?
W pytaniu „Dlaczego budować kolejną bibliotekę Express?” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy rejestrować czasy wykonywania i koszty obok wyników funkcjonalnych. Wczesna widoczność zapobiega nieoczekiwanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Waliduj na granicach za pomocą schematów, które jednocześnie generują dokumentację. Jedno źródło prawdy jest lepsze niż rozbieżności pomiędzy OpenAPI a obsługą.
Jak to wygląda obecnie
Dla rozwiązania obecnego, zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Weryfikuj dane na granicach za pomocą schematów, które jednocześnie generują dokumentację. Jedno źródło prawdy zapobiega rozbieżnościom pomiędzy OpenAPI a obsługą. Dla rozwiązania obecnego, zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić dany krok od znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Wolno preferować małe, testowalne jednostki nad rozbudowanymi skryptami. Gdy dany krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowaną ścieżkę przetwarzania.
Bardzo chciałbyś otrzymać opinie od programistów
Aby móc cieszyć się opiniami od programistów, określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy artefaktom, zdefiniuj sprawdzenia sukcesu i odrzuć ciche, częściowe ukończenie zadania. Zwracaj strukturyzowane błędy, na których klienci mogą się oprzeć. Ścisłe określenie typów błędów zmusza do domysławania się.
Listwa kontrolna operacyjna
Dla listwy kontrolnej operacyjnej określ dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie wykonać dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu.
Zdokumentuj zarówno ścieżkę prawidłowego działania, jak i ścieżkę naprawczą. Próby ponownych działań, mechanizmy ludzkiej kontroli oraz obsługa wiadomości błędnych stanowią część produktu, a nie coś do dodania później.
Zwracaj strukturyzowane błędy, na których klienci mogą się opierać. Sztywne wymagania dotyczące typów powodują konieczność domysłów.
Wolimy nudną niezawodność od sprytnych, jednorazowych demonstracji.
Wolimy małe, testowalne jednostki od rozbudowanych skryptów. Gdy jakiś krok zawiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.
Zwracaj strukturyzowane błędy, na których klienci mogą się opierać. Sztywne wymagania dotyczące typów powodują konieczność domysłów.
Zanim wdrożysz nową architekturę, zamroź wersje produktu, utwórz dokładny zapis działań dla kluczowej ścieżki oraz potwierdź kroki odwracające zmiany. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji dostępności oraz jasnego odpowiedzialnego za rotację haseł. Wolimy nudną niezawodność od sprytnych, jednorazowych demonstracji.
Literatura pokrewna
- Wykrywanie niewidzialnych zmian w umowie API za pomocą type’ów wywnioskowanych z przykładów i Zod — Dlaczego ręcznie napisane type’y TypeScript dla API third-party stają się przestarzałe, jak wywnioskowywanie type’ów i schematów Zod z rzeczywistych odpowiedzi pomaga, oraz jak różnice w snapshotach ujawniają te zmiany.
- Wykrywanie zmian w umowie API w czasie kompilacji za pomocą stopniowego wdrażania tRPC — Jak tRPC przekształca przemienione pole w backendzie w błąd kompilacji, jak wprowadzać je endpoint po endpoint obok REST, oraz w których przypadkach jest niewłaściwym narzędziem.