Si vous définissez un type avec Python Own ORM (fsglue) dans un Firestore sans schéma et le combinez avec OpenAPI ou Typescript, un environnement de développement flexible mais typé et confortable Je l'ai fait, alors j'ai essayé de le résumer facilement
En tant que passe-temps, je développe la plate-forme d'application commerciale à faible code Bizglue, et c'est une histoire en coulisse. Pour connaître les motifs de développement du service, voir note, donc si vous êtes intéressé, veuillez également le vérifier.
Écoulement brutal jusqu'à la configuration finale
--AppEngine (environnement standard)
Ce qui est "doux", c'est que Firestore lui-même est fondamentalement sans schéma, donc l'ajout de champs et de modifications rétrocompatibles peut être fait simplement en changeant la définition du modèle (pas besoin de traitement de migration gênant). .. Il est un peu gênant de générer manuellement le client API, mais je pense qu'il est assez pratique de pouvoir vérifier le type avec Typescript en fonction de la définition du modèle définie côté serveur.
Je vais l'expliquer un peu plus concrètement avec un exemple de code.
Si vous définissez un modèle comme celui-ci
import fsglue
TAGS_SCHEMA = {
"type": "array",
"items": {
"type": "string",
},
}
class User(fsglue.BaseModel):
COLLECTION_PATH = "users"
COLLECTION_PATH_PARAMS = []
name = fsglue.StringProperty(required=True)
tags = fsglue.JsonProperty(schema=TAGS_SCHEMA, default=[])
created_at = fsglue.TimestampProperty(auto_now=True)
updated_at = fsglue.TimestampProperty(auto_now_add=True)
Vous pouvez générer la définition JsonSchema suivante avec ʻUser.to_schema () `.
{
"type": "object",
"required": [
"name",
"owner"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"created_at": {
"type": "number"
},
"updated_at": {
"type": "number"
}
}
}
ʻPasser le résultat de l'exécution de User.to_schema () `à flasgger afin qu'il puisse être référencé dans la définition de chaque point final.
from flasgger import Swagger
from xxx import models #Définition du modèle
from xxx import app #application flacon
template = {
"swagger": "2.0",
...Omission...
"definitions": {
"User": models.User.to_schema(), #Définir le modèle
...Omission...
},
...Omission...
}
swagger = Swagger(app, template=template)
Par exemple, implémentez une API pour obtenir une liste d'utilisateurs appartenant à une certaine organisation avec l'image suivante.
from flask import Blueprint
from flasgger.utils import swag_from
app = Blueprint("user", __name__, url_prefix="/api/v1")
@app.route('/organization/<org_id>/user/', methods=['GET'])
@swag_from({
"operationId": "getUserList",
"summary": "getUserList",
"parameters": [
{"name": "org_id", "in": "path", "type": "string", "required": "true"},
],
"responses": {
"200": {
"description": "users",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/User", #Voir les modèles enregistrés dans flasgger
}
},
}
},
"tags": ["user"],
})
@auth.xxx_required #Décorateur de contrôle d'autorité
def list_user(org_id, **kwargs):
users = User.all(org_id, to_dict=True)
return jsonify(users)
Vous pouvez installer openapi-generator et générer un client API dans l'environnement de développement avec la commande suivante (cette fois, typescript-fetch
J'utilise un client)
#Obtenir json de la définition OpenAPI
curl http://localhost:8080/apispec_1.json > ./xxx/apispec.json
# openapi-Générer un client API avec un générateur
./node_modules/.bin/openapi-generator \
generate \
-g typescript-fetch \
-o ./yyy/api/ \
-i ./xxx/apispec.json \
--additional-properties modelPropertyNaming=snake_case \ #Les options sont votre choix
--additional-properties supportsES6=true \
--additional-properties typescriptThreePlus=true \
--additional-properties disallowAdditionalPropertiesIfNotPresent=false
Avec l'image ci-dessous, vous pouvez utiliser le client API tout en bénéficiant du type Typescript. (Lors de son utilisation, afin de fournir des informations d'authentification et d'implémenter un traitement commun, l'API générée est appelée via un wrapper au lieu d'être appelée directement.)
import { UserApi } from "xxx/UserApi";
const api = new OrganizationApi();
//Ci-dessous, l'argument API de getUserList et le type de retour fonctionnent avec Typescript.
const users = await api.getUserList({ orgId: "test" });
Le générateur openapi convertit automatiquement la définition de schéma Json en un type TypeScript, mais il y avait des endroits où je ne pouvais pas atteindre les démangeaisons subtiles dans les détails. Cela ne peut pas être aidé car il n'est pas complètement compatible en termes de spécifications, mais spécifiquement [dépendances](https://json-schema.org/understanding-json-schema/reference/object.html (#dependencies) n'est pas converti en un type correctement, ou enum ne peut pas être converti en un type d'union Typescript. Cette fois, je l'ai fait Open API au milieu du développement, donc si vous voulez l'intégrer depuis le début, il peut être préférable de le faire en ajustant le type du côté Json Schema afin que le type du côté Typescript se sente bien.
Il était un peu difficile d'incorporer un traitement commun (passer un jeton lors de la frappe d'une API, incorporer une gestion d'erreur commune, etc.) dans toutes les API. Il semble pratique d'utiliser le client API généré tel quel, mais j'ai senti qu'il n'y avait pas beaucoup d'interfaces pour l'étendre plus tard, donc j'attends avec impatience le développement futur.
Lors de l'ajout ou de la modification d'un schéma côté serveur, la vérification de type de Typescript montre dans une certaine mesure l'influence du front-end, donc je pense que ce point a conduit à une amélioration de la vitesse de développement. Vérifier la cohérence de l'implémentation côté serveur et côté frontal est une tâche courante et fastidieuse, c'est donc bien de pouvoir réduire cela.
Puisque Firestore lui-même est sans schéma, les modifications qui n'entrent pas en conflit avec les données existantes et les modifications qui n'affectent pas l'environnement de l'index peuvent être développées simplement en modifiant la définition du modèle, donc tout en bénéficiant de la vérification de type sans schéma de Firestore Je pense que c'est un bon mécanisme par lequel vous pouvez également bénéficier de la détection précoce des bogues. (Je ne pense pas que ce soit adapté au développement à grande échelle, mais dans ce cas, je n'ai pas envie d'utiliser Firestore en premier lieu.)
Je ne l'ai pas beaucoup utilisé cette fois, mais il sera possible d'utiliser l'écosystème maintenu par OpenAPI, donc s'il est bien incorporé, il semble qu'il y ait aussi les méthodes d'utilisation suivantes.
--Génération automatique de documents API --Validation des demandes et réponses --Génération de Mock / Stub pour les tests
Je développe personnellement un service appelé plateforme de développement d'applications Low-code Bizglue. Veuillez l'utiliser!
Recommended Posts