Saltearse al contenido

Jack

3 posts by Jack

Migración desde AWS PDK

Esta guía te lleva paso a paso a través de un ejemplo de migración de un proyecto AWS PDK al Nx Plugin para AWS, además de proporcionar orientación general sobre este tema.

Migrar al Nx Plugin para AWS ofrece los siguientes beneficios frente a PDK:

  • Construcciones más rápidas
  • Más fácil de usar (UI y CLI)
  • Compatible con vibe-coding (¡prueba nuestro servidor MCP!)
  • Tecnologías más modernas
  • Desarrollo local de APIs y sitios web
  • Más control (modifica archivos provistos para adaptarlos a tu caso de uso)
  • ¡Y mucho más!

Ejemplo de Migración: Aplicación de Lista de Compras

Sección titulada «Ejemplo de Migración: Aplicación de Lista de Compras»

En esta guía, usaremos la Aplicación de Lista de Compras del Tutorial de PDK como nuestro proyecto objetivo para migrar. Sigue los pasos de ese tutorial para crear el proyecto objetivo si deseas replicar el proceso.

La aplicación de lista de compras consiste en los siguientes tipos de proyecto PDK:

  • MonorepoTsProject
  • TypeSafeApiProject
  • CloudscapeReactTsWebsiteProject
  • InfrastructureTsProject

Para comenzar, crearemos un nuevo espacio de trabajo para nuestro proyecto nuevo. Aunque más extremo que una migración in situ, este enfoque nos da el resultado final más limpio. Crear un espacio de trabajo Nx es equivalente a usar el MonorepoTsProject de PDK:

Terminal window
npx create-nx-workspace@21.4.1 shopping-list --pm=pnpm --preset=@aws/nx-plugin@0.50.0 --iacProvider=CDK --ci=skip

Abre el directorio shopping-list que crea este comando en tu IDE favorito.

El TypeSafeApiProject utilizado en la aplicación de lista de compras hizo uso de:

  • Smithy como lenguaje de modelado
  • TypeScript para implementar operaciones
  • Generación de hooks TypeScript para integración con un sitio web en React

Por lo tanto, podemos usar el generador ts#smithy-api para proporcionar funcionalidad equivalente.

Ejecuta el generador ts#smithy-api para configurar tu proyecto de API en packages/api:

  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - ts#smithy-api
  5. Complete los parámetros requeridos
    • name: api
    • namespace: com.aws
    • auth: IAM
  6. Haga clic en Generate

Notarás que esto genera un proyecto model, así como un proyecto backend. El proyecto model contiene tu modelo Smithy, y backend contiene la implementación del servidor.

El backend utiliza el Smithy Server Generator for TypeScript. Exploraremos esto más adelante.

Ahora que tenemos la estructura básica para nuestro proyecto de API Smithy, podemos migrar el modelo:

  1. Elimina los archivos Smithy de ejemplo generados en packages/api/model/src

  2. Copia tu modelo desde el directorio packages/api/model/src/main/smithy del proyecto PDK al directorio packages/api/model/src de tu nuevo proyecto.

  3. Actualiza el nombre del servicio y namespace en smithy-build.json para que coincidan con la aplicación PDK:

    smithy-build.json
    "plugins": {
    "openapi": {
    "service": "com.aws#MyApi",
    ...
  4. Actualiza el servicio en main.smithy para agregar el error ValidationException, requerido cuando se usa el Smithy TypeScript Server SDK.

    main.smithy
    use smithy.framework#ValidationException
    /// My Shopping List API
    @restJson1
    service MyApi {
    version: "1.0"
    operations: [
    GetShoppingLists
    PutShoppingList
    DeleteShoppingList
    ]
    errors: [
    BadRequestError
    NotAuthorizedError
    InternalFailureError
    ValidationException
    ]
    }
  5. Agrega un archivo extensions.smithy en packages/api/model/src donde definiremos un trait que proporciona información de paginación al cliente generado:

    extensions.smithy
    $version: "2"
    namespace com.aws
    use smithy.openapi#specificationExtension
    @trait
    @specificationExtension(as: "x-cursor")
    structure cursor {
    inputToken: String
    enabled: Boolean
    }
  6. Agrega el nuevo trait @cursor a la operación GetShoppingLists en get-shopping-lists.smithy:

    operations/get-shopping-lists.smithy
    @readonly
    @http(method: "GET", uri: "/shopping-list")
    @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize", items: "shoppingLists")
    @cursor(inputToken: "nextToken")
    @handler(language: "typescript")
    operation GetShoppingLists {
    input := with [PaginatedInputMixin] {
    @httpQuery("shoppingListId")
    shoppingListId: ShoppingListId
    }

    Cualquier operación @paginated también debe usar @cursor si estás usando el generador de clientes proporcionado por el Nx Plugin para AWS (a través del generador api-connection).

  7. Finalmente, elimina el trait @handler de todas las operaciones ya que no es compatible con el Nx Plugin para AWS. Al usar ts#smithy-api, no necesitamos las construcciones CDK de funciones lambda generadas automáticamente ni los objetivos de bundling generados por este trait, ya que usamos un único bundle para todas las funciones lambda.

En este punto, ejecutemos un build para verificar los cambios en el modelo y asegurarnos de tener código de servidor generado para trabajar. Habrá algunos errores en el proyecto backend (@shopping-list/api), pero los abordaremos a continuación.

Terminal window
pnpm nx run-many --target build

Puedes considerar el proyecto api/backend como algo equivalente al proyecto api/handlers/typescript de Type Safe API.

Una de las principales diferencias entre Type Safe API y el generador ts#smithy-api es que los manejadores se implementan usando el Smithy Server Generator for TypeScript, en lugar de los wrappers de manejadores generados por Type Safe API (encontrados en el proyecto api/generated/typescript/runtime).

Los manejadores lambda de la aplicación de lista de compras dependen del paquete @aws-sdk/client-dynamodb, así que instalémoslo primero:

Terminal window
pnpm add -w @aws-sdk/client-dynamodb

Luego, copiemos el archivo handlers/src/dynamo-client.ts del proyecto PDK a backend/src/operations para que esté disponible para nuestros manejadores.

Para migrar los manejadores, puedes seguir estos pasos generales:

  1. Copia el manejador desde el directorio packages/api/handlers/typescript/src de tu proyecto PDK al directorio packages/api/backend/src/operations de tu nuevo proyecto.

  2. Elimina las importaciones de my-api-typescript-runtime e importa el tipo de operación desde el SDK de servidor TypeScript generado, así como el ServiceContext:

    import {
    deleteShoppingListHandler,
    DeleteShoppingListChainedHandlerFunction,
    INTERCEPTORS,
    Response,
    LoggingInterceptor,
    } from 'myapi-typescript-runtime';
    import { DeleteShoppingList as DeleteShoppingListOperation } from '../generated/ssdk/index.js';
    import { ServiceContext } from '../context.js';
  3. Elimina la exportación del wrapper del manejador

    export const handler = deleteShoppingListHandler(
    ...INTERCEPTORS,
    deleteShoppingList,
    );
  4. Actualiza la firma de tu manejador de operación para usar el SSDK:

    export const deleteShoppingList: DeleteShoppingListChainedHandlerFunction = async (request) => {
    export const DeleteShoppingList: DeleteShoppingListOperation<ServiceContext> = async (input, ctx) => {
  5. Reemplaza el uso de LoggingInterceptor con ctx.logger. (También aplica para métricas y tracing interceptors):

    LoggingInterceptor.getLogger(request).info('...');
    ctx.logger.info('...');
  6. Actualiza referencias a parámetros de entrada. Como el SSDK provee tipos que coinciden exactamente con tu modelo Smithy (en lugar de agrupar parámetros path/query/header separados del body), actualiza cualquier referencia de entrada:

    const shoppingListId = request.input.requestParameters.shoppingListId;
    const shoppingListId = input.shoppingListId;
  7. Elimina el uso de Response. En su lugar, devolvemos objetos simples en el SSDK.

    return Response.success({ shoppingListId });
    return { shoppingListId };

    Tampoco lanzamos ni devolvemos Response, en su lugar lanzamos los errores generados por el SSDK:

    throw Response.badRequest({ message: 'oh no' });
    return Response.badRequest({ message: 'oh no' });
    import { BadRequestError } from '../generated/ssdk/index.js';
    throw new BadRequestError({ message: 'oh no' });
  8. Actualiza las importaciones para usar sintaxis ESM, agregando la extensión .js a las importaciones relativas.

  9. Agrega la operación a service.ts

    service.ts
    import { ServiceContext } from './context.js';
    import { MyApiService } from './generated/ssdk/index.js';
    import { DeleteShoppingList } from './operations/delete-shopping-list.js';
    import { GetShoppingLists } from './operations/get-shopping-lists.js';
    import { PutShoppingList } from './operations/put-shopping-list.js';
    // Registra las operaciones en el servicio aquí
    export const Service: MyApiService<ServiceContext> = {
    PutShoppingList,
    GetShoppingLists,
    DeleteShoppingList,
    };
Haz clic aquí para ver ejemplos completos antes/después de las tres operaciones del tutorial

Generamos el proyecto Smithy API con el nombre api inicialmente para que se agregue a packages/api y sea consistente con el proyecto PDK. Como nuestra API Smithy ahora define service MyApi en lugar de service Api, necesitamos actualizar cualquier instancia de getApiServiceHandler con getMyApiServiceHandler.

Realiza este cambio en handler.ts:

packages/api/backend/src/handler.ts
import { getApiServiceHandler } from './generated/ssdk/index.js';
import { getMyApiServiceHandler } from './generated/ssdk/index.js';
process.env.POWERTOOLS_METRICS_NAMESPACE = 'Api';
process.env.POWERTOOLS_SERVICE_NAME = 'Api';
const tracer = new Tracer();
const logger = new Logger();
const metrics = new Metrics();
const serviceHandler = getApiServiceHandler(Service);
const serviceHandler = getMyApiServiceHandler(Service);

Y en local-server.ts:

packages/api/backend/src/local-server.ts
import { getApiServiceHandler } from './generated/ssdk/index.js';
import { getMyApiServiceHandler } from './generated/ssdk/index.js';
const PORT = 3001;
const tracer = new Tracer();
const logger = new Logger();
const metrics = new Metrics();
const serviceHandler = getApiServiceHandler(Service);
const serviceHandler = getMyApiServiceHandler(Service);

Además, actualiza packages/api/backend/project.json y modifica metadata.apiName a my-api:

packages/api/backend/project.json
"metadata": {
"generator": "ts#smithy-api",
"apiName": "api",
"apiName": "my-api",
"auth": "IAM",
"modelProject": "@shopping-list/api-model",
"ports": [3001]
},

Ahora podemos construir el proyecto para verificar que la migración ha funcionado hasta ahora:

Terminal window
pnpm nx run-many --target build

El CloudscapeReactTsWebsiteProject utilizado en la aplicación de lista de compras configuró un sitio web React con CloudScape y autenticación Cognito integrada.

Este tipo de proyecto utilizaba create-react-app, que ahora está obsoleto. Para migrar el sitio web en esta guía, usaremos el generador ts#react-website, que emplea tecnologías más modernas y soportadas, específicamente Vite.

Como parte de la migración, también cambiaremos del React Router configurado por PDK a TanStack Router, que añade mayor seguridad de tipos al enrutamiento del sitio web.

Ejecuta el generador ts#react-website para configurar tu proyecto de sitio web en packages/website:

  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - ts#react-website
  5. Complete los parámetros requeridos
    • name: website
  6. Haga clic en Generate

El generador de sitios web React anterior no incluye autenticación Cognito por defecto como CloudscapeReactTsWebsiteProject, en su lugar se añade explícitamente mediante el generador ts#react-website#auth.

  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - ts#react-website#auth
  5. Complete los parámetros requeridos
    • project: website
    • cognitoDomain: shopping-list
  6. Haga clic en Generate

Esto añade componentes React que gestionan las redirecciones necesarias para asegurar que los usuarios inicien sesión usando la interfaz alojada de Cognito. También añade un constructo CDK para desplegar los recursos de Cognito en packages/common/constructs, llamado UserIdentity.

En PDK podías pasar proyectos Projen configurados entre sí para activar la integración automática. Esto se usaba en la aplicación de lista de compras para configurar la integración del sitio web con la API.

Con el Plugin Nx para AWS, la integración de API se realiza mediante el generador api-connection. A continuación, usamos este generador para que nuestro sitio web pueda invocar nuestra API Smithy:

  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - api-connection
  5. Complete los parámetros requeridos
    • sourceProject: website
    • targetProject: api
  6. Haga clic en Generate

Esto genera los proveedores de cliente y objetivos de construcción necesarios para que tu sitio web llame a tu API mediante un cliente TypeScript generado.

El CloudscapeReactTsWebsiteProject incluía automáticamente una dependencia de @aws-northstar/ui que se usa en nuestra aplicación de lista de compras, así que la añadimos aquí:

Terminal window
pnpm add -w @aws-northstar/ui

La aplicación de lista de compras tiene un componente llamado CreateItem, y dos páginas, ShoppingList y ShoppingLists. Migraremos estos elementos al nuevo sitio web, haciendo ajustes por el uso de TanStack Router y el generador de código cliente TypeScript del Plugin Nx para AWS.

  1. Copia packages/website/src/components/CreateItem/index.tsx del proyecto PDK a la misma ubicación en el nuevo proyecto.

  2. Copia packages/website/src/pages/ShoppingLists/index.tsx a packages/website/src/routes/index.tsx, ya que ShoppingLists es nuestra página principal y usamos enrutamiento basado en archivos con TanStack Router.

  3. Copia packages/website/src/pages/ShoppingList/index.tsx a packages/website/src/routes/$shoppingListId.tsx, ya que ShoppingList es la página que queremos mostrar en la ruta /:shoppingListId.

Notarás algunos errores de compilación en tu IDE, necesitaremos hacer algunos cambios más para adaptarnos al nuevo framework, como se detalla a continuación.

Al usar enrutamiento basado en archivos, podemos usar el servidor de desarrollo local para generar automáticamente la configuración de rutas. Iniciemos el servidor local:

Terminal window
pnpm nx serve-local website

Verás algunos errores, pero el servidor local debería iniciarse en el puerto 4200, junto con el servidor Smithy local en el puerto 3001.

Sigue estos pasos en ambos archivos routes/index.tsx y routes/$shoppingListId.tsx para migrar a TanStack Router:

  1. Añade createFileRoute para registrar cada ruta:

    import { createFileRoute } from "@tanstack/react-router";
    ...
    export default ShoppingLists;
    export const Route = createFileRoute('/')({
    component: ShoppingLists,
    });

    Al guardar, los errores de tipos con createFileRoute desaparecerán.

  2. Reemplaza el hook useNavigate.

    Actualiza la importación:

    import { useNavigate } from 'react-router-dom';
    import { useNavigate } from '@tanstack/react-router';

    Actualiza las llamadas al método navigate para usar rutas tipadas:

    navigate(`/${cell.shoppingListId}`);
    navigate({
    to: '/$shoppingListId',
    params: { shoppingListId: cell.shoppingListId },
    });
  3. Reemplaza el hook useParams.

    Elimina la importación:

    import { useParams } from 'react-router-dom';

    Actualiza las llamadas a useParams con el hook provisto por la Route. ¡Ahora son tipados!

    const { shoppingListId } = useParams();
    const { shoppingListId } = Route.useParams();

Como nuestras rutas están en otra ubicación, necesitamos ajustar la importación de CreateItem en ambos archivos:

import CreateItem from "../../components/CreateItem";
import CreateItem from "../components/CreateItem";

El AppLayoutContext también tiene una ubicación diferente:

import { AppLayoutContext } from "../../layouts/App";
import { AppLayoutContext } from "../components/AppLayout";

Casi listos. Ahora migraremos al cliente TypeScript generado por el Plugin Nx para AWS:

  1. Importa el nuevo cliente generado:

    import {
    ShoppingList,
    usePutShoppingList,
    useDeleteShoppingList,
    useGetShoppingLists,
    } from "myapi-typescript-react-query-hooks";
    import { ShoppingList } from "../generated/my-api/types.gen";
    import { useMyApi } from "../hooks/useMyApi";
    import { useInfiniteQuery, useMutation } from "@tanstack/react-query";

    En routes/$shoppingListId.tsx, importa ShoppingList como _ShoppingList desde types.gen.

  2. Instancia los nuevos hooks de TanStack Query:

    const getShoppingLists = useGetShoppingLists({ pageSize: PAGE_SIZE });
    const putShoppingList = usePutShoppingList();
    const deleteShoppingList = useDeleteShoppingList();
    const api = useMyApi();
    const getShoppingLists = useInfiniteQuery(
    api.getShoppingLists.infiniteQueryOptions(
    { pageSize: PAGE_SIZE },
    { getNextPageParam: (res) => res.nextToken },
    ),
    );
    const putShoppingList = useMutation(api.putShoppingList.mutationOptions());
    const deleteShoppingList = useMutation(
    api.deleteShoppingList.mutationOptions(),
    );
  3. Elimina el wrapper <operation>RequestContent en llamadas a operaciones:

    await putShoppingList.mutateAsync({
    putShoppingListRequestContent: {
    name: item,
    },
    });

Quedan algunos errores por diferencias entre v4 y v5:

  1. Reemplaza isLoading por isPending en mutaciones:

    putShoppingList.isLoading
    putShoppingList.isPending
  2. Suprime el error de tipo en InfiniteQueryTable:

    <InfiniteQueryTable
    query={getShoppingLists}
    query={getShoppingLists as any}

Ahora puedes acceder al sitio en http://localhost:4200/

¡El sitio debería cargarse correctamente! Si tienes una tabla DynamoDB llamada shopping_list en la región y credenciales AWS locales con acceso, funcionará completamente. Si no, migraremos la infraestructura después.

Haz clic para ver ejemplos completos antes/después de las páginas

El último proyecto que necesitamos migrar para nuestra aplicación de lista de compras es el InfrastructureTsProject. Este es un proyecto CDK en TypeScript, para el cual el equivalente en el Nx Plugin para AWS es el generador ts#infra.

Al igual que los proyectos Projen, PDK también proporcionaba constructs CDK de los que dependen estos proyectos. También migraremos la aplicación de lista de compras desde estos constructs CDK, en favor de los generados por el Nx Plugin para AWS.

Generar un proyecto de infraestructura TypeScript CDK

Sección titulada «Generar un proyecto de infraestructura TypeScript CDK»

Ejecuta el generador ts#infra para configurar tu proyecto de infraestructura en packages/infra:

  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - ts#infra
  5. Complete los parámetros requeridos
    • name: infra
  6. Haga clic en Generate

La aplicación de lista de compras PDK instanciaba los siguientes constructs dentro de la pila de aplicación CDK:

  • DatabaseConstruct para la tabla DynamoDB que almacena las listas de compras
  • UserIdentity para recursos de Cognito, importado directamente desde PDK
  • MyApi para desplegar la API Smithy, que usaba el constructo CDK TypeScript generado con integraciones type-safe, dependiendo internamente del constructo CDK TypeSafeRestApi de PDK.
  • Website para desplegar el sitio web, envolviendo el constructo CDK StaticWebsite de PDK.

A continuación, migraremos cada uno de estos al nuevo proyecto.

Copia packages/infra/src/stacks/application-stack.ts de la aplicación PDK de lista de compras a la misma ubicación exacta en tu nuevo proyecto. Verás algunos errores de TypeScript que abordaremos más adelante.

La aplicación PDK de lista de compras tenía un constructo Database en packages/src/constructs/database.ts. Cópialo a la misma ubicación exacta en tu nuevo proyecto.

Dado que el Nx Plugin para AWS usa Checkov para pruebas de seguridad, que es un poco más estricto que PDK Nag, también necesitamos agregar algunas supresiones:

constructs/database.ts
import { suppressRules } from ':shopping-list/common-constructs';
...
suppressRules(
this.shoppingListTable,
['CKV_AWS_28', 'CKV_AWS_119'],
'Backup and KMS key not required for this project',
);

En application-stack.ts, actualiza la importación para DatabaseConstruct para usar sintaxis ESM:

stacks/application-stack.ts
import { DatabaseConstruct } from '../constructs/database';
import { DatabaseConstruct } from '../constructs/database.js';

El constructo UserIdentity generalmente puede intercambiarse sin cambios ajustando las importaciones.

import { UserIdentity } from "@aws/pdk/identity";
import { UserIdentity } from ':shopping-list/common-constructs';
...
const userIdentity = new UserIdentity(this, `${id}UserIdentity`);

Nota que los constructs subyacentes usados por el nuevo UserIdentity se obtienen directamente de aws-cdk-lib, mientras que PDK usaba @aws-cdk/aws-cognito-identitypool-alpha.

La aplicación PDK de lista de compras tenía un constructo en constructs/apis/myapi.ts que instanciaba un constructo CDK generado por Type Safe API desde tu modelo Smithy.

Además de este constructo, como el proyecto PDK usaba el trait @handler, también se generaban constructs CDK de funciones lambda.

Al igual que Type Safe API, el Nx Plugin para AWS proporciona type-safety para integraciones basadas en tu modelo Smithy, pero se logra de una manera mucho más simple y flexible. En lugar de generar un constructo CDK completo en tiempo de compilación, solo se generan “metadatos” mínimos, que el archivo packages/common/constructs/src/app/apis/api.ts usa de manera genérica. Puedes aprender más sobre cómo usar el constructo en la guía del generador ts#smithy-api.

Sigue estos pasos:

  1. Instanciar el constructo Api en application-stack.ts

    stacks/application-stack.ts
    import { MyApi } from "../constructs/apis/myapi";
    import { Api } from ':shopping-list/common-constructs';
    ...
    const myapi = new MyApi(this, "MyApi", {
    databaseConstruct,
    userIdentity,
    });
    const api = new Api(this, 'MyApi', {
    integrations: Api.defaultIntegrations(this).build(),
    });

    Nota que usamos Api.defaultIntegrations(this).build() - el comportamiento por defecto es crear una función lambda para cada operación en nuestra API, igual que teníamos en myapi.ts.

  2. Otorgar permisos para que las funciones lambda accedan a la tabla DynamoDB.

    En la aplicación PDK, DatabaseConstruct se pasaba a MyApi, y este manejaba los permisos relevantes para cada función generada. Haremos esto directamente en application-stack.ts accediendo a la propiedad type-safe integrations del constructo Api:

    stacks/application-stack.ts
    // Otorgar acceso limitado a Dynamo para nuestras funciones lambda
    databaseConstruct.shoppingListTable.grantReadData(
    api.integrations.getShoppingLists.handler,
    );
    [
    api.integrations.putShoppingList.handler,
    api.integrations.deleteShoppingList.handler,
    ].forEach((f) => databaseConstruct.shoppingListTable.grantWriteData(f));
  3. Otorgar permisos para que usuarios autenticados invoquen la API.

    Dentro de myapi.ts de la aplicación PDK, los usuarios autenticados también tenían permisos IAM para invocar la API. Haremos el equivalente en application-stack.ts:

    stacks/application-stack.ts
    api.grantInvokeAccess(userIdentity.identityPool.authenticatedRole);

Finalmente, agregamos el constructo Website desde packages/common/constructs/src/app/static-websites/website.ts a application-stack.ts, ya que es el equivalente al packages/infra/src/constructs/websites/website.ts de la aplicación PDK.

import { Website } from "../constructs/websites/website";
import { Website } from ':shopping-list/common-constructs';
...
new Website(this, "Website", {
userIdentity,
myapi,
});
new Website(this, 'Website');

Nota que no pasamos la identidad ni la API al sitio web - la configuración en tiempo de ejecución se maneja dentro de cada constructo proporcionado por el Nx Plugin para AWS, donde UserIdentity y Api registran los valores necesarios, y Website maneja su despliegue en /runtime-config.json en tu sitio web estático.

Compilemos el proyecto ahora que hemos migrado todas las partes relevantes del código base a nuestro nuevo proyecto.

Terminal window
pnpm nx run-many --target build

Ahora que tenemos nuestra base de código completamente migrada, podemos considerar su despliegue. Existen dos caminos que podemos tomar en este punto.

El enfoque más simple es tratar esto como una aplicación completamente nueva, lo que significa que “comenzaremos de nuevo” con una tabla DynamoDB fresca y un Grupo de Usuarios de Cognito nuevo - perdiendo todos los usuarios y sus listas de compras. Para este enfoque, simplemente:

  1. Elimina la tabla DynamoDB llamada shopping_list

  2. Despliega la nueva aplicación:

    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*

🎉 ¡Y hemos terminado! 🎉

Migrar Recursos con Estado Existentes sin Tiempo de Inactividad (Más Complejo)

Sección titulada «Migrar Recursos con Estado Existentes sin Tiempo de Inactividad (Más Complejo)»

En la realidad, es más probable que quieras migrar los recursos existentes de AWS para que sean gestionados por la nueva base de código, evitando cualquier tiempo de inactividad para tus clientes.

Para nuestra aplicación de lista de compras, los recursos con estado que nos importan son la tabla DynamoDB que contiene las listas de compras de nuestros usuarios, y el Grupo de Usuarios que contiene los detalles de todos nuestros usuarios registrados. Nuestro plan de alto nivel será retener estos dos recursos clave y moverlos para que sean gestionados por nuestro nuevo stack, luego actualizar el DNS para apuntar a nuestro nuevo sitio web (y API si está expuesta a los clientes).

  1. Actualiza tu nueva aplicación para hacer referencia a los recursos existentes que deseas conservar.

    Para la aplicación de lista de compras, hacemos esto para la tabla DynamoDB

    constructs/database.ts
    this.shoppingListTable = new Table(this, 'ShoppingList', {
    ...
    this.shoppingListTable = Table.fromTableName(
    this,
    'ShoppingList',
    'shopping_list',
    );

    Y para el Grupo de Usuarios de Cognito

    packages/common/constructs/src/core/user-identity.ts
    this.userPool = this.createUserPool();
    this.userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );
  2. Construye y despliega la nueva aplicación:

    Terminal window
    pnpm nx run-many --target build
    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*

    Ahora tenemos nuestra nueva aplicación implementada haciendo referencia a los recursos existentes, sin recibir tráfico aún.

  3. Realiza pruebas de integración completas para asegurar que la nueva aplicación funciona como se espera. Para la aplicación de lista de compras, carga el sitio web y verifica que puedes iniciar sesión y crear, ver, editar y eliminar listas de compras.

  4. Revierte los cambios que referencian los recursos existentes en tu nueva aplicación, pero no los despliegues aún.

    constructs/database.ts
    this.shoppingListTable = new Table(this, 'ShoppingList', {
    ...
    this.shoppingListTable = Table.fromTableName(
    this,
    'ShoppingList',
    'shopping_list',
    );

    Y para el Grupo de Usuarios de Cognito

    packages/common/constructs/src/core/user-identity.ts
    this.userPool = this.createUserPool();
    this.userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );

    Y luego ejecuta una compilación

    Terminal window
    pnpm nx run-many --target build
  5. Usa cdk import en la carpeta packages/infra de tu nueva aplicación para ver qué recursos nos pedirá importar.

    New Application
    cd packages/infra
    pnpm exec cdk import shopping-list-infra-sandbox/Application --force

    Avanza por las indicaciones presionando enter. La importación fallará porque los recursos están gestionados por otro stack - esto es esperado, hicimos este paso solo para confirmar qué recursos necesitaremos retener. Verás una salida como esta:

    Ventana de terminal
    shopping-list-infra-sandbox/Application/ApplicationUserIdentity/UserPool/smsRole/Resource (AWS::IAM::Role): ingresa RoleName (vacío para omitir)
    shopping-list-infra-sandbox/Application/ApplicationUserIdentity/UserPool/Resource (AWS::Cognito::UserPool): ingresa UserPoolId (vacío para omitir)
    shopping-list-infra-sandbox/Application/Database/ShoppingList/Resource (AWS::DynamoDB::Table): importar con TableName=shopping_list (y/n) y

    Esto nos dice que en realidad hay 3 recursos que necesitaremos importar a nuestro nuevo stack.

  6. Actualiza tu proyecto PDK antiguo para establecer RemovalPolicy en RETAIN para los recursos descubiertos en el paso anterior. Al momento de escribir esto, es el valor predeterminado tanto para el Grupo de Usuarios como para la tabla DynamoDB, pero necesitamos actualizarlo para el Rol SMS que descubrimos arriba:

    application-stack.ts
    const userIdentity = new UserIdentity(this, `${id}UserIdentity`, {
    userPool,
    });
    const smsRole = userIdentity.userPool.node.findAll().filter(
    c => CfnResource.isCfnResource(c) &&
    c.node.path.includes('/smsRole/'))[0] as CfnResource;
    smsRole.applyRemovalPolicy(RemovalPolicy.RETAIN);
  7. Despliega tu proyecto PDK para que las políticas de eliminación se apliquen

    PDK Application
    cd packages/infra
    npx projen deploy
  8. Revisa la consola de CloudFormation y registra los valores que te solicitaron en el paso anterior de cdk import

    1. El ID del Grupo de Usuarios, ej. us-west-2_XXXXX
    2. El Nombre del Rol SMS, ej. infra-sandbox-UserIdentityUserPoolsmsRoleXXXXXX
  9. Actualiza tu proyecto PDK para hacer referencia a los recursos existentes en lugar de crearlos

    constructs/database.ts
    this.shoppingListTable = new Table(this, 'ShoppingList', {
    ...
    this.shoppingListTable = Table.fromTableName(
    this,
    'ShoppingList',
    'shopping_list',
    );

    Y para el Grupo de Usuarios de Cognito

    application-stack.ts
    const userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );
    const userIdentity = new UserIdentity(this, `${id}UserIdentity`, {
    // El constructo PDK acepta UserPool no IUserPool, ¡pero esto aún funciona!
    userPool: userPool as any,
    });
  10. Despliega tu proyecto PDK nuevamente, esto significará que los recursos ya no son gestionados por el stack de CloudFormación de tu proyecto PDK.

    PDK Application
    cd packages/infra
    npx projen deploy
  11. Ahora que los recursos no están gestionados, podemos ejecutar cdk import en nuestra nueva aplicación para realizar la importación realmente:

    New Application
    cd packages/infra
    pnpm exec cdk import shopping-list-infra-sandbox/Application --force

    Ingresa los valores cuando se soliciten, la importación debería completarse exitosamente.

  12. Despliega la nueva aplicación nuevamente para asegurar que cualquier cambio en estos recursos existentes (ahora gestionados por tu nuevo stack) se realice:

    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*
  13. Realiza una prueba completa de tu nueva aplicación nuevamente

  14. Actualiza los registros DNS para apuntar a tu nuevo Sitio web (y API si es requerido).

    Recomendamos un enfoque gradual usando Enrutamiento Ponderado de Route53, donde una fracción de las solicitudes se dirigen a la nueva aplicación inicialmente. Mientras monitoreas tus métricas, puedes incrementar el peso para la nueva aplicación hasta que no se envíe tráfico a tu antigua aplicación PDK.

    Si no tienes DNS y usaste los dominios auto-generados para el sitio web y API, siempre puedes considerar proxy de solicitudes (ej. vía un origen HTTP de CloudFront o integración(es) HTTP de API Gateway).

  15. Monitorea las métricas de la aplicación PDK para asegurar que no hay tráfico, y finalmente destruye el stack de CloudFormation antiguo:

    Ventana de terminal
    cd packages/infra
    npx projen destroy

¡Esto fue bastante más involucrado, pero migramos exitosamente a nuestros usuarios sin problemas a la nueva aplicación! 🎉🎉🎉

Ahora tenemos los nuevos beneficios del Plugin Nx para AWS sobre PDK:

  • Compilaciones más rápidas
  • Soporte para desarrollo local de API
  • Una base de código amigable para el coding de ambiente (¡prueba nuestro servidor MCP!)
  • Código cliente/servidor con tipos más intuitivo
  • ¡Y más!

Esta sección proporciona orientación para características de PDK que no están cubiertas por el ejemplo de migración anterior.

Como regla general al migrar desde PDK, recomendamos comenzar cualquier proyecto con un Espacio de Trabajo Nx, dada su similitud con el Monorepo de PDK. También recomendamos usar nuestros generadores como primitivas para construir nuevos tipos.

Terminal window
npx create-nx-workspace@21.4.1 my-project --pm=pnpm --preset=@aws/nx-plugin --ci=skip

CDK Graph construye gráficos de tus recursos CDK conectados y ofrece dos plugins:

El CDK Graph Diagram Plugin genera diagramas de arquitectura de AWS a partir de tu infraestructura CDK.

Para un enfoque determinista similar, una alternativa viable es CDK-Dia.

Con los avances en IA Generativa, muchos modelos fundacionales pueden crear diagramas de alta calidad a partir de tu infraestructura CDK. Recomendamos probar el AWS Diagram MCP Server. Consulta esta entrada de blog para ver un tutorial paso a paso.

El CDK Graph Threat Composer Plugin genera un modelo de amenazas inicial para Threat Composer a partir de tu código CDK.

Este plugin funcionaba simplemente filtrando un modelo de amenazas base que contenía ejemplos de amenazas, y filtrándolas según los recursos utilizados por tu stack.

Si te interesan estos ejemplos específicos de amenazas, puedes copiar y filtrar el modelo base, o usarlo como contexto para que un modelo fundacional genere uno similar.

AWS Arch proporciona mapeos entre recursos de CloudFormation y sus iconos de arquitectura asociados para CDK Graph.

Consulta la página de iconos de arquitectura de AWS para recursos relacionados con iconos. Diagrams también ofrece una forma de construir diagramas como código.

Si estabas usando esto directamente, ¡considera hacer un fork del proyecto y tomar posesión del mismo!

El PDK proporcionaba un PDKPipelineProject que configuraba un proyecto de infraestructura CDK y utilizaba un constructo CDK que encapsulaba algunos recursos de CDK Pipelines.

Para migrar desde esto, puedes usar directamente los constructos de CDK Pipelines. Sin embargo, en la práctica suele ser más sencillo usar soluciones como GitHub Actions o GitLab CI/CD, donde defines CDK Stages y ejecutas el comando de despliegue para la etapa correspondiente directamente.

PDK Nag envuelve CDK Nag y proporciona un conjunto de reglas específicas para la creación de prototipos.

Para migrar desde PDK Nag, utiliza CDK Nag directamente. Si necesitas el mismo conjunto de reglas, puedes crear tu propio “pack” siguiendo la documentación aquí.

Los componentes más utilizados de Type Safe API están cubiertos en el ejemplo de migración anterior, sin embargo, hay otras características cuyos detalles de migración se describen a continuación.

El Plugin de Nx para AWS admite APIs modeladas en Smithy, pero no aquellas modeladas directamente en OpenAPI. El generador ts#smithy-api es un buen punto de partida que luego puedes modificar. Puedes definir tu especificación OpenAPI en la carpeta src del proyecto model en lugar de Smithy, y modificar el build.Dockerfile para usar tu herramienta de generación de código preferida para clientes/servidores si no están disponibles en NPM. Si tus herramientas deseadas están en NPM, puedes instalarlas como dependencias de desarrollo en tu espacio de trabajo Nx y llamarlas directamente como objetivos de compilación de Nx.

Para backends type-safe modelados en OpenAPI, puedes considerar usar uno de los Generadores de Servidor de OpenAPI Generator. Estos no generan directamente para AWS Lambda, pero puedes usar el AWS Lambda Web Adapter como puente para muchos de ellos.

Para clientes TypeScript, puedes usar el generador ts#react-website y el generador api-connection con un ejemplo de ts#smithy-api para ver cómo se generan e integran los clientes con un sitio web. Esto configura objetivos de compilación que generan clientes invocando nuestros generadores open-api#ts-client o open-api#ts-hooks. Puedes usar estos generadores tú mismo apuntándolos a tu Especificación OpenAPI.

Para otros lenguajes, también puedes ver si alguno de los generadores de OpenAPI Generator se ajusta a tus necesidades.

También puedes construir un generador personalizado usando el generador ts#nx-generator. Consulta la documentación de ese generador para detalles sobre cómo generar código desde OpenAPI. Puedes usar las plantillas del Plugin de Nx para AWS como punto de partida. Incluso puedes consultar las plantillas del código base de PDK para más inspiración, notando que la estructura de datos sobre la que operan las plantillas es un poco diferente a la del Plugin de Nx para AWS.

Para TypeSpec, aplica también la sección anterior sobre OpenAPI. Puedes comenzar generando un ts#smithy-api, instalar el compilador de TypeSpec y los paquetes de OpenAPI en tu espacio de trabajo Nx, y actualizar el objetivo compile del proyecto model para ejecutar tsp compile en su lugar, asegurando que genere una especificación OpenAPI en el directorio dist.

El enfoque recomendado sería usar el generador de servidor HTTP TypeSpec para JavaScript para generar tu código de servidor, ya que funciona directamente sobre tu modelo TypeSpec.

Puedes usar el AWS Lambda Web Adapter para ejecutar el servidor generado en AWS Lambda.

También puedes usar cualquiera de las opciones de OpenAPI mencionadas anteriormente.

TypeSpec tiene sus propios generadores de código para clientes en los tres lenguajes soportados por Type Safe API:

La sección anterior sobre OpenAPI también aplica ya que TypeSpec puede compilar a OpenAPI.

El ejemplo de migración anterior describe la migración para usar el generador ts#smithy-api. Esta sección cubre las opciones para backends y clientes en Python y Java.

El generador de código Smithy para Java. Este incluye un generador de servidor Java así como un adaptador para ejecutar el servidor Java generado en AWS Lambda.

Smithy no tiene un generador de servidor para Python, por lo que necesitarás usar OpenAPI. Consulta la sección anterior sobre APIs modeladas con OpenAPI para opciones potenciales.

El generador de código Smithy para Java. Este incluye un generador de cliente Java.

Para clientes Python, puedes revisar Smithy Python.

Para TypeScript, consulta Smithy TypeScript, o usa el mismo enfoque que hemos tomado en ts#smithy-api mediante OpenAPI (optamos por esto para tener consistencia entre APIs tRPC, FastAPI y Smithy mediante hooks de TanStack Query).

Type Safe API proporcionaba un tipo de proyecto Projen llamado SmithyShapeLibraryProject que configuraba un proyecto con modelos Smithy reutilizables por múltiples APIs basadas en Smithy.

La forma más directa de lograr esto es:

  1. Crea tu biblioteca de formas usando el generador smithy#project:

    1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
    2. Abra la consola Nx en VSCode
    3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
    4. Busque @aws/nx-plugin - smithy#project
    5. Complete los parámetros requeridos
      • Haga clic en Generate

      Especifica cualquier nombre para la opción serviceName, ya que eliminaremos la forma service.

    6. Reemplaza el modelo predeterminado en src con las formas que deseas definir

    7. Actualiza smithy-build.json para eliminar los plugins y cualquier dependencia Maven no utilizada

    8. Reemplaza build.Dockerfile con pasos de compilación mínimos:

      build.Dockerfile
      FROM public.ecr.aws/docker/library/node:24 AS builder
      # Output directory
      RUN mkdir /out
      # Install Smithy CLI
      # https://smithy.io/2.0/guides/smithy-cli/cli_installation.html
      WORKDIR /smithy
      ARG TARGETPLATFORM
      RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then ARCH="aarch64"; else ARCH="x86_64"; fi && \
      mkdir -p smithy-install/smithy && \
      curl -L https://github.com/smithy-lang/smithy/releases/download/1.61.0/smithy-cli-linux-$ARCH.zip -o smithy-install/smithy-cli-linux-$ARCH.zip && \
      unzip -qo smithy-install/smithy-cli-linux-$ARCH.zip -d smithy-install && \
      mv smithy-install/smithy-cli-linux-$ARCH/* smithy-install/smithy
      RUN smithy-install/smithy/install
      # Copy project files
      COPY smithy-build.json .
      COPY src src
      # Smithy build with Maven cache mount
      RUN --mount=type=cache,target=/root/.m2/repository,id=maven-cache \
      smithy build
      RUN cp -r build/* /out/
      # Export the /out directory
      FROM scratch AS export
      COPY --from=builder /out /

    En tus proyectos de modelo de servicio, realiza los siguientes cambios para consumir la biblioteca de formas:

    1. Actualiza el objetivo compile en project.json para agregar el contexto de compilación del workspace y una dependencia en el objetivo build de la biblioteca de formas

      project.json
      {
      "cache": true,
      "outputs": ["{workspaceRoot}/dist/{projectRoot}/build"],
      "executor": "nx:run-commands",
      "options": {
      "commands": [
      "rimraf dist/packages/api/model/build",
      "make-dir dist/packages/api/model/build",
      "docker build --build-context workspace=. -f packages/api/model/build.Dockerfile --target export --output type=local,dest=dist/packages/api/model/build packages/api/model"
      ],
      "parallel": false,
      "cwd": "{workspaceRoot}"
      },
      "dependsOn": ["@my-project/shapes:build"]
      }
    2. Actualiza el build.Dockerfile para copiar el directorio src de tu biblioteca de formas. Por ejemplo, asumiendo que la biblioteca está en packages/shapes:

      build.Dockerfile
      # Copy project files
      COPY smithy-build.json .
      COPY src src
      COPY --from=workspace packages/shapes/src shapes
    3. Actualiza smithy-build.json para agregar el directorio de formas a sus sources:

      smithy-build.json
      {
      "version": "1.0",
      "sources": ["src/", "shapes/"],
      "plugins": {
      ...
      }

    Type Safe API proporcionaba los siguientes interceptores predeterminados:

    • Interceptores de logging, tracing y métricas usando Powertools para AWS Lambda
    • Interceptor try-catch para manejar excepciones no capturadas
    • Interceptor CORS para devolver encabezados CORS

    El generador ts#smithy-api instrumenta logging, tracing y métricas con Powertools para AWS Lambda usando Middy. El comportamiento del interceptor try-catch está integrado en Smithy TypeScript SSDK, y los encabezados CORS se agregan en handler.ts.

    Para interceptores de logging, tracing y métricas en cualquier lenguaje, usa Powertools para AWS Lambda directamente.

    Para migrar interceptores personalizados, recomendamos usar las siguientes bibliotecas:

    Type Safe API proporcionaba generación de documentación usando Redocly CLI. Esto es muy fácil de agregar a un proyecto existente una vez migrado.

    1. Instala Redocly CLI

      Terminal window
      pnpm add -Dw @redocly/cli
    2. Agrega un objetivo de generación de documentación a tu proyecto model usando redocly build-docs, por ejemplo:

      model/project.json
      {
      ...
      "documentation": {
      "cache": true,
      "outputs": ["{workspaceRoot}/dist/{projectRoot}/documentation"],
      "executor": "nx:run-commands",
      "options": {
      "command": "redocly build-docs dist/packages/api/model/build/openapi/openapi.json --output=dist/packages/api/model/documentation/index.html",
      "cwd": "{workspaceRoot}"
      },
      "dependsOn": ["compile"]
      }
      }

    También puedes considerar los generadores de documentación de OpenAPI Generator.

    Type Safe API generaba simulaciones para ti dentro de su paquete de infraestructura generado.

    Puedes migrar a JSON Schema Faker que puede crear datos simulados basados en JSON Schemas. Esto puede funcionar directamente en una especificación OpenAPI, y tiene una CLI que podrías ejecutar como parte de la compilación de tu proyecto model.

    Puedes actualizar tu infraestructura CDK para leer el archivo JSON generado por JSON Schema Faker y devolver la MockIntegration apropiada de API Gateway para una integración, basada en el metadata.gen.ts generado (asumiendo que usaste el generador ts#smithy-api).

    Type Safe API admitía implementar APIs con una mezcla de diferentes lenguajes en el backend. Esto también se puede lograr proporcionando “overrides” a las integraciones al instanciar tu constructo de API en CDK:

    application-stack.ts
    const pythonLambdaHandler = new Function(this, 'PythonImplementation', {
    runtime: Runtime.PYTHON_3_12,
    ...
    });
    new MyApi(this, 'MyApi', {
    integrations: Api.defaultIntegrations(this)
    .withOverrides({
    echo: {
    integration: new LambdaIntegration(pythonLambdaHandler),
    handler: pythonLambdaHandler,
    },
    })
    .build(),
    });

    Necesitarás “stubear” tu servicio/router para que tu servicio se compile si usas ts#smithy-api y el SDK de servidor TypeScript, ej:

    service.ts
    export const Service: ApiService<ServiceContext> = {
    ...
    Echo: () => { throw new Error(`Not Implemented`); },
    };

    Type Safe API agregaba validación nativa de API Gateway para cuerpos de solicitud basada en tu especificación OpenAPI, ya que usaba el constructo SpecRestApi internamente.

    Con el generador ts#smithy-api, la validación la realiza el propio SDK del servidor. Esto es igual para la mayoría de generadores de servidores.

    Si deseas implementar validación nativa de API Gateway, podrías hacerlo modificando packages/common/constructs/src/core/api/rest-api.ts para leer el JSON schema relevante del cuerpo de solicitud de cada operación desde tu especificación OpenAPI.

    Desafortunadamente no hay una ruta de migración directa para las APIs WebSocket de Type Safe API usando API Gateway y Lambda con desarrollo de API basado en modelos. Sin embargo, esta sección del guía busca al menos ofrecer algunas ideas.

    Considera usar AsyncAPI para modelar tu API en lugar de OpenAPI o TypeSpec, ya que está diseñado para APIs asíncronas. La Plantilla NodeJS de AsyncAPI puede generar un backend WebSocket Node que podrías alojar en ECS, por ejemplo.

    También puedes considerar AppSync Events para infraestructura, y usar Powertools. Este blog post vale la pena leerlo.

    Otra opción es usar APIs GraphQL con WebSocket en AppSync, para lo cual tenemos un issue de GitHub que puedes +1. Consulta la guía para desarrolladores de AppSync para detalles y enlaces a proyectos de ejemplo.

    También puedes considerar crear tus propios generadores de código que interpreten las mismas extensiones de vendor que Type Safe API. Consulta la sección APIs modeladas con OpenAPI para detalles sobre cómo construir generadores de código personalizados basados en OpenAPI. Puedes encontrar las plantillas que Type Safe API usa para los manejadores Lambda de API Gateway WebSocket aquí, y el cliente aquí.

    También puedes considerar migrar al generador ts#trpc-api para usar tRPC. Al momento de escribir esto, aún no tenemos soporte para suscripciones/streaming, pero si necesitas esto, agrega un +1 a nuestro issue de GitHub.

    Smithy es agnóstico al protocolo, pero aún no tiene soporte para el protocolo WebSocket, consulta este issue de GitHub.

    El PDK admite infraestructura CDK escrita en Python y Java. Actualmente, esto no está soportado en el Plugin de Nx para AWS al momento de escribir este documento.

    La ruta recomendada sería migrar tu infraestructura CDK a TypeScript, o usar nuestros generadores y migrar el paquete de construcciones comunes a tu lenguaje deseado. Puedes usar IA Generativa para acelerar este tipo de migraciones, por ejemplo Amazon Q CLI. Un agente de IA puede iterar en la migración hasta que las plantillas sintetizadas de CloudFormation sean idénticas.

    Lo mismo aplica para la infraestructura generada por Type Safe API en Python o Java - puedes traducir el constructo genérico rest-api.ts del paquete de construcciones comunes, e implementar tu propio generador de metadatos simple para el lenguaje objetivo (consulta la sección APIs Modelled with OpenAPI).

    Puedes usar el generador py#project como base para proyectos Python donde agregar tu código CDK (y migrar tu archivo cdk.json, añadiendo targets relevantes). Para proyectos Java, puedes usar el plugin @nx/gradle de Nx, o @jnxplus/nx-maven para Maven.

    El PDK fue construido sobre Projen. Projen y los generadores de Nx tienen diferencias bastante fundamentales, lo que significa que, aunque técnicamente es posible combinarlos, probablemente sea un antipatrón. Projen gestiona los archivos del proyecto como código de tal manera que no se pueden modificar directamente, mientras que los generadores de Nx generan los archivos del proyecto una vez y luego el código se puede modificar libremente.

    Si deseas continuar usando Projen, puedes implementar tus tipos de proyectos Projen deseados por tu cuenta. Para seguir los patrones del Nx Plugin para AWS, puedes ejecutar nuestros generadores o examinar su código fuente en GitHub para ver cómo se construyen los tipos de proyectos que necesitas, e implementar las partes relevantes usando las primitivas de Projen.

    Presentando el Plugin de Nx para AWS MCP Server

    En un panorama en rápida evolución del desarrollo de software, los asistentes de IA se han convertido en colaboradores valiosos en nuestro viaje de codificación. Muchos desarrolladores han adoptado lo que cariñosamente llamamos “vibe-coding”: la danza colaborativa entre la creatividad humana y la asistencia de IA. Como cualquier práctica emergente, viene con beneficios emocionantes y desafíos notables. Esta publicación presenta el Nx Plugin para AWS MCP Server, que mejora la experiencia de desarrollo asistido por IA al trabajar con productos y servicios de AWS.

    El vibe-coding, la práctica de construir software colaborativamente con asistentes de IA, ha transformado cómo muchas organizaciones abordan el desarrollo de software. Describes lo que quieres construir, y tu asistente de IA ayuda a materializar tu visión, mediante la escritura de código y pruebas, ejecución de comandos de construcción, e iteración colaborativa para completar tareas tanto grandes como pequeñas.

    Este enfoque colaborativo ha acelerado significativamente los ciclos de desarrollo, ya que implementaciones complejas que antes tomaban horas en escribirse manualmente, ahora pueden completarse en minutos.

    A pesar de sus beneficios, el vibe-coding conlleva trampas que pueden interrumpir tu flujo y generar frustración. Las herramientas de IA pueden producir patrones inconsistentes en un proyecto, creando dolores de cabeza de mantenimiento a futuro. Sin orientación específica, la IA puede pasar por alto mejores prácticas específicas de AWS o consideraciones de seguridad que desarrolladores experimentados incorporarían naturalmente.

    Sin una estructura de proyecto clara, el código asistido por IA puede volverse desorganizado y difícil de mantener. La IA podría crear implementaciones personalizadas para problemas que ya tienen soluciones establecidas, reinventando la rueda innecesariamente.

    Estos desafíos pueden generar deuda técnica, vulnerabilidades de seguridad y frustración, especialmente al trabajar con diversos servicios interconectados de AWS, no solo dentro de los límites de un único framework.

    El Nx Plugin para AWS proporciona una base estructurada para construir aplicaciones AWS utilizando la herramienta de monorepo Nx. En lugar de comenzar desde una hoja en blanco, el plugin ofrece un framework consistente para la organización de proyectos.

    El plugin garantiza un scaffolding de proyecto consistente mediante generadores para tipos de proyectos comunes, manteniendo integridad estructural en tu base de código. Incorpora plantillas preconfiguradas que siguen las mejores prácticas de AWS, ayudando a los desarrolladores a evitar errores comunes y problemas de seguridad. La herramientería integrada proporciona comandos incorporados para construir, probar y desplegar aplicaciones AWS, optimizando el flujo de trabajo de desarrollo mediante servidores de desarrollo locales. Adicionalmente, aprovecha la potente gestión de dependencias de Nx para proyectos complejos, simplificando la administración de monorepos.

    Al proporcionar esta estructura, el Nx Plugin para AWS le da a los asistentes de IA un marco claro para operar. En lugar de inventar patrones desde cero, los asistentes de IA pueden seguir convenciones establecidas, resultando en una base de código más consistente y mantenible.

    El Model Context Protocol (MCP) es un estándar abierto que permite a los asistentes de IA interactuar con herramientas y recursos externos. El Nx Plugin para AWS MCP server amplía las capacidades de tu asistente de IA con conocimiento especializado sobre el Nx Plugin para AWS.

    El servidor MCP provee información contextual sobre mejores prácticas, estructuras de proyecto disponibles y patrones de implementación específicos para desarrollo en AWS. Permite que tus herramientas de IA creen espacios de trabajo y ejecuten generadores para scaffold de tipos de proyectos comunes. Esta conciencia contextual ayuda a la IA a hacer sugerencias más informadas que se alinean con patrones establecidos y evitan errores comunes.

    En lugar de producir código que podría no alinearse con mejores prácticas o referenciar características inexistentes, tu asistente de IA puede aprovechar el servidor MCP para sentar una base sólida de tu proyecto. El resultado es una experiencia de desarrollo más determinista y confiable, donde puedes comenzar con una base sólida para los componentes centrales de tu proyecto y usar la IA para completar la lógica de negocio.

    Si estás interesado en explorar el desarrollo AWS asistido por IA con más estructura y confiabilidad, prueba el Nx Plugin para AWS MCP Server. Puedes configurarlo en tu asistente de IA favorito (Amazon Q Developer, Cline, Claude Code, etc) con la siguiente configuración del servidor MCP:

    {
    "mcpServers": {
    "aws-nx-mcp": {
    "command": "npx",
    "args": ["-y", "-p", "@aws/nx-plugin", "aws-nx-mcp"]
    }
    }
    }

    Para instrucciones detalladas, consulta nuestra guía Building with AI.

    Bienvenido al @aws/nx-plugin

    ¡Y estamos en vivo! 🚀

    El Plugin Nx para AWS es un plugin de Nx que proporciona un conjunto de herramientas para simplificar el desarrollo e implementación de aplicaciones full-stack en AWS. Ofrece a los desarrolladores plantillas preconfiguradas tanto para aplicaciones como para código de Infraestructura como Código (IaC), reduciendo significativamente el tiempo de configuración inicial. El plugin maneja la complejidad de integración con servicios de AWS manteniendo flexibilidad para personalizaciones.

    Los usuarios simplemente seleccionan los componentes deseados de la lista de generadores disponibles, proporcionan las opciones de configuración y el @aws/nx-plugin genera el código inicial requerido. El kit incluye generadores para crear APIs, sitios web, infraestructura, e incluso funcionalidades más avanzadas como integrar frontend con backend (¡incluyendo actualización de archivos existentes mediante transformaciones AST!) con clientes type-safe.

    generator

    Para aprender más, comienza con nuestro tutorial de Aventura en la Mazmorra, que cubre todos los componentes principales del plugin y te dará una buena idea de cómo usarlo.

    ¡Nos interesa tu feedback! No dudes en crear una discusión o reportar un issue para contarnos tu opinión y qué te gustaría ver próximamente.

    ¡Pruébalo!