Como acelerar o desenvolvimento de soluções móveis offline utilizando o comando sf Modeler workspace add, decifrar as transformações automáticas de nomenclatura do compilador e evitar erros de duplicação de prefixos.
No desenvolvimento de aplicações enterprise para o Salesforce Consumer Goods Cloud (CGC) Modeler, criar novas funcionalidades a partir do zero digitando contratos XML manualmente é uma receita para frustração e perda de tempo. Cada novo Business Object (BO) exige, além de seu próprio arquivo XML, um DataSource correspondente, a declaração de schemas XSD e até onze arquivos JavaScript individuais (.bl.js) contendo comentários canônicos protegidos, marcadores de inserção com indentação exata de quatro espaços e metadados JSDoc completos.
Escrever essa estrutura à mão consome horas de engenharia e quase invariavelmente resulta em erros de compilação como 03112630 (marcador inicial ausente) ou 00000001 (violação estrutural).
Para eliminar esse trabalho repetitivo, a Salesforce disponibiliza o gerador oficial de scaffolding embutido no plugin do CLI: o comando sf modeler workspace add (ou seu atalho universal sf mdl add).
No entanto, o gerador do CLI não é um simples copiador de arquivos. Ele opera baseado em um motor de templates interno (templateEngine.js) que transforma automaticamente os nomes passados por parâmetro, injetando prefixos de tipo e identificadores de arquitetura corporativa.
Se o desenvolvedor não compreender essas regras automáticas, ele se deparará com aberrações de nomenclatura (como BoMyBoCallHelper), quebras silenciosas em bindings do ProcessContext e falhas inesperadas de automação em esteiras de CI/CD.
Neste artigo técnico, vamos dissecar o funcionamento interno do comando de scaffolding, analisar os tipos de artefatos gerados, decifrar as regras de transformação de strings do motor de templates e estruturar um fluxo de trabalho profissional para times de arquitetura e desenvolvimento.
1. A anatomia do comando: sf Modeler workspace add
O comando de scaffolding é responsável por criar a topologia de pastas e os esqueletos estruturais de contratos XML e lógica de negócios.
A sintaxe e seus atalhos:
O desenvolvedor pode utilizar a forma verbosa ou os atalhos rápidos equivalentes:
# Forma completa
sf modeler workspace add --type <TIPO> --module <MODULO> --name <NOME>
# Atalhos canônicos equivalentes
sf mdl ws add -t <TIPO> -m <MODULO> -n <NOME>
sf mdl add -t <TIPO> -m <MODULO> -n <NOME>
Flags de configuração:
-t, --type: O tipo de artefato que será gerado (ver catálogo abaixo).-m, --module: O módulo de destino dentro desrc/(exemplo:Call,Order,Customer).-n, --name: O nome identificador do artefato. Deve ser passado sempre limpo, sem prefixos de tipo.-p, --path: Caminho opcional do workspace (quando omitido, utiliza o diretório atual de execução).
2. O catálogo de tipos de artefatos gerados
O parâmetro --type define a complexidade da árvore de arquivos que será criada no workspace:
Valor de --type | O Que o CLI Gera no Workspace | Arquivos Físicos Criados |
|---|---|---|
module | Cria um módulo de negócio completo com todas as subpastas. | Estrutura de pastas: {Nome}/BO/, {Nome}/DS/, {Nome}/PL/, {Nome}/PR/, {Nome}/TB/. |
businessobject | Um BO completo, seu DataSource e 11 hooks de ciclo de vida. | Bo{Nome}.businessobject.xml, DsBo{Nome}_sf.datasource.xml e 11 arquivos .bl.js em Mv2/. |
listobject | Um ListObject completo, seu ListItem, DataSource e 6 hooks. | Lo{Nome}.listobject.xml, Li{Nome}.listitem.xml, DsLo{Nome}_sf.datasource.xml e 6 arquivos .bl.js. |
lookupobject | Um LookupObject leve e seu DataSource de leitura. | Lu{Nome}.lookupobject.xml e DsLu{Nome}_sf.datasource.xml. |
datasource | Apenas o arquivo de DataSource isolado. | Ds{Nome}_sf.datasource.xml. |
businesslogic | Um método customizado em um BO ou LO existente. | Cria 1 arquivo .bl.js e injeta a tag <Method> automaticamente no XML do objeto via XPath. |
process | Um ProcessFlow completo (e opção de criar a UI). | {Mod}_{Nome}Process.processflow.xml com namespace configurado. |
userinterface | Uma tela de interface vinculada a um processo existente. | {Mod}_{Nome}UI.userinterface.xml e adiciona a ação VIEW no processo. |
3. O ganho massivo de produtividade: Os 11 hooks de ciclo de vida
O maior benefício de gerar um Business Object através do CLI (--type businessobject) reside na criação instantânea da pasta Mv2/ contendo os 11 métodos de ciclo de vida exigidos pelo compilador:
src/Call/BO/BoMyVisitHelper/Mv2/
├── CreateAsync/
│ ├── BoMyVisitHelper.BeforeCreateAsync.bl.js
│ └── BoMyVisitHelper.AfterCreateAsync.bl.js
├── Initialize/
│ ├── BoMyVisitHelper.BeforeInitialize.bl.js
│ └── BoMyVisitHelper.AfterInitialize.bl.js
├── LoadAsync/
│ ├── BoMyVisitHelper.BeforeLoadAsync.bl.js
│ └── BoMyVisitHelper.AfterLoadAsync.bl.js
├── SaveAsync/
│ ├── BoMyVisitHelper.BeforeSaveAsync.bl.js
│ └── BoMyVisitHelper.AfterSaveAsync.bl.js
└── DoValidateAsync/
├── BoMyVisitHelper.BeforeDoValidateAsync.bl.js
└── BoMyVisitHelper.AfterDoValidateAsync.bl.js
Cada um desses arquivos .bl.js já é gerado rigorosamente em conformidade com as regras do compilador:
- Inicia com
'use strict';na linha 1. - Contém o bloco de comentários protegidos (linhas 3 a 21) verbatim.
- Possui o bloco JSDoc com
@function,@this,@kind,@asynce@namespace CUSTOMpreenchidos. - Contém os marcadores de três linhas
Add your customizing javaScript code below/abovecom exatamente quatro espaços de indentação. - Contém o corpo inicial seguro:
var promise = when.resolve(context); return promise;.
Esse scaffolding economiza centenas de linhas de código boilerplate e garante que o projeto passe na compilação (sf mdl build) imediatamente após a geração.
4. O motor interno de naming: Como o CLI transforma strings
Ao inspecionar o arquivo templateEngine.js do plugin oficial da Salesforce, descobrimos a lógica exata que governa a transformação de nomes:
// Lógica interna do plugin @ind-rcg/modeler-sfdx-cli-plugin
var NameIdentifier;
!function(e){ e.Core = ""; e.Custom = "My"; }(NameIdentifier || (NameIdentifier = {}));
O framework do Modeler separa rigidamente artefatos nativos da Salesforce (Core) de extensões criadas pelo cliente ou parceiro (Custom). Para evitar que uma atualização futura de pacote sobrescreva arquivos customizados, o CLI impõe o identificador My por padrão em qualquer artefato gerado.
Essa arquitetura resulta em duas regras automáticas de transformação:
Regra 1: O prefixo do tipo é adicionado automaticamente
O valor passado na flag --type dita o prefixo arquitetural:
businessobjectadicionaBolistobjectadicionaLolookupobjectadicionaLudatasourceadicionaDs
Regra 2: O identificador custom (My) é injetado por padrão
Como todo recurso novo pertence ao namespace de customização, o CLI concatena My entre o prefixo do tipo e o nome passado:
--name VisitHelpertransforma-se emBoMyVisitHelper--name PendingOrderstransforma-se emLoMyPendingOrders--name CustomerLookuptransforma-se emLuMyCustomerLookup
5. A armadilha crítica: O erro do nome pré-corrigido (BoMyBoX)
A armadilha mais comum entre desenvolvedores que utilizam o CLI pela primeira vez é tentar “ajudar” a ferramenta passando o nome já com o prefixo do tipo.
Observe o que acontece quando você comete esse equívoco:
# ❌ COMANDO ERRADO: Passando o prefixo "Bo" manualmente
sf mdl add -t businessobject -m Call -n BoCallSpeechHelper
# RESULTADO GERADO PELO MOTOR:
# Nome da classe: BoMyBoCallSpeechHelper
# Arquivo XML: BoMyBoCallSpeechHelper.businessobject.xml
# DataSource: DsBoMyBoCallSpeechHelper_sf.datasource.xml
O motor de templates do CLI não valida se a string já possui Bo no início. Ele simplesmente aplica a fórmula: Bo + My + --name. O resultado é um nome bizarro com prefixos duplicados que polui o workspace e gera confusão arquitetural.
A forma correta:
Passe sempre o nome limpo e sem prefixos:
# ✅ COMANDO CORRETO
sf mdl add -t businessobject -m Call -n CallSpeechHelper
# RESULTADO CANÔNICO:
# Nome da classe: BoMyCallSpeechHelper
# Arquivo XML: BoMyCallSpeechHelper.businessobject.xml
# DataSource: DsBoMyCallSpeechHelper_sf.datasource.xml
6. O efeito cascata do prefixo “My” nas demais camadas
Como o objeto gerado chama-se BoMyCallSpeechHelper (e não BoCallSpeechHelper), o arquiteto deve assegurar que **todas as referências subsequentes no ProcessFlow e na UserInterface utilizem o nome com My**.
Se você tentar referenciar o nome sem o prefixo, o compilador não encontrará o tipo:
<!-- No Call_VisitDetailProcess.processflow.xml -->
<ProcessContext>
<Declarations>
<!-- ✅ CORRETO: Utiliza o nome canônico gerado pelo CLI -->
<Declaration name="mySpeechHelper" type="BoMyCallSpeechHelper" />
<!-- ❌ ERRADO: O tipo BoCallSpeechHelper NÃO existe no workspace! -->
<!-- <Declaration name="mySpeechHelper" type="BoCallSpeechHelper" /> -->
</Declarations>
</ProcessContext>
<EntryActions>
<!-- ✅ Ação de carga apontando para o tipo correto -->
<Action name="initSpeechHelper" actionType="LOAD" type="BoMyCallSpeechHelper">
<Return name="ProcessContext::mySpeechHelper" />
</Action>
</EntryActions>
7. Derivação de métodos e a pegadinha do CLI interativo
Ao utilizar o comando para adicionar um método de negócio a um objeto existente:
sf mdl add --type businesslogic --module Call --name MyCustomCalculation
Code language: JavaScript (javascript)
O CLI executa duas transformações distintas de capitalização:
- Nome do Método (
getMethodName): Converte o primeiro caractere para minúsculo (myCustomCalculation). É esse nome que vai para a tag<Method name="myCustomCalculation" />e para a anotação@functionno JSDoc. - Nome do Arquivo Físico (
getMethodFileName): Mantém o primeiro caractere maiúsculo (BoMyHelper.MyCustomCalculation.bl.js).
A restrição de execução interativa (atenção ao CI/CD!):
Existe uma diferença operacional crítica entre os tipos de comandos do scaffolding:
- Tipos Autônomos (
businessobject,listobject,datasource,module): Solicitam apenas confirmação de criação (Y/n). Podem ser automatizados em scripts via pipe:echo "Y" | sf mdl add -t businessobject -m Call -n MyService - Tipos Dependentes (
businesslogic,userinterface): Exigem que o usuário selecione interativamente em uma lista qual é o objeto ou processo pai. Esses comandos utilizam a biblioteca@inquirer/prompts, que exige obrigatoriamente um terminal TTY real.
Se você tentar rodar sf mdl add -t businesslogic em uma esteira de CI/CD não interativa (como GitHub Actions ou GitLab CI sem TTY alocado), o processo será abortado imediatamente com o erro:
User force closed the prompt with 13 null
Code language: JavaScript (javascript)
Para esteiras de automação contínua, crie os métodos customizados utilizando templates pré-definidos via script bash em vez de acionar os prompts interativos do plugin.

Conclusão
O comando de scaffolding sf modeler workspace add é uma das ferramentas mais poderosas de produtividade no ecossistema do Salesforce Consumer Goods Cloud. Ao compreender as regras internas de derivação do motor de templates, passar nomes limpos sem prefixos manuais e respeitar a injeção corporativa do identificador My, arquitetos e desenvolvedores constroem novos módulos com velocidade incomparável, total conformidade com os schemas XSD e garantia de compatibilidade com futuros upgrades da plataforma.
Como a sua equipe estrutura a geração de novos artefatos e a automação de templates no Modeler? Deixe suas dúvidas e experiências nos comentários abaixo ou compartilhe este guia com seu time técnico no LinkedIn.
