@data7expressions/typ3s 5.0.0

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.
@@ -0,0 +1,905 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Type = void 0;
4
+ /* eslint-disable no-use-before-define */
5
+ const primitive_1 = require("../domain/primitive");
6
+ const helper_1 = require("./helper");
7
+ class Type {
8
+ // eslint-disable-next-line no-useless-constructor
9
+ constructor(primitive, obj, list, func) {
10
+ this.primitive = primitive;
11
+ this.obj = obj;
12
+ this.list = list;
13
+ this.func = func;
14
+ }
15
+ static get any() {
16
+ return new Type(primitive_1.Primitive.any);
17
+ }
18
+ static get string() {
19
+ return new Type(primitive_1.Primitive.string);
20
+ }
21
+ static get integer() {
22
+ return new Type(primitive_1.Primitive.integer);
23
+ }
24
+ static get decimal() {
25
+ return new Type(primitive_1.Primitive.decimal);
26
+ }
27
+ static get number() {
28
+ return new Type(primitive_1.Primitive.number);
29
+ }
30
+ static get boolean() {
31
+ return new Type(primitive_1.Primitive.boolean);
32
+ }
33
+ static get date() {
34
+ return new Type(primitive_1.Primitive.date);
35
+ }
36
+ static get dateTime() {
37
+ return new Type(primitive_1.Primitive.dateTime);
38
+ }
39
+ static get time() {
40
+ return new Type(primitive_1.Primitive.time);
41
+ }
42
+ static get void() {
43
+ return new Type(primitive_1.Primitive.void);
44
+ }
45
+ // eslint-disable-next-line no-use-before-define,
46
+ static Obj(properties = []) {
47
+ return new Type(primitive_1.Primitive.obj, { properties });
48
+ }
49
+ static List(items) {
50
+ return new Type(primitive_1.Primitive.list, undefined, { items });
51
+ }
52
+ static Function(params, ret) {
53
+ return new Type(primitive_1.Primitive.function, undefined, undefined, { params, ret });
54
+ }
55
+ static isPrimitive(type) {
56
+ let value;
57
+ if (typeof type === 'string') {
58
+ value = type;
59
+ }
60
+ else if (type !== undefined && type.primitive !== undefined) {
61
+ value = type.primitive.toString();
62
+ }
63
+ else {
64
+ return false;
65
+ }
66
+ return ['string', 'integer', 'decimal', 'number', 'boolean', 'date', 'dateTime', 'time'].includes(value);
67
+ }
68
+ static to(primitive) {
69
+ if (typeof primitive === 'string') {
70
+ const primitiveKey = primitive;
71
+ return new Type(primitive_1.Primitive[primitiveKey]);
72
+ }
73
+ return new Type(primitive);
74
+ }
75
+ static get(value) {
76
+ if (value === null || value === undefined) {
77
+ return Type.any;
78
+ }
79
+ else if (Array.isArray(value)) {
80
+ if (value.length > 0) {
81
+ return Type.List(this.get(value[0]));
82
+ }
83
+ return Type.any;
84
+ }
85
+ else if (typeof value === 'object') {
86
+ const properties = [];
87
+ for (const entry of Object.entries(value)) {
88
+ properties.push({ name: entry[0], type: this.get(entry[1]) });
89
+ }
90
+ return Type.Obj(properties);
91
+ }
92
+ else if (typeof value === 'string') {
93
+ // TODO determinar si es fecha.
94
+ return Type.string;
95
+ }
96
+ else if (typeof value === 'number') {
97
+ if (Number.isInteger(value)) {
98
+ return Type.integer;
99
+ }
100
+ return Type.decimal;
101
+ }
102
+ else if (typeof value === 'boolean') {
103
+ return Type.boolean;
104
+ }
105
+ return Type.any;
106
+ }
107
+ static isList(type) {
108
+ if (typeof type === 'string') {
109
+ return type.startsWith('[') && type.endsWith(']');
110
+ }
111
+ return type.primitive === primitive_1.Primitive.list;
112
+ }
113
+ static isObj(type) {
114
+ if (typeof type === 'string') {
115
+ return type.startsWith('{') && type.endsWith('}');
116
+ }
117
+ return type.primitive === primitive_1.Primitive.obj;
118
+ }
119
+ // Examples:
120
+ // sin valor de retorno: (name:string,nro:int)
121
+ // sin arguments: (>dateTime)
122
+ // simple: (name:string,nro:int>string)
123
+ // retorna otra function: (name:string,nro:int>(name:string>int))
124
+ // function que recibe function : ((name:string>string),nro:int>int)
125
+ static isFunc(type) {
126
+ if (typeof type === 'string') {
127
+ return type.startsWith('(') && type.endsWith(')');
128
+ }
129
+ return type.primitive === primitive_1.Primitive.function;
130
+ }
131
+ static stringify(type) {
132
+ if (type === undefined) {
133
+ return 'any';
134
+ }
135
+ if (this.isPrimitive(type)) {
136
+ return this.modifier(type) + type.primitive.toString();
137
+ }
138
+ if (this.isObj(type)) {
139
+ const properties = [];
140
+ const objectType = type.obj;
141
+ for (const propertyType of objectType.properties) {
142
+ properties.push(`${propertyType.name}:${this.stringify(propertyType.type)}`);
143
+ }
144
+ return `${this.modifier(type)}{${properties.join(',')}}`;
145
+ }
146
+ if (this.isList(type)) {
147
+ const arrayType = type.list;
148
+ return `${this.modifier(type)}[${this.stringify(arrayType.items)}]`;
149
+ }
150
+ if (this.isFunc(type)) {
151
+ const funcType = type.func;
152
+ const params = [];
153
+ for (const paramType of funcType.params) {
154
+ params.push(`${paramType.name}:${this.stringify(paramType.type)}`);
155
+ }
156
+ return `(${params.join(',')}>${this.modifier(type)} ${this.stringify(funcType.ret)})`;
157
+ }
158
+ return 'any';
159
+ }
160
+ static parse(stringified) {
161
+ return new TypeParser(stringified).parse();
162
+ }
163
+ static serialize(type, indentation) {
164
+ if (type === undefined || type === null) {
165
+ return undefined;
166
+ }
167
+ if (indentation) {
168
+ return JSON.stringify(type, null, indentation);
169
+ }
170
+ return JSON.stringify(type);
171
+ }
172
+ static deserialize(type) {
173
+ if (type === undefined || type === null || type.trim() === '') {
174
+ return undefined;
175
+ }
176
+ return JSON.parse(type);
177
+ }
178
+ static validate(value, type) {
179
+ try {
180
+ const _type = typeof type === 'string' ? this.parse(type) : type;
181
+ this._validate(value, _type);
182
+ return [true, ''];
183
+ }
184
+ catch (error) {
185
+ return [false, error.message];
186
+ }
187
+ }
188
+ static type(value, options) {
189
+ const type = new Type(primitive_1.Primitive.undefined);
190
+ this._type(value, type);
191
+ if (options) {
192
+ this.info(value, type, options);
193
+ }
194
+ return type;
195
+ }
196
+ static modifier(type) {
197
+ return (type.undefinable ? '?' : type.nullable ? '!' : type.unique ? '#' : type.async ? '~' : '');
198
+ }
199
+ static _validate(value, type) {
200
+ const stringified = this.stringify(type);
201
+ if (type.nullable === undefined && (type.nullable = false) && value === null) {
202
+ throw new Error(`${stringified} is null`);
203
+ }
204
+ if (type.undefinable === undefined && (type.undefinable = false) && value === undefined) {
205
+ throw new Error(`${stringified} is undefined`);
206
+ }
207
+ if (Type.isObj(type) && type.obj) {
208
+ if (!helper_1.typeH3lp.val.isObject(value)) {
209
+ throw new Error(`${stringified} value: ${value} is not an object`);
210
+ }
211
+ for (const property of type.obj.properties) {
212
+ try {
213
+ this._validate(value[property.name], property.type);
214
+ }
215
+ catch (error) {
216
+ throw new Error(`${stringified} property ${property.name} ${error.message}`);
217
+ }
218
+ }
219
+ }
220
+ else if (Type.isList(type) && type.list && type.list.items) {
221
+ if (!helper_1.typeH3lp.val.isArray(value)) {
222
+ throw new Error(`${stringified} value: ${value} is not an array`);
223
+ }
224
+ for (const item of value) {
225
+ try {
226
+ this._validate(item, type.list.items);
227
+ }
228
+ catch (error) {
229
+ throw new Error(`${stringified} item ${error.message}`);
230
+ }
231
+ }
232
+ }
233
+ else if (Type.isPrimitive(type)) {
234
+ const primitive = type.primitive;
235
+ switch (primitive) {
236
+ case primitive_1.Primitive.string:
237
+ if (!helper_1.typeH3lp.val.isString(value)) {
238
+ throw new Error(`Value ${value} is not a string`);
239
+ }
240
+ break;
241
+ case primitive_1.Primitive.integer:
242
+ if (!helper_1.typeH3lp.val.isInteger(value)) {
243
+ throw new Error(`Value ${value} is not an integer`);
244
+ }
245
+ break;
246
+ case primitive_1.Primitive.decimal:
247
+ if (!helper_1.typeH3lp.val.isDecimal(value)) {
248
+ throw new Error(`Value ${value} is not a number`);
249
+ }
250
+ break;
251
+ case primitive_1.Primitive.number:
252
+ if (!helper_1.typeH3lp.val.isNumber(value)) {
253
+ throw new Error(`Value ${value} is not a number`);
254
+ }
255
+ break;
256
+ case primitive_1.Primitive.boolean:
257
+ if (!helper_1.typeH3lp.val.isBoolean(value)) {
258
+ throw new Error(`Value ${value} is not a boolean`);
259
+ }
260
+ break;
261
+ case primitive_1.Primitive.date:
262
+ if (!helper_1.typeH3lp.val.isDate(value)) {
263
+ throw new Error(`Value ${value} is not a date`);
264
+ }
265
+ break;
266
+ case primitive_1.Primitive.dateTime:
267
+ if (!helper_1.typeH3lp.val.isDateTime(value)) {
268
+ throw new Error(`Value ${value} is not a date`);
269
+ }
270
+ break;
271
+ case primitive_1.Primitive.time:
272
+ if (!helper_1.typeH3lp.val.isTime(value)) {
273
+ throw new Error(`Value ${value} is not a date`);
274
+ }
275
+ break;
276
+ case primitive_1.Primitive.void:
277
+ if (value !== undefined) {
278
+ throw new Error(`Value ${value} is not undefined`);
279
+ }
280
+ break;
281
+ default:
282
+ throw new Error(`Primitive ${primitive} not implemented`);
283
+ }
284
+ }
285
+ }
286
+ static _type(value, type) {
287
+ if (value === undefined || value === null) {
288
+ return;
289
+ }
290
+ if (Array.isArray(value)) {
291
+ if (type.primitive === primitive_1.Primitive.undefined) {
292
+ type.primitive = primitive_1.Primitive.list;
293
+ type.list = { items: new Type(primitive_1.Primitive.undefined) };
294
+ }
295
+ else if (type.primitive !== primitive_1.Primitive.list && type.primitive !== primitive_1.Primitive.any) {
296
+ type.primitive = primitive_1.Primitive.any;
297
+ }
298
+ if (type.list === undefined || type.list.items === undefined) {
299
+ type.list = { items: new Type(primitive_1.Primitive.undefined) };
300
+ }
301
+ for (const item of value) {
302
+ this._type(item, type.list.items);
303
+ }
304
+ }
305
+ else if (typeof value === 'function') {
306
+ const str = value.toString();
307
+ type.primitive = primitive_1.Primitive.function;
308
+ const funcType = new TypeParser(str).parse().func;
309
+ type.func = funcType;
310
+ console.log(str);
311
+ }
312
+ else if (typeof value === 'object') {
313
+ if (type.primitive === primitive_1.Primitive.undefined) {
314
+ type.primitive = primitive_1.Primitive.obj;
315
+ type.obj = { properties: [] };
316
+ }
317
+ else if (type.primitive !== primitive_1.Primitive.obj && type.primitive !== primitive_1.Primitive.any) {
318
+ type.primitive = primitive_1.Primitive.any;
319
+ }
320
+ if (type.obj === undefined || type.obj.properties === undefined) {
321
+ type.obj = { properties: [] };
322
+ }
323
+ for (const entry of Object.entries(value)) {
324
+ let property = type.obj.properties.find(p => p.name === entry[0]);
325
+ if (property === undefined) {
326
+ property = { name: entry[0], type: new Type(primitive_1.Primitive.undefined) };
327
+ type.obj.properties.push(property);
328
+ }
329
+ else if (property.type === undefined) {
330
+ property.type = new Type(primitive_1.Primitive.undefined);
331
+ }
332
+ this._type(entry[1], property.type);
333
+ }
334
+ }
335
+ else if (typeof value === 'string') {
336
+ if (type.primitive === primitive_1.Primitive.undefined) {
337
+ type.primitive = primitive_1.Primitive.string;
338
+ }
339
+ else if (type.primitive !== primitive_1.Primitive.string && type.primitive !== primitive_1.Primitive.any) {
340
+ type.primitive = primitive_1.Primitive.any;
341
+ }
342
+ }
343
+ else if (typeof value === 'number') {
344
+ if (type.primitive === primitive_1.Primitive.undefined) {
345
+ if (Number.isInteger(value)) {
346
+ type.primitive = primitive_1.Primitive.integer;
347
+ }
348
+ else {
349
+ type.primitive = primitive_1.Primitive.decimal;
350
+ }
351
+ }
352
+ else if (type.primitive === primitive_1.Primitive.integer && !Number.isInteger(value)) {
353
+ type.primitive = primitive_1.Primitive.decimal;
354
+ }
355
+ else if (type.primitive !== primitive_1.Primitive.integer && type.primitive !== primitive_1.Primitive.decimal && type.primitive !== primitive_1.Primitive.any) {
356
+ type.primitive = primitive_1.Primitive.any;
357
+ }
358
+ }
359
+ else if (typeof value === 'boolean') {
360
+ if (type.primitive === primitive_1.Primitive.undefined) {
361
+ type.primitive = primitive_1.Primitive.boolean;
362
+ }
363
+ else if (type.primitive !== primitive_1.Primitive.boolean && type.primitive !== primitive_1.Primitive.any) {
364
+ type.primitive = primitive_1.Primitive.any;
365
+ }
366
+ }
367
+ }
368
+ static info(value, type, options) {
369
+ if (Type.isList(type) && type.list && Type.isObj(type.list.items) && type.list.items.obj) {
370
+ // List of objects
371
+ const typeObj = type.list.items;
372
+ if (!typeObj.repeated && !typeObj.nullables && !typeObj.indefinite) {
373
+ typeObj.repeated = 0;
374
+ typeObj.nullables = 0;
375
+ typeObj.indefinite = 0;
376
+ const listObjects = [];
377
+ for (const obj of value) {
378
+ if (obj === undefined) {
379
+ typeObj.indefinite++;
380
+ }
381
+ else if (obj === null) {
382
+ typeObj.nullables++;
383
+ }
384
+ else {
385
+ const key = this.key(obj, typeObj);
386
+ listObjects.push({ key, obj });
387
+ }
388
+ }
389
+ const distinctObjects = [];
390
+ for (let i = 0; i < listObjects.length; i++) {
391
+ const item = listObjects[i];
392
+ if (distinctObjects.find(o => o.key === item.key) === undefined) {
393
+ distinctObjects.push(item);
394
+ }
395
+ for (let j = i + 1; j < listObjects.length; j++) {
396
+ const item2 = listObjects[j];
397
+ if (item.key === item2.key) {
398
+ typeObj.repeated++;
399
+ }
400
+ }
401
+ }
402
+ this.onObjectProperties(distinctObjects.map(p => p.obj), typeObj);
403
+ this.completeInfoProperties(typeObj, value.length);
404
+ }
405
+ for (const property of type.list.items.obj.properties) {
406
+ this.propertyInfo(value, property, options);
407
+ }
408
+ }
409
+ else if (Type.isObj(type) && type.obj) {
410
+ // Object
411
+ for (const property of type.obj.properties) {
412
+ this.propertyInfo(value, property, options);
413
+ }
414
+ }
415
+ else if (Type.isList(type) && type.list && Type.isPrimitive(type.list.items) && type.list.items.primitive) {
416
+ // List of primitives
417
+ type.list.items.indefinite = 0;
418
+ type.list.items.nullables = 0;
419
+ type.list.items.repeated = 0;
420
+ const distinct = [];
421
+ for (let i = 0; i < value.length; i++) {
422
+ const item = value[i];
423
+ if (distinct.find(o => o === item) === undefined) {
424
+ distinct.push(item);
425
+ }
426
+ if (item === undefined) {
427
+ type.list.items.indefinite++;
428
+ }
429
+ else if (item === null) {
430
+ type.list.items.nullables++;
431
+ }
432
+ else {
433
+ for (let j = i + 1; j < value.length; j++) {
434
+ const item2 = value[j];
435
+ if (item === item2) {
436
+ type.list.items.repeated++;
437
+ }
438
+ }
439
+ }
440
+ }
441
+ type.distinctCount = distinct.length;
442
+ type.list.items.distinctCount = distinct.length;
443
+ this.completeInfoProperties(type.list.items, value.length);
444
+ if (options.describe) {
445
+ this.describe(value, type.list.items);
446
+ }
447
+ if (options.enums) {
448
+ this.enums(value, type);
449
+ }
450
+ }
451
+ }
452
+ static propertyInfo(list, property, options) {
453
+ if (!property.type) {
454
+ return;
455
+ }
456
+ property.type.indefinite = 0;
457
+ property.type.nullables = 0;
458
+ property.type.repeated = 0;
459
+ if (property.type && Type.isPrimitive(property.type)) {
460
+ // Property is a primitive in List of objects
461
+ const values = list.map(p => p[property.name]);
462
+ for (let i = 0; i < values.length; i++) {
463
+ const item = values[i];
464
+ if (item === undefined) {
465
+ property.type.indefinite++;
466
+ }
467
+ else if (item === null) {
468
+ property.type.nullables++;
469
+ }
470
+ else {
471
+ for (let j = i + 1; j < list.length; j++) {
472
+ const item2 = values[j];
473
+ if (item === item2) {
474
+ property.type.repeated++;
475
+ }
476
+ }
477
+ }
478
+ }
479
+ this.completeInfoProperties(property.type, list.length);
480
+ if (options.describe) {
481
+ this.describe(values, property.type);
482
+ }
483
+ if (options.enums) {
484
+ this.enums(values, property.type);
485
+ }
486
+ }
487
+ else if (property.type && Type.isObj(property.type) && property.type.obj) {
488
+ // Property is an object in List of objects
489
+ const listObjects = [];
490
+ for (const objs of list) {
491
+ const obj = objs[property.name];
492
+ if (obj === undefined) {
493
+ property.type.indefinite++;
494
+ }
495
+ else if (obj === null) {
496
+ property.type.nullables++;
497
+ }
498
+ else {
499
+ listObjects.push({ key: JSON.stringify(obj), obj });
500
+ }
501
+ }
502
+ const distinctObjects = [];
503
+ for (let i = 0; i < listObjects.length; i++) {
504
+ const item = listObjects[i];
505
+ if (distinctObjects.find(o => o.key === item.key) === undefined) {
506
+ distinctObjects.push(item);
507
+ }
508
+ for (let j = i + 1; j < listObjects.length; j++) {
509
+ const item2 = listObjects[j];
510
+ if (item.key === item2.key) {
511
+ property.type.repeated++;
512
+ }
513
+ }
514
+ }
515
+ this.onObjectProperties(distinctObjects.map(p => p.obj), property.type);
516
+ this.completeInfoProperties(property.type, list.length);
517
+ this.info(listObjects.map(o => o.obj), property.type, options);
518
+ }
519
+ else if (property.type && Type.isList(property.type) && property.type.list && property.type.list.items) {
520
+ // Property is a list in List of objects
521
+ const dictionary = [];
522
+ for (const item of list) {
523
+ const children = item[property.name];
524
+ if (children === undefined) {
525
+ property.type.indefinite++;
526
+ }
527
+ else if (children === null) {
528
+ property.type.nullables++;
529
+ }
530
+ else {
531
+ for (const child of children) {
532
+ const key = this.key(child, property.type.list.items);
533
+ dictionary.push({ key, obj: child });
534
+ }
535
+ }
536
+ }
537
+ for (let i = 0; i < dictionary.length; i++) {
538
+ const item = dictionary[i];
539
+ for (let j = i + 1; j < dictionary.length; j++) {
540
+ const item2 = dictionary[j];
541
+ if (item.key === item2.key) {
542
+ property.type.repeated++;
543
+ }
544
+ }
545
+ }
546
+ this.completeInfoProperties(property.type, dictionary.length);
547
+ this.info(dictionary.map(p => p.obj), property.type, options);
548
+ }
549
+ }
550
+ static onObjectProperties(list, type) {
551
+ if (!type.obj) {
552
+ return;
553
+ }
554
+ type.distinctCount = list.length;
555
+ for (const property of type.obj.properties) {
556
+ if (property.type && Type.isPrimitive(property.type)) {
557
+ property.type.onParentDistinctRepeated = 0;
558
+ const distinct = [];
559
+ const values = list.map(p => p[property.name]);
560
+ for (let i = 0; i < values.length; i++) {
561
+ const field = values[i];
562
+ if (field === undefined || field === null) {
563
+ continue;
564
+ }
565
+ else {
566
+ if (distinct.find(o => o === field) === undefined) {
567
+ distinct.push(field);
568
+ }
569
+ for (let j = i + 1; j < values.length; j++) {
570
+ const field2 = values[j];
571
+ if (field === field2) {
572
+ property.type.onParentDistinctRepeated++;
573
+ }
574
+ }
575
+ }
576
+ }
577
+ property.type.distinctCount = distinct.length;
578
+ property.type.onParentDistinctRepeatedRate = property.type.onParentDistinctRepeated / this.iterations(list.length - 1);
579
+ property.type.onParentDistinctUnique = property.type.onParentDistinctRepeated === 0 && list.length > 0;
580
+ }
581
+ }
582
+ }
583
+ static completeInfoProperties(type, count) {
584
+ type.count = count;
585
+ if (type.repeated !== undefined && type.nullables !== undefined && type.indefinite !== undefined) {
586
+ type.repeatRate = type.repeated / this.iterations(count - 1);
587
+ type.nullable = type.nullables > 0;
588
+ type.undefinable = type.indefinite > 0;
589
+ type.unique = type.repeated === 0 && type.count > 0;
590
+ }
591
+ }
592
+ static describe(list, type) {
593
+ if (!this.isPrimitive(type) || !type.count) {
594
+ return null;
595
+ }
596
+ const primitive = type.primitive;
597
+ const sorted = list.sort((a, b) => a - b);
598
+ const percentiles = this.percentiles(sorted, [10, 25, 50, 75, 90]);
599
+ type.percent10 = percentiles[0];
600
+ type.percent25 = percentiles[1];
601
+ type.percent50 = percentiles[2];
602
+ type.percent75 = percentiles[3];
603
+ type.percent90 = percentiles[4];
604
+ if (['decimal', 'number', 'integer'].includes(primitive)) {
605
+ type.sum = 0;
606
+ for (let i = 0; i < list.length; i++) {
607
+ const item = list[i];
608
+ if (item === undefined || item === null) {
609
+ continue;
610
+ }
611
+ type.sum += item;
612
+ if (type.max === undefined || type.max < item) {
613
+ type.max = item;
614
+ }
615
+ if (type.min === undefined || type.min > item) {
616
+ type.min = item;
617
+ }
618
+ }
619
+ type.mean = type.sum / list.length;
620
+ // calculate standard deviation
621
+ const differencesSquared = [];
622
+ for (let i = 0; i < list.length; i++) {
623
+ const difference = list[i] - type.mean;
624
+ const diferenciaCuadrada = Math.pow(difference, 2);
625
+ differencesSquared.push(diferenciaCuadrada);
626
+ }
627
+ const meanSquareDifferences = differencesSquared.reduce((total, value) => total + value, 0) / list.length;
628
+ type.std = Math.sqrt(meanSquareDifferences);
629
+ }
630
+ else if (['dateTime', 'date', 'time'].includes(primitive)) {
631
+ let millisecondsTotal = 0;
632
+ for (let i = 0; i < list.length; i++) {
633
+ const item = list[i];
634
+ if (item === undefined || item === null) {
635
+ continue;
636
+ }
637
+ millisecondsTotal += item.getTime();
638
+ if (type.max === undefined || type.max < item) {
639
+ type.max = item;
640
+ }
641
+ if (type.min === undefined || type.min > item) {
642
+ type.min = item;
643
+ }
644
+ }
645
+ type.mean = new Date(millisecondsTotal / list.length);
646
+ }
647
+ else if (primitive === 'string') {
648
+ for (let i = 0; i < list.length; i++) {
649
+ const item = list[i];
650
+ if (item === undefined || item === null) {
651
+ continue;
652
+ }
653
+ if (type.max === undefined || type.max < item) {
654
+ type.max = item;
655
+ }
656
+ if (type.min === undefined || type.min > item) {
657
+ type.min = item;
658
+ }
659
+ if (type.maxLen === undefined || type.maxLen < item.length) {
660
+ type.maxLen = item.length;
661
+ }
662
+ if (type.minLen === undefined || type.minLen > item.length) {
663
+ type.minLen = item.length;
664
+ }
665
+ }
666
+ }
667
+ }
668
+ static percentiles(sorted, percentiles) {
669
+ const indicesPercentiles = percentiles.map(p => Math.floor((p / 100) * sorted.length));
670
+ return indicesPercentiles.map(index => sorted[index]);
671
+ }
672
+ static enums(list, type) {
673
+ if (!this.isPrimitive(type) || !type.count) {
674
+ return null;
675
+ }
676
+ const primitive = type.primitive;
677
+ if (['number', 'integer', 'string'].includes(primitive) &&
678
+ type.count && type.distinctCount &&
679
+ (type.distinctCount === 1 ||
680
+ (type.count > 6 && type.distinctCount < 3) ||
681
+ (type.count > 12 && type.distinctCount < 4) ||
682
+ (type.count > 100 && type.distinctCount / type.count < 0.1) ||
683
+ (type.count > 1000 && type.distinctCount / type.count < 0.05))) {
684
+ type.enums = [];
685
+ for (let i = 0; i < list.length; i++) {
686
+ const item = list[i];
687
+ if (item === undefined || item === null) {
688
+ continue;
689
+ }
690
+ const enumItem = type.enums.find(e => e.value === item);
691
+ if (enumItem === undefined) {
692
+ type.enums.push({ value: item, count: 1 });
693
+ }
694
+ else {
695
+ enumItem.count++;
696
+ }
697
+ }
698
+ }
699
+ else if (primitive === 'boolean') {
700
+ let trueCount = 0;
701
+ let falseCount = 0;
702
+ for (let i = 0; i < list.length; i++) {
703
+ const item = list[i];
704
+ if (item === undefined || item === null) {
705
+ continue;
706
+ }
707
+ if (item) {
708
+ trueCount++;
709
+ }
710
+ else {
711
+ falseCount++;
712
+ }
713
+ }
714
+ type.enums = [{ value: true, count: trueCount }, { value: false, count: falseCount }];
715
+ }
716
+ }
717
+ static iterations(n) {
718
+ if (n === 0) {
719
+ return 0;
720
+ }
721
+ return n + this.iterations(n - 1);
722
+ }
723
+ static key(value, type) {
724
+ if (Type.isList(type) && type.list) {
725
+ const keys = [];
726
+ for (const item of value) {
727
+ keys.push(this.key(item, type.list.items));
728
+ }
729
+ return '[' + keys.sort().join(',') + ']';
730
+ }
731
+ else if (Type.isObj(type) && type.obj) {
732
+ const keys = [];
733
+ for (const property of type.obj.properties.sort((a, b) => a.name.localeCompare(b.name))) {
734
+ if (property.type) {
735
+ const propertyValue = value[property.name];
736
+ if (propertyValue !== undefined && propertyValue !== null) {
737
+ keys.push(property.name + ':' + this.key(propertyValue, property.type));
738
+ }
739
+ }
740
+ }
741
+ return '{' + keys.join(',') + '}';
742
+ }
743
+ else if (Type.isPrimitive(type)) {
744
+ return value.toString();
745
+ }
746
+ else {
747
+ return value.toString();
748
+ }
749
+ }
750
+ }
751
+ exports.Type = Type;
752
+ class TypeParser {
753
+ constructor(source) {
754
+ this.buffer = source.split('');
755
+ this.length = this.buffer.length;
756
+ this.index = 0;
757
+ this.reAlphanumeric = /[a-zA-Z0-9_.]+$/;
758
+ }
759
+ get end() {
760
+ return this.index >= this.length;
761
+ }
762
+ get current() {
763
+ return this.buffer[this.index];
764
+ }
765
+ chars(count = 1, offset = 0) {
766
+ const chars = [];
767
+ for (let i = this.index + offset; i < count; i++) {
768
+ if (i >= this.length) {
769
+ return chars.join('');
770
+ }
771
+ chars.push(this.buffer[i]);
772
+ }
773
+ return chars.join('');
774
+ }
775
+ parse() {
776
+ return this.getType();
777
+ }
778
+ isAlphanumeric(value) {
779
+ if (value === null || value === undefined) {
780
+ return false;
781
+ }
782
+ return this.reAlphanumeric.test(value);
783
+ }
784
+ getType() {
785
+ const char = this.current;
786
+ if (this.isAlphanumeric(char)) {
787
+ const value = this.getValue();
788
+ if (Type.isPrimitive(value) || value === primitive_1.Primitive.any) {
789
+ return Type.to(value);
790
+ }
791
+ else {
792
+ throw new Error(`Cannot solve ${value}`);
793
+ }
794
+ }
795
+ else if (char === '{') {
796
+ this.index += 1;
797
+ this.forwardSpaces();
798
+ const objectType = this.getObject();
799
+ return new Type(primitive_1.Primitive.obj, objectType);
800
+ }
801
+ else if (char === '[') {
802
+ this.index += 1;
803
+ this.forwardSpaces();
804
+ const listType = this.getList();
805
+ return new Type(primitive_1.Primitive.list, undefined, listType);
806
+ }
807
+ else if (char === '(') {
808
+ this.index += 1;
809
+ this.forwardSpaces();
810
+ const functionType = this.getFunction();
811
+ return new Type(primitive_1.Primitive.function, undefined, undefined, functionType);
812
+ }
813
+ else {
814
+ throw new Error('Cannot solve type');
815
+ }
816
+ }
817
+ getValue(increment = true) {
818
+ const buff = [];
819
+ if (increment) {
820
+ while (!this.end && this.isAlphanumeric(this.current)) {
821
+ buff.push(this.current);
822
+ this.index += 1;
823
+ }
824
+ }
825
+ else {
826
+ let index = this.index;
827
+ while (!this.end && this.isAlphanumeric(this.buffer[index])) {
828
+ buff.push(this.buffer[index]);
829
+ index += 1;
830
+ }
831
+ }
832
+ return buff.join('');
833
+ }
834
+ getObject() {
835
+ const properties = [];
836
+ while (true) {
837
+ const name = this.getValue();
838
+ this.forwardSpaces();
839
+ if (this.current === ':')
840
+ this.index += 1;
841
+ else
842
+ throw new Error(`attribute ${name} without value`);
843
+ const type = this.getType();
844
+ properties.push({ name, type });
845
+ this.forwardSpaces();
846
+ if (this.current === ',') {
847
+ this.index += 1;
848
+ }
849
+ else if (this.current === '}') {
850
+ this.index += 1;
851
+ break;
852
+ }
853
+ else {
854
+ throw new Error('Object without end');
855
+ }
856
+ }
857
+ return { properties };
858
+ }
859
+ getList() {
860
+ const type = this.getType();
861
+ this.forwardSpaces();
862
+ if (this.current === ']')
863
+ this.index += 1;
864
+ else
865
+ throw new Error('List without end');
866
+ return { items: type };
867
+ }
868
+ getFunction() {
869
+ const params = [];
870
+ let ret = Type.void;
871
+ while (true) {
872
+ const name = this.getValue();
873
+ this.forwardSpaces();
874
+ let type = Type.any;
875
+ if (this.current === ':') {
876
+ this.index += 1;
877
+ type = this.getType();
878
+ }
879
+ params.push({ name, type });
880
+ this.forwardSpaces();
881
+ if (this.current === ',') {
882
+ this.index += 1;
883
+ continue;
884
+ }
885
+ if (this.chars(2) === '>') {
886
+ this.index += 2;
887
+ ret = this.getType();
888
+ }
889
+ if (this.current === ')') {
890
+ this.index += 1;
891
+ break;
892
+ }
893
+ else {
894
+ throw new Error('Function without end');
895
+ }
896
+ }
897
+ return { params, ret };
898
+ }
899
+ forwardSpaces() {
900
+ while (!this.end && this.buffer[this.index] === ' ') {
901
+ this.index += 1;
902
+ }
903
+ }
904
+ }
905
+ //# sourceMappingURL=type.js.map