pwi-plata-type 0.1.0 → 0.1.1

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.
Files changed (3) hide show
  1. package/index.ts +2 -0
  2. package/libs/model.ts +305 -0
  3. package/package.json +1 -1
package/index.ts CHANGED
@@ -2,10 +2,12 @@ import * as PlataCluster from './libs/cluster.js'
2
2
  import * as PlataEnv from './libs/env.js'
3
3
  import * as PlataRoutes from './libs/routes.js'
4
4
  import * as PlataTools from './libs/tools.js'
5
+ import * as PlataModels from './libs/model.js'
5
6
 
6
7
  export {
7
8
  PlataCluster,
8
9
  PlataEnv,
9
10
  PlataRoutes,
10
11
  PlataTools,
12
+ PlataModels,
11
13
  }
package/libs/model.ts ADDED
@@ -0,0 +1,305 @@
1
+ export interface ErroValidacao {
2
+ errorID: string
3
+ error?: any
4
+ msg: string
5
+ }
6
+
7
+ export interface RetornoValidacaoPrimitivo {
8
+ error?: ErroValidacao
9
+ cotinua: boolean
10
+ }
11
+
12
+ export interface RetornoValicadaoModel {
13
+ value: any,
14
+ errors: ErroValidacao[]
15
+ }
16
+
17
+ export type ModelValicacao = (value: any) => Promise<ErroValidacao | null>
18
+
19
+ export type ModelValicacaoPrimitivo = (nome: string, valor: any) => Promise<RetornoValidacaoPrimitivo>
20
+
21
+ export interface ModelType {
22
+ [name: string]: ModelValicacaoPrimitivo[] | ModelType[] | ModelType
23
+ }
24
+
25
+ export class Model {
26
+ public readonly template: ModelType
27
+ public readonly validacoes: Map<string, ModelValicacao>
28
+
29
+ constructor(template: ModelType) {
30
+ this.template = template
31
+ this.validacoes = new Map()
32
+ }
33
+
34
+ public addValidacao(nome: string, callback: ModelValicacao) {
35
+ this.validacoes.set(nome, callback)
36
+ }
37
+ }
38
+
39
+ export async function _validaCampo(value: any, pipeline: ModelValicacaoPrimitivo[], name: string): Promise<ErroValidacao | null> {
40
+ for (let i = 0; i < pipeline.length; i++) {
41
+ const result = await pipeline[i](name, value)
42
+
43
+ if (result.error !== undefined) {
44
+ return result.error
45
+ }
46
+
47
+ if (!result.cotinua) {
48
+ break
49
+ }
50
+ }
51
+
52
+ return null
53
+ }
54
+
55
+ export function _filtraModel(value: any, model: Model): any {
56
+ for (const campo in model.template) {
57
+ const t = model.template[campo]
58
+
59
+ if (t.length === undefined) {
60
+ if (value[campo] === undefined) {
61
+ value[campo] = {}
62
+ }
63
+
64
+ const m = new Model(t as ModelType)
65
+ value[campo] = _filtraModel(value[campo], m)
66
+ continue
67
+ }
68
+
69
+ if (typeof t[0] === 'function') {
70
+ if (value[campo] === undefined) {
71
+ value[campo] = null
72
+ }
73
+
74
+ continue
75
+ }
76
+
77
+ if (value[campo] === undefined) {
78
+ value[campo] = []
79
+
80
+ continue
81
+ }
82
+
83
+ const m = new Model(t[0] as ModelType)
84
+
85
+ for (let i = 0; i < value[campo].length; i++) {
86
+ value[campo][i] = _filtraModel(value[campo][i], m)
87
+ }
88
+ }
89
+
90
+ return value
91
+ }
92
+
93
+ export async function _validaModel(value: any, model: Model, name?: string): Promise<ErroValidacao[]> {
94
+ let promises: any[] = []
95
+ let errors: ErroValidacao[] = []
96
+
97
+ for(const campo in model.template) {
98
+ const t = model.template[campo]
99
+
100
+ if (t.length === undefined) {
101
+ const m = new Model(t as ModelType)
102
+
103
+ promises.push(_validaModel(value[campo], m, `${campo}.`))
104
+ continue
105
+ }
106
+
107
+ if (typeof t[0] === 'function') {
108
+ promises.push(
109
+ _validaCampo(
110
+ value[campo],
111
+ t as ModelValicacaoPrimitivo[],
112
+ `${name ?? ''}${campo}`
113
+ )
114
+ )
115
+ continue
116
+ }
117
+
118
+ const m = new Model(t[0])
119
+
120
+ for (let i = 0; i < value[campo].length; i++) {
121
+ promises.push(
122
+ _validaModel(
123
+ value[campo][i],
124
+ m,
125
+ `${name ?? ''}${campo}[${i}].`
126
+ )
127
+ )
128
+ }
129
+ }
130
+
131
+ let Erros = await Promise.all(promises).then(
132
+ result => [].concat(...result).filter(v => v !== null),
133
+ err => {
134
+ return {
135
+ errorID: 'BPLM0002',
136
+ error: err,
137
+ msg: 'Erro ao validar o body',
138
+ }
139
+ }
140
+ )
141
+
142
+ if ((Erros as any).errorID !== undefined) {
143
+ errors.push(Erros as ErroValidacao)
144
+
145
+ return errors
146
+ }
147
+
148
+ errors = errors.concat(Erros)
149
+
150
+ if (errors.length !== 0) {
151
+ return errors
152
+ }
153
+
154
+ promises = []
155
+
156
+ for (const [ _, callback ] of model.validacoes) {
157
+ promises.push(callback(value))
158
+ }
159
+
160
+ Erros = await Promise.all(promises).then(
161
+ result => [].concat(...result),
162
+ err => {
163
+ return {
164
+ errorID: 'BPLM0003',
165
+ error: err,
166
+ msg: 'Erro ao validar o body',
167
+ }
168
+ }
169
+ )
170
+
171
+ if ((Erros as any).errorID !== undefined) {
172
+ errors.push(Erros as ErroValidacao)
173
+
174
+ return errors
175
+ }
176
+
177
+ return errors.concat(Erros)
178
+ }
179
+
180
+ export async function valida(value: any, model: Model): Promise<RetornoValicadaoModel> {
181
+ value = _filtraModel(value, model)
182
+
183
+ return {
184
+ value,
185
+ errors: await _validaModel(value, model),
186
+ }
187
+ }
188
+
189
+ export function DateTime(): ModelValicacaoPrimitivo {
190
+ return async (nome: string, valor: any) => {
191
+ const regex = /(\d{4})-([01]\d)-([0-3]\d)T([0-2]\d):([0-5]\d):([0-5]\d)/
192
+
193
+ if (!regex.test(valor)) {
194
+ return {
195
+ error: {
196
+ errorID: "BPMVDT001",
197
+ msg: `A data no campo ${nome} tem que está no formato yyyy-mm-ddTHH:MM:SS`,
198
+ },
199
+ cotinua: false
200
+ }
201
+ }
202
+
203
+ const [ _, ano, mes, dia, hora, minutos, segundos ] = valor.match(regex)
204
+
205
+ if (isNaN(+ano) || isNaN(+mes) || isNaN(+dia) || isNaN(+hora) || isNaN(+minutos) || isNaN(+segundos) ){
206
+ return {
207
+ error: {
208
+ errorID: "BPMVDT002",
209
+ msg: `A data no campo ${nome} tem que está no formato yyyy-mm-ddTHH:MM:SS`
210
+ },
211
+ cotinua: false
212
+ }
213
+ }
214
+
215
+ if ((+dia) > 31 || (+mes) > 12 || (+hora) > 24){
216
+ return {
217
+ error: {
218
+ errorID: "BCVDT003",
219
+ msg: `A data no campo ${nome} tem que está no formato yyyy-mm-ddTHH:MM:SS`,
220
+ },
221
+ cotinua: false
222
+ }
223
+ }
224
+
225
+ return { cotinua: true }
226
+ }
227
+ }
228
+
229
+ export function Decimal(tamanhoInteiro: number, casasDecimais: number): ModelValicacaoPrimitivo {
230
+ return async (nome: string, valor: any) => {
231
+ if (isNaN(+valor)) {
232
+ return {
233
+ error: {
234
+ errorID: "BPMVDEC001",
235
+ msg: `O campo ${nome} tem que ser um decimal`
236
+ },
237
+ cotinua: false,
238
+ }
239
+ }
240
+
241
+ const v = `${valor}`
242
+
243
+ if (v.length > (tamanhoInteiro + casasDecimais + 1)) {
244
+ return {
245
+ error: {
246
+ errorID: "BPMVDEC002",
247
+ msg: `O campo ${nome} não pode ser maior que ${(tamanhoInteiro + casasDecimais + 1)}`
248
+ },
249
+ cotinua: false,
250
+ }
251
+ }
252
+
253
+ const n = v.split('.')
254
+
255
+ if (n[0].length > tamanhoInteiro) {
256
+ return {
257
+ error: {
258
+ errorID: "BPMVDEC003",
259
+ msg: `A parte inteira do ${nome} não pode ter mais de ${tamanhoInteiro} digitos`
260
+ },
261
+ cotinua: false,
262
+ }
263
+ }
264
+
265
+ if (n[1] !== undefined) {
266
+ if (n[1].length > casasDecimais) {
267
+ return {
268
+ error: {
269
+ errorID: "BPMVDEC004",
270
+ msg: `A parte decimal do ${nome} não pode ter mais de ${casasDecimais} digitos`
271
+ },
272
+ cotinua: false,
273
+ }
274
+ }
275
+ }
276
+
277
+ return { cotinua: true }
278
+ }
279
+ }
280
+
281
+ export function Int(): ModelValicacaoPrimitivo {
282
+ return async (nome: string, valor: any) => {
283
+ if (isNaN(+valor)) {
284
+ return {
285
+ error: {
286
+ errorID: "BPMVINT001",
287
+ msg: `O campo ${nome} tem que ser um número inteiro`
288
+ },
289
+ cotinua: false,
290
+ }
291
+ }
292
+
293
+ if (Math.round(valor) !== valor) {
294
+ return {
295
+ error: {
296
+ errorID: "BPMVINT002",
297
+ msg: `O campo ${nome} tem que ser um número inteiro`
298
+ },
299
+ cotinua: false,
300
+ }
301
+ }
302
+
303
+ return { cotinua: true }
304
+ }
305
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pwi-plata-type",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "bin": {