@m3r/sdk 0.5.0
Padrões de desenvolvimento
Como fatiar a extensão por pastas — tabelas, telas, nav, relatórios e IPs — e ligar tudo no index.ts.
O Core não lê a sua árvore de pastas. Ele lê o que o activate declara. A pasta existe para você não misturar venda com estoque num único arquivo.
O m3r.json → entry aponta para src/index.ts. Esse arquivo só orquestra. Cada domínio registra o próprio contrato.
Árvore
my-extension
src
shared
vendas
tabelas
telas
relatorios
compras/ só entra quando houver tabela, tela ou IP daquele domínio. Não crie pasta vazia.
Referência viva: sample 0.6.1 (examples/sample-extension).
O que vai em cada pasta
| Pasta | Contém | Chama |
|---|---|---|
tabelas/ | um arquivo por tabela | ctx.ext.tables.ensure |
telas/ | um arquivo por code | ctx.ext.screens.define |
relatorios/ | um arquivo por code | ctx.ext.reports.define |
nav.ts | itens de menu daquele domínio | ctx.ext.nav.define |
ips.ts | handlers entryPoints.on | ctx.subscriptions.add |
events.ts | handlers events.on | ctx.subscriptions.add |
register.ts | ordem do domínio | as funções acima |
shared/ | helper sem ensure/define | records, payload |
index.ts | defineExtension | registerVendas, registerCompras, … |
Um arquivo de tabela não define tela. Uma tela não registra IP. IP que grava linha importa o helper de shared/, não o ensure.
Ordem no register
Tela aponta para table que já passou pelo ensure. Nav aponta para tela ou relatório já definidos. IP AFTER_SAVE pode gravar record — a tabela já existe.
Como o index.ts inicia
Não registre entryPoints.on no index. Não chame tables.ensure no index. O deactivate não desfaz ensure — só encerra o processo.
m3r.json lista todos os tables[], screens[], nav[], reports[] da extensão, de todos os domínios. O validate varre src/**/*.ts.
Nomes
| Coisa | Padrão | Exemplo |
|---|---|---|
| Pasta de domínio | slug do módulo de negócio | vendas, compras, estoque, financeiro, rh |
Tabela name | [a-z][a-z0-9_]{1,47} | demo_auditoria, demo_lote |
| Coluna | mesmo slug | pedido_codigo |
Tela / nav / relatório code | [a-z][a-z0-9_.-]{1,62} | demo.auditoria.novo |
| Prefixo | id da extensão ou domínio | demo. |
Não use o código físico FAX#### como name da tabela. name é lógico. O físico vem no retorno do ensure.
Tabela documento vs física
document (padrão) | physical | |
|---|---|---|
| Onde | JSONB em FADEV07 | Postgres FAX0001–FAX9999 |
| Quem cria | Core, sem DDL seu | Core (CREATE TABLE), nunca a extensão |
physicalName | — | opcional; omitido = Core atribui e devolve |
uniqueKeys | o Core checa as linhas JSONB | UNIQUE de verdade no Postgres |
| Quando usar | cadastro leve, auditoria | volume, unicidade, relatório denso |
Colunas reservadas (não declare): id, company_id, extension_id, created_by, created_at, updated_at, delete_date, table_id.
remove é soft delete. Isolamento: companyId + extensionId. Ambiente FADEV02 não separa dado.
Evolução só adiciona coluna. Sem drop, rename, troca de tipo ou de storage.
Detalhe da API: ctx.ext.
Telas
kind | Host | Uso |
|---|---|---|
Page | /apps/extensions/{code} | lista + formulário |
Modal | overlay a partir de venda ou action | bind SdkFormBind |
actions[].opens: openScreen:, openModal:, openReport:. Sem prefixo = tela.
Depois do mount: IP.EXT.SCREEN.ON_LOAD — setField / hideField / disableField. Não nega o load.
Menu
placement.parent ou placement.section: Extensions. Nunca os dois.
SdkMenuParent (const → menuKey do ERP):
| Const | menuKey |
|---|---|
Vendas | vendas |
Comissoes | commissions |
Devolucoes | returns |
Crm | crm |
Relatorios | reports |
Cadastros | cadastros |
Operacoes | operacoes |
Producao | producao |
EntradaDocumentos | entrada-documentos |
Movimentacao | movimentacao |
Inventory | inventory |
PurchaseIntelligence | purchase-intelligence |
FiscalOperational | fiscal-operational |
NfeMonitor | nfe-monitor |
Sped | sped |
RhGestao | rh-gestao |
RhFolha | rh-folha |
Lancamentos | lancamentos |
RecuperacaoCredito | recuperacao-credito |
Typo (parent: "Vendas") não compile. Use SdkMenuParent.Vendas.
Novo domínio
- Pasta
src/compras/comtabelas/,telas/,register.ts. registerComprasna mesma ordem (tabela → tela → nav → …).- Uma linha no
activate:await registerCompras(ctx). - Incluir os novos ids no
m3r.json. m3r validate.
ctx.m3r.purchase ainda é planned. Pasta compras/ hoje serve para tabela/tela/IP da extensão, não para chamar o módulo de compras do Core.
