Generatore Nx Migration
Aggiunge una Nx Migration a un Nx Plugin. Le migrazioni consentono a nx migrate di aggiornare automaticamente i progetti generati da una versione precedente del tuo plugin quando apporti una modifica che rompe la compatibilità — target rinominati, configurazione fornita modificata o un aggiornamento di dipendenza che richiede modifiche al codice accompagnatorie.
Il generatore crea lo scaffold della migrazione, la registra nel migrations.json del tuo plugin e collega il campo nx-migrations nel package.json del tuo plugin (creandoli entrambi se non esistono ancora).
Utilizzo
Sezione intitolata “Utilizzo”Generare una Migration
Sezione intitolata “Generare una Migration”pnpm nx g @aws/nx-plugin:ts#nx-migrationyarn nx g @aws/nx-plugin:ts#nx-migrationnpx nx g @aws/nx-plugin:ts#nx-migrationbunx nx g @aws/nx-plugin:ts#nx-migrationPuoi anche eseguire una prova per vedere quali file verrebbero modificati
pnpm nx g @aws/nx-plugin:ts#nx-migration --dry-runyarn nx g @aws/nx-plugin:ts#nx-migration --dry-runnpx nx g @aws/nx-plugin:ts#nx-migration --dry-runbunx nx g @aws/nx-plugin:ts#nx-migration --dry-run- Installa il Nx Console VSCode Plugin se non l'hai già fatto
- Apri la console Nx in VSCode
- Clicca su
Generate (UI)nella sezione "Common Nx Commands" - Cerca
@aws/nx-plugin - ts#nx-migration - Compila i parametri richiesti
- Clicca su
Generate
Opzioni
Sezione intitolata “Opzioni”| Parametro | Tipo | Predefinito | Descrizione |
|---|---|---|---|
| project Obbligatorio | string | - | Il progetto Nx Plugin a cui aggiungere la migrazione. Si consiglia di utilizzare il generatore ts#nx-plugin per crearlo. |
| name Obbligatorio | string | - | Nome della migrazione, in formato kebab-case (es. rename-foo-target) |
| description | string | - | Una descrizione di ciò che fa la migrazione, mostrata da nx migrate |
| kind | deterministic | agentic | hybrid | deterministic | Il tipo di migrazione: deterministic (un codemod), agentic (un prompt applicato tramite AI per codice di proprietà dell'utente), o hybrid (un codemod che esegue la parte meccanica e poi passa il controllo a un agente) |
| preferInstallDependencies | boolean | true | Se preferire l'installazione delle dipendenze dopo l'esecuzione del generatore. Impostare su false per rimandare l'installazione quando si eseguono più generatori in batch (l'installazione viene comunque eseguita se necessaria affinché i generatori successivi possano calcolare il grafo dei progetti Nx); installare una volta alla fine. |
I tre tipi di migrazione
Sezione intitolata “I tre tipi di migrazione”Le migrazioni si presentano in tre forme, discriminate dai campi che contiene la voce migrations.json. Passa --kind per scegliere (predefinito deterministic):
- Deterministic (
implementation) — un codemod con un prima/dopo esatto, ed è quello da preferire per primo. Viene eseguito senza supervisione, anche in CI e terminali non interattivi, e si applica in modo identico per ogni utente. Usalo da solo quando la modifica ha una forma che puoi abbinare in modo affidabile ovunque appaia, segnalando tutto ciò che ha saltato tramitenextSteps. - Hybrid (
implementation+prompt) — entrambe le metà di una modifica. Usalo quando una modifica rompe la compatibilità e non può essere applicata completamente in modo meccanico: il codemod fa tutto ciò che può abbinare in sicurezza e restituisceagentContextdescrivendo cosa ha modificato e cosa ha saltato; Nx passa quel contesto alpromptabbinato, che dirige l’agente verso il resto. Il prompt è ciò che impedisce che un workspace venga lasciato rotto quando le modifiche rimanenti coprono troppe forme per essere codificate. - Agentic (
prompt) — un file di istruzioni markdown applicato dall’agente di codifica locale dell’utente tramite il flusso agenticonx migratedi Nx. Usalo da solo quando non esiste alcun prima/dopo meccanico, perché la modifica corretta dipende da ciò che l’utente ha costruito. Quando nessun agente viene eseguito (CI, nessun agente installato, consenso negato), Nx presenta il prompt come istruzioni manuali — quindi scrivi i prompt come passaggi autonomi e attuabili dall’utente.
Output del Generatore
Sezione intitolata “Output del Generatore”Il generatore crea i seguenti file nella cartella sorgente del progetto del tuo plugin, a seconda del kind scelto:
Directorysrc/migrations/latest/<name>/
- migration.ts Implementazione del codemod (deterministic e hybrid)
- migration.spec.ts Test per la tua migrazione (deterministic e hybrid)
- prompt.md Istruzioni per agente/umano (agentic e hybrid)
- migrations.json Creato o aggiornato per registrare la tua migrazione
- package.json Creato o aggiornato per aggiungere una voce “nx-migrations”
Una nuova migrazione viene posizionata in latest/. Raggruppare le migrazioni per il rilascio che le spedisce mantiene il loro ordine visibile a colpo d’occhio man mano che la collezione cresce — sposta una migrazione in una cartella v<x.y.z>/ (e aggiorna i suoi percorsi in migrations.json) quando assegni la sua versione.
Registra la migrazione in migrations.json con i campi per il suo tipo e senza version — vedi Versionamento di seguito. La chiave registrata è prefissata con la cartella in cui vive la migrazione (latest-<name>), quindi riutilizzare un nome per una modifica successiva non può sovrascrivere silenziosamente una migrazione che è già stata spedita.
Implementare una Migration
Sezione intitolata “Implementare una Migration”Una migrazione deterministica (o ibrida) è una funzione che muta il filesystem virtuale (il Tree), restituendo un MigrationReturnObject. Ecco una ibrida, che restituisce entrambi:
import { type MigrationReturnObject, type Tree } from '@nx/devkit';import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
export default async function migration( tree: Tree,): Promise<MigrationReturnObject> { const nextSteps: string[] = []; const agentContext: string[] = [];
// Read and update the files your generators produce here.
await formatFilesInSubtree(tree);
return { nextSteps, agentContext };}nextSteps— le azioni di follow-up che Nx stampa per l’utente dopo l’esecuzione dinx migrate. Ogni voce dovrebbe essere qualcosa che devono fare manualmente: riconciliare un file che hai saltato (vedi le protezioni di seguito), o completare qualcosa oltre la portata della migrazione, come un’installazione per aggiornare un file di lock. Non sono un registro di ciò che hai modificato — quando una trasformazione si applica in modo pulito, non aggiungere nulla, altrimenti le voci che necessitano effettivamente di azione vengono sepolte.agentContext(solo hybrid) — un riepilogo di ciò che il codemod ha modificato, passato alpromptabbinato quando viene eseguito sotto il flusso agentico di Nx in modo che l’agente possa concentrarsi sulle parti di proprietà dell’utente.
Per alcuni esempi di operazioni che puoi eseguire nella tua migrazione (generare file, modificare file esistenti usando GritQL, leggere e aggiornare JSON), fai riferimento alla guida Nx Generator.
Protezioni
Sezione intitolata “Protezioni”Le migrazioni vengono eseguite su workspace che non controlli, quindi si consiglia di aderire a quanto segue (lo scheletro generato li incorpora):
- Trasforma il codice sorgente con GritQL. Usa gli helper GritQL (
applyGritQL,matchGritQL) per modificare il sorgente piuttosto che regex o sostituzioni di stringhe. GritQL abbina l’AST, quindi un pattern funziona attraverso la formattazione, gli spazi bianchi e le virgolette in cui la copia dell’utente potrebbe essere derivata, dove l’abbinamento del testo perde silenziosamente codice equivalente o corrompe il file. UsaupdateJsonper JSON e il parser corrispondente per altre configurazioni strutturate. - Abbina il pattern prima di scrivere. Se un file di destinazione è divergente dalla forma che i tuoi generatori producono, saltalo e segnalalo tramite
nextSteps, o considera una migrazione ibrida, piuttosto che sovrascrivere le modifiche dell’utente.matchGritQLè un modo conveniente per effettuare quel controllo. - Segnala solo ciò che resta da fare.
nextStepsè per il lavoro che l’utente deve riprendere, non un registro delle modifiche che hai fatto — quelle sono già nel lorogit diff. - Idempotente. Rieseguire la migrazione deve essere un no-op. Proteggi le riscritture GritQL che iniettano codice con una clausola
where { ... <: not contains ... }in modo che una seconda esecuzione non aggiunga un duplicato. - Formatta ciò che scrivi. Termina con
formatFilesInSubtree(tree)in modo che i file scritti dalla tua migrazione siano formattati correttamente.
Testare la Tua Migration
Sezione intitolata “Testare la Tua Migration”Il migration.spec.ts generato usa createTreeUsingTsSolutionSetup() per costruire un workspace virtuale che corrisponde alla forma generata dal nostro preset. Testa che la migrazione porti un workspace dallo stato “prima” allo stato target, salti (e segnali) il codice che non riconosce, e sia idempotente:
import type { Tree } from '@nx/devkit';import { createTreeUsingTsSolutionSetup } from '@aws/nx-plugin/sdk/utils/test';import migration from './migration.js';
describe('my migration', () => { let tree: Tree;
beforeEach(() => { tree = createTreeUsingTsSolutionSetup(); });
it('should update the generated shape', async () => { // Set up a tree with the "before" state tree.write('project.json', JSON.stringify({ targets: { foo: {} } }));
// Run the migration await migration(tree);
// Check that the tree matches the target state const projectJson = JSON.parse(tree.read('project.json', 'utf-8')); expect(projectJson.targets).toHaveProperty('bar'); expect(projectJson.targets).not.toHaveProperty('foo'); });});I test unitari dimostrano solo che la migrazione fa ciò che hai scritto che faccia. Testala anche su un workspace generato dalla versione pubblicata del tuo plugin — lo stato da cui i tuoi utenti aggiornano — e conferma che il risultato corrisponda a ciò che i tuoi generatori producono oggi: ispeziona il diff, genera gli stessi progetti in un workspace nuovo e confronta, controlla che il workspace si compili ancora, quindi riesegui la migrazione per confermare che non cambi nulla. Ripeti con un workspace che hai personalizzato prima, per verificare che la migrazione lasci le tue modifiche da sole e le segnali invece.
Versionamento
Sezione intitolata “Versionamento”Nx esegue una migrazione quando la versione del plugin installata dall’utente è inferiore alla version della migrazione. Questo generatore non scrive alcun campo version — assegnalo (o stampalo dal tuo processo di rilascio) quando tagli il rilascio che spedisce la migrazione, in modo che venga eseguita per tutti coloro che aggiornano da una versione precedente.
Una volta assegnate le versioni, un migrations.json che registra una migrazione di ogni tipo appare così:
{ "$schema": "http://json-schema.org/schema", "name": "my-plugin", "generators": { "v2.0.0-rename-foo-target": { "version": "2.0.0", "description": "Rename the foo target to bar", "implementation": "./src/migrations/v2.0.0/rename-foo-target/migration" }, "v3.0.0-migrate-custom-handlers": { "version": "3.0.0", "description": "Update custom handlers for the new API", "prompt": "./src/migrations/v3.0.0/migrate-custom-handlers/prompt.md" }, "v4.0.0-upgrade-framework": { "version": "4.0.0", "description": "Upgrade the framework and reconcile call sites", "implementation": "./src/migrations/v4.0.0/upgrade-framework/migration", "prompt": "./src/migrations/v4.0.0/upgrade-framework/prompt.md" } }}Eseguire le Migrations
Sezione intitolata “Eseguire le Migrations”Gli utenti applicano le migrazioni del tuo plugin con il flusso in due fasi nx migrate — genera le migrazioni in sospeso, installa, quindi eseguile:
pnpm nx migrate my-plugin@latestpnpm nx migrate --run-migrationsyarn nx migrate my-plugin@latestyarn nx migrate --run-migrationsnpx nx migrate my-plugin@latestnpx nx migrate --run-migrationsbunx nx migrate my-plugin@latestbunx nx migrate --run-migrationsLe migrazioni agentiche e ibride vengono applicate dall’agente di codifica locale dell’utente durante nx migrate --run-migrations quando ne è disponibile uno.
Per il flusso completo dalla prospettiva dell’utente che aggiorna — incluso l’output di esempio per migrazioni deterministiche e agentiche — vedi Aggiornare il Tuo Workspace.