Génération de code nest pour l'outil CLI de nestjs

Veloma 2021-09-15 05:03:25
ration code nest pour outil


Préface

En service NestJs + Mysql Développement du projet, Peut - être activerez - vous la façon dont les tables de données sont générées par la synchronisation des classes d'entités, C'est bien comme ça. , Et ça aussi.typeorm Ce à quoi je suis bon. , Mais il y a aussi le risque que les données soient effacées par erreur, Et alors? Quelques - uns d'entre nous voulaient faire un outil pour résoudre ce problème.

Objectifs

On se fiche de ce qu'on va développer. , Tout d'abord, Soyez clair, Qu'est - ce qu'on veut que ça fasse? , Quelles sont les caractéristiques?, Comment ces fonctions sont - elles mises en œuvre? ? Il est préférable d'avoir une bonne composition ou un organigramme à l'avance Nous résumons ici les points suivants: , Ce que nous voulons que cet outil nous aide à faire:

Structure de la table de données via la base de données

  • Inverser la classe d'entité correspondante
  • Inverser la génération du Contrôleur correspondant
  • Inverser la génération du niveau de service correspondant

Une idée générale.

  1. Je crois que Commenest-cli Ou vue-cli Ces bons cliC'est pareil, Vous pouvez générer une variété deDocumentation(entity、controller、services), Parce que c'est très pratique .
  2. Je veux obtenir la table de données spécifiée par l'utilisateur Structure, Et le transformer en une structure dont vous avez besoin.
  3. Entrée de l'utilisateur v type src L'outil sera basé sur Fiche techniquetype GénérerClasse d'entité、Controller、Niveau de service Et monter le dossier généré dans srcSous la table des matières.

C'est parti.

Commençons par examiner comment Le code fonctionne par commande

  1. Commençons par exécuter la commande suivante pour créer un projetnpm init -y && mkdir bin && touch ./bin/code-gen && mkdir src && touch ./src/index.ts
  2. On vapackage.json Ajouter un attribut bin, Sa valeur est un objet , Objetkey- Oui. "Directives" Nom, Objetvalue- Oui. " Fichier d'exécution de l'instruction " Comme ça. :

image.png

Voici deux questions. :

  1. J'en ai désigné plusieurs. key(v、code-gen、nest-code-generate), Soyons clairs. Ce ne sont que des alias. , Prends autant de noms que tu veux., L'auteur ne fait que tester .
  2. code-gen Il semble que ce soit un fichier sans suffixe , Ni l'un ni l'autre..jsPas du tout..ts, C'est vrai. Ce fichier n'a vraiment pas de suffixe
  1. On est là.bin/code-gen Il y a quelque chose dedans.

Si le petit ami devant l'ordinateur utilise vscodeEt si, Compilationcode-gen Il n'y a généralement pas d'indice de code , Nous allons le résoudre en suivant le diagramme ci - dessous.

image.png

#!/usr/bin/env node
console.log('code-gen');
Copier le Code

Regardons le code ci - dessus. :

  • Première ligne #!/usr/bin/env node L'interpréteur utilisé pour spécifier ce fichier script, Ce que nous désignons ici est node, Et nous avons simplement imprimé quelque chose .
  • Alors comment allons - nous exécuter ce programme? ? Exécuter sur la ligne de commande à ce moment v, Pouvons - nous voir l'impression sur la ligne de commande code-genEt alors??
  • Apparemment non. , Parce qu'il nous manque une dernière étape très importante, C'est l'exécution.npm linkCette commande.
  • Le but de cette commande est de créer un raccourci local, Vous permet de ne pas publier de paquets Vous pouvez expérimenter la fonctionnalité du paquet , Informations sur cette commande , Les gars, regardez ça. npmDocuments officiels, Ou en ligne. C'est encore très simple, Si vous exécutez cette commande Il y a eu conflit, On peut en ajouter un. --force Suffixe, Force la mise à jour .
  • C'est le moment d'exécuter sur la ligne de commande v Vous verrez la ligne de commande imprimer code-genLes nouvelles.

image.png

Comment recevoir les paramètres entrés par l'utilisateur sur la ligne de commande?

  1. Une grande partie de ce que nous allons utiliser ici cli Un sac qui sera utilisé , Il s'appellecommander, Mise en œuvrenpm i commander C'est très simple., Nous allons simplement parler des connaissances utilisées ici, Parce que j'ai découvert que le site Web n'était pas clair ( Je ne comprends pas. ).
  2. Regardons ce code:
  • Premier paragraphe: program.version().usage() C'est très simple., C'est quand on entre v -vQuand Imprimera le numéro de publication , usage()C'est l'exécutionv -h Conseils pour le temps .
  • Paragraphe 2: program.argument().argument().action() Ce code signifie Accepter deux paramètres L'un esttable-name L'un estdir Parmi euxdirEst optionnel, Derrière.action C'est le rappel. , Cette méthode accepte 2Paramètres, Ce sont les deux que nous acceptons. argument.
#!/usr/bin/env node
const program = require('commander');
program
.version(`nest-code-generate@${require("../package.json").version}`)
.usage(`<table_name2,table_name2...> [dir]`);
program
.argument('<table-name>', " Nom de la Feuille de données ")
.argument('[dir]', 'Chemin du dossier')
.action((tableName, dir) => {
console.log(tableName, dir);
});
program.parse(process.argv);
Copier le Code

Obtenir la structure de la Feuille de données

AdoptioncommanderNous pouvons facilement interagir avec les utilisateurs via la ligne de commande, Si l'utilisateur entre une telle commandev type src Qu'est - ce qu'on fait? ? La première chose que nous devons faire est de lire les utilisateurstypeTableau, Ici aussi, nous allons emprunter un outil de connexion à la base de données, Il s'appelleali-rds-async, Peut être exécuté parnpm i ali-rds-async Pour l'installer .

ali-rds-asyncMode d'emploi:

  • On commence parsrcCréer unclientDossiers, Et créer unindex.ts
  • Connexion à la base de données(Est - ce très simple)
    import AsyncAliRds from "ali-rds-async";
    export const db = new AsyncAliRds({
    host: 'localhost',
    port: 3306,
    user: 'root',
    password: 'password',
    database: 'nest-code-generate'
    });
    Copier le Code
  • Lire la structure du tableau : Ici, on peut passer par Exécuter unSQLPour réaliser, Mais ici, nous devons changer le fichier. Pour faciliter nos tests et notre codage .
  1. Nouveautsconfig.json;
  2. bin/code-gen: Ici.ParserDelib( Chemin d'emballage ) Introduit à l'intérieur

image.png

  1. src/index.ts: Voici le fichier d'entrée emballé , ExpositionParser

image.png

  1. package.json: Voici quelques ajouts script

image.png

  • Modification du fichier terminée , On commence. npm run serve Ou npm run build Packaging files to libSous le dossier, Et ensuite exécuter v type Directives Regarde ce qui va se passer? On atypeStructure du tableau.

image.png

Générer une classe d'entité

Lors de la génération d'une classe d'entité Il y a aussi une autre question Mode Q & a en ligne de commande Ici, nous allons d'abord implémenter cette fonctionnalité , Cette fonctionnalité permet aux utilisateurs d'implémenter vue-cliC'est pareil Créer un fichier en sélectionnant .

  • Avec des outilsinquirer Pour réaliser le mode Q & a en ligne de commande , L'outil est également relativement simple à utiliser , À l'arrière. Je vais te le dire.

  • Commençons par un morceau de code.

    import { prompt } from 'inquirer';
    import { findPath } from "./utils";
    export class Parser {
    tableName : string; // Nom de la Feuille de données
    dir : string; // Chemin de construction
    type !: string; // Générer une classe d'entité Toujours Niveau de contrôle Ou le niveau de service 
    targetPath !: string; // Chemin de construction
    constructor(tableName: string, dir: string) {
    this.tableName = tableName;
    this.dir = dir;
    this.prompt();
    }
    // Demander 
    async prompt() {
    const { type } = await prompt([
    {
    name: 'type',
    type: 'list',
    message: 'What content is generated( Ce qu'il faut générer )?: ',
    choices: [
    { name: 'Entity (Classe d'entité)', value: 'entity' },
    { name: 'Tier (Classe d'entité + Méthodes de contrôle et de niveau de service )', value: 'tier' },
    { name: 'CURD (Classe d'entité + Simple ajout, suppression et modification de la requête )', value: 'curd' },
    { name: 'All ( Générer tout : Classe d'entité + Méthodes de contrôle et de niveau de service + Simple ajout, suppression et modification de la requête )', value: 'all' }
    ]
    }
    ]);
    this.type = type;
    // Obtenir le chemin de construction 
    const targetPath = findPath(this.dir);
    this.targetPath = targetPath;
    this.parseOption();
    }
    }
    Copier le Code

    Regardons le Code. promptLa méthode a fait quelque chose:

    1. AppelezinquirerDepromptMéthodes, Lancer une requête en ligne de commande , Comme ça.;

    image.png Voyons ce qu'il faut transmettre à promptParamètres pour, Nous n'utilisons actuellement que le premier paramètre , C'est un tableau. , Chaque élément du tableau représente un problème , Nous n'avons transmis qu'une seule question ici. , Regardons ça. key Qu'est - ce que ça veut dire? .

    • name : Ce n'est qu'une minute que cette méthode vous renvoie le nom du champ;
    • type : Type de problème actuel , Ce qui est actuellement utilisé list Et input, L'un est une liste L'un est l'entrée .
    • message : C'est plus simple, C'est la question que tu poses. .
    • choices : Cette propriété est un tableau , SeulementtypePourlist C'est le seul attribut , Dans chaque élément du tableau name Est ce qui est affiché à l'utilisateur , Et l'autrevalue Après que l'utilisateur a sélectionné Valeur retournée à vous .

    Regardons les applications pratiques , Qu'avez - vous reçu? ? image.png

    1. Oui.typeGardez - le, Parce que c'est ce que l'utilisateur va générer;
    2. Obtenir le chemin de construction , Cette méthode n'a qu'une seule fonction , Est d'obtenir le chemin de construction final de l'utilisateur , Par défautsrc;
    3. AppelezparseOptionMéthodes;
  • parseOptionMéthodes Voyons ce que cette méthode a accompli:

    async parseOption() {
    const typeMap: { [k in Options]: () => any } = {
    'entity': () => this.generateEntity(),
    'tier': () => this.generateTier(),
    'curd': () => this.generateCURD(),
    'all': () => this.generateAll()
    };
    if (this.type && Reflect.has(typeMap, this.type)) {
    await typeMap[this.type]();
    } else {
    await typeMap.entity();
    }
    this.exit();
    }
    Copier le Code
    • Créer une politique map Adoptiontype Pour appeler la méthode correspondante , Si ce n'est pas le castypeOu typeNon.mapMoyenne, Appeler directement la méthode de construction de l'Instance ;
    • Appelezexit()Méthode de sortie.
  • generateEntityMéthodes

Nous regardons principalement ici generateEntityMéthodes, Parce que tout ce que nous avons à dire c'est comment générer Classe d'entité, Je ne sais pas comment le faire. Niveau de contrôleOuNiveau de service, Regarde le Code.:

// Générer des classes d'entités individuellement 
async generateEntity() {
// Obtenir tous les noms de table 
const tableNames: string[] = this.tableName.split(",");
await hasTableName(tableNames, async () => {
// Obtenir la structure du tableau(Source)
const structure = await getTableStructure(tableNames);
// Déterminer si l'Instance a une classe de base 
const { collect, base_name } = baseEntity();
// Convertir la structure source en structure souhaitée 
const columnStructure = transformStructure(structure, collect);
// Générer une classe d'entité 
generateEntity(columnStructure, this.targetPath, base_name);
});
}
Copier le Code
  1. Obtenir tous les noms de table , Parce que les noms des formulaires sont probablement multiples , Et divisé par des virgules , C'est pour ça qu'il faut l'avoir ici. tableNames;
  2. AppelezhasTableNameMéthodes, Déterminer si le nom de la table est passé , S'il n'y a pas de fin directe ;
  3. S'il y a un nom de table Effectuer un rappel;

Que fait la méthode de rappel? ?

  1. Mise en œuvregetTableStructureMéthodes, Obtenir la structure de toutes les tables de données ;
  2. AppelezbaseEntityMéthodes, Déterminer si l'Instance a une classe de base ;
  3. AppeleztransformStructureMéthodes, Convertir les données sources en structure souhaitée ;
  4. AppelezgenearteEntityMéthodes, Générer une classe d'entité ;

getTableStructureMéthodes

// Obtenir la structure du tableau
export const getTableStructure = async (tableNames: string[]): Promise<RowMap> => {
// @ts-ignore
const structure: Promise<RowMap> = tableNames.reduce(async (map: Promise<RowMap>, name: string) => {
const newMap = (await map);
try {
newMap[name] = await db.query(`SHOW FULL FIELDS FROM ${name}`);
} catch (error) {
throw error;
}
return map;
}, {});
return structure;
}
Copier le Code

C'est très simple. , C'est à travers le tableau reduce Méthode pour obtenir la structure de chaque table , Tout cela est vrai pour reducepromiseUtilisation de base, Je ne vais pas le répéter ici.; La structure obtenue est :

{
type: [
{
Field: 't_binary',
Type: 'binary(10)',
Collation: null,
Null: 'NO',
Key: '',
Default: null,
Extra: '',
Privileges: 'select,insert,update,references',
Comment: ''
},
{...}
],
// S'il y a plus d'un nom de table , Par exemple v type,sys_file, Il y en aura un autre en bas. 
sys_file: [
{...},
{...}
]
}
Copier le Code

baseEntityMéthodes

export const baseEntity = (): { base_name: string, collect: string[] } => {
let { base_name = '', collect = '' } = readYMLConfig('data_config') || {};
if (collect !== '' && collect != null) {
collect = collect.split(',').map((field: string) => field.trim()).filter((field: string) => field !== '');
}
return { base_name, collect: collect === '' ? [] : collect };
}
Copier le Code

Cette méthode est utilisée pour obtenir code-gen.ymlDans le profildata_configChamp, C'est très simple. , Plus de détails.;

transformStructureMéthodes(Plus de codes, Les enfants qui veulent voir le Code peuvent voir le code source )

Le but de cette approche est , Oui.getTableStructure La structure de données source obtenue par la méthode est convertie en @ColumnNécessaireoptionDonnées, Par exemple,:
Données sources

{
type: [
{
Field: 't_dec',
Type: 'decimal(20,8)',
Collation: null,
Null: 'NO',
Key: '',
Default: null,
Extra: '',
Privileges: 'select,insert,update,references',
Comment: ''
}
]
}
Copier le Code

Données converties

{
type: [
{
type: 'decimal',
length: undefined,
precision: 20,
scale: 8,
primaryGeneratedColumn: false,
enum: undefined,
name: 't_dec',
collation: undefined,
nullable: undefined,
default: undefined,
comment: undefined,
update: undefined,
jsType: 'number',
isIndex: false
}
]
}
Copier le Code

genearteEntityMéthodes(Plus de codes, Les enfants qui veulent voir le Code peuvent voir le code source )

La méthode est basée sur transformStructure Données générées par la méthode , Génération de fichiers ;

Conclusion

La mise en œuvre de l'outil lui - même est simple , Mais cela peut nous aider à alléger beaucoup de fardeau de développement, Résoudre de nombreux problèmes de développement . En fait, beaucoup de choses ont l'air magnifiques et complexes, Mais il n'a jamais été séparé de son père, Traitement des données C'est très important., J'espère que les jeunes feront des progrès ensemble. , Jour après jour!

Coordonnées

github: github.com/Veloma-Time…
npm: www.npmjs.com/package/nes…
Il y a des choses que je ne comprends pas. Vous pouvez également ajouter mon Wechat : __veloma__

版权声明
本文为[Veloma]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/09/20210914174203411y.html

  1. Vue bidirectional binding (V-model bidirectional binding,. Sync bidirectional binding,. Sync transfer object)
  2. Vue3.0 using Gaode map to obtain longitude and latitude information
  3. React realizes the function of copying pictures with one click
  4. White space, word break and word wrap are the three most basic and confusing attributes in CSS - thoroughly understand
  5. Trois ans d'expérience d'entrevue avec une femme de programmation diplômée, une réflexion sur la cohérence de l'expiration des données de redis Master slave Node,
  6. Résumé de l'entrevue Android de Dachang, carte technique Android
  7. Un plan de carrière Java correct, découvrez les questions que vous devez poser lors de l'entrevue d'embauche du printemps Java de cette année.
  8. Le résumé de l'entrevue Android de Dachang est en retard
  9. Un article vous a appris à gérer les entrevues sur le Web, à partager 350 vraies questions d'entrevue Java,
  10. Jquery Tools Methodology collation, Sharing a little interview Experience
  11. Jquery plug - in urianchor, app front end Development
  12. $in jquery, Visualized Web Development Tool
  13. Le développement Java doit être fait. Les entrevues https demandent souvent une analyse complète.
  14. vue v-if未生效问题
  15. vue动态改变组件外部元素样式
  16. Jdk's Past Life: The Classic Features of Thin Number - java5 - - - 15 -, webfront Development
  17. Résumé des questions d'entrevue pour les ingénieurs en développement Java, analyse des questions d'entrevue à haute fréquence Dubbo,
  18. The new front-end lady asked: there was a 404 problem refreshing the page in Vue routing history mode
  19. A Simple Css Meun
  20. Vue modifier dynamiquement le style de l'élément externe du composant
  21. Vue V - si problème non valable
  22. N'osez pas vous opposer à l'intervieweur et obtenir des commentaires personnels des stagiaires d'offer Ali après cinq rondes d'entrevue.
  23. Améliorer continuellement leur capacité à créer des primes, et les questions d'entrevue Java d'Alibaba Huawei Tencent et d'autres grandes usines sont sautées en octets.
  24. The new front-end lady asked: there was a 404 problem refreshing the page in Vue routing history mode
  25. Who doesn't want to make a scratch music by himself? Scratch music is realized by native JS
  26. Learn XPath to help climb the data of major e-commerce platforms in the Mid Autumn Festival
  27. vue動態改變組件外部元素樣式
  28. vue v-if未生效問題
  29. Je ne comprends pas comment la machine virtuelle JVM peut encore interviewer, et j'ai terminé ce dictionnaire d'entrevue Java de 1307 pages.
  30. Dongxh, mid autumn festival gifts 🥮, [CSS starry sky realization, Mid Autumn Festival poem]
  31. What if you want to see the moon and don't want to go out
  32. Mid Autumn Festival, Chang'e looks at the moon
  33. Mid Autumn Festival special! Use the simplest animation animation to make the most local and trendy holiday blessing greeting card. This romantic male and female tears of Xiao Chen.
  34. [Pixi] super beautiful! How to make mid autumn festival scene level animation!!
  35. Echarts realizes the rotation of the moon (super simple, you can see it at a glance)
  36. Dart mixin full resolution
  37. Some suggestions on Vue code readability | comments are rewarded
  38. 120 lines of code to achieve pure web video editing
  39. Yang yangsun took a selfie to celebrate his 30th birthday, and Wang Yanlin sent blessings.
  40. Comment passer une entrevue avec une entreprise Internet de première ligne, Android Classic Getting started tutoriel
  41. Comment essayer un développeur Android vraiment niveau, 【 résumé de l'entrevue 】
  42. Wang Ou went back to the hotel with the man at night. It was suspected that his relationship was open. The netizen replied mercilessly: is the man single
  43. 借助HTML ping属性实现数据上报
  44. APNG在线制作、兼容、播放和暂停
  45. Apng production, compatibilité, lecture et pause en ligne
  46. Mise en œuvre de l'escalade des données avec l'attribut de Ping HTML
  47. Comment envoyer 100 000 requêtes http le plus rapidement possible
  48. JQuery Basics
  49. Front and back end data interaction (V) -- what is Axios?
  50. Serverless is a model architecture invented driven by economic benefits- Grady
  51. Les questions d'entrevue pour les ingénieurs Java d'Internet, les intervieweurs rencontrés sont tous de niveau architecte,
  52. Cinq ans d'entrevue d'expérience en développement Java, découvrez les questions que vous devez poser lors de l'entrevue d'embauche du printemps Java de cette année.
  53. La dernière collection de questions d'entrevue Java haute fréquence organisée cette année, 2021 Java Universal Popular Framework
  54. Intel selected Weilai es8 to promote driverless taxis in Europe
  55. JavaScript operator (1), Web Development Engineer
  56. Trier les questions d'entrevue Javascript, trier les points de connaissance des itinéraires d'apprentissage
  57. Song Mengjun's "sleepless night" triggered an upsurge of dance storm after 00
  58. Module management of "free and open source" front-end spa project crudapi background management system based on Vue and Quasar (14)
  59. Encapsulated PHP sends HTTP requests with curl. Get and post are very easy to use
  60. Front and back end data interaction (V) -- what is Axios?