Tabelas de Apoio
Tabelas de Apoio são tabelas relacionais gerenciadas pelo TunnelHub para guardar dados operacionais que precisam ser consultados ou alterados por automações.
Use esse recurso quando o dado tem estrutura própria, chave primária, colunas tipadas e precisa ir além de um simples de/para.
Quando usar
Seção intitulada “Quando usar”Tabelas de Apoio fazem sentido para cenários como:
- cache operacional compartilhado por execuções;
- controle de processamento por entidade de negócio;
- tabelas auxiliares com várias colunas;
- dados importados por CSV e consumidos por automações;
- estado de integração que precisa ser visível e administrado no produto.
Se o caso for apenas traduzir um valor de origem para um valor de destino, prefira Tabelas De/Para.
Modelo de dados
Seção intitulada “Modelo de dados”Cada Tabela de Apoio possui:
externalCode, usado por automações e SDK;- descrição funcional;
- pacote associado;
- lista opcional de usuários limitados;
schemaDefinition, com colunas e tipos;primaryKey, com uma ou mais colunas;indexesDefinition, para índices adicionais.
Tipos de coluna suportados:
TEXT;INTEGER;REAL;NUMERIC;BOOLEAN;DATETIME.
Além da chave primária definida no schema, o TunnelHub mantém um rowId técnico para operações sobre linhas.
Operações disponíveis
Seção intitulada “Operações disponíveis”No produto, Tabelas de Apoio permitem:
- criar e editar a definição da tabela;
- listar linhas com paginação, filtros e ordenação;
- inserir, editar e remover linhas;
- importar dados por CSV;
- exportar dados por CSV;
- controlar visibilidade para usuários limitados.
Alterações de schema são tratadas pela plataforma. Mudanças destrutivas ou troca de chave primária podem exigir recriação planejada da tabela.
Uso em automações
Seção intitulada “Uso em automações”Para usar Tabelas de Apoio em uma automação, associe a tabela à automação no produto e habilite o runtime compatível no tunnelhub.yml.
Exemplo:
configuration: runtimeEngine: LAMBDA entrypoint: index.handler runtime: nodejs24.x memorySize: 1024 timeout: 60 runInVpc: true sqlTables: enabled: trueRequisitos quando sqlTables.enabled é true:
runtimedeve sernodejs24.x;runInVpcdeve sertrue;runtimeEnginedeve serLAMBDAouECS_FARGATE.
Uso no SDK
Seção intitulada “Uso no SDK”O SDK expõe o helper SqlTables para operar linhas durante a execução.
Exemplo conceitual:
const sqlTables = new SqlTables(event);
const inserted = await sqlTables.insertRow('customer-cache', { document: '12345678900', name: 'Cliente exemplo', active: true,});
const page = await sqlTables.queryRows('customer-cache', { current: 1, pageSize: 20, filter: { document: ['12345678900'], },});
await sqlTables.updateRow('customer-cache', inserted.rowId, { name: 'Cliente atualizado',});O helper acessa o arquivo SQLite montado pela plataforma durante a execução. Ele não deve ser usado fora do runtime gerenciado do TunnelHub.
Testes locais
Seção intitulada “Testes locais”Para testes unitários com Jest, defina SDK.testMode = true antes de construir a integração. Nesse modo, o construtor de
SqlTables não valida os requisitos do runtime gerenciado. As operações continuam precisando de mock explícito.
testMode não fornece persistência local e não simula SQLite, EFS ou DynamoDB. O exemplo a seguir usa fixtures por
externalCode e mantém as inserções apenas em memória durante o processo do Jest:
import fs from 'node:fs';import path from 'node:path';import {ProcessorPayload, SDK, SqlTables} from '@tunnelhub/sdk';
type CustomerCacheRow = { document: string; name: string; active: boolean;};
type MockRow = { rowId: string; values: CustomerCacheRow;};
const rowsByTable = new Map<string, MockRow[]>();let nextRowId = 1;
const testEvent = { tenantId: 'test-tenant', environmentId: 'test-environment', automationId: 'test-automation', executionId: 'test-execution', systems: [], parameters: {},} as ProcessorPayload;
function getRows(externalCode: string): MockRow[] { const rows = rowsByTable.get(externalCode); if (rows) return rows;
const fixturePath = path.join(__dirname, 'data', `${externalCode}.json`); const fixture = JSON.parse(fs.readFileSync(fixturePath, 'utf8')) as MockRow[]; const clonedRows = structuredClone(fixture); rowsByTable.set(externalCode, clonedRows); return clonedRows;}
describe('CustomerCacheIntegration', () => { beforeAll(() => { SDK.testMode = true; });
beforeEach(() => { jest.spyOn(SqlTables.prototype, 'queryRows').mockImplementation(async (externalCode, request = {}) => { const current = request.current ?? 1; const pageSize = request.pageSize ?? 20; const rows = getRows(externalCode);
return { success: true, current, pageSize, total: rows.length, data: rows.slice((current - 1) * pageSize, current * pageSize), }; });
jest.spyOn(SqlTables.prototype, 'insertRow').mockImplementation(async (externalCode, values) => { const row = {rowId: `test-row-${nextRowId++}`, values}; getRows(externalCode).push(row as MockRow); return row; }); });
afterEach(() => { jest.restoreAllMocks(); rowsByTable.clear(); nextRowId = 1; });
afterAll(() => { SDK.testMode = false; });
test('insere cliente ausente do cache', async () => { const sqlTables = new SqlTables(testEvent);
await sqlTables.insertRow('customer-cache', {document: '12345678900', name: 'Ana', active: true});
expect(await sqlTables.queryRows('customer-cache')).toEqual({ success: true, current: 1, pageSize: 20, total: 1, data: [ { rowId: 'test-row-1', values: {document: '12345678900', name: 'Ana', active: true}, }, ], }); });});Organize as fixtures em __tests__/data/<externalCode>.json. Cada arquivo deve conter uma lista de linhas no formato
retornado por queryRows. Por exemplo, o arquivo __tests__/data/customer-cache.json usado no teste de inserção pode
conter apenas:
[]Uma fixture vazia representa uma tabela existente sem registros.
O mock é apropriado para testar o fluxo da automação. Ele não reproduz schema, constraints, normalização de tipos nem o
comportamento do SQLite. Teste esses cenários com SqlTables real, usando um arquivo SQLite preparado ou o runtime
gerenciado do TunnelHub.
Boas práticas
Seção intitulada “Boas práticas”- escolha
externalCodeestável e orientado ao domínio; - defina uma chave primária natural quando possível;
- modele colunas com tipos claros;
- use índices somente para consultas recorrentes;
- evite armazenar segredos ou credenciais;
- prefira Tabelas de Apoio para dados estruturados e Tabelas De/Para para mapeamentos simples.