Pular para o conteúdo

Projetos TypeScript

O gerador de projetos TypeScript pode ser usado para criar uma biblioteca ou aplicação TypeScript moderna configurada com as melhores práticas, como ECMAScript Modules (ESM), referências de projeto do TypeScript, Vitest para executar testes e Biome para linting e formatação.

Você pode gerar um novo projeto TypeScript de duas maneiras:

Terminal window
pnpm nx g @aws/nx-plugin:ts#project
Você também pode realizar uma execução simulada para ver quais arquivos seriam alterados
Terminal window
pnpm nx g @aws/nx-plugin:ts#project --dry-run
ParâmetroTipoPadrãoDescrição
name Obrigatóriostring-Nome do projeto TypeScript
directory stringpackagesDiretório pai onde a biblioteca é colocada.
subDirectory string-O subdiretório onde a biblioteca é colocada. Por padrão, este é o nome da biblioteca.
preferInstallDependencies booleantrueSe deve preferir instalar dependências após a execução do gerador. Defina como false para adiar a instalação ao executar múltiplos geradores em lote (uma instalação ainda é executada se necessário para que geradores subsequentes possam calcular o grafo de projetos Nx); instale uma vez no final.

O gerador criará a seguinte estrutura de projeto no diretório <directory>/<name>:

  • Directorysrc Código-fonte TypeScript
    • index.ts
  • package.json Manifesto do projeto definindo o nome do pacote e dependências do projeto
  • project.json Configuração do projeto e alvos de build
  • tsconfig.json Configuração base do TypeScript para este projeto (estende o tsconfig.base.json da raiz do workspace)
  • tsconfig.lib.json Configuração do TypeScript para sua biblioteca (seu código-fonte de runtime ou empacotado)
  • tsconfig.spec.json Configuração do TypeScript para seus testes
  • vitest.config.mts Configuração para o Vitest

Você também notará algumas mudanças nos seguintes arquivos na raiz do seu workspace:

  • nx.json A configuração do Nx é atualizada para configurar o plugin @nx/js/typescript para o seu projeto
  • tsconfig.base.json um alias do TypeScript é configurado para o seu projeto para que ele possa ser importado por outros projetos no seu workspace
  • tsconfig.json uma referência de projeto do TypeScript é adicionada para o seu projeto

Adicione seu código TypeScript no diretório src.

Como seu projeto TypeScript é um ES Module, certifique-se de escrever suas declarações de importação com a sintaxe ESM correta, referenciando explicitamente a extensão do arquivo:

index.ts
import { sayHello } from './hello.js';

O ponto de entrada para o seu projeto TypeScript é src/index.ts. Você pode adicionar exportações aqui para qualquer coisa que você gostaria que outros projetos pudessem importar:

src/index.ts
export { sayHello } from './hello.js';
export * from './algorithms/index.js';

Importando o Código da Sua Biblioteca em Outros Projetos

Seção intitulada “Importando o Código da Sua Biblioteca em Outros Projetos”

Aliases do TypeScript para o seu projeto são configurados no tsconfig.base.json do workspace, o que permite que você referencie seu projeto TypeScript de outros projetos TypeScript:

packages/my-other-project/src/index.ts
import { sayHello } from '@my-scope/my-library';

Quando você adiciona uma declaração de importação para um novo projeto no seu workspace pela primeira vez, você provavelmente verá um erro no seu IDE semelhante ao abaixo:

Erro de importação
Terminal window
File '/path/to/my/workspace/packages/my-library/src/index.ts' is not under 'rootDir' '/path/to/my/workspace/packages/my-consumer'. 'rootDir' is expected to contain all source files.
File is ECMAScript module because '/path/to/my/workspace/package.json' has field "type" with value "module" ts(6059)
File '/path/to/my/workspace/packages/my-library/src/index.ts' is not listed within the file list of project '/path/to/my/workspace/packages/my-consumer/tsconfig.lib.json'. Projects must list all files or use an 'include' pattern.
File is ECMAScript module because '/path/to/my/workspace/package.json' has field "type" with value "module" ts(6307)

Isso ocorre porque uma referência de projeto ainda não foi configurada, e o projeto importado ainda não foi declarado como uma dependência do workspace no package.json do seu projeto.

Seu workspace está configurado com geradores de sincronização que gerenciam ambos para você, então você não precisa configurá-los manualmente. Simplesmente execute o seguinte comando e o Nx adicionará a configuração necessária:

Terminal window
pnpm nx sync
Terminal window
NX The workspace is out of sync
[@nx/js:typescript-sync]: Some TypeScript configuration files are missing project references to the projects they depend on, contain stale project references, or have duplicate project references.
[@aws/nx-plugin:ts#sync]: Local project dependencies are out of sync. The following workspace dependencies will be declared:
packages/my-other-project/package.json:
- @my-scope/my-library: workspace:*
Syncing the workspace...
The workspace was synced successfully!

O gerador de sincronização do TypeScript do Nx adiciona a referência do projeto, e o gerador ts#sync do plugin declara o projeto importado no package.json do seu projeto (workspace:* onde o gerenciador de pacotes suporta o protocolo workspace, * no npm e yarn classic), para que o gerenciador de pacotes vincule o projeto local na instalação. Depois disso, o erro no seu IDE deve desaparecer e você está pronto para usar sua biblioteca.

Se você adicionar entradas personalizadas de compilerOptions.paths no tsconfig.json de um projeto, o TypeScript para de herdar os aliases do workspace definidos em tsconfig.base.json. O gerador oculto ts#sync é executado antes do alvo compile (configurado em nx.json) para copiar quaisquer aliases base ausentes nos arquivos tsconfig.json, tsconfig.lib.json e tsconfig.app.json que já declaram paths. Para desativar, remova @aws/nx-plugin:ts#sync de targetDefaults.compile.syncGenerators em nx.json.

Cada projeto TypeScript declara suas dependências de runtime de terceiros em seu próprio package.json. Ferramentas de build e teste compartilhadas entre projetos são definidas no package.json raiz.

Para adicionar uma dependência de runtime a um projeto, instale-a nesse projeto:

Terminal window
pnpm add some-npm-package --filter my-library

Você também pode executar o comando simples add/install do seu gerenciador de pacotes de dentro do diretório do projeto.

Para adicionar uma ferramenta de desenvolvimento compartilhada, instale-a na raiz do workspace:

Terminal window
pnpm add -Dw some-dev-tool

Para gerenciadores de pacotes que suportam catálogos (pnpm, yarn e bun), os geradores registram cada versão no catálogo e a referenciam com o protocolo catalog: (por exemplo, "zod": "catalog:"), então o catálogo é a única fonte de verdade para versões, independentemente de qual projeto declara a dependência. Isso ajuda você a seguir uma política de versão única, evitando conflitos de tipo e múltiplas cópias de pacotes em bundles de implantação.

Quando você adicionar uma nova dependência por conta própria, mantenha-a no catálogo também:

O workspace define catalogMode: strict, então pnpm add registra a versão no catálogo e a referencia automaticamente — sem etapas extras.

Terminal window
pnpm add some-npm-package --filter my-library

Os catálogos são habilitados por padrão. Para desativá-los, crie seu workspace com --catalog false:

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

Ou defina-o em aws-nx-plugin.config.mts a qualquer momento:

aws-nx-plugin.config.mts
export default {
packageManager: {
catalogs: false,
},
} satisfies AwsNxPluginConfig;

Com os catálogos desabilitados, os geradores escrevem versões de dependências diretamente no package.json de cada projeto, e manter as versões alinhadas entre projetos é sua responsabilidade.

Se você preferir declarar todas as dependências apenas no package.json raiz (sem declarações de dependências por projeto), desative a regra de lint no biome.json do workspace:

biome.json
{
"linter": {
"rules": {
"correctness": {
"noUndeclaredDependencies": "off"
}
}
}
}

Os projetos resolvem pacotes instalados na raiz no momento do build, então tudo ainda é construído — você abre mão de manifestos por projeto como um registro preciso das dependências de cada projeto (o que importa se você posteriormente publicar um projeto ou dividir o repositório).

Quando você usa seu projeto TypeScript como código de runtime (por exemplo, como o handler para uma função AWS Lambda), é recomendado que você use uma ferramenta como Rolldown para empacotar seu projeto, pois isso pode fazer tree-shake para garantir que apenas as dependências que seu projeto realmente referencia sejam incluídas.

Você pode conseguir isso adicionando um alvo como o seguinte ao seu arquivo project.json:

{
...
"targets": {
...
"bundle": {
"cache": true,
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/dist/packages/my-library/bundle"],
"options": {
"command": "rolldown -c rolldown.config.ts"
}
},
},
}

E adicionando o arquivo rolldown.config.ts da seguinte forma:

rolldown.config.ts
import { defineConfig } from 'rolldown';
export default defineConfig([
{
input: 'src/index.ts',
output: {
file: '../../dist/packages/my-library/bundle/index.js',
format: 'cjs',
codeSplitting: false,
},
},
]);

Seu projeto TypeScript está configurado com um alvo build (definido em project.json), que você pode executar via:

Terminal window
pnpm nx build <project-name>

Onde <project-name> é o nome totalmente qualificado do seu projeto.

O alvo build irá compilar, fazer lint e testar seu projeto.

A saída do build pode ser encontrada na pasta dist raiz no seu workspace, dentro de um diretório para seu pacote e alvo, por exemplo dist/packages/<my-library>/tsc

Para fazer o build de todos os projetos no seu workspace, execute:

Terminal window
pnpm nx run-many --target build

Ou use o comando abreviado:

Terminal window
pnpm build

Vitest está configurado para testar seu projeto.

Os testes devem ser escritos em arquivos .spec.ts ou .test.ts, co-localizados na pasta src do seu projeto.

Por exemplo:

  • Directorysrc
    • hello.ts Código-fonte da biblioteca
    • hello.spec.ts Testes para hello.ts

O Vitest fornece sintaxe semelhante ao Jest para definir testes, com utilitários como describe, it, test e expect.

hello.spec.ts
import { sayHello } from './hello.js';
describe('sayHello', () => {
it('should greet the caller', () => {
expect(sayHello('Darth Vader')).toBe('Hello, Darth Vader!');
});
});

Para mais detalhes sobre como escrever testes e recursos como simular dependências, consulte a documentação do Vitest

Os testes serão executados como parte do alvo build para o seu projeto, mas você também pode executá-los separadamente executando o alvo test:

Terminal window
pnpm nx test <project-name>

Você pode executar um teste individual ou conjunto de testes usando a flag -t do Vitest. Passe-a após um separador -- para que o Nx a encaminhe para o Vitest em vez de consumi-la como sua própria opção --target:

Terminal window
pnpm nx test <project-name> -- -t 'sayHello'

Os projetos TypeScript usam Biome para linting e formatação. O Biome é configurado no arquivo biome.json da raiz do workspace — alterações nele se aplicam a todos os projetos TypeScript no seu workspace e garantem consistência.

Para invocar o linter para verificar seu projeto, você pode executar o alvo lint.

Terminal window
pnpm nx lint <project-name>

A maioria dos problemas de linting ou formatação pode ser corrigida automaticamente executando com o argumento --configuration=fix.

Terminal window
pnpm nx lint <project-name> --configuration=fix

Da mesma forma, se você gostaria de corrigir todos os problemas de lint em todos os pacotes no seu workspace, você pode executar:

Terminal window
pnpm nx run-many --target lint --all --configuration=fix

Para evitar que problemas de linting o atrasem durante o desenvolvimento (particularmente se você tiver problemas não corrigíveis automaticamente no seu projeto), você pode executar um build com a configuração skip-lint:

Terminal window
pnpm nx run-many --target build --configuration=skip-lint

Isso ignora o alvo de lint inteiramente durante o build.