Dialecto NestJS
@pbuilder/sdk/nestjs edita los archivos .ts de un proyecto NestJS. Su handle tiene todas
las ops de @pbuilder/sdk/typescript más cuatro ops que importan una clase y la registran en
el decorador @Module del archivo. Todas las ops se encadenan sobre un handle y el archivo se
escribe una sola vez; ver Modify
para cómo funciona un handle.
import * as nestjs from "@pbuilder/sdk/nestjs";
export const run = async () => { await nestjs .find("src/app.module.ts") .addModuleImport("UsersModule", "./users/users.module") .addProvider("UsersService", "./users/users.service");};// antes@Module({ providers: [AppService] })export class AppModule {}
// despuésimport { UsersModule } from "./users/users.module";import { UsersService } from "./users/users.service";
@Module({ providers: [AppService, UsersService], imports: [UsersModule] })export class AppModule {}Ops heredadas de TypeScript
Sección titulada «Ops heredadas de TypeScript»El handle tiene todas las ops del dialecto TypeScript: addImport,
addDefaultImport, addNamespaceImport, addTypeImport, addSideEffectImport,
addReExport, addExportAll, addFunction, addVariable, addClass, addArrayElement,
addClassProperty, removeImport, removeExport y removeExportAll. Una op que el dialecto TypeScript
sume más adelante también queda disponible acá.
Ops de @Module
Sección titulada «Ops de @Module»Cada op recibe (name, from) y hace dos cosas:
- Agrega
import { name } from "from"con las mismas reglas que eladdImportde TypeScript. Un import existente denamedesdefromse reutiliza, y unnameque ya está ligado de otra forma en el archivo se rechaza. - Agrega
nameal final de un array de la metadata del@Moduledel archivo. Si@Module()no tiene argumento, o la metadata no tiene ese array, la op lo crea. Si el array ya tiene una entrada llamadaname, la op la deja como está.
| Op | Agrega a |
|---|---|
addProvider(name, from) |
providers |
addController(name, from) |
controllers |
addModuleImport(name, from) |
imports, los otros módulos de Nest que importa este módulo |
addExport(name, from) |
exports |
addModuleImport se llama así porque addImport ya es la op heredada de TypeScript, que
agrega una sentencia import.
Preservación del formato
Sección titulada «Preservación del formato»Una entrada nueva sigue el formato de la lista a la que se suma. Una lista de una línea queda
en una línea, una lista multilínea recibe una línea nueva con la indentación de su última
entrada, y una coma final se mantiene. Una coma dentro de un comentario después de la última
entrada ([A /* x, y */]) no se toma como coma final. Todo lo que está fuera del texto
insertado queda idéntico byte a byte.
Rechazos
Sección titulada «Rechazos»Una op se rechaza, y el archivo queda sin cambios, cuando:
- el archivo no tiene ninguna clase decorada con
@Module, o tiene más de una; - el argumento de
@Moduleno es un object literal (por ejemplo@Module(METADATA)); - la propiedad destino no es un array literal (por ejemplo
providers: PROVIDERS); nameno es un identificador válido, o ya está ligado de otra forma en el archivo.
Igual que el dialecto TypeScript, find(path) acepta cualquier ruta .ts. Un archivo sin
@Module solo falla cuando corre una de estas ops.
Entradas que no son un nombre de clase
Sección titulada «Entradas que no son un nombre de clase»Las ops de @Module reciben un nombre de clase. Para una entrada como ConfigModule.forRoot()
o { provide: TOKEN, useValue: 1 }, usa la op heredada
addArrayElement con una raíz
decorator, y agrega el import tú mismo:
await nestjs .find("src/app.module.ts") .addImport("ConfigModule", "@nestjs/config") .addArrayElement({ decorator: "Module", path: ["imports"] }, { expression: "ConfigModule.forRoot()" });// antes: @Module({ imports: [] })// después: @Module({ imports: [ConfigModule.forRoot()] })Ediciones a medida con .modify()
Sección titulada «Ediciones a medida con .modify()»Usa .modify(fn) para los archivos que las ops rechazan y para ediciones que ninguna op cubre.
El callback recibe el SourceFile vivo de ts-morph, y el export astLibrary del módulo es
ts-morph. Este ejemplo hace a mano la misma edición que la llamada a addArrayElement de arriba:
import * as nestjs from "@pbuilder/sdk/nestjs";
await nestjs .find("src/app.module.ts") .addImport("ConfigModule", "@nestjs/config") .modify((ast) => { const imports = ast .getClassOrThrow("AppModule") .getDecoratorOrThrow("Module") .getArguments()[0]! .asKindOrThrow(nestjs.astLibrary.SyntaxKind.ObjectLiteralExpression) .getPropertyOrThrow("imports") .asKindOrThrow(nestjs.astLibrary.SyntaxKind.PropertyAssignment) .getInitializerIfKindOrThrow(nestjs.astLibrary.SyntaxKind.ArrayLiteralExpression); imports.addElement("ConfigModule.forRoot()"); });Próximos pasos
Sección titulada «Próximos pasos»- Modify: los dialectos TypeScript y React y cómo funciona un handle.
- Librerías AST: qué librería y qué versión respalda cada dialecto.