
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@agtm/nuxt-model
Advanced tools
Módulo que dá suporte a criação de "modelos de dados" orientado a objeto baseado em classes e relacionamento entre classes.
Este módulo permite criar objetos (instancia de classes) a partir de dados no formato JSON simples com todos os relacionamentos automaticamente.
Caso prefira que o nome das classes sejam identificadas corretamente nas mensagens de erro no ambiente de produção, pode adicionar a seguinte configuração no arquivo nuxt.config.js:
NOTA: Caso habilite a opção "typeValidation", e não queira utilizar className, está configuração será necessária.
build: {
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
keep_classnames: true,
keep_fnames: true
}
})
]
}
}
Por padrão ao comprimir/otimizar o código para produção, o nome de classes são renomeados para nomes compactados.
REFs:
Podemos também identificar o nome da classe através do atributo className quando enableConstructorName for falso como no exemplo:
export default class TesteModel extends Model {
static className = 'TesteModel'
}
Execute o comando:
npm install --save @agtm/nuxt-model
Adicione o seguinte no arquivo nuxt.config.js:
['@agtm/nuxt-model/nuxt', { /* Options */ }]
Ao intanciar um novo Model, caso este Model tenha relacionamentos, esses relacionamentos são instancia de outros Models. O NuxtModel importa automaticamente a classe do Model relacionado.
Para que o NuxtModel saiba onde está localizado a classe, é utilizado um padrão de diretório:
Exemplo:
models\
aluno.model.js
carteira-do-aluno.model.js
Também podemos ter tipos customizados:
types\
money.type.js
Caso precisemos utilizar uma estrutura de diretório diferente, podemos alterar dois atributos na configuraçao do modulo: importPath e fileCaseStyle
Por padrão importPath é definido como:
~/models/${modelName}.model.js
Onde ${modelName} é substituído pelo nome do model
Por exemplo, podemos criar a seguinte estrutura de diretório:
src\
models\
meu-model\
index.js
Para isso configuramos importPath como:
~/src/models/${modelName}/index.js
E finalmente para utilizar outro padrão de nome de model podemos definir fileCaseStyle como:
kebabCase, camelCase ou snakeCase
Seguindo a mesma regra também podemos customizar a estrutura de diretório dos tipos padrões
Models são criados utilizando o padrão de classe do ES6, utilizando herança, getters, setters entre outros.
Na configuração padrão model deve ser criado na pasta models. Por exemplo, para criar um model "Aluno", na pasta models vamos criar o seguinte arquivo:
aluno.model.js
Devemos exportar uma classe como no exemplo:
import { Model } from '@agtm/nuxt-model'
export default class AlunoModel extends Model {
}
Regras:
No nosso exemplo anterior não defininos nenhum atributo, ou seja nenhum valor pode ser carregado na instancia do model. Apenas atributos definidos podem ser utilizado, isso permite validar os atributos permitidos ou exigidos no nosso model
Vamos criar alguns atributos:
import { Model } from '@agtm/nuxt-model'
export default class AlunoModel extends Model {
static nomeType = 'string'
static idadeType = 'number'
static matriculadoType = 'boolean'
static turmaType = 'turmaModel'
static nascimentoType = 'data'
}
IMPORTANTE: Nome de atributos que iniciam com _ são ignorados
Podemos definir valores iniciais no nosso model, para isso simplesmente declare um atributo estatico diretamente como no exemplo:
import { Model } from '@agtm/nuxt-model'
export default class TesteModel extends Model {
static idType = 'number'
static profissaoType = 'string'
id = 123
profissao = 'Desenvolvedor'
}
Podemos criar getters e setters nos models para atributos dinamicos, implementando qualquer lógica desejada, como: acesso a informações do nuxt, formatação de dados (tanto no setter quanto no getter) entre outros:
Por exemplo:
import { Model } from '@agtm/nuxt-model'
export default class TesteModel extends Model {
static nameType = 'string'
static sobrenomeType = 'string'
/**
* Se o Nuxt estpa no modo desenvolvimento
*
* @return {boolean|*}
*/
get idDev () {
return Model.context.isDev
}
get nomeCompleto () {
return `${this.name} ${this.sobrenome}`
}
}
Todo o atributo no Nuxt Model tem um tipo, esse tipo é utilizado para transformar ou validar dados. Podemos utilizar tipos pré-definidos ou criar um tipo customizado.
São tipos básicos do javascript: https://developer.mozilla.org/en-US/docs/Glossary/Primitive
No Nuxt Model são permitidos:
string, number, bigint, boolean e symbol
undefined e null, são tratado como dados vazio e portanto são ignorados.
Os dados são validados se estão no seu tipo correto.
No tipo Date, somente são permitidos tipo primitivo string ou instancia do objeto Date do javascript.
Caso seja do tipo string será convertido para Date.
No Nuxt Model podemos criar atributos especiais que são outros models criando relacionamento entre models.
Para criarmos um atributo do tipo "Model", precisamos colocar o nome do "model" no tipo, e todo "model" tem o sufixo " Model"
Por exemplo:
// aluno.model.js
export default class AlunoModel extends Model {
static idType = 'number'
static nameType = 'string'
static sobrenomeType = 'string'
get nomeCompleto () {
return `${this.name} ${this.sobrenome}`
}
}
// turma.model.js
import { Model } from '@agtm/nuxt-model'
export default class Turma extends Model {
static alunoType = 'AlunoModel'
}
// exemplo.js
const turma = await Turma.create({
aluno:
{
id: 1,
nome: 'João',
sobrenome: 'Silva'
}
})
console.log(turma.aluno.nomeCompleto)
// João Silva
NOTA: Submodels são instanciados internamente automaticamente pelo Nuxt Model
Array é um tipo especial que representa um array de tipos, por exemplo:
export default class AlunoModel extends Model {
static nameType = 'string[]'
}
Exemplo:
const escola = await Escola.create({
turma: {
alunos: [
{
id: 1,
}, {
id: 2
}
]
}
})
escola.turma.alunos.push({
id: 5
})
Com tipos customizados podemos validar dados antes de atribuir, formatar, criar atributos dinamicos entre outros.
O objetivo principal dos tipos customizados é evitar código repetitivo, pois tudo que pode ser criado com tipo, poderia ser criados com 'getters' e ‘setters’ no model. Porém, existem casos em que utilizamos a mesma lógica em muitos models do nossso projeto, por exemplo, formatação de dados monetários.
Podemos então criar um tipo especial 'money' e toda a vez que for ler o atributo já vem no formato correto.
Por padrão os tipos customizados devem ser criado na pasta "types" na raiz do projeto.
NOTA: Este comportamento pode ser alterado pela opção "typeImportPath". Segue a mesma regra dos models.
Vamos criar um tipo customizado chamado money:
// /types/money.type.js
import { cloneDeep } from 'lodash'
import { ModelType } from '@agtm/nuxt-model'
export default class MoneyType extends ModelType {
static setup (instance, attrName, attrType) {
Object.defineProperty(instance, attrName, {
get () {
if (instance.__rawValues[attrName] !== undefined) {
return 'R$ ' + instance.__rawValues[attrName].toFixed(2)
}
},
set (value) {
instance.__rawValues[attrName] = cloneDeep(value)
}
})
}
}
// exemplo.js:
this.teste = await Teste.create({
valor: 23.3,
})
console.log(teste.valor)
// R$ 23.30
Note que criar um Tipo customizado, precisamos criar um método setup obrigatório, que ira alterar a instância do model.
O método setup recebe três parâmetros:
Veja que o método setup é bastante livre para fazemos qualquer manipulação que quisermos.
Aqui é importante entender o funcionamento interno de um model, todos os valores não são armazenados por padrão no atributo da instancia e sim dentro de um objeto chamado "__rawValues".
Utilizamos getters e setters para ler o valor armazenado ali.
Todos os tipos internos são implentados usando esta técnica.
O valor diretamente no atributo da instância é lido apenas na inicialização para definir o valor inicial, em seguida é descartado.
Podemos alterar todo esse comportamento caso desejarmos, porém por padrão utilizamos Object.defineProperty para criarmos getters e setters que irão obter/gravar o valor em __rawValues.
Observe outros exemplos dentro do projeto nuxt-model na pasta "src/types"
Não foi testado, veja mais detalhes em: https://medium.com/trabe/async-getters-and-setters-is-it-possible-c18759b6f7e4
O Nuxt Model tem integração com o nuxt, métodos e atributos estão definidos na classe.
Por exemplo:
'use strict'
import { Model } from '@agtm/nuxt-model'
export default class TesteModel extends Model {
get isStatic () {
return Model.context.isStatic + this.id
}
}
Também é possível utilizar this.constructor
'use strict'
import { Model } from '@agtm/nuxt-model'
export default class TesteModel extends Model {
get isStatic () {
return this.constructor.context.isStatic + this.id
}
}
Documentação no Nuxt:
Com os Models criados, podemos instanciar da seguinte forma:
this.teste = await Teste.create({
id: 1,
valor: 23.34,
nascimento: '2020-01-01',
name: {
id: 2,
name: [{
id: 3,
__typename: 'teste'
}, {
id: 4
}]
}
})
Podemos atribuir normalmente como se fosse um objeto javascript:
this.teste.pais = 'Argentina'
Se o tipo por um submodel, será instanciado um novo Model do tipo especificado automaticamente.
Podemos atribuir varios valores de uma vez com setValues:
this.teste.setValues({
id: 2,
valor: 50,
})
IMPORTANTE: Se passar um atributo não definido no model via metodos "create" e "setValues", a Model irá validar automaticamente, exibindo um erro que o atributo não existe.
Porém, se atribuir diretamente:
this.teste.pais = 'Argentina'
Nenhum erro será disparado, porém o atributo será ignorado por métodos como toJSON e toString ou poderá ser exluído a qualquer momento. Portando nunca utilize um atributo não definido no model.
Isso ocorre porque no javascript não é possível criar getters e setters genericos, impossibilidando a validação.
O método toJson() retorna um objeto plano representando o model (é o equivalente ao setModels invertido).
Use toString() pra uma representação textual do json
Se os dados em JSON utilizado ao instanciar um movo Model conter informação de tipo, podemos utilizar para realizar uma validação extra.
Por exemplo, o GraphQl envia com os dados um atributo especial "__typename" para identificar o tipo do dado enviado.
Podemos validar se esse tipo é o mesmo tipo do model criado. Para isso precisamos definir a opção "typeValidation" como "__typename"
Caso typeValidation esteja habilitado, podemos instanciar um novo model com o método createFromData.
Por exemplo:
//Em vez de fazer:
AlunoModel.create(data)
// Podemos utilizar:
Model.createFromData(data)
Útil quando não sabemos qual Model será enviado pelo backend.
Podemos adicionar outras propriedades aos atriburos do Model (por exemplo para criação de um formulário).
Podemos definir atributos como required, minLengt etc...
Importante notar que com exceção do atributo type, os outros atributos serão ignorado pelo nuxt Model, sendo útil apenas para aplicações externas (como nuxt form)
Exemplo:
import { Model } from '@agtm/nuxt-model'
export default class TesteModel extends Model {
static nameType = {
type: 'SubTesteModel',
required: true
}
}
Note que é um atributo de classe, na instância terá q acessar da seguinte forma:
console.log(meu_model.constructor.nameType.required)
Ao configurar o modulo no projeto, podemos definir as seguintes opções:
| Atributo | Descrição | Padrão |
|---|---|---|
| importPath | Nuxt-model, carrega e instancia objetos automaticamente, através de importPath o nuxt-model consegue encontrar as classes. Está no formato "template string" e a variável "modelName" representa o nome da classe. É usado para definir a estrutura de diretório utilizado para os models. | "~/models/${modelName}.model.js" |
| typeImportPath | Regra de carregamento para os tipos customizados. | "~/types/${typeName}.type.js" |
| enableConstructorName | Habilita identificação da classe pelo constructorName, caso esta opção esteja desativada é necessário especificar o nome da classe no atributo estático "class". Para ativar esta opção é necessário realizar uma pré-configuração. | true |
| fileCaseStyle | Estilo de caixa (Case Style) do arquivos do model, por exemplo para kebabCase o model será sub-teste.model.js, para camelCase será subTeste.model.js. | 'kebabCase' |
| typeValidation | Se definido, irá validar se um objeto de valores vinculado à um model está correto. Por exemplo, no graphql é utilizado _typename junto com o json de dados para identificar o tipo do objetos, caso seja definido o atributo será obrigatorio no objeto de dados utilizado por create e setValue. | undefined |
Table Editor: https://www.tablesgenerator.com/markdown_tables
https://dev.to/bawa_geek/how-to-setup-jest-testing-in-nuxt-js-project-5c84
FAQs
Classe para implementação de modelos de dado orientado a objeto
The npm package @agtm/nuxt-model receives a total of 1 weekly downloads. As such, @agtm/nuxt-model popularity was classified as not popular.
We found that @agtm/nuxt-model demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.