@oondemand/oon-core-back 0.3.31 → 0.3.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/package.json +1 -1
- package/src/core/factories/crudService.js +84 -8
package/README.md
CHANGED
|
@@ -20,3 +20,22 @@ Compatibilidade temporária: `CENTRAL_ATIVACAO_BACKEND_URL` e `MEUS_APPS_BACKEND
|
|
|
20
20
|
`GET /ativacao/status` informa estado sem segredos. `POST /ativacao/validar-codigo` valida sem consumir. `POST /ativacao/concluir` revalida, chama `/ativar`, criptografa imediatamente o token da instância, executa hooks declarativos, chama `/concluir` e marca a instância como `ativa`. `POST /ativacao/tentar-novamente` retoma uma ativação já registrada sem exigir novo código.
|
|
21
21
|
|
|
22
22
|
Campos adicionais podem ser declarados em `activation.fields`; `password` e `secret` são sanitizados na configuração retornada ao frontend. Hooks opcionais: `validate`, `beforeComplete`, `afterComplete`.
|
|
23
|
+
|
|
24
|
+
## Rótulos de campos relacionados
|
|
25
|
+
|
|
26
|
+
Por padrão, campos declarados com `fields.ref(...)` continuam sendo devolvidos pelo CRUD como `ObjectId`. Uma model pode optar pela população segura das referências usadas em grids e cards:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
defineModel({
|
|
30
|
+
name: "Pedido",
|
|
31
|
+
schema: {
|
|
32
|
+
clienteId: fields.ref("Cliente", { required: true, label: "Cliente" }),
|
|
33
|
+
},
|
|
34
|
+
crud: {
|
|
35
|
+
enabled: true,
|
|
36
|
+
populateRefs: ["clienteId"],
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Use `populateRefs: true` para todas as referências da model ou informe uma lista explícita. O CRUD devolve somente `_id` e campos usuais de identificação, como nome, razão social, descrição, código, e-mail e campos pesquisáveis da model referenciada. Exportações mantêm os identificadores originais.
|
package/package.json
CHANGED
|
@@ -1,4 +1,71 @@
|
|
|
1
1
|
const GenericError = require("../errors/GenericError");
|
|
2
|
+
const registry = require("../registry");
|
|
3
|
+
|
|
4
|
+
const COMMON_REFERENCE_LABEL_FIELDS = [
|
|
5
|
+
"nome",
|
|
6
|
+
"razaoSocial",
|
|
7
|
+
"razao_social",
|
|
8
|
+
"descricao",
|
|
9
|
+
"numero",
|
|
10
|
+
"codigoIndividual",
|
|
11
|
+
"codigo_individual",
|
|
12
|
+
"codigo",
|
|
13
|
+
"label",
|
|
14
|
+
"email",
|
|
15
|
+
"sigla",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gera especificações de populate somente quando a model opta explicitamente
|
|
20
|
+
* por `crud.populateRefs`. O select é restrito a campos de identificação para
|
|
21
|
+
* evitar devolver o documento relacionado inteiro nas listagens genéricas.
|
|
22
|
+
*/
|
|
23
|
+
function referencePopulateSpecs(entry) {
|
|
24
|
+
const setting = entry.definition?.crud?.populateRefs;
|
|
25
|
+
if (!setting) return [];
|
|
26
|
+
|
|
27
|
+
const allowed = Array.isArray(setting) ? new Set(setting) : null;
|
|
28
|
+
const metaFields = Object.values(entry.metaFields || {});
|
|
29
|
+
|
|
30
|
+
return metaFields
|
|
31
|
+
.filter((field) =>
|
|
32
|
+
field?.kind === "ref" &&
|
|
33
|
+
field.ref &&
|
|
34
|
+
(!allowed || allowed.has(field.name))
|
|
35
|
+
)
|
|
36
|
+
.map((field) => {
|
|
37
|
+
const referencedEntry = registry.getModel(field.ref);
|
|
38
|
+
const select = [
|
|
39
|
+
"_id",
|
|
40
|
+
...COMMON_REFERENCE_LABEL_FIELDS,
|
|
41
|
+
...(referencedEntry?.searchableFields || []),
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
path: field.name,
|
|
46
|
+
select: [...new Set(select)].join(" "),
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function populateQuery(query, specs) {
|
|
52
|
+
return specs.length ? query.populate(specs) : query;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Aceita tanto uma Query Mongoose quanto uma Promise/Document devolvida por
|
|
57
|
+
* uma model que sobrescreveu métodos como `findByIdAndUpdate`.
|
|
58
|
+
*/
|
|
59
|
+
async function resolvePopulated(result, specs) {
|
|
60
|
+
if (!specs.length) return result;
|
|
61
|
+
if (result && typeof result.populate === "function") {
|
|
62
|
+
return result.populate(specs);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const doc = await result;
|
|
66
|
+
if (doc && typeof doc.populate === "function") await doc.populate(specs);
|
|
67
|
+
return doc;
|
|
68
|
+
}
|
|
2
69
|
|
|
3
70
|
/**
|
|
4
71
|
* Gera um service de CRUD genérico para uma model registrada.
|
|
@@ -6,6 +73,7 @@ const GenericError = require("../errors/GenericError");
|
|
|
6
73
|
*/
|
|
7
74
|
function createCrudService(entry) {
|
|
8
75
|
const { mongooseModel: Model, searchableFields } = entry;
|
|
76
|
+
const populateSpecs = referencePopulateSpecs(entry);
|
|
9
77
|
|
|
10
78
|
async function listPaginated({ pageIndex = 0, pageSize = 20, searchTerm, sort, filtros = {} } = {}) {
|
|
11
79
|
const page = Math.max(0, Number(pageIndex) || 0);
|
|
@@ -18,8 +86,12 @@ function createCrudService(entry) {
|
|
|
18
86
|
}
|
|
19
87
|
|
|
20
88
|
const sortSpec = parseSort(sort);
|
|
89
|
+
const listQuery = populateQuery(
|
|
90
|
+
Model.find(query).sort(sortSpec).skip(page * limit).limit(limit),
|
|
91
|
+
populateSpecs
|
|
92
|
+
);
|
|
21
93
|
const [results, totalItems] = await Promise.all([
|
|
22
|
-
|
|
94
|
+
listQuery.lean(),
|
|
23
95
|
Model.countDocuments(query),
|
|
24
96
|
]);
|
|
25
97
|
|
|
@@ -35,20 +107,24 @@ function createCrudService(entry) {
|
|
|
35
107
|
}
|
|
36
108
|
|
|
37
109
|
async function getById(id) {
|
|
38
|
-
const doc = await Model.findById(id);
|
|
110
|
+
const doc = await resolvePopulated(Model.findById(id), populateSpecs);
|
|
39
111
|
if (!doc) throw new GenericError("Registro não encontrado.", { statusCode: 404 });
|
|
40
112
|
return doc;
|
|
41
113
|
}
|
|
42
114
|
|
|
43
115
|
async function create(data) {
|
|
44
|
-
|
|
116
|
+
const doc = await Model.create(data);
|
|
117
|
+
return resolvePopulated(doc, populateSpecs);
|
|
45
118
|
}
|
|
46
119
|
|
|
47
120
|
async function update(id, data) {
|
|
48
|
-
const doc = await
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
121
|
+
const doc = await resolvePopulated(
|
|
122
|
+
Model.findByIdAndUpdate(id, data, {
|
|
123
|
+
new: true,
|
|
124
|
+
runValidators: true,
|
|
125
|
+
}),
|
|
126
|
+
populateSpecs
|
|
127
|
+
);
|
|
52
128
|
if (!doc) throw new GenericError("Registro não encontrado.", { statusCode: 404 });
|
|
53
129
|
return doc;
|
|
54
130
|
}
|
|
@@ -93,4 +169,4 @@ function escapeRegex(str) {
|
|
|
93
169
|
return String(str).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
94
170
|
}
|
|
95
171
|
|
|
96
|
-
module.exports = { createCrudService };
|
|
172
|
+
module.exports = { createCrudService, referencePopulateSpecs, resolvePopulated };
|