Tutorial: Criar um aplicativo TypeScript com o DocumentDB e implantar no Azure DocumentDB

Neste tutorial, você usa o DocumentDB como um banco de dados de desenvolvimento local em um contêiner do Docker, cria um aplicativo TypeScript com o driver do MongoDB e, em seguida, migra para Azure DocumentDB trocando sua cadeia de conexão.

Neste tutorial, você:

  • Iniciar o DocumentDB em um contêiner do Docker
  • Criar um aplicativo TypeScript
  • Conectar o aplicativo ao banco de dados local
  • Criar um cluster do DocumentDB Azure
  • Implantar o aplicativo no Azure DocumentDB

Pré-requisitos

Iniciar o contêiner

Use a imagem de contêiner do Docker para o DocumentDB para criar um banco de dados de desenvolvimento local.

  1. Faça o download da imagem de contêiner do DocumentDB.

    docker pull ghcr.io/documentdb/documentdb/documentdb-local:latest
    
  2. Inicie o contêiner com um nome de usuário e uma senha.

    docker run --detach --publish 10260:10260 --name documentdb ghcr.io/documentdb/documentdb/documentdb-local:latest --username <admin-username> --password <admin-password>
    

    Importante

    Substitua <admin-username> e <admin-password> com suas próprias credenciais.

  3. Verifique se o contêiner está em execução.

    docker ps --filter "name=documentdb"
    

    Importante

    O ponto de extremidade do gateway do DocumentDB está disponível na porta 10260. Use o seguinte formato cadeia de conexão para se conectar:

    mongodb://<admin-username>:<admin-password>@localhost:10260/?tls=true&tlsAllowInvalidCertificates=true
    
    Configurações Valor
    Ponto de extremidade https://localhost:10260
    Nome de usuário <admin-username>
    Senha <admin-password>
    TLS true
    TLS permitem certificados inválidos true

    Substitua <admin-username> e <admin-password> com suas próprias credenciais.

Criar o aplicativo

Crie um aplicativo Next.js e conecte-o ao banco de dados local.

  1. Crie um novo aplicativo Next.js em uma pasta vazia.

    npx create-next-app .
    
  2. Instale o driver Node.js MongoDB.

    npm install --save mongodb
    
  3. Crie um novo arquivo nomeado app/data.tsx com o código a seguir. Esse arquivo contém as ações do servidor que interagem com o banco de dados.

    "use server";
    
    import { MongoClient, ObjectId } from "mongodb";
    import { revalidatePath } from "next/cache";
    
    const connectionString = "<documentdb-connection-string>";
    
    const client = new MongoClient(connectionString);
    const db = client.db("work-management");
    const collection = db.collection("tasks");
    
    export type Todo = {
      id: string;
      title: string;
      completed: boolean;
    };
    
    export async function getTodos(): Promise<Todo[]> {
      const docs = await collection.find().sort({ _id: -1 }).toArray();
      return docs.map((doc) => ({
        id: doc._id.toString(),
        title: doc.title,
        completed: doc.completed,
      }));
    }
    
    export async function addTodo(formData: FormData) {
      const title = formData.get("title") as string;
      if (!title?.trim()) return;
      await collection.insertOne({ title: title.trim(), completed: false });
      revalidatePath("/");
    }
    
    export async function toggleTodo(formData: FormData) {
      const id = formData.get("id") as string;
      const doc = await collection.findOne({ _id: new ObjectId(id) });
      if (doc) {
        await collection.updateOne(
          { _id: new ObjectId(id) },
          { $set: { completed: !doc.completed } }
        );
      }
      revalidatePath("/");
    }
    
    export async function deleteTodo(formData: FormData) {
      const id = formData.get("id") as string;
      await collection.deleteOne({ _id: new ObjectId(id) });
      revalidatePath("/");
    }
    

    Importante

    Substitua o espaço reservado da string de conexão pelas credenciais especificadas anteriormente neste tutorial ao iniciar o contêiner.

  4. Exclua o arquivo existente app/page.tsx e substitua-o pelo código a seguir.

    import { getTodos, addTodo, toggleTodo, deleteTodo } from "./data";
    
    export default async function Home() {
      const todos = await getTodos();
    
      return (
        <div className="min-h-screen bg-black text-zinc-50 font-sans">
          <main className="max-w-lg mx-auto py-16 px-8">
            <h1 className="text-2xl font-semibold tracking-tight mb-8">Todo App</h1>
    
            <form action={addTodo} className="flex gap-2 mb-8">
              <input
                name="title"
                placeholder="Add a todo..."
                required
                className="flex-1 rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm text-zinc-100 placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-600"
              />
              <button type="submit" className="rounded-md bg-zinc-100 px-4 py-2 text-sm font-medium text-zinc-900 hover:bg-zinc-300 transition-colors">
                Add
              </button>
            </form>
    
            <ul className="space-y-2">
              {todos.map((todo) => (
                <li key={todo.id} className="flex items-center gap-3 rounded-md border border-zinc-800 bg-zinc-900 px-3 py-2">
                  <form action={toggleTodo}>
                    <input type="hidden" name="id" value={todo.id} />
                    <button type="submit" className="text-lg leading-none">{todo.completed ? "✅" : "⬜"}</button>
                  </form>
                  <span className={`flex-1 text-sm ${todo.completed ? "line-through text-zinc-500" : "text-zinc-100"}`}>{todo.title}</span>
                  <form action={deleteTodo}>
                    <input type="hidden" name="id" value={todo.id} />
                    <button type="submit" className="text-sm text-red-400 hover:text-red-300 transition-colors">✕</button>
                  </form>
                </li>
              ))}
            </ul>
    
            {todos.length === 0 && <p className="text-center text-sm text-zinc-500 mt-4">No todos yet.</p>}
          </main>
        </div>
      );
    }
    
  5. Executar o aplicativo localmente.

    npm run dev
    
  6. Abra http://localhost:3000 no navegador para verificar se o aplicativo está em execução e conectado ao banco de dados local.

    Captura de tela do novo aplicativo em execução em um navegador da Web com vários itens persistidos no banco de dados.

    Tip

    Você pode exibir os dados que esse aplicativo cria conectando-se ao contêiner do DocumentDB com a extensão DocumentDB para Visual Studio Code. O banco de dados é nomeado work-management e a coleção é nomeada tasks.

  7. Interrompa o aplicativo.

Criar um cluster do DocumentDB Azure

Crie um Azure cluster do DocumentDB para hospedar os dados do aplicativo na nuvem.

  1. Crie variáveis para o nome do cluster e o nome do grupo de recursos de destino.

    RESOURCE_GROUP_NAME="<resource-group-name>"
    CLUSTER_NAME="<cluster-name>"
    ADMIN_USERNAME="<admin-username>"
    ADMIN_PASSWORD="<admin-password>"
    

    Importante

    Substitua os valores do espaço reservado pelos seus. O nome do cluster deve ser globalmente exclusivo.

  2. Crie um cluster Azure DocumentDB.

    az cosmosdb mongocluster create \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --location "eastus" \
      --administrator-login $ADMIN_USERNAME \
      --administrator-login-password $ADMIN_PASSWORD \
      --server-version "8.0" \
      --shard-node-tier "M30" \
      --shard-node-ha false \
      --shard-node-disk-size-gb 128 \
      --shard-node-count 1
    
  3. Crie uma regra de firewall para permitir o acesso do seu endereço IP atual.

    MY_IP=$(curl -s ifconfig.me)
    
    az cosmosdb mongocluster firewall rule create \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --rule-name "allow-my-ip" \
      --start-ip-address $MY_IP \
      --end-ip-address $MY_IP
    
  4. Obtenha a string de conexão do cluster.

    az cosmosdb mongocluster show \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --query "connectionString" \
      --output tsv
    
  5. Registre o valor da cadeia de conexão. Você o usará na próxima etapa.

Conectar o aplicativo ao Azure DocumentDB

Atualize o aplicativo para se conectar ao Azure DocumentDB em vez do contêiner local.

  1. Em app/data.tsx, substitua a string de conexão local pela string de conexão do Azure DocumentDB.

    const connectionString = "<azure-documentdb-connection-string>";
    

    Importante

    Substitua <azure-documentdb-connection-string> pelo cadeia de conexão que você registrou na etapa anterior. O cadeia de conexão do portal não inclui a senha. Substitua o espaço reservado <password> na cadeia de conexão pela senha que você especificou ao criar o cluster.

  2. Inicie o aplicativo novamente.

    npm run dev
    
  3. Abra http://localhost:3000 no navegador. O aplicativo agora lê e grava dados em seu cluster Azure DocumentDB.

Limpar os recursos

Quando você não precisar mais dos recursos criados neste tutorial, exclua-os para evitar incorrer em encargos.

  1. Exclua o cluster Azure DocumentDB.

    az cosmosdb mongocluster delete \
      --resource-group $RESOURCE_GROUP_NAME \
      --cluster-name $CLUSTER_NAME \
      --yes
    
  2. Pare e remova o contêiner do DocumentDB.

    docker stop documentdb
    docker rm documentdb
    

Próxima etapa