@ejfdelgado/ejflab-common 1.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.
Files changed (88) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +2 -0
  3. package/package.json +29 -0
  4. package/src/CollisionsEngine.js +252 -0
  5. package/src/CsvFormatter.js +54 -0
  6. package/src/CsvFormatter.test.js +119 -0
  7. package/src/CsvFormatterFilters.js +79 -0
  8. package/src/CsvParser.js +51 -0
  9. package/src/CsvParser.test.js +41 -0
  10. package/src/CsvWithFilters.js +114 -0
  11. package/src/FaceEncoder.js +64 -0
  12. package/src/FlowChartDiagram.js +503 -0
  13. package/src/IdGen.js +211 -0
  14. package/src/ModuloDatoSeguro.js +142 -0
  15. package/src/ModuloDatoSeguro.test.js +29 -0
  16. package/src/ModuloDatoSeguro.test.mjs +45 -0
  17. package/src/ModuloDatoSeguroBack.mjs +55 -0
  18. package/src/ModuloDatoSeguroFront.js +73 -0
  19. package/src/ModuloSonido.js +83 -0
  20. package/src/ModuloVideos.js +51 -0
  21. package/src/MyColor.js +136 -0
  22. package/src/MyColor.test.js +37 -0
  23. package/src/MyConstants.js +147 -0
  24. package/src/MyCookies.js +34 -0
  25. package/src/MyDates.js +412 -0
  26. package/src/MyDates.test.js +26 -0
  27. package/src/MyDatesBack.mjs +21 -0
  28. package/src/MyDatesFront.js +41 -0
  29. package/src/MyJsPdf.js +52 -0
  30. package/src/MyRoutes.js +29 -0
  31. package/src/MyTemplate.js +272 -0
  32. package/src/MyTemplate.test.js +90 -0
  33. package/src/MyTensorflow.js +248 -0
  34. package/src/MyTensorflow.test.js +19 -0
  35. package/src/MyTensorflowBack.mjs +33 -0
  36. package/src/MyThrottle.js +80 -0
  37. package/src/MyTuples.js +445 -0
  38. package/src/MyTuples.test.js +330 -0
  39. package/src/MyUtilities.js +137 -0
  40. package/src/SimpleObj.js +153 -0
  41. package/src/SimpleObj.test.js +58 -0
  42. package/src/TriangulacionGeometric.js +335 -0
  43. package/src/changePath.js +38 -0
  44. package/src/data/case0.csv +3 -0
  45. package/src/data/case0.json +24 -0
  46. package/src/data/case1.csv +2 -0
  47. package/src/data/case1.json +24 -0
  48. package/src/data/case2.csv +3 -0
  49. package/src/data/case2.json +24 -0
  50. package/src/data/case3.csv +3 -0
  51. package/src/data/case3.json +24 -0
  52. package/src/data/format0.json +0 -0
  53. package/src/data/format0.txt +1 -0
  54. package/src/data/tensordata.csv +10 -0
  55. package/src/data/tensordata.json +37 -0
  56. package/src/data/tensordata.test.csv +10 -0
  57. package/src/data/tensormodel.json +113 -0
  58. package/src/fft.js +224 -0
  59. package/src/flowchart/FlowChartExec.js +763 -0
  60. package/src/flowchart/steps/CommandBasic.js +32 -0
  61. package/src/flowchart/steps/CommandInc.js +19 -0
  62. package/src/flowchart/steps/CommandMilvus.js +47 -0
  63. package/src/flowchart/steps/CommandMinio.js +28 -0
  64. package/src/flowchart/steps/CommandMongo.js +59 -0
  65. package/src/flowchart/steps/CommandPrint.js +12 -0
  66. package/src/flowchart/steps/CommandSet.js +14 -0
  67. package/src/flowchart/steps/CommandTimeline.js +21 -0
  68. package/src/flowchart/steps/CommandTimelineNext.js +28 -0
  69. package/src/flowchart/steps/StepBasic.js +184 -0
  70. package/src/flowchart/steps/StepCheckProcessor.js +26 -0
  71. package/src/flowchart/steps/StepCheckSrc.js +42 -0
  72. package/src/flowchart/steps/StepIsTrue.js +12 -0
  73. package/src/flowchart/steps/StepOneTime.js +21 -0
  74. package/src/flowchart/steps/StepProcess.js +163 -0
  75. package/src/flowchart/steps/StepReadSrc.js +66 -0
  76. package/src/flowchart/steps/StepSleep.js +22 -0
  77. package/src/flowchart/steps/StepTimeLineEnds.js +21 -0
  78. package/src/flowchart/steps/StepTimeLineHasMore.js +16 -0
  79. package/src/gif/index.d.ts +20 -0
  80. package/src/gif/index.mjs +85 -0
  81. package/src/gif/utils/checkTypes.d.ts +2 -0
  82. package/src/gif/utils/checkTypes.mjs +11 -0
  83. package/src/js-colormaps.js +19484 -0
  84. package/src/sortify.js +75 -0
  85. package/src/sqlmodelparser/SqlModelParser.js +22 -0
  86. package/src/test/csv/test_1000_20230429204538700.csv +1001 -0
  87. package/src/test/csv/test_5_20230429204525930.csv +6 -0
  88. package/src/test/svg/test.html +5 -0
@@ -0,0 +1,330 @@
1
+ const { MyTuples } = require('./MyTuples.js');
2
+ const sortify = require('./sortify.js');
3
+
4
+ const test = async () => {
5
+ const BATCH_SIZE = 3;
6
+ const reverse = false;
7
+ const show = false;
8
+ const useProcessor = ["none", "good", "bad"][0];
9
+ const pruebas = [
10
+ {
11
+ f: { a: 2 },
12
+ i: {},
13
+ e: { "+": [{ "k": "a", "v": 2 }], "-": [], "*": [] },//solo agregar
14
+ },
15
+ {
16
+ f: [{}],
17
+ i: [{ 0: true }],
18
+ e: { "+": [], "-": [{ "k": "0.0" }], "*": [] },//solo quitar
19
+ },
20
+ {
21
+ f: [true],
22
+ i: [false],
23
+ e: { "+": [], "-": [], "*": [{ "k": "0", "v": true }] },//solo modificar
24
+ },
25
+ {
26
+ f: { a: 1, b: "t", c: true, e: null, f: "soy nuevo" },
27
+ i: { a: 1, b: "t", c: true, d: false, e: null, f: undefined },
28
+ e: { "+": [{ "k": "f", "v": "soy nuevo" }], "-": [{ "k": "d" }], "*": [] }//agregar y quitar
29
+ },
30
+ {
31
+ f: { a: [], b: { g: 6, h: 7 } },
32
+ i: { a: [2], b: { g: 5 } },
33
+ e: { "+": [{ "k": "b.h", "v": 7 }], "-": [{ "k": "a.0" }], "*": [{ "k": "b.g", "v": 6 }] }//agregar, quitar y modificar
34
+ },
35
+ {
36
+ f: { a: { b: { c: [{ h: "hola", i: "como", j: "estas" }] } } },
37
+ i: { a: { b: { c: [3, { h: "hola" }] } } },
38
+ e: { "+": [{ "k": "a.b.c.0.h", "v": "hola" }, { "k": "a.b.c.0.i", "v": "como" }, { "k": "a.b.c.0.j", "v": "estas" }], "-": [{ "k": "a.b.c.1" }, { "k": "a.b.c.1.h" }], "*": [{ "k": "a.b.c.0", "v": {} }] }
39
+ },
40
+ {
41
+ f: [{ e: 3 }, 5, 8, [9]],
42
+ i: [{ e: 3 }, 5, 8, [9]],
43
+ e: { "+": [], "-": [], "*": [] },
44
+ },
45
+ {
46
+ f: { a: 5, b: [], c: {} },
47
+ i: { a: 5, b: [], c: {} },
48
+ e: { "+": [], "-": [], "*": [] },
49
+ },
50
+ {
51
+ f: [1, 2, 3, 4],
52
+ i: [1, 2, 3, 4],
53
+ e: { "+": [], "-": [], "*": [] },
54
+ },
55
+ {
56
+ f: ["1", "2", "3"],
57
+ i: ["1", "2", "3"],
58
+ e: { "+": [], "-": [], "*": [] },
59
+ },
60
+ {
61
+ f: [true, false, true],
62
+ i: [true, false, true],
63
+ e: { "+": [], "-": [], "*": [] },
64
+ },
65
+ {
66
+ f: { a: [5, 6, 7], b: { n: true, h: false, ert: "dzfgfsdgfsdg" }, c: [{ g: 5 }, { g: 6 }, { g: 7 }] },
67
+ i: { a: [5, 6, 7], b: { n: true, h: false, ert: "dzfggfsdg" }, c: [{ g: 6 }, { g: 7 }] },
68
+ e: { "*": [{ "k": "b.ert", "v": "dzfgfsdgfsdg" }, { "k": "c.0.g", "v": 5 }, { "k": "c.1.g", "v": 6 }], "+": [{ "k": "c.2", "v": {} }, { "k": "c.2.g", "v": 7 }], "-": [] },
69
+ },
70
+ {
71
+ f: { a: { 1: 6, 4: 5 } },
72
+ i: { a: { 1: 6, 4: 5 } },
73
+ e: { "+": [], "-": [], "*": [] },
74
+ }, //esto no se debe guardar porque pasará a ser un arreglo
75
+ ];
76
+
77
+ const mockProcessorGood = (payload) => {
78
+ return new Promise((resolve, reject) => {
79
+ setTimeout(() => {
80
+ console.log(`Processing ${JSON.stringify(payload, null, 4)} OK`);
81
+ resolve();
82
+ }, 0);
83
+ });
84
+ };
85
+
86
+ const getBadProcessor = () => {
87
+ let count = 0;
88
+ let maxCount = 3;
89
+ const mockProcessorBad = (payload) => {
90
+ return new Promise((resolve, reject) => {
91
+ setTimeout(() => {
92
+ if (count < maxCount) {
93
+ console.log(`Processing ${JSON.stringify(payload, null, 4)} ERROR`);
94
+ reject();
95
+ count++;
96
+ } else {
97
+ console.log(`Processing ${JSON.stringify(payload, null, 4)} OK`);
98
+ resolve();
99
+ count = 0;
100
+ }
101
+
102
+ }, 500);
103
+ });
104
+ };
105
+ return mockProcessorBad;
106
+ };
107
+
108
+ // Las funciones se deben ignorar
109
+ pruebas[0].i.p = function () { };
110
+ // Los loops se deben ignorar
111
+ pruebas[5].i.loop = pruebas[5].i;
112
+
113
+ for (let i = 0; i < pruebas.length; i++) {
114
+ console.log(`Prueba ${i + 1} ----------------------------------------------`);
115
+ const prueba = pruebas[i];
116
+ const tuplas = MyTuples.getTuples(prueba.i);
117
+ const referencia = sortify(prueba.i);
118
+ const intercambio = sortify(tuplas);
119
+ let buffer = {};
120
+ const builder = MyTuples.getBuilder();
121
+ const builder2 = MyTuples.getBuilder();
122
+ if (useProcessor == "bad") {
123
+ builder.setProcesor(getBadProcessor());
124
+ }
125
+ if (useProcessor == "good") {
126
+ builder.setProcesor(mockProcessorGood);
127
+ }
128
+ let llaves1 = Object.keys(tuplas);
129
+ if (reverse) {
130
+ llaves1 = llaves1.reverse();
131
+ }
132
+ llaves1.forEach(element => {
133
+ buffer[element] = tuplas[element];
134
+ if (Object.keys(buffer).length >= BATCH_SIZE) {
135
+ builder.build(buffer);
136
+ builder2.build(buffer);
137
+ buffer = {};
138
+ }
139
+ });
140
+ if (Object.keys(buffer).length > 0) {
141
+ builder.build(buffer);
142
+ builder2.build(buffer);
143
+ buffer = {};
144
+ }
145
+ const resultadoTxt = sortify(builder.end());
146
+ builder2.end();
147
+
148
+ const indicadorActividad = new Promise((resolve) => {
149
+ builder.addActivityListener((status) => {
150
+ if (!status) {
151
+ resolve();
152
+ console.log("Terminado...");
153
+ } else {
154
+ console.log("Esperando...");
155
+ }
156
+ });
157
+ });
158
+ const differences = builder.trackDifferences(prueba.f);
159
+ await indicadorActividad;
160
+
161
+ const afectado = builder2.affect(differences);
162
+
163
+ const differencesTxt = sortify(differences);
164
+
165
+ if (show) {
166
+ console.log("--------------------------------------------------------");
167
+ console.log(referencia);
168
+ console.log(intercambio);
169
+ console.log(resultadoTxt);
170
+ }
171
+
172
+ if (referencia != resultadoTxt) {
173
+ throw Error(`referencia ${referencia} \nintercambio ${intercambio}\nresultadoTxt ${resultadoTxt}`);
174
+ }
175
+
176
+ if (sortify(prueba.e) != differencesTxt) {
177
+ throw Error(`Modificación fallida ${JSON.stringify(prueba)}\n${differencesTxt}`);
178
+ }
179
+
180
+ if (sortify(prueba.f) != sortify(afectado)) {
181
+ throw Error(`Afectación fallida ${JSON.stringify(prueba)}`);
182
+ }
183
+ console.log(`Prueba ${i + 1} OK`);
184
+ }
185
+ }
186
+
187
+ const testConverter = () => {
188
+ const pruebas = [
189
+ {
190
+ i: [
191
+ { k: "6543:fdgfd.ghgf.t", v: 2 },
192
+ { k: "6543:fdgfd.ghgf", v: {} },
193
+ { k: "6543:fdgfd", v: {} },
194
+ ],
195
+ o: {
196
+ "6543:fdgfd.ghgf.t": 2,
197
+ "6543:fdgfd.ghgf": {},
198
+ "6543:fdgfd": {},
199
+ }
200
+ },
201
+ {
202
+ i: [],
203
+ o: {},
204
+ }
205
+ ];
206
+
207
+ for (let i = 0; i < pruebas.length; i++) {
208
+ const actual = pruebas[i];
209
+ const input = actual.i;
210
+ const o = actual.o;
211
+ const response = MyTuples.convertFromBD(input);
212
+
213
+ const oText = sortify(o);
214
+ const responseTxt = sortify(response);
215
+ if (oText != responseTxt) {
216
+ throw new Error(`Prueba fallida ${oText} != ${responseTxt}`);
217
+ }
218
+ }
219
+ };
220
+
221
+ const testArray = () => {
222
+ const restas = [
223
+ { a: [1, 3, 5], b: [3], r: [1, 5] },
224
+ { a: [], b: [4, 7], r: [] },
225
+ { a: [3, 4, 5], b: [], r: [3, 4, 5] },
226
+ ];
227
+ const interseccion = [
228
+ { a: [1, 3, 5], b: [3], r: [3] },
229
+ { a: [], b: [4, 8, 9], r: [] },
230
+ { a: [4, 8, 9], b: [], r: [] },
231
+ ];
232
+ for (let i = 0; i < restas.length; i++) {
233
+ const prueba = restas[i];
234
+ const response = MyTuples.restarArreglo(prueba.a, prueba.b);
235
+ const responseTxt = sortify(response);
236
+ const refTxt = sortify(prueba.r);
237
+ if (responseTxt != refTxt) {
238
+ throw Error(`Resta fallida ${JSON.stringify(prueba)}`);
239
+ }
240
+ }
241
+ for (let i = 0; i < interseccion.length; i++) {
242
+ const prueba = interseccion[i];
243
+ const response = MyTuples.intersecionArreglo(prueba.a, prueba.b);
244
+ const responseTxt = sortify(response);
245
+ const refTxt = sortify(prueba.r);
246
+ if (responseTxt != refTxt) {
247
+ throw Error(`Interseccion fallida ${JSON.stringify(prueba)}`);
248
+ }
249
+ }
250
+ }
251
+
252
+ const testArrayCompress = () => {
253
+ const casos = [
254
+ { i: { someArray: [1, 23, 3, 4], maxLength: 5 }, myExpected: ["[1]", "[23]", "[3,4]"] },
255
+ { i: { someArray: [1, 230, 3, 4], maxLength: 5 }, myExpected: ["[1]", "[230]", "[3,4]"] },
256
+ { i: { someArray: [1, 2301, 3, 4], maxLength: 5 }, myExpected: "Can't compress with size 5 one item has size 4" },
257
+ { i: { someArray: [1, 2, 3, 4], maxLength: 5 }, myExpected: ["[1,2]", "[3,4]"] },
258
+ ];
259
+
260
+ for (let i = 0; i < casos.length; i++) {
261
+ const caso = casos[i];
262
+ let myActual = null;
263
+ let myRaw = null;
264
+ try {
265
+ myRaw = MyTuples.arrayCompress(caso.i);
266
+ myActual = sortify(myRaw);
267
+ } catch (err) {
268
+ myActual = sortify(err.message);
269
+ }
270
+
271
+ myExpected = sortify(caso.myExpected);
272
+ if (myExpected != myActual) {
273
+ throw Error(`Compresion fallida expected: ${myExpected} actual ${myActual}`);
274
+ } else {
275
+ console.log(`Case compress ${i + 1} Ok`);
276
+ }
277
+
278
+ if (caso.myExpected instanceof Array) {
279
+ // Se valida la descompresión
280
+ const uncompressed = MyTuples.arrayUnCompress(myRaw);
281
+ const unCompressExpected = sortify(caso.i.someArray);
282
+ const unCompressActual = sortify(uncompressed);
283
+ if (unCompressExpected != unCompressActual) {
284
+ throw Error(`Descompresion fallida expected: ${unCompressExpected} actual ${unCompressActual}`);
285
+ } else {
286
+ console.log(`Case uncompress ${i + 1} Ok`);
287
+ }
288
+ }
289
+ }
290
+ }
291
+
292
+ const testSimple = () => {
293
+
294
+ const mockProcessorGood = (payload) => {
295
+ return new Promise((resolve, reject) => {
296
+ setTimeout(() => {
297
+ console.log(`Processing ${JSON.stringify(payload, null, 4)} OK`);
298
+ resolve();
299
+ }, 0);
300
+ });
301
+ };
302
+
303
+ let model = { persona: { nombre: "Edgar", edad: 38 } };
304
+ const builderConfig = { MAX_SEND_SIZE: 1000, LOW_PRESSURE_MS: 0, BACK_OFF_MULTIPLIER: 0 };
305
+ const builder = MyTuples.getBuilder(builderConfig);
306
+ builder.setProcesor(mockProcessorGood);
307
+ builder.build({});
308
+ const res1 = builder.end();
309
+ model.persona.nombre = "Edgar Delgado";
310
+ delete model.persona.edad;
311
+ model.persona.color = "red";
312
+ model.persona.animal = "dog";
313
+ //console.log(res1);
314
+
315
+ const differences1 = builder.trackDifferences(model);
316
+ const afectado1 = builder.affect(differences1);
317
+ console.log(afectado1);
318
+
319
+ const differences2 = builder.trackDifferences({});
320
+ const afectado2 = builder.affect(differences2);
321
+ console.log(afectado2);
322
+
323
+ const differences3 = builder.trackDifferences({ a: 1 });
324
+ const afectado3 = builder.affect(differences3);
325
+ console.log(afectado3);
326
+ }
327
+
328
+ testSimple();
329
+ //testArrayCompress();
330
+ //testConverter();
@@ -0,0 +1,137 @@
1
+ class MyUtilities {
2
+ static MIN_LENGTH_TOKENS = 3;
3
+ static MAX_LENGTH_TOKENS = 25;
4
+ static LISTA_NEGRA_TOKENS = [
5
+ 'de', 'en', 'con', 'para', 'el', 'él',
6
+ 'la', 'sin', 'mas', 'ella', 'ellos',
7
+ 'es', 'un', 'una', 'mas', 'pero', 'aún',
8
+ 'aunque', 'sino', 'que', 'no', 'porque', 'pues'];
9
+
10
+ static stringify(circ) {
11
+ const cache = [];
12
+ const text = JSON.stringify(circ, (key, value) => {
13
+ if (typeof value === 'object' && value !== null) {
14
+ if (cache.includes(value)) return;
15
+ cache.push(value);
16
+ }
17
+ return value;
18
+ });
19
+ cache = null;
20
+ return text;
21
+ };
22
+ static htmlEntities(str) {
23
+ return String(str)
24
+ .replace(/&/g, "&amp;")
25
+ .replace(/</g, "&lt;")
26
+ .replace(/>/g, "&gt;")
27
+ .replace(/"/g, "&quot;");
28
+ }
29
+ static splitPageData(path) {
30
+ const partes = /(\/[^/]+)(\/\d+|\/)?/ig.exec(path);
31
+ let pageId = null;
32
+ if (typeof partes[2] == "string") {
33
+ pageId = parseInt(partes[2].replace("/", ""));
34
+ }
35
+ return {
36
+ pageId,
37
+ pageType: partes[1],
38
+ };
39
+ }
40
+ static partirTexto(q, buscable = true, permisivo = false) {
41
+ //solo minusculas
42
+ q = q.toLowerCase();
43
+ //Quito caracteres no validos
44
+ if (!permisivo) {
45
+ q = q.replace(/[^\w\d\sá-úü]/g, '');
46
+ }
47
+ //Reemplazar tildes dieresis
48
+ q = q.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
49
+
50
+ let tokens = q.split(/\s+/);
51
+ // Elimino textos con tamaño pequeño
52
+ tokens = tokens.filter((word) => { return word.length >= MyUtilities.MIN_LENGTH_TOKENS });
53
+
54
+ // Elimino textos con tamaño grande
55
+ tokens = tokens.filter((word) => { return word.length <= MyUtilities.MAX_LENGTH_TOKENS });
56
+
57
+ // Elimino los que pertenecen a la lista negra
58
+ tokens = tokens.filter((word) => { return MyUtilities.LISTA_NEGRA_TOKENS.indexOf(word) < 0 });
59
+
60
+ if (buscable) {
61
+ // Se debe partir en pedazos mas pequeños cada palabra
62
+ tokens = tokens.reduce((acc, word, index) => {
63
+ let temp = word;
64
+ do {
65
+ acc.push(temp);
66
+ temp = temp.substring(0, temp.length - 1);
67
+ } while (temp.length >= MyUtilities.MIN_LENGTH_TOKENS);
68
+ return acc;
69
+ }, []);
70
+
71
+ //Elimino duplicados
72
+ tokens = tokens.filter((word, index) => { return (index == tokens.indexOf(word)) });
73
+ } else {
74
+ tokens = tokens.filter((word, index) => { return (index == tokens.indexOf(word)) });
75
+ }
76
+
77
+ return tokens;
78
+ }
79
+ static isHidden(el) {
80
+ let is = (el.offsetParent === null);
81
+ if (!is) {
82
+ const style = window.getComputedStyle(el);
83
+ return (style.display === 'none');
84
+ }
85
+ return is;
86
+ }
87
+ static downloadTextData({ text = "", mime = "text/plain", filename = "file.txt" }) {
88
+ function downloadBlob(blob, name) {
89
+ const blobUrl = URL.createObjectURL(blob);
90
+ const link = document.createElement("a");
91
+ link.href = blobUrl;
92
+ link.download = name;
93
+ document.body.appendChild(link);
94
+ link.dispatchEvent(
95
+ new MouseEvent('click', {
96
+ bubbles: true,
97
+ cancelable: true,
98
+ view: window
99
+ })
100
+ );
101
+ document.body.removeChild(link);
102
+ }
103
+ function text2Blob(bstr, mime) {
104
+ return new Blob([bstr], { type: mime });
105
+ }
106
+ const blob2 = text2Blob(text, mime);
107
+ downloadBlob(blob2, filename);
108
+ }
109
+
110
+ static async replaceAsync(str, regex, asyncFn) {
111
+ const promises = [];
112
+ str.replace(regex, (match, ...args) => {
113
+ const promise = asyncFn(match, ...args);
114
+ promises.push(promise);
115
+ });
116
+ const data = await Promise.all(promises);
117
+ return str.replace(regex, () => data.shift());
118
+ }
119
+
120
+ static async replaceAsync2(str, regex, asyncFn) {
121
+ const promises = [];
122
+ str.replace(regex, (match, ...args) => {
123
+ const promise = asyncFn(match, ...args);
124
+ promises.push(promise);
125
+ });
126
+ const data = await Promise.all(promises);
127
+ const copy = [...data];
128
+ return {
129
+ first: str.replace(regex, () => data.shift()[0]),
130
+ second: str.replace(regex, () => copy.shift()[1]),
131
+ }
132
+ }
133
+ }
134
+
135
+ module.exports = {
136
+ MyUtilities
137
+ };
@@ -0,0 +1,153 @@
1
+ class SimpleObj {
2
+ static convertMapToArray(myMap) {
3
+ const keys = Object.keys(myMap);
4
+ const response = [];
5
+ for (let i = 0; i < keys.length; i++) {
6
+ const myKey = parseInt(keys[i]);
7
+ if (!isNaN(myKey)) {
8
+ response[myKey] = myMap[keys[i]];
9
+ }
10
+ }
11
+ return response;
12
+ }
13
+ static transFromModel(model, configList) {
14
+ const response = {};
15
+ for (let i = 0; i < configList.length; i++) {
16
+ const config = configList[i];
17
+ let { orig, dest, def } = config;
18
+ if (def === undefined) {
19
+ def = null;
20
+ }
21
+ let valor = SimpleObj.getValue(model, orig);
22
+ if ([null, undefined].indexOf(valor) >= 0) {
23
+ valor = def;
24
+ }
25
+ response[dest] = valor;
26
+ }
27
+ return response;
28
+ }
29
+ static getValue(obj, key, myDefault = undefined) {
30
+ let current = obj;
31
+ const canIterate = (some) => {
32
+ return (typeof some == "object" && some !== null);
33
+ };
34
+ if (!canIterate(current)) {
35
+ return myDefault;
36
+ }
37
+ const partes = key.split(".");
38
+ while (canIterate(current) && partes.length > 0) {
39
+ const firstKey = partes.splice(0, 1)[0];
40
+ current = current[firstKey];
41
+ }
42
+ if (current !== undefined && partes.length == 0) {
43
+ return current;
44
+ } else {
45
+ return myDefault;
46
+ }
47
+ }
48
+ static createBasic(todo, llave, llave2) {
49
+ const llave2EsNumero = (/^\d+$/.exec(llave2) != null);
50
+ if (!(llave in todo)) {
51
+ if (llave2EsNumero) {
52
+ todo[llave] = [];
53
+ } else {
54
+ todo[llave] = {};
55
+ }
56
+ } else {
57
+ const indice = todo[llave];
58
+ if (indice instanceof Array && !llave2EsNumero) {
59
+ //migrar de arreglo a objeto
60
+ const temporal = {};
61
+ for (let i = 0; i < indice.length; i++) {
62
+ temporal[i] = indice[i];
63
+ }
64
+ todo[llave] = temporal;
65
+ }
66
+ }
67
+ return todo;
68
+ }
69
+ static objectWrite(indice, ultimaLlave, valor) {
70
+ //console.log(`indice ${JSON.stringify(indice)}, ultimaLlave ${ultimaLlave}, valor ${JSON.stringify(valor)}`);
71
+ if (typeof indice[ultimaLlave] == "object" && [null, undefined].indexOf(indice[ultimaLlave]) < 0) {
72
+ //console.log("Caso 1");
73
+ // El destino es un objeto o arreglo
74
+ if (typeof valor == "object" && [null, undefined].indexOf(valor) < 0) {
75
+ // Tanto origen como destino son objetos o arreglos, se podría intentar mezclar
76
+ if (valor instanceof Array) {
77
+ /*
78
+ for (let k = 0; k < valor.length; k++) {
79
+ const elem = valor[k];
80
+ if (elem != undefined) {
81
+ indice[ultimaLlave][k] = elem;
82
+ }
83
+ }
84
+ */
85
+ indice[ultimaLlave] = valor;
86
+ } else {
87
+ Object.assign(indice[ultimaLlave], valor);
88
+ }
89
+ } else if (valor === undefined) {
90
+ // El valor es indefinido, se entiende que se quiere borrar
91
+ delete indice[ultimaLlave];
92
+ } else {
93
+ // El nuevo valor no es un objeto, se entiende que se desea reemapolzar simplemente
94
+ indice[ultimaLlave] = valor;
95
+ }
96
+ } else {
97
+ //console.log("Caso 2");
98
+ // El destino no era un objeto entonces no hay necesidad de mezclar, solo asignar
99
+ // Sin importar lo que sea el nuevo valor
100
+ indice[ultimaLlave] = valor;
101
+ }
102
+ }
103
+ static recreate(todo, llave, valor, simple = false) {
104
+ const partes = llave.split(".");
105
+ let indice = todo;
106
+ for (let i = 0; i < partes.length - 1; i++) {
107
+ const parte = partes[i];
108
+ if (!(parte in indice)) {
109
+ SimpleObj.createBasic(indice, parte, partes[i + 1]);
110
+ }
111
+ indice = indice[parte];
112
+ }
113
+ const ultimaLlave = partes[partes.length - 1];
114
+ if (simple) {
115
+ if (valor === undefined) {
116
+ delete indice[ultimaLlave];
117
+ } else {
118
+ SimpleObj.objectWrite(indice, ultimaLlave, valor);
119
+ }
120
+ return todo;
121
+ }
122
+ if (typeof valor == "object" && valor !== null) {
123
+ if (!indice[ultimaLlave]) {
124
+ if (valor instanceof Array) {
125
+ indice[ultimaLlave] = [];
126
+ } else {
127
+ indice[ultimaLlave] = {};
128
+ }
129
+ } else {
130
+ if (!(valor instanceof Array) && indice[ultimaLlave] instanceof Array) {
131
+ //migrar de arreglo a objeto
132
+ const temporal = indice[ultimaLlave];
133
+ const nuevo = {};
134
+ for (let i = 0; i < temporal.length; i++) {
135
+ const valorLocal = temporal[i];
136
+ if (valorLocal !== null) {
137
+ nuevo[i] = valorLocal;
138
+ }
139
+ }
140
+ indice[ultimaLlave] = nuevo;
141
+ }
142
+ }
143
+ SimpleObj.objectWrite(indice, ultimaLlave, valor);
144
+ } else {
145
+ indice[ultimaLlave] = valor;
146
+ }
147
+ return todo;
148
+ }
149
+ };
150
+
151
+ module.exports = {
152
+ SimpleObj
153
+ };
@@ -0,0 +1,58 @@
1
+ const { SimpleObj } = require("./SimpleObj");
2
+ const sortify = require("./sortify");
3
+
4
+ const testGetValue = () => {
5
+ const MY_CASES = [
6
+ { obj: { a: 1 }, key: "a", val: 1 },
7
+ { obj: { a: { b: 4 } }, key: "a.b", val: 4 },
8
+ { obj: [6], key: "0", val: 6 },
9
+ { obj: [{ x: 9 }], key: "0.x", val: 9 },
10
+ { obj: null, key: "noex", val: null, def: null },
11
+ { obj: { a: ["a", true, false] }, key: "a.2", val: false },
12
+ { obj: { a: 1 }, key: "b", val: undefined },
13
+ { obj: { x: { v: { a: null } } }, key: "x.v.a.n.j", val: "nada", def: "nada" },
14
+ ];
15
+
16
+ for (let i = 0; i < MY_CASES.length; i++) {
17
+ const MY_CASE = MY_CASES[i];
18
+ const obj = MY_CASE.obj;
19
+ const key = MY_CASE.key;
20
+ const def = MY_CASE.def;
21
+ const myExpected = MY_CASE.val;
22
+ const response = SimpleObj.getValue(obj, key, def);
23
+ if (response !== myExpected) {
24
+ throw Error(`expected ${JSON.stringify(myExpected)} actual ${JSON.stringify(response)}`);
25
+ } else {
26
+ console.log(`case ${i + 1} OK! ${JSON.stringify(myExpected)} equals ${JSON.stringify(response)}`);
27
+ }
28
+ }
29
+
30
+ console.log(JSON.stringify(SimpleObj.convertMapToArray({ "0": "Primero", "1": "Segundo" })));
31
+ console.log(JSON.stringify(SimpleObj.convertMapToArray({ "1": "Primero", "2": "Segundo" })));
32
+ }
33
+
34
+ const testWriteValue = () => {
35
+ const MY_CASES = [
36
+ { obj: { a: 1 }, key: "a", val: 2, exp: { a: 2 } },
37
+ { obj: { players: {} }, key: "players.P12", val: { name: "Edgar" }, exp: { players: { P12: { name: "Edgar" } } } },
38
+ ];
39
+ for (let i = 0; i < MY_CASES.length; i++) {
40
+ const MY_CASE = MY_CASES[i];
41
+ const obj = MY_CASE.obj;
42
+ const key = MY_CASE.key;
43
+ const val = MY_CASE.val;
44
+ const myExpected = MY_CASE.exp;
45
+ const response = SimpleObj.recreate(obj, key, val);
46
+ const textoEsperado = sortify(myExpected);
47
+ const textoCalculado = sortify(response);
48
+ if (textoCalculado !== textoEsperado) {
49
+ throw Error(`expected ${JSON.stringify(textoEsperado)} actual ${JSON.stringify(textoCalculado)}`);
50
+ } else {
51
+ console.log(`case ${i + 1} OK! ${JSON.stringify(textoEsperado)} equals ${JSON.stringify(textoCalculado)}`);
52
+ }
53
+ }
54
+ };
55
+
56
+ //testGetValue();
57
+ //testWriteValue();
58
+