jsegd-fluig-lint
v2.1.0
Published
Plugin de lint para projetos Fluig utilizando ESLint.
Readme
jsegd-fluig-lint
Plugin ESLint para validar arquivos JavaScript executados no Rhino (Java 11) da plataforma Fluig, garantindo compatibilidade com ES5 e expondo automaticamente os globais declarados em jsegd-fluig-types.
Compatível com ESLint 10 e Flat Config.
🎯 Objetivo
O Fluig executa scripts JavaScript em um runtime Rhino, que suporta apenas ES5 e possui particularidades na interoperabilidade com Java. Este plugin:
- Avalia somente arquivos
.jsdiretamente dentro dos diretórios oficiais de scripts Fluig (em qualquer nível do projeto):datasets/mechanisms/workflow/scripts/events/
- Configura o parser para
ecmaVersion: 2015esourceType: "script", permitindo que o plugin reporte explicitamente template literals e spread/rest. - Disponibiliza, por padrão, os símbolos globais de
jsegd-fluig-types(DatasetFactory,hAPI,log,java,com, etc.). - Permite excluir pastas específicas via opção
ignores.
📦 Instalação
Instale o plugin e o pacote de tipos como dependências de desenvolvimento — ambos são peerDependencies obrigatórias:
npm install -D jsegd-fluig-lint jsegd-fluig-types eslint@^10ou com yarn:
yarn add -D jsegd-fluig-lint jsegd-fluig-types eslint@^10ou com pnpm:
pnpm add -D jsegd-fluig-lint jsegd-fluig-types eslint@^10🚀 Uso (ESLint Flat Config)
Configuração recomendada
Em eslint.config.mjs:
import jsegdFluigLint from "jsegd-fluig-lint";
export default [
{
plugins: {
"jsegd-fluig-lint": jsegdFluigLint,
},
},
...jsegdFluigLint.configs.recommended(),
];recommended é uma função que retorna o array de configurações. Sem argumentos, avalia todos os arquivos .js diretos nas pastas Fluig e ignora node_modules.
Excluindo pastas específicas
Passe ignores com padrões glob para desconsiderar caminhos:
import jsegdFluigLint from "jsegd-fluig-lint";
export default [
{
plugins: {
"jsegd-fluig-lint": jsegdFluigLint,
},
},
...jsegdFluigLint.configs.recommended({
ignores: [
"forms/**", // ignora qualquer pasta "forms" em qualquer nível
"legacy/**", // ignora qualquer pasta "legacy"
],
}),
];Os padrões informados em ignores são combinados com node_modules/** e aplicados globalmente.
Tabela de blocos gerados
| Bloco | Pastas avaliadas | O que aplica |
| ---------------------------------- | ----------------------------------------------------------- | ---------------------------- |
| jsegd-fluig-lint/ignores | — | Ignores globais |
| jsegd-fluig-lint/rhino-es5 | datasets/*.js, mechanisms/*.js, workflow/scripts/*.js, events/*.js | Parser ES5 + todas as regras |
| jsegd-fluig-lint/globals-dataset | datasets/*.js | Globais de Dataset |
| jsegd-fluig-lint/globals-backend | mechanisms/*.js, workflow/scripts/*.js, events/*.js | Globais de Backend/Workflow |
Cada padrão captura arquivos
.jsdiretamente dentro da pasta indicada, em qualquer nível do projeto. Arquivos em subpastas (ex.:datasets/sub/arquivo.js) não são avaliados.
Configuração manual
Se quiser controlar regras e globals separadamente:
import jsegdFluigLint from "jsegd-fluig-lint";
const DATASET_FILES = ["datasets/*.js"];
const BACKEND_FILES = [
"mechanisms/*.js",
"workflow/scripts/*.js",
"events/*.js",
];
export default [
{
plugins: { "jsegd-fluig-lint": jsegdFluigLint },
},
{
files: [...DATASET_FILES, ...BACKEND_FILES],
languageOptions: {
ecmaVersion: 5,
sourceType: "script",
},
rules: {
"jsegd-fluig-lint/no-const-let": "error",
"jsegd-fluig-lint/no-for-of": "error",
"jsegd-fluig-lint/no-strict-equality": "error",
"jsegd-fluig-lint/no-arrow-functions": "error",
"jsegd-fluig-lint/no-modern-es": "error",
"jsegd-fluig-lint/no-optional-chaining": "error",
"jsegd-fluig-lint/no-promises": "error",
"jsegd-fluig-lint/no-es6-builtins": "error",
"jsegd-fluig-lint/no-template-literals": "error",
"jsegd-fluig-lint/no-spread-rest": "error",
},
},
{
files: DATASET_FILES,
languageOptions: {
globals: jsegdFluigLint.globals.dataset,
},
},
{
files: BACKEND_FILES,
languageOptions: {
globals: jsegdFluigLint.globals.backend,
},
},
];📋 Regras
Todas as regras só agem em arquivos .js dentro do escopo Fluig descrito acima.
Nota sobre sintaxe moderna:
async/awaite outras construções mais novas continuam sendo rejeitadas pelo parser ou por regras específicas. Template literals e spread/rest são aceitos pelo parser em modo ES2015 para que o plugin possa reportá-los com mensagens próprias.
no-const-let
Proíbe const/let (ES6+). Auto-fix: substitui por var.
// ❌ Errado
const total = 10;
let nome = "x";
// ✅ Correto
var total = 10;
var nome = "x";no-for-of
Proíbe for...of (ES6+). Não oferece autofix por segurança, porque a conversão automática pode mudar a semântica para iteráveis que não são arrays.
// ❌ Errado
for (var item of lista) {
/* ... */
}
// ✅ Correto
for (var i = 0; i < lista.length; i++) {
var item = lista[i];
/* ... */
}no-strict-equality
Proíbe === e !== (não funcionam corretamente com interop Java ↔ JS no Rhino). Auto-fix.
// ❌ Errado
if (valor === null) {
/* ... */
}
// ✅ Correto
if (valor == null) {
/* ... */
}no-arrow-functions
Proíbe arrow functions (ES6+ e quebram o this no interop com Java).
// ❌ Errado
var arrow = () => 1;
// ✅ Correto
function fn() {
return 1;
}no-modern-es
Proíbe identificadores globais ES6+ que o parser ES5 não captura (porque são nomes válidos em ES5) e que não existem no Rhino:
- Construtores:
Map,Set,WeakMap,WeakSet(apenas vianew). - Identificadores:
Symbol,BigInt,Reflect,Proxy,WeakRef,FinalizationRegistry,globalThis(qualquer referência — chamada, acesso a membro ou valor).
A regra ignora propriedades de objeto (obj.Symbol, { Symbol: 1 }) e referências a variáveis locais com o mesmo nome (shadowing).
// ❌ Errado
var m = new Map();
var s = new Set();
var sym = Symbol("x");
var big = BigInt(10);
Reflect.has(obj, "key");
var g = globalThis;
// ✅ Correto — use estruturas ES5 ou APIs equivalentes do Rhino/Java
var m = {};
var s = [];no-optional-chaining
Proíbe optional chaining (?.). Não oferece autofix por segurança, porque a expansão automática pode repetir expressões com efeito colateral.
// ❌ Errado
var nome = user?.profile?.name;
// ✅ Correto
var nome = user && user.profile && user.profile.name;no-promises
Proíbe o uso de Promise (construtor e APIs estáticas). O Rhino do Fluig não fornece Promise nativo — use callbacks ou execução síncrona. A regra ignora propriedades (obj.Promise) e shadowing por variável local.
// ❌ Errado
var p = new Promise(function (resolve) { resolve(1); });
Promise.resolve(valor).then(handle);
// ✅ Correto — use callbacks
function buscar(callback) {
var dados = DatasetFactory.getDataset("ds", null, null, null);
callback(dados);
}no-template-literals
Proíbe template literals com crases.
// ❌ Errado
var teste = `formMode = '${tipoValido[0]}'`;
// ✅ Correto
var teste = "formMode = '" + tipoValido[0] + "'";no-spread-rest
Proíbe spread/rest (...) em arrays, objetos, chamadas e parâmetros.
// ❌ Errado
var copia = [...lista];
function fn(...args) {
return args;
}
// ✅ Correto
var copia = lista.slice();
function fn(args) {
return args;
}no-es6-builtins
Proíbe chamadas a métodos e funções de built-ins ES6+ que não existem no Rhino ES5. Não oferece autofix porque a substituição correta depende do contexto.
Métodos estáticos bloqueados (verifica objeto exato):
| Chamada | Disponível no Rhino? |
|---|---|
| Array.from(iteravel) | ❌ |
| Object.values(obj) | ❌ |
| Object.entries(obj) | ❌ |
| Object.assign(alvo, ...) | ❌ |
Métodos de protótipo bloqueados (qualquer receptor):
| Método | Disponível no Rhino? |
|---|---|
| .find(fn) | ❌ |
| .findIndex(fn) | ❌ |
| .includes(val) | ❌ |
| .startsWith(str) | ❌ |
| .endsWith(str) | ❌ |
| .padStart(n, str) | ❌ |
| .padEnd(n, str) | ❌ |
Object.keys()é ES5 e está disponível no Rhino — não é bloqueado.
// ❌ Errado
var primeiro = lista.find(function(i) { return i.ativo; });
var idx = lista.findIndex(function(i) { return i.id === id; });
var tem = lista.includes(item);
var arr = Array.from(colecaoJava);
var vals = Object.values(obj);
var pares = Object.entries(obj);
var merged = Object.assign({}, defaults, opts);
if (texto.startsWith('prefixo')) { /* ... */ }
// ✅ Correto — use equivalentes ES5
var primeiro = null;
for (var i = 0; i < lista.length; i++) {
if (lista[i].ativo) { primeiro = lista[i]; break; }
}
var tem = false;
for (var i = 0; i < lista.length; i++) {
if (lista[i] === item) { tem = true; break; }
}
var arr = [];
for (var i = 0; i < colecaoJava.size(); i++) { arr.push(colecaoJava.get(i)); }
var vals = [];
for (var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) vals.push(obj[k]); }
var merged = {};
for (var k in defaults) { if (Object.prototype.hasOwnProperty.call(defaults, k)) merged[k] = defaults[k]; }
for (var k in opts) { if (Object.prototype.hasOwnProperty.call(opts, k)) merged[k] = opts[k]; }
if (texto.indexOf('prefixo') === 0) { /* ... */ }🌐 Globais de jsegd-fluig-types
Os globais não são duplicados em listas estáticas dentro do plugin: eles são extraídos em tempo de carga dos blocos declare global { ... } dos arquivos .d.ts de jsegd-fluig-types. Assim, qualquer símbolo novo adicionado ao pacote de tipos passa a ser reconhecido automaticamente após atualizar a dependência.
A configuração recomendada injeta automaticamente:
datasets/→ globais defluig.dataset.d.ts+java.d.ts(ex.:DatasetFactory,DatasetBuilder,DefaultDataset,ConstraintType,AddColumn,setKey,addIndex,defineStructure,onSync,createDataset,onMobileSync,java,javax).mechanisms/,workflow/scripts/,events/→ globais defluig.backend.d.ts+fluig.sdk.d.ts+fluig.dataset.d.ts+fluig.api.d.ts+fluig.webservice.d.ts+java.d.ts(ex.:globalVars,getValue,hAPI,log,ServiceManager,Service,JSONUtil,FormController,customHTML,displayFields,enableFields,inputFields,validateForm,DatasetFactory,java,com, …).
Esses símbolos também ficam disponíveis programaticamente em jsegdFluigLint.globals.dataset e jsegdFluigLint.globals.backend para configs personalizadas.
Como a derivação acontece em runtime,
jsegd-fluig-typesdeve estar instalado — por isso é umapeerDependencyobrigatória.
🔧 Scripts sugeridos no package.json
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
}
}📄 Licença
Consulte LICENSE.md.
Desenvolvido com ❤️ pela EGD Tecnologia
