Salta ai contenuti

Migrazione da AWS PDK

Questa guida ti accompagna attraverso un esempio di migrazione di un progetto AWS PDK al Nx Plugin for AWS, fornendo anche indicazioni generali su questo argomento.

La migrazione al Nx Plugin for AWS offre i seguenti vantaggi rispetto a PDK:

  • Build più veloci
  • Più facile da usare (UI e CLI)
  • Adatto al vibe-coding (prova il nostro server MCP!)
  • Tecnologie più moderne
  • Sviluppo locale di API e siti web
  • Maggiore controllo (modifica i file forniti per adattarli al tuo caso d’uso)
  • E molto altro!

In questa guida, useremo la Shopping List Application dal Tutorial PDK come progetto target da migrare. Segui i passaggi in quel tutorial per creare il progetto target se desideri seguire tu stesso.

L’applicazione shopping list consiste nei seguenti tipi di progetto PDK:

  • MonorepoTsProject
  • TypeSafeApiProject
  • CloudscapeReactTsWebsiteProject
  • InfrastructureTsProject

Per iniziare, creeremo un nuovo workspace per il nostro nuovo progetto. Sebbene più estremo di una migrazione in loco, questo approccio ci dà il risultato finale più pulito. Creare un workspace Nx è equivalente a usare il MonorepoTsProject di PDK:

Terminal window
pnpm create @aws/nx-workspace@1.0.0-rc.47 shopping-list --iac=cdk

Apri la directory shopping-list che questo comando crea nel tuo IDE preferito.

Il TypeSafeApiProject utilizzato nell’applicazione della lista della spesa faceva uso di:

  • Smithy come linguaggio di modellazione
  • TypeScript per l’implementazione delle operazioni
  • Generazione di hook TypeScript per l’integrazione con un sito web React

Possiamo quindi utilizzare il generatore ts#smithy-api per fornire funzionalità equivalenti.

Esegui il generatore ts#api con framework impostato su smithy per configurare il tuo progetto API in packages/api:

Terminal window
pnpm nx g @aws/nx-plugin:ts#api --name=api --framework=smithy --namespace=com.aws --auth=iam --no-interactive
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:ts#api --name=api --framework=smithy --namespace=com.aws --auth=iam --no-interactive --dry-run

Noterai che questo genera un progetto model, così come un progetto backend. Il progetto model contiene il tuo modello Smithy, e backend contiene l’implementazione del server.

Il backend utilizza il Smithy Server Generator for TypeScript. Esploreremo questo aspetto più in dettaglio di seguito.

Ora che abbiamo la struttura di base per il nostro progetto API Smithy, possiamo migrare il modello:

  1. Elimina i file Smithy di esempio generati in packages/api/model/src

  2. Copia il tuo modello dalla directory packages/api/model/src/main/smithy del progetto PDK nella directory packages/api/model/src del tuo nuovo progetto.

  3. Aggiorna il nome del servizio e il namespace in smithy-build.json per corrispondere all’applicazione PDK:

    smithy-build.json
    "plugins": {
    "openapi": {
    "service": "com.aws#MyApi",
    ...
  4. Aggiorna il servizio in main.smithy per aggiungere l’errore ValidationException, che è richiesto quando si utilizza 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. Aggiungi un file extensions.smithy a packages/api/model/src dove definiremo un trait che fornisce informazioni di paginazione al client generato:

    extensions.smithy
    $version: "2"
    namespace com.aws
    use smithy.openapi#specificationExtension
    @trait
    @specificationExtension(as: "x-cursor")
    structure cursor {
    inputToken: String
    enabled: Boolean
    }
  6. Aggiungi il nuovo trait @cursor all’operazione GetShoppingLists in 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
    }

    Qualsiasi operazione @paginated dovrebbe utilizzare anche @cursor se stai usando il generatore di client fornito da Nx Plugin for AWS (tramite il generatore api-connection).

  7. Infine, rimuovi il trait @handler da tutte le operazioni poiché non è supportato da Nx Plugin for AWS. Utilizzando ts#smithy-api, non abbiamo bisogno dei costrutti CDK delle funzioni lambda auto-generate e dei target di bundling generati da questo trait, poiché utilizziamo un singolo bundle per tutte le funzioni lambda.

A questo punto, eseguiamo una build per verificare le modifiche al modello e assicurarci di avere del codice server generato con cui lavorare. Ci saranno alcuni errori nel progetto backend (@shopping-list/api) ma li risolveremo successivamente.

Terminal window
pnpm nx run-many --target build

Puoi considerare il progetto api/backend come in qualche modo equivalente al progetto api/handlers/typescript di Type Safe API.

Una delle principali differenze tra Type Safe API e il generatore ts#smithy-api è che gli handler sono implementati utilizzando il Smithy Server Generator for TypeScript, piuttosto che i wrapper di handler generati da Type Safe API (che si trovano nel progetto api/generated/typescript/runtime).

I lambda handler dell’applicazione della lista della spesa si basano sul pacchetto @aws-sdk/client-dynamodb, quindi installiamolo nel progetto @shopping-list/api:

Terminal window
pnpm add @aws-sdk/client-dynamodb --filter api

Quindi, copiamo il file handlers/src/dynamo-client.ts dal progetto PDK in backend/src/operations in modo che sia disponibile per i nostri handler.

Il generatore ts#smithy-api crea uno scaffold di un’operazione Echo di esempio. Poiché l’abbiamo rimossa dal nostro modello, elimina l’handler corrispondente in backend/src/operations/echo.ts. Registreremo le nostre operazioni migrate in service.ts più avanti.

Per migrare gli handler, puoi seguire questi passaggi generali:

  1. Copia l’handler dalla directory packages/api/handlers/typescript/src del tuo progetto PDK nella directory packages/api/backend/src/operations del tuo nuovo progetto.

  2. Rimuovi gli import di my-api-typescript-runtime e importa invece il tipo di operazione dal TypeScript Server SDK generato, così come il ServiceContext ad esempio:

    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 l’export del wrapper dell’handler

    export const handler = deleteShoppingListHandler(
    ...INTERCEPTORS,
    deleteShoppingList,
    );
  4. Aggiorna la firma per il tuo handler di operazione per utilizzare l’SSDK:

    export const deleteShoppingList: DeleteShoppingListChainedHandlerFunction = async (request) => {
    export const DeleteShoppingList: DeleteShoppingListOperation<ServiceContext> = async (input, ctx) => {
  5. Sostituisci l’uso di LoggingInterceptor con ctx.logger. (Si applica anche agli interceptor di metriche e tracing):

    LoggingInterceptor.getLogger(request).info('...');
    ctx.logger.info('...');
  6. Aggiorna i riferimenti ai parametri di input. Poiché l’SSDK fornisce tipi che corrispondono esattamente al tuo modello Smithy (piuttosto che raggruppare separatamente i parametri path/query/header dal parametro body), aggiorna di conseguenza tutti i riferimenti agli input:

    const shoppingListId = request.input.requestParameters.shoppingListId;
    const shoppingListId = input.shoppingListId;
  7. Rimuovi l’uso di Response. Invece restituiamo semplicemente oggetti semplici nell’SSDK.

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

    Inoltre non lanciamo più o restituiamo Response, invece lanciamo gli errori generati dall’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. Aggiorna tutti gli import per utilizzare la sintassi ESM, ovvero aggiungendo l’estensione .js agli import relativi.

  9. Aggiungi l’operazione 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';
    // Register operations to the service here
    export const Service: MyApiService<ServiceContext> = {
    PutShoppingList,
    GetShoppingLists,
    DeleteShoppingList,
    };
Clicca qui per esempi completi prima/dopo per le tre operazioni della lista della spesa dal tutorial

Abbiamo generato il progetto API Smithy con il nome api inizialmente perché volevamo che fosse aggiunto a packages/api per coerenza con il progetto PDK. Poiché la nostra API Smithy ora definisce service MyApi invece di service Api, dobbiamo aggiornare tutte le istanze di getApiServiceHandler con getMyApiServiceHandler.

Apporta questa modifica a 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);

E a 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);

Inoltre, aggiorna packages/api/backend/project.json e modifica metadata.apiName in 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]
},

Ora possiamo compilare il progetto per verificare che la migrazione abbia funzionato finora:

Terminal window
pnpm nx run-many --target build

Il CloudscapeReactTsWebsiteProject utilizzato nell’applicazione shopping list configurava un sito web React con CloudScape e autenticazione Cognito integrata.

Questo tipo di progetto sfruttava create-react-app, che ora è deprecato. Per migrare il sito web in questa guida, utilizzeremo il generatore ts#website, che utilizza tecnologie più moderne e supportate, in particolare Vite.

Come parte della migrazione, passeremo anche da React Router configurato in PDK a TanStack Router, che aggiunge ulteriore type-safety al routing del sito web.

Esegui il generatore ts#website con framework impostato su react per configurare il tuo progetto website in packages/website. Poiché l’applicazione shopping list è costruita con componenti CloudScape, impostiamo anche ux su cloudscape (il valore predefinito è shadcn):

Terminal window
pnpm nx g @aws/nx-plugin:ts#website --name=website --framework=react --ux=cloudscape --no-interactive
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:ts#website --name=website --framework=react --ux=cloudscape --no-interactive --dry-run

Il generatore React website sopra non include l’autenticazione cognito per impostazione predefinita come CloudscapeReactTsWebsiteProject, invece viene aggiunta esplicitamente tramite il generatore ts#website#auth.

Terminal window
pnpm nx g @aws/nx-plugin:ts#website#auth --project=website --cognitoDomain=shopping-list --no-interactive
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:ts#website#auth --project=website --cognitoDomain=shopping-list --no-interactive --dry-run

Questo aggiunge componenti React che gestiscono i reindirizzamenti appropriati per garantire che gli utenti effettuino il login utilizzando l’interfaccia utente ospitata di Cognito. Questo aggiunge anche un costrutto CDK per distribuire le risorse Cognito in packages/common/constructs, chiamato UserIdentity.

In PDK potevi passare i progetti Projen forniti l’uno all’altro per attivare la generazione del codice di integrazione. Questo veniva utilizzato nell’applicazione shopping list per configurare il sito web in modo che potesse integrarsi con l’API.

Con Nx Plugin for AWS, l’integrazione API è supportata tramite il generatore connection. Successivamente, utilizziamo questo generatore in modo che il nostro sito web possa invocare la nostra API Smithy:

Terminal window
pnpm nx g @aws/nx-plugin:connection --sourceProject=website --targetProject=api --no-interactive
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:connection --sourceProject=website --targetProject=api --no-interactive --dry-run

Questo genera i provider client necessari e i target di build per consentire al tuo sito web di chiamare la tua API tramite un client TypeScript generato.

Il CloudscapeReactTsWebsiteProject includeva automaticamente una dipendenza da @aws-northstar/ui che viene utilizzata nella nostra applicazione shopping list, quindi la aggiungiamo al progetto @shopping-list/website:

Terminal window
pnpm add @aws-northstar/ui --filter website

@aws-northstar/ui include un componente editor di codice che dipende da ace-builds, utilizzando un’importazione specifica per webpack che Vite non può risolvere. Poiché la nostra applicazione shopping list non utilizza questo componente, lo escludiamo dal bundle aggiungendolo alla configurazione external all’interno delle opzioni build esistenti in packages/website/vite.config.mts:

packages/website/vite.config.mts
build: {
outDir: '../../dist/packages/website/bundle',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
rollupOptions: {
external: ['ace-builds/webpack-resolver'],
},
},

L’applicazione shopping list ha un componente chiamato CreateItem e due pagine, ShoppingList e ShoppingLists. Migreremo questi al nuovo sito web, apportando alcune modifiche poiché stiamo utilizzando TanStack Router e il generatore di codice client TypeScript di Nx Plugin for AWS.

  1. Copia packages/website/src/components/CreateItem/index.tsx dal progetto PDK nella stessa identica posizione nel nuovo progetto.

  2. Copia packages/website/src/pages/ShoppingLists/index.tsx in packages/website/src/routes/index.tsx, poiché ShoppingLists è la nostra home page e utilizziamo il routing basato su file con TanStack router.

  3. Copia packages/website/src/pages/ShoppingList/index.tsx in packages/website/src/routes/$shoppingListId.tsx, poiché ShoppingList era la pagina che vogliamo mostrare sulla route /:shoppingListId.

Nota che ora avrai alcuni errori di build visibili nel tuo IDE, dovremo apportare alcune modifiche aggiuntive per adattarci al nuovo framework, descritte di seguito.

Poiché stiamo utilizzando il routing basato su file, possiamo utilizzare il server di sviluppo locale del sito web per gestire automaticamente la generazione della configurazione delle route.

Avviamo il server del sito web locale:

Terminal window
pnpm nx dev website

Vedrai alcuni errori, ma il server del sito web locale dovrebbe avviarsi sulla porta 4200, così come il server API Smithy locale sulla porta 3001.

Segui i passaggi seguenti sia in routes/index.tsx che in routes/$shoppingListId.tsx per migrare a TanStack Router:

  1. Aggiungi createFileRoute per registrare ogni route:

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

    Dopo aver salvato il file, noterai che gli errori di tipo con la chiamata a createFileRoute sono scomparsi.

  2. Sostituisci l’hook useNavigate.

    Aggiorna l’importazione:

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

    Aggiorna le chiamate al metodo navigate (restituito da useNavigate) per passare le route type-safe:

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

    Rimuovi l’importazione:

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

    Aggiorna le chiamate a useParams con l’hook fornito dalla Route creata sopra. Ora sono type-safe!

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

Poiché i nostri file di route non sono annidati così profondamente nell’albero dei file come lo erano nel nostro progetto PDK, dobbiamo correggere l’importazione per CreateItem sia in routes/index.tsx che in routes/$shoppingListId.tsx:

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

Anche AppLayoutContext è fornito in una posizione leggermente diversa nel nostro nuovo progetto:

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

Migrare per Utilizzare il Nuovo Client TypeScript Generato

Sezione intitolata “Migrare per Utilizzare il Nuovo Client TypeScript Generato”

Ci stiamo avvicinando ora! Successivamente, dobbiamo migrare per utilizzare il client TypeScript fornito da Nx Plugin for AWS, che ha alcuni miglioramenti rispetto a Type Safe API. Per ottenere questo, segui i passaggi seguenti

  1. Importa il nuovo client e i tipi generati invece di quelli vecchi, per esempio:

    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";

    Nota che routes/$shoppingListId.tsx importa il tipo ShoppingList come _ShoppingList - in quel file dovremmo fare lo stesso, ma importando nuovamente da types.gen.

    Nota anche che importiamo gli hook rilevanti direttamente da @tanstack/react-query, poiché il client generato fornisce metodi per generare opzioni per gli hook TanStack query, piuttosto che wrapper di hook.

  2. Istanzia i nuovi hook TanStack Query, per esempio:

    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: (p) => p.nextToken },
    ),
    );
    const putShoppingList = useMutation(api.putShoppingList.mutationOptions());
    const deleteShoppingList = useMutation(
    api.deleteShoppingList.mutationOptions(),
    );
  3. Rimuovi il wrapper <operation>RequestContent per le chiamate alle operazioni che accettano parametri nel corpo della richiesta:

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

Ci sono alcuni errori rimasti da correggere a causa delle differenze tra TanStack Query v4 (utilizzato da PDK) e v5 che il generatore connection ha aggiunto:

  1. Sostituisci isLoading con isPending per le mutazioni, per esempio:

    putShoppingList.isLoading
    putShoppingList.isPending
  2. L’applicazione shopping list utilizzava InfiniteQueryTable da @aws-northstar/ui che si aspetta un tipo da TanStack Query v4. Questo funziona effettivamente con query infinite da v5, quindi possiamo semplicemente sopprimere l’errore di tipo:

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

Ora puoi visitare il sito web locale su http://localhost:4200/

Il sito web dovrebbe caricarsi ora che tutto è stato migrato! Poiché l’unica infrastruttura su cui si basa l’applicazione shopping list oltre ad API, Website e Identity è la tabella DynamoDB - se hai una tabella DynamoDB denominata shopping_list nella regione e credenziali AWS locali che possono accedervi, il sito web sarà completamente funzionale!

Se no, va bene, migreremo l’infrastruttura successivamente.

Clicca qui per esempi completi prima/dopo per le due pagine shopping list del tutorial

L’ultimo progetto che dobbiamo migrare per la nostra applicazione shopping list è l’InfrastructureTsProject. Questo è un progetto TypeScript CDK, per il quale l’equivalente di Nx Plugin for AWS è il generatore ts#infra.

Oltre ai progetti Projen, PDK forniva anche costrutti CDK da cui questi progetti dipendevano. Migreremo l’applicazione shopping list anche da questi costrutti CDK, a favore di quelli generati da Nx Plugin for AWS.

Generare un Progetto di Infrastruttura TypeScript CDK

Sezione intitolata “Generare un Progetto di Infrastruttura TypeScript CDK”

Esegui il generatore ts#infra per configurare il tuo progetto di infrastruttura in packages/infra:

Terminal window
pnpm nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:ts#infra --name=infra --no-interactive --dry-run

L’applicazione shopping list PDK istanziava i seguenti costrutti all’interno dello stack dell’applicazione CDK:

  • DatabaseConstruct per la tabella DynamoDB che memorizza le shopping list
  • UserIdentity per le risorse Cognito, importato direttamente da PDK
  • MyApi per il deployment dell’API Smithy, che utilizzava il costrutto TypeScript CDK generato con integrazioni type-safe, dipendendo dal costrutto CDK TypeSafeRestApi di PDK sotto il cofano.
  • Website per il deployment del sito web, che avvolgeva il costrutto CDK StaticWebsite di PDK.

Successivamente, migreremo ciascuno di questi al nuovo progetto.

Copia packages/infra/src/stacks/application-stack.ts dall’applicazione shopping list PDK nella stessa identica posizione nel tuo nuovo progetto. Vedrai alcuni errori TypeScript che risolveremo di seguito.

L’applicazione shopping list PDK aveva un costrutto Database in packages/src/constructs/database.ts. Copialo nella stessa identica posizione nel tuo nuovo progetto.

Poiché Nx Plugin for AWS utilizza Checkov per i test di sicurezza, che è un po’ più rigoroso di PDK Nag, dobbiamo anche aggiungere alcune soppressioni:

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',
);

In application-stack.ts, aggiorna l’import per il DatabaseConstruct per utilizzare la sintassi ESM:

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

Il costrutto UserIdentity può generalmente essere sostituito senza modifiche regolando gli import.

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

Nota che i costrutti sottostanti utilizzati dal nuovo costrutto UserIdentity sono forniti direttamente da aws-cdk-lib, mentre PDK utilizzava @aws-cdk/aws-cognito-identitypool-alpha.

L’applicazione shopping list PDK aveva un costrutto in constructs/apis/myapi.ts che istanziava un costrutto CDK che Type Safe API generava dal tuo modello Smithy.

Oltre a questo costrutto, poiché il progetto PDK utilizzava il trait @handler, venivano generati anche costrutti CDK di funzioni lambda.

Come Type Safe API, Nx Plugin for AWS fornisce type-safety per le integrazioni basate sul tuo modello Smithy, tuttavia è ottenuto in un modo molto più semplice e flessibile. Invece di generare un intero costrutto CDK al momento della build, vengono generati solo “metadati” minimi, che il packages/common/constructs/src/app/apis/api.ts utilizza in modo generico. Puoi saperne di più su come utilizzare il costrutto nella guida del generatore ts#smithy-api.

Segui i passaggi seguenti:

  1. Istanzia il costrutto Api in 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 qui che usiamo Api.defaultIntegrations(this).build() - il comportamento predefinito è creare una funzione lambda per ogni operazione nella nostra API, che è lo stesso comportamento che avevamo in myapi.ts.

  2. Concedi i permessi alle funzioni lambda per accedere alla tabella DynamoDB.

    Nell’applicazione shopping list PDK, il DatabaseConsruct veniva passato a MyApi, e gestiva l’aggiunta dei permessi rilevanti a ciascun costrutto di funzione generato. Lo faremo direttamente nel file application-stack.ts accedendo alla proprietà integrations type-safe del costrutto Api:

    stacks/application-stack.ts
    // Grant our lambda functions scoped access to call Dynamo
    databaseConstruct.shoppingListTable.grantReadData(
    api.integrations.getShoppingLists.handler,
    );
    [
    api.integrations.putShoppingList.handler,
    api.integrations.deleteShoppingList.handler,
    ].forEach((f) => databaseConstruct.shoppingListTable.grantWriteData(f));
  3. Concedi i permessi agli utenti autenticati per invocare l’API.

    All’interno del myapi.ts dell’applicazione PDK, agli utenti autenticati venivano anche concessi i permessi IAM per invocare l’API. Faremo l’equivalente in application-stack.ts:

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

Infine, aggiungiamo il costrutto Website da packages/common/constructs/src/app/static-websites/website.ts a application-stack.ts, poiché questo è l’equivalente del packages/infra/src/constructs/websites/website.ts dell’applicazione shopping list 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 che non passiamo l’identità o l’API al sito web - la configurazione runtime è gestita all’interno di ogni costrutto fornito da Nx Plugin for AWS, dove UserIdentity e Api registrano i valori necessari, e Website gestisce il deployment su /runtime-config.json sul tuo sito web statico.

Costruiamo ora il progetto ora che abbiamo migrato tutte le parti rilevanti della codebase al nostro nuovo progetto.

Terminal window
pnpm nx run-many --target build

Ora che abbiamo la nostra codebase completamente migrata, possiamo occuparci del deploy. Ci sono due percorsi che possiamo seguire a questo punto.

L’approccio più semplice è trattare questa come un’applicazione completamente nuova, il che significa che “ricominceremo da capo” con una nuova tabella DynamoDB e un nuovo Cognito User Pool - perdendo tutti gli utenti e le loro liste della spesa. Per questo approccio, semplicemente:

  1. Elimina la tabella DynamoDB denominata shopping_list

  2. Esegui il deploy della nuova applicazione:

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

🎉 E abbiamo finito! 🎉

Migrare le Risorse Stateful Esistenti senza Interruzioni (Più Complesso)

Sezione intitolata “Migrare le Risorse Stateful Esistenti senza Interruzioni (Più Complesso)”

In realtà, è più probabile che tu voglia migrare le risorse AWS esistenti in modo che siano gestite dalla nuova codebase, evitando al contempo qualsiasi downtime per i tuoi clienti.

Per la nostra applicazione shopping list, le risorse stateful che ci interessano sono la tabella DynamoDB che contiene le liste della spesa dei nostri utenti e lo User Pool che contiene i dettagli di tutti i nostri utenti registrati. Il nostro piano ad alto livello sarà quello di mantenere queste due risorse chiave e spostarle in modo che siano gestite dal nostro nuovo stack, quindi aggiornare il DNS per puntare al nostro nuovo sito web (e API se esposta ai clienti).

  1. Aggiorna la tua nuova applicazione per fare riferimento alle risorse esistenti che desideri mantenere.

    Per l’applicazione shopping list, lo facciamo per la tabella DynamoDB

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

    E per il Cognito User Pool

    packages/common/constructs/src/core/user-identity.ts
    this.userPool = this.createUserPool();
    this.userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );
  2. Esegui il build e il deploy della nuova applicazione:

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

    Ora abbiamo la nostra nuova applicazione attiva che fa riferimento alle risorse esistenti, non ancora in ricezione di traffico.

  3. Esegui test di integrazione completi per assicurarti che la nuova applicazione funzioni come previsto. Per l’applicazione shopping list, carica il sito web e verifica di poter accedere e creare, visualizzare, modificare ed eliminare liste della spesa.

  4. Ripristina le modifiche che fanno riferimento alle risorse esistenti nella tua nuova applicazione, ma non eseguire ancora il deploy.

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

    E per il Cognito User Pool

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

    E poi esegui un build

    Terminal window
    pnpm nx run-many --target build
  5. Usa cdk import nella cartella packages/infra della tua nuova applicazione per vedere quali risorse ci verrà richiesto di importare.

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

    Procedi attraverso i prompt premendo invio. L’importazione fallirà perché le risorse sono gestite da un altro stack - questo è previsto, abbiamo fatto questo passaggio solo per confermare quali risorse dovremo mantenere. Vedrai un output come questo:

    Terminal window
    shopping-list-infra-sandbox/Application/ApplicationUserIdentity/UserPool/smsRole/Resource (AWS::IAM::Role): enter RoleName (empty to skip)
    shopping-list-infra-sandbox/Application/ApplicationUserIdentity/UserPool/Resource (AWS::Cognito::UserPool): enter UserPoolId (empty to skip)
    shopping-list-infra-sandbox/Application/Database/ShoppingList/Resource (AWS::DynamoDB::Table): import with TableName=shopping_list (y/n) y

    Questo ci dice che ci sono in realtà 3 risorse che dovremo importare nel nostro nuovo stack.

  6. Aggiorna il tuo vecchio progetto PDK per impostare RemovalPolicy su RETAIN per le risorse scoperte dal passaggio precedente. Al momento della scrittura questo è il default sia per lo User Pool che per la tabella DynamoDB, ma dobbiamo aggiornarlo per l’SMS Role che abbiamo scoperto sopra:

    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. Esegui il deploy del tuo progetto PDK in modo che le removal policy vengano applicate

    PDK Application
    cd packages/infra
    npx projen deploy
  8. Dai un’occhiata alla console CloudFormation e registra i valori che ti sono stati richiesti nel passaggio cdk import sopra

    1. L’ID dello User Pool, ad es. us-west-2_XXXXX
    2. Il nome dell’SMS Role, ad es. infra-sandbox-UserIdentityUserPoolsmsRoleXXXXXX
  9. Aggiorna il tuo progetto PDK per fare riferimento alle risorse esistenti invece di crearle

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

    E per il Cognito User Pool

    application-stack.ts
    const userPool = UserPool.fromUserPoolId(
    this,
    'UserPool',
    '<your-user-pool-id>',
    );
    const userIdentity = new UserIdentity(this, `${id}UserIdentity`, {
    // PDK construct accepts UserPool not IUserPool, but this still works!
    userPool: userPool as any,
    });
  10. Esegui nuovamente il deploy del tuo progetto PDK, questo significherà che le risorse non sono più gestite dallo stack CloudFormation del nostro progetto PDK.

    PDK Application
    cd packages/infra
    npx projen deploy
  11. Ora che le risorse non sono gestite, possiamo eseguire cdk import nella nostra nuova applicazione per eseguire effettivamente l’importazione:

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

    Inserisci i valori quando richiesto, l’importazione dovrebbe completarsi con successo.

  12. Esegui nuovamente il deploy della nuova applicazione per assicurarti che vengano apportate eventuali modifiche a queste risorse esistenti (ora gestite dal tuo nuovo stack):

    Terminal window
    pnpm nx deploy infra shopping-list-infra-sandbox/*
  13. Esegui un test completo della tua nuova applicazione ancora una volta

  14. Aggiorna i record DNS per puntare al tuo nuovo sito web (e API se necessario).

    Raccomandiamo un approccio graduale utilizzando il Weighted Routing di Route53, per cui una frazione delle richieste viene inizialmente indirizzata alla nuova applicazione. Man mano che monitori le tue metriche puoi aumentare il peso per la nuova applicazione fino a quando nessun traffico viene inviato alla tua vecchia applicazione PDK.

    Se non hai alcun DNS e hai utilizzato i domini generati automaticamente per il sito web e l’API, puoi sempre considerare di fare il proxy delle richieste (ad es. tramite un CloudFront HTTP origin o API Gateway HTTP integration(s)).

  15. Monitora le metriche dell’applicazione PDK per assicurarti che non ci sia traffico e infine distruggi il vecchio stack CloudFormation:

    Terminal window
    cd packages/infra
    npx projen destroy

È stato un po’ più complesso, ma abbiamo migrato con successo i nostri utenti senza interruzioni alla nuova applicazione! 🎉🎉🎉

Ora abbiamo i nuovi vantaggi di Nx Plugin for AWS rispetto a PDK:

  • Build più veloci
  • Supporto per lo sviluppo locale dell’API
  • Una codebase adatta al vibe-coding (prova il nostro server MCP!)
  • Codice client/server type-safe più intuitivo
  • E molto altro!

Questa sezione fornisce indicazioni per le funzionalità di PDK che non sono coperte dall’esempio di migrazione sopra.

Come regola generale quando si passa da PDK, raccomandiamo di iniziare qualsiasi progetto con un Nx Workspace, date le sue somiglianze con il PDK Monorepo. Raccomandiamo anche di usare i nostri generatori come primitive su cui costruire qualsiasi nuovo tipo.

Terminal window
pnpm create @aws/nx-workspace my-project

CDK Graph costruisce grafici delle risorse CDK connesse e forniva due plugin:

Il CDK Graph Diagram Plugin genera diagrammi dell’architettura AWS dalla tua infrastruttura CDK.

Per un approccio deterministico simile, un’alternativa valida è CDK-Dia.

Con i progressi nell’AI Generativa, molti modelli fondazionali sono in grado di creare diagrammi di alta qualità dalla tua infrastruttura CDK. Consigliamo di provare l’AWS Diagram MCP Server. Consulta questo post del blog per una guida dettagliata.

Il CDK Graph Threat Composer Plugin genera un Threat Composer iniziale di modello di minaccia dal tuo codice CDK.

Questo plugin funzionava semplicemente filtrando un modello di minaccia di base contenente minacce di esempio e filtrandole in base alle risorse utilizzate dal tuo stack.

Se sei interessato a queste specifiche minacce di esempio, puoi copiare e filtrare il modello di minaccia di base, oppure usarlo come contesto per aiutare un modello fondazionale a generarne uno simile.

AWS Arch forniva mappature tra le risorse CloudFormation e le loro icone di architettura associate per CDK Graph sopra.

Fare riferimento alla pagina AWS Architecture Icons per le risorse relative alle icone. Diagrams fornisce anche un modo per costruire diagrammi come codice.

Se stavi utilizzando questo direttamente, considera di fare un fork del progetto e prenderne la proprietà!

PDK forniva un PDKPipelineProject che configurava un progetto di infrastruttura CDK e utilizzava un costrutto CDK che racchiudeva alcune risorse di CDK Pipelines.

Per migrare da questo, puoi utilizzare direttamente i costrutti CDK Pipelines. In pratica, tuttavia, è probabilmente più semplice utilizzare qualcosa come GitHub actions o GitLab CI/CD, dove definisci CDK Stages ed esegui il comando deploy per lo stage appropriato direttamente.

PDK Nag racchiude CDK Nag e fornisce un insieme di regole specifiche per la creazione di prototipi.

Per migrare da PDK Nag, utilizza CDK Nag direttamente. Se hai bisogno dello stesso insieme di regole, puoi creare un “pack” personalizzato seguendo la documentazione qui.

I componenti più comunemente utilizzati di Type Safe API sono trattati nell’esempio di migrazione precedente, tuttavia ci sono altre funzionalità, per le quali i dettagli di migrazione sono riportati di seguito.

Nx Plugin for AWS supporta API modellate in Smithy, ma non quelle modellate direttamente in OpenAPI. Il generatore ts#smithy-api è un buon punto di partenza che puoi poi modificare. Puoi definire la tua specifica OpenAPI nella cartella src del progetto model invece di Smithy, e modificare il build.Dockerfile per utilizzare il tuo strumento di generazione del codice desiderato per client/server se non sono disponibili su NPM. Se i tuoi strumenti desiderati sono su NPM, puoi semplicemente installarli come dipendenze di sviluppo nel tuo workspace Nx e chiamarli direttamente come target di build Nx.

Per backend type-safe modellati in OpenAPI, puoi considerare l’utilizzo di uno dei generatori di server di OpenAPI Generator. Questi non genereranno direttamente per AWS Lambda, ma puoi utilizzare AWS Lambda Web Adapter per colmare il divario per molti di essi.

Per i client TypeScript, puoi utilizzare il generatore ts#website e il generatore connection con un esempio di ts#api (con framework impostato su smithy) per vedere come vengono generati e integrati i client con un sito web. Questo configura target di build che generano client invocando i nostri generatori open-api#ts-client o open-api#ts-hooks. Puoi utilizzare questi generatori tu stesso puntandoli alla tua specifica OpenAPI.

Per altri linguaggi, puoi anche verificare se uno dei generatori di OpenAPI Generator soddisfa le tue esigenze.

Puoi anche costruire un generatore personalizzato utilizzando il generatore ts#nx-generator. Fai riferimento alla documentazione di quel generatore per i dettagli su come generare codice da OpenAPI. Puoi utilizzare i template di Nx Plugin for AWS come punto di partenza. Puoi anche fare riferimento ai template dalla codebase PDK per ulteriore ispirazione, notando che la struttura dati su cui operano i template è leggermente diversa da Nx Plugin for AWS.

Per TypeSpec, si applica anche la sezione precedente per OpenAPI. Puoi iniziare generando un ts#smithy-api, installare il compilatore TypeSpec e i pacchetti OpenAPI nel tuo workspace Nx, e aggiornare il target compile del progetto model per eseguire tsp compile invece, assicurandoti che produca una specifica OpenAPI nella directory dist.

L’approccio consigliato sarebbe utilizzare il generatore di server HTTP TypeSpec per JavaScript per generare il codice del tuo server, poiché funziona direttamente sul tuo modello TypeSpec.

Puoi utilizzare AWS Lambda Web Adapter per eseguire il server generato su AWS Lambda.

Puoi anche utilizzare una qualsiasi delle opzioni OpenAPI sopra indicate.

TypeSpec ha i propri generatori di codice per i client in tutti e tre i linguaggi supportati da Type Safe API:

Si applica anche la sezione OpenAPI precedente poiché TypeSpec può compilare in OpenAPI.

L’esempio di migrazione precedente delinea la migrazione per utilizzare il generatore ts#smithy-api. Questa sezione copre le opzioni per backend e client Python e Java.

Il generatore di codice Smithy per Java. Questo ha un generatore di server Java così come un adattatore per eseguire il server Java generato su AWS Lambda.

Smithy non ha un generatore di server per Python, quindi dovrai passare tramite OpenAPI. Fai riferimento alla sezione precedente riguardante API modellate con OpenAPI per le opzioni potenziali.

Il generatore di codice Smithy per Java. Questo ha un generatore di client Java.

Per i client Python, puoi dare un’occhiata a Smithy Python.

Per TypeScript, dai un’occhiata a Smithy TypeScript, oppure utilizza lo stesso approccio che abbiamo adottato in ts#smithy-api passando tramite OpenAPI (abbiamo optato per questo in quanto ci dà coerenza tra API tRPC, FastAPI e Smithy tramite hook TanStack Query).

Type Safe API forniva un tipo di progetto Projen chiamato SmithyShapeLibraryProject che configurava un progetto contenente modelli Smithy che potevano essere riutilizzati da più API basate su Smithy.

L’equivalente è il generatore smithy#project con type impostato su shapes:

Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes --dry-run

Sposta le forme dal tuo SmithyShapeLibraryProject nella cartella src del progetto generato, quindi fai riferimento alla guida del progetto Smithy per come collegare la libreria come dipendenza del modello della tua API.

Type Safe API forniva i seguenti interceptor predefiniti:

  • Interceptor di logging, tracing e metriche utilizzando Powertools for AWS Lambda
  • Interceptor try-catch per gestire le eccezioni non catturate
  • Interceptor CORS per restituire header CORS

Il generatore ts#smithy-api strumenta logging, tracing e metriche con Powertools for AWS Lambda utilizzando Middy. Il comportamento dell’interceptor try-catch è integrato nel Smithy TypeScript SSDK, e gli header CORS vengono aggiunti in handler.ts.

Per interceptor di logging, tracing e metriche in qualsiasi linguaggio, utilizza direttamente Powertools for AWS Lambda.

Per migrare interceptor personalizzati, consigliamo di utilizzare le seguenti librerie:

Type Safe API forniva la generazione della documentazione utilizzando Redocly CLI. Questo è molto facile da aggiungere a un progetto esistente una volta che l’hai migrato come sopra.

  1. Installa Redocly CLI

    Terminal window
    pnpm add -Dw @redocly/cli
  2. Aggiungi un target di generazione della documentazione al tuo progetto model utilizzando redocly build-docs, per esempio:

    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"]
    }
    }

Puoi anche considerare i generatori di documentazione di OpenAPI Generator.

Type Safe API generava mock per te all’interno del suo pacchetto di infrastruttura generato.

Puoi passare a JSON Schema Faker che può creare i dati mock basati su JSON Schema. Questo può funzionare direttamente su una specifica OpenAPI, e ha una CLI che potresti eseguire come parte della build del tuo progetto model.

Puoi aggiornare la tua infrastruttura CDK per leggere il file JSON prodotto da JSON Schema Faker, e restituire l’appropriata MockIntegration di API Gateway per un’integrazione, basata sul metadata.gen.ts generato (supponendo che tu abbia utilizzato il generatore ts#smithy-api).

Type Safe API supportava l’implementazione di API con una miscela di diversi linguaggi nel backend. Questo può essere ottenuto anche fornendo “override” alle integrazioni quando si istanzia il costrutto API in 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(),
});

Dovrai creare uno “stub” del tuo servizio/router affinché il tuo servizio possa compilare se utilizzi ts#smithy-api e il TypeScript Server SDK, ad esempio:

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

Type Safe API aggiungeva la validazione nativa di API Gateway per i corpi delle richieste basata sulla tua specifica OpenAPI poiché utilizzava il costrutto SpecRestApi sotto il cofano.

Con il generatore ts#smithy-api, la validazione viene eseguita dal Server SDK stesso. Questo è lo stesso per la maggior parte dei generatori di server.

Se desideri implementare la validazione nativa di API Gateway, potresti farlo modificando packages/common/constructs/src/core/api/rest-api.ts per leggere il JSON schema rilevante per il corpo della richiesta di ciascuna operazione dalla tua specifica OpenAPI.

Sfortunatamente non esiste un percorso di migrazione diretto per l’API websocket di Type Safe API utilizzando API Gateway e Lambda con lo sviluppo di API model-driven. Tuttavia, questa sezione della guida mira almeno a offrire alcune idee.

Considera l’utilizzo di AsyncAPI per modellare la tua API invece di OpenAPI o TypeSpec poiché questo è progettato per gestire API asincrone. Il template NodeJS di AsyncAPI può generare un backend websocket Node che potresti ospitare su ECS per esempio.

Puoi anche considerare AppSync Events per l’infrastruttura, e utilizzare Powertools. Questo post del blog vale la pena leggerlo!

Un’altra opzione è utilizzare API GraphQL con websocket su AppSync, per cui abbiamo una issue GitHub a cui puoi dare un +1! Fai riferimento alla guida per sviluppatori AppSync per dettagli e link a progetti di esempio.

Puoi anche considerare di creare i tuoi generatori di codice che interpretano le stesse estensioni vendor di Type Safe API. Fai riferimento alla sezione API modellate con OpenAPI per i dettagli sulla costruzione di generatori di codice personalizzati basati su OpenAPI. Puoi trovare i template che Type Safe API utilizza per i gestori Lambda di API Gateway Websocket API qui, e il client qui.

Puoi anche considerare di migrare per utilizzare il generatore ts#trpc-api per utilizzare tRPC. Al momento della scrittura non abbiamo ancora supporto per sottoscrizioni/streaming ma se questo è qualcosa di cui hai bisogno aggiungi un +1 alla nostra issue GitHub che traccia questo.

Smithy è agnostico al protocollo, ma non ha ancora supporto per il protocollo Websocket, fai riferimento a questa issue GitHub che traccia il supporto.

PDK supportava l’infrastruttura CDK scritta in Python e Java. Al momento della scrittura, non supportiamo questo nel Nx Plugin for AWS.

Il percorso consigliato sarebbe quello di migrare la tua infrastruttura CDK a TypeScript, oppure di utilizzare i nostri generatori e migrare il pacchetto di costrutti comuni al linguaggio desiderato. Puoi utilizzare l’IA Generativa per accelerare questo tipo di migrazioni, ad esempio Kiro CLI. Puoi far iterare un agente AI sulla migrazione fino a quando i template CloudFormation sintetizzati sono identici.

Lo stesso vale per l’infrastruttura generata da Type Safe API in Python o Java - puoi tradurre il costrutto generico rest-api.ts dal pacchetto di costrutti comuni e implementare il tuo semplice generatore di metadati per il linguaggio di destinazione (fai riferimento alla sezione API Modellate con OpenAPI).

Puoi utilizzare il generatore py#project per un progetto Python di base a cui aggiungere il tuo codice CDK (e spostare il tuo file cdk.json, aggiungendo i target rilevanti). Puoi utilizzare il plugin @nx/gradle di Nx per progetti Java, oppure @jnxplus/nx-maven per Maven.

PDK è stato costruito su Projen. Projen e Nx Generators hanno differenze abbastanza fondamentali, il che significa che sebbene sia tecnicamente possibile combinarli, è probabilmente un anti-pattern. Projen gestisce i file di progetto come codice in modo tale che non possano essere modificati direttamente, mentre i generatori Nx forniscono i file di progetto una volta sola e poi il codice può essere liberamente modificato.

Se desideri continuare a utilizzare Projen, puoi implementare tu stesso i tipi di progetto Projen desiderati. Per seguire i pattern di Nx Plugin for AWS, puoi eseguire i nostri generatori o esaminare il loro codice sorgente su GitHub per vedere come sono costruiti i tipi di progetto desiderati e implementare le parti rilevanti utilizzando le primitive di Projen.