jupyter-ijavascript-utils 1.8.5 → 1.9.2
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/DOCS.md +2 -1
- package/Dockerfile +34 -0
- package/README.md +4 -0
- package/package.json +1 -1
- package/src/TableGenerator.js +121 -21
- package/src/file.js +86 -0
- package/src/format.js +40 -0
- package/src/ijs.js +1 -1
- package/src/object.js +154 -0
package/DOCS.md
CHANGED
|
@@ -28,7 +28,8 @@ See the [#Installation section for requirements and installation](#install)
|
|
|
28
28
|
|
|
29
29
|
## What's New
|
|
30
30
|
|
|
31
|
-
* 1.
|
|
31
|
+
* 1.9 - allow {@link TableGenerator#transpose|transposing results} on TableGenerator.
|
|
32
|
+
* 1.8 - add in What can I Do tutorial, and {@link module:object.join|object.join methods}
|
|
32
33
|
* 1.7 - revamp of `animation` method for ijs.htmlScript
|
|
33
34
|
* 1.6 - add SVG support for rendering SVGs and animations with {@link module:svg}.
|
|
34
35
|
* 1.5 - Add LaTeX / KaTeX support with {@link module:latex} for rendering Math formulas and PlantUML support for Diagrams
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# per https://github.com/n-riesco/ijavascript/issues/273
|
|
2
|
+
# and https://github.com/paulroth3d/jupyter-ijavascript-utils/issues/4
|
|
3
|
+
|
|
4
|
+
# as of today this is python-3.7.1
|
|
5
|
+
FROM jupyter/base-notebook:latest
|
|
6
|
+
|
|
7
|
+
# for nbhosting
|
|
8
|
+
USER root
|
|
9
|
+
COPY start-in-dir-as-uid.sh /usr/local/bin
|
|
10
|
+
|
|
11
|
+
# prerequisites with apt-get
|
|
12
|
+
# we do install python(2) here because
|
|
13
|
+
# some npm build part named gyp still requires it
|
|
14
|
+
RUN apt-get update && apt-get install -y gcc g++ make python
|
|
15
|
+
|
|
16
|
+
# !!! dirty trick!!!
|
|
17
|
+
# original PATH is
|
|
18
|
+
# /opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
19
|
+
# move conda's path **at the end**
|
|
20
|
+
# so that python resolves in /usr/bin/python(2)
|
|
21
|
+
# but node is still found in conda
|
|
22
|
+
ENV PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/conda/bin"
|
|
23
|
+
USER jovyan
|
|
24
|
+
RUN npm install -g ijavascript
|
|
25
|
+
RUN ijsinstall
|
|
26
|
+
|
|
27
|
+
# for displaying html fragments
|
|
28
|
+
RUN npm install -g jsdom d3
|
|
29
|
+
|
|
30
|
+
# !!! clean up!!!
|
|
31
|
+
USER root
|
|
32
|
+
RUN apt-get autoremove -y python
|
|
33
|
+
ENV PATH="/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
34
|
+
USER jovyan
|
package/README.md
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
<img src="https://img.shields.io/badge/License-MIT-green" />
|
|
7
7
|
</a>
|
|
8
8
|
<img src="https://img.shields.io/badge/Coverage-98-green" />
|
|
9
|
+
<a href="https://github.com/paulroth3d/jupyter-ijavascript-utils" alt="npm">
|
|
10
|
+
<img src="https://img.shields.io/badge/npm-%5E1.9.2-red" />
|
|
11
|
+
</a>
|
|
9
12
|
</p>
|
|
10
13
|
|
|
11
14
|
# Overview
|
|
@@ -18,6 +21,7 @@ See documentation at: [https://jupyter-ijavascript-utils.onrender.com/](https://
|
|
|
18
21
|
|
|
19
22
|
# What's New
|
|
20
23
|
|
|
24
|
+
* 1.9 - allow transposing results on TableGenerator.
|
|
21
25
|
* 1.8 - add in What can I Do tutorial, and object.join methods
|
|
22
26
|
* 1.7 - revamp of `animation` method to htmlScript
|
|
23
27
|
* 1.6 - add SVG support for rendering SVGs and animations
|
package/package.json
CHANGED
package/src/TableGenerator.js
CHANGED
|
@@ -17,6 +17,8 @@ const generateRange = (length, defaultValue) => new Array(length).fill(defaultVa
|
|
|
17
17
|
|
|
18
18
|
const IJSUtils = require('./ijs');
|
|
19
19
|
|
|
20
|
+
const ArrayUtils = require('./array');
|
|
21
|
+
|
|
20
22
|
const { createSort } = require('./array');
|
|
21
23
|
|
|
22
24
|
/**
|
|
@@ -62,29 +64,32 @@ const { createSort } = require('./array');
|
|
|
62
64
|
* * change the columns and headers
|
|
63
65
|
* * {@link TableGenerator#columns|columns(field, field, ...)} - specify fields and order
|
|
64
66
|
* * {@link TableGenerator#columnsToExclude|columnsToExclude(field, ...)} - specify fields not to show
|
|
65
|
-
* * {@link TableGenerator#labels|lables(obj} - labels for field headers
|
|
67
|
+
* * {@link TableGenerator#labels|lables(obj)} - labels for field headers
|
|
66
68
|
* * augment and change the values (non-destructively)
|
|
67
|
-
* * {@link TableGenerator#formatter|formatter(obj} - adjust values of specific fields
|
|
68
|
-
* * {@link TableGenerator#formatterFn|formatterFn(fn} - row, column aware adjustment
|
|
69
|
-
* * {@link TableGenerator#printOptions|printOptions(object} - options for value rendering
|
|
69
|
+
* * {@link TableGenerator#formatter|formatter(obj)} - adjust values of specific fields
|
|
70
|
+
* * {@link TableGenerator#formatterFn|formatterFn(fn)} - row, column aware adjustment
|
|
71
|
+
* * {@link TableGenerator#printOptions|printOptions(object)} - options for value rendering
|
|
70
72
|
* * {@link TableGenerator#augment|augment(obj)} - add fields to table
|
|
71
73
|
* * sort and limit the output
|
|
72
|
-
* * {@link TableGenerator#filter|filter(fn)
|
|
73
|
-
* * {@link TableGenerator#limit|limit(number} - limit only specific # of rows
|
|
74
|
-
* * {@link TableGenerator#sortFn|sortFn(fn} - Standard Array sort function
|
|
75
|
-
* * {@link TableGenerator#sort|sort(field, field, ...} - sorts by fields, or descending with -
|
|
74
|
+
* * {@link TableGenerator#filter|filter(fn)} - determine which rows to include or not
|
|
75
|
+
* * {@link TableGenerator#limit|limit(number)} - limit only specific # of rows
|
|
76
|
+
* * {@link TableGenerator#sortFn|sortFn(fn)} - Standard Array sort function
|
|
77
|
+
* * {@link TableGenerator#sort|sort(field, field, ...)} - sorts by fields, or descending with '-'
|
|
78
|
+
* * transpose the output
|
|
79
|
+
* * {@link TableGenerator#transpose|transpose()} - transposes the output prior to rendering
|
|
76
80
|
* * style the table
|
|
77
|
-
* * {@link TableGenerator#styleTable|styleTable(string} - css style for the table
|
|
78
|
-
* * {@link TableGenerator#styleHeader|styleHeader(string} - css styles for the header row
|
|
81
|
+
* * {@link TableGenerator#styleTable|styleTable(string)} - css style for the table
|
|
82
|
+
* * {@link TableGenerator#styleHeader|styleHeader(string)} - css styles for the header row
|
|
79
83
|
* * {@link TableGenerator#styleRow|styleRow(fn)} - Function to style rows
|
|
80
|
-
* * {@link TableGenerator#styleCell|styleCell(fn} - Function to style cells
|
|
84
|
+
* * {@link TableGenerator#styleCell|styleCell(fn)} - Function to style cells
|
|
81
85
|
* * generate output
|
|
82
|
-
* * {@link TableGenerator#generateHTML|generateHTML(} - returns html table with the results
|
|
83
|
-
* * {@link TableGenerator#generateMarkdown|generateMarkdown(} - returns markdown with the results
|
|
84
|
-
* * {@link TableGenerator#generateCSV|generateCSV(} - generates a CSV with the results
|
|
85
|
-
* * {@link TableGenerator#generateArray|generateArray(} - generates an array for further process
|
|
86
|
+
* * {@link TableGenerator#generateHTML|generateHTML()} - returns html table with the results
|
|
87
|
+
* * {@link TableGenerator#generateMarkdown|generateMarkdown()} - returns markdown with the results
|
|
88
|
+
* * {@link TableGenerator#generateCSV|generateCSV()} - generates a CSV with the results
|
|
89
|
+
* * {@link TableGenerator#generateArray|generateArray()} - generates an array of headers and data for further process
|
|
90
|
+
* * {@link TableGenerator#generateArray2|generateArray2()} - generates a single array for further process
|
|
86
91
|
* * render in jupyter
|
|
87
|
-
* * {@link TableGenerator#render|render(} - renders the results in a table within jupyter
|
|
92
|
+
* * {@link TableGenerator#render|render()} - renders the results in a table within jupyter
|
|
88
93
|
*
|
|
89
94
|
*/
|
|
90
95
|
class TableGenerator {
|
|
@@ -191,6 +196,12 @@ class TableGenerator {
|
|
|
191
196
|
*/
|
|
192
197
|
#styleCell = null;
|
|
193
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Whether the data should be output transposed
|
|
201
|
+
* @type {Boolean}
|
|
202
|
+
*/
|
|
203
|
+
#isTransposed = false;
|
|
204
|
+
|
|
194
205
|
/**
|
|
195
206
|
* Function to format a value for a cell
|
|
196
207
|
*
|
|
@@ -237,6 +248,7 @@ class TableGenerator {
|
|
|
237
248
|
this.#styleHeader = '';
|
|
238
249
|
this.#styleRow = null;
|
|
239
250
|
this.#styleCell = null;
|
|
251
|
+
this.#isTransposed = false;
|
|
240
252
|
}
|
|
241
253
|
|
|
242
254
|
//-- GETTER SETTERS
|
|
@@ -781,6 +793,53 @@ class TableGenerator {
|
|
|
781
793
|
return this;
|
|
782
794
|
}
|
|
783
795
|
|
|
796
|
+
/**
|
|
797
|
+
* Transposes (flips along the diagonal) prior to output.
|
|
798
|
+
*
|
|
799
|
+
* This can be very handy for wide, but short, tables.
|
|
800
|
+
*
|
|
801
|
+
* For example, given the data:
|
|
802
|
+
*
|
|
803
|
+
* ```
|
|
804
|
+
* const data = [
|
|
805
|
+
* { name: 'John', color: 'green', age: 23, hair: 'blond', state: 'IL' },
|
|
806
|
+
* { name: 'Jane', color: 'brown', age: 23, hair: 'blonde', state: 'IL' }
|
|
807
|
+
* ];
|
|
808
|
+
* ```
|
|
809
|
+
*
|
|
810
|
+
* Running normally would give
|
|
811
|
+
*
|
|
812
|
+
* ```
|
|
813
|
+
* new utils.TableGenerator(data)
|
|
814
|
+
* .generateMarkdown();
|
|
815
|
+
* ```
|
|
816
|
+
*
|
|
817
|
+
* name|color|age|hair |state
|
|
818
|
+
* -- |-- |-- |-- |--
|
|
819
|
+
* John|green|23 |blond |IL
|
|
820
|
+
* Jane|brown|23 |blonde|IL
|
|
821
|
+
*
|
|
822
|
+
* Running that transposed flips it.
|
|
823
|
+
*
|
|
824
|
+
* ```
|
|
825
|
+
* new utils.TableGenerator(data)
|
|
826
|
+
* .transpose()
|
|
827
|
+
* .generateMarkdown();
|
|
828
|
+
* ```
|
|
829
|
+
*
|
|
830
|
+
* name |John |Jane
|
|
831
|
+
* -- |-- |--
|
|
832
|
+
* color|green|brown
|
|
833
|
+
* age |23 |23
|
|
834
|
+
* hair |blond|blonde
|
|
835
|
+
* state|IL |IL
|
|
836
|
+
* @returns {TableGenerator}
|
|
837
|
+
*/
|
|
838
|
+
transpose() {
|
|
839
|
+
this.#isTransposed = true;
|
|
840
|
+
return this;
|
|
841
|
+
}
|
|
842
|
+
|
|
784
843
|
//-- Table Generation
|
|
785
844
|
|
|
786
845
|
/**
|
|
@@ -833,7 +892,7 @@ class TableGenerator {
|
|
|
833
892
|
record: row
|
|
834
893
|
}));
|
|
835
894
|
|
|
836
|
-
|
|
895
|
+
let headers = keys.map(translateHeader);
|
|
837
896
|
let data = cleanCollection.map(translateData);
|
|
838
897
|
|
|
839
898
|
if (this.#limit < 0) {
|
|
@@ -842,6 +901,15 @@ class TableGenerator {
|
|
|
842
901
|
data = data.slice(0, this.#limit);
|
|
843
902
|
}
|
|
844
903
|
|
|
904
|
+
if (this.#isTransposed) {
|
|
905
|
+
let transposedResults = [headers, ...data];
|
|
906
|
+
transposedResults = ArrayUtils.transpose(transposedResults);
|
|
907
|
+
|
|
908
|
+
// eslint-disable-next-line prefer-destructuring
|
|
909
|
+
headers = transposedResults[0];
|
|
910
|
+
data = transposedResults.slice(1);
|
|
911
|
+
}
|
|
912
|
+
|
|
845
913
|
return ({ headers, data });
|
|
846
914
|
}
|
|
847
915
|
|
|
@@ -995,8 +1063,10 @@ class TableGenerator {
|
|
|
995
1063
|
*/
|
|
996
1064
|
|
|
997
1065
|
/**
|
|
998
|
-
* Generates an
|
|
1066
|
+
* Generates an a result set to allow for further processing
|
|
999
1067
|
*
|
|
1068
|
+
* @see {@link TableGenerator#generateArray2|generateArray2()}
|
|
1069
|
+
* @returns {TableArray}
|
|
1000
1070
|
* @example
|
|
1001
1071
|
*
|
|
1002
1072
|
* dataSet = [{reg:'z', source: 'A', temp: 99},
|
|
@@ -1019,14 +1089,44 @@ class TableGenerator {
|
|
|
1019
1089
|
* ['A', 100],
|
|
1020
1090
|
* ]
|
|
1021
1091
|
* }
|
|
1022
|
-
*
|
|
1023
|
-
* @returns {TableArray}
|
|
1024
1092
|
*/
|
|
1025
|
-
generateArray() {
|
|
1093
|
+
generateArray(returnUnifiedArray = false) {
|
|
1026
1094
|
const results = this.prepare();
|
|
1027
1095
|
return results;
|
|
1028
1096
|
}
|
|
1029
1097
|
|
|
1098
|
+
/**
|
|
1099
|
+
* Generates an array of objects in a 2d Array
|
|
1100
|
+
*
|
|
1101
|
+
* NOTE: this can be helpful for needing to transpose results
|
|
1102
|
+
*
|
|
1103
|
+
* @returns {any[][]} - 2d array with both headers and data included
|
|
1104
|
+
* @see {@link TableGenerator#generateArray|generateArray()}
|
|
1105
|
+
* @example
|
|
1106
|
+
*
|
|
1107
|
+
* dataSet = [{reg:'z', source: 'A', temp: 99},
|
|
1108
|
+
* {reg: 'z', source: 'B', temp: 98},
|
|
1109
|
+
* {reg: 'z', source:'A', temp: 100}
|
|
1110
|
+
* ];
|
|
1111
|
+
*
|
|
1112
|
+
* //-- only show the temp and source columns
|
|
1113
|
+
* new TableGenerator(dataSet)
|
|
1114
|
+
* .columnsToExclude('reg') // or .columnsToExclude(['reg'])
|
|
1115
|
+
* .generateArray2();
|
|
1116
|
+
*
|
|
1117
|
+
* //--
|
|
1118
|
+
* [
|
|
1119
|
+
* ['source', 'temp'],
|
|
1120
|
+
* ['A', 99],
|
|
1121
|
+
* ['B', 98],
|
|
1122
|
+
* ['A', 100],
|
|
1123
|
+
* ];
|
|
1124
|
+
*/
|
|
1125
|
+
generateArray2() {
|
|
1126
|
+
const results = this.prepare();
|
|
1127
|
+
return [...results.headers, ...results.data];
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1030
1130
|
/**
|
|
1031
1131
|
* Renders the html table in the cell results.
|
|
1032
1132
|
*
|
package/src/file.js
CHANGED
|
@@ -26,6 +26,8 @@ const logger = require('./logger');
|
|
|
26
26
|
* * listing directory
|
|
27
27
|
* * {@link module:file.pwd|pwd()} - list the current path
|
|
28
28
|
* * {@link module:file.listFiles|listFiles(path)} - list files in a diven path
|
|
29
|
+
* * checking files exist
|
|
30
|
+
* * {@link module:file.checkFile|checkFile(...paths)} - check if a file at a path exists
|
|
29
31
|
*
|
|
30
32
|
* ---
|
|
31
33
|
*
|
|
@@ -299,3 +301,87 @@ module.exports.listFiles = function listFiles(directoryPath) {
|
|
|
299
301
|
logger.error(`unable to read directory: ${resolvedPath}`);
|
|
300
302
|
}
|
|
301
303
|
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Synchronously checks if any of the files provided do not exist.
|
|
307
|
+
*
|
|
308
|
+
* For example:
|
|
309
|
+
*
|
|
310
|
+
* ```
|
|
311
|
+
* //-- these exist
|
|
312
|
+
* // ./data/credentials.env
|
|
313
|
+
* // ./data/results.json
|
|
314
|
+
*
|
|
315
|
+
* if (!utils.file.checkFile('./data/results.json')) {
|
|
316
|
+
* //-- retrieve the results
|
|
317
|
+
* utils.ijs.await(async($$, console) => {
|
|
318
|
+
* results = await connection.query('SELECT XYZ from Contacts');
|
|
319
|
+
* utils.file.write('./data/results.json', results);
|
|
320
|
+
* });
|
|
321
|
+
* } else {
|
|
322
|
+
* results = utils.file.readJSON('./data/results.json');
|
|
323
|
+
* }
|
|
324
|
+
* ```
|
|
325
|
+
*
|
|
326
|
+
* Note, you can also ask for multiple files at once
|
|
327
|
+
*
|
|
328
|
+
* ```
|
|
329
|
+
* utils.file.checkFile(
|
|
330
|
+
* './data/credentials.env',
|
|
331
|
+
* './data/results.json',
|
|
332
|
+
* './data/results.csv'
|
|
333
|
+
* );
|
|
334
|
+
* // false
|
|
335
|
+
* ```
|
|
336
|
+
*
|
|
337
|
+
* or as an array:
|
|
338
|
+
*
|
|
339
|
+
* ```
|
|
340
|
+
* utils.file.checkFile(['./data/credentails.env']);
|
|
341
|
+
* // true
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* @param {...String} files - List of file paths to check (can use relative paths, like './') <br />
|
|
345
|
+
* see {@link file:listFiles|listFiles()} or {@link file:pwd|pwd()} to help you)
|
|
346
|
+
* @returns {String[]} - null if all files are found, or array of string paths of files not found
|
|
347
|
+
*/
|
|
348
|
+
module.exports.checkFile = function checkFile(...files) {
|
|
349
|
+
//-- allow passing an array of files
|
|
350
|
+
const cleanFiles = files.length === 1 && Array.isArray(files[0])
|
|
351
|
+
? files[0]
|
|
352
|
+
: files;
|
|
353
|
+
|
|
354
|
+
const resolvedFiles = cleanFiles.map((unresolvedPath) => path.resolve(unresolvedPath));
|
|
355
|
+
|
|
356
|
+
const notFoundFiles = resolvedFiles.map((resolvedPath) => fs.existsSync(resolvedPath)
|
|
357
|
+
? null
|
|
358
|
+
: resolvedPath);
|
|
359
|
+
|
|
360
|
+
//-- do not filter empty files, as position in array is helpful
|
|
361
|
+
if (notFoundFiles.filter((p) => p).length === 0) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return notFoundFiles;
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/*
|
|
369
|
+
* Execute an async function if any of the files do not exist
|
|
370
|
+
* @param {String[]} filePaths - list of paths of files to check that they exist
|
|
371
|
+
* @param {*} fnIfFailed - async function tha will run - but only if any of the files are not found.
|
|
372
|
+
*/
|
|
373
|
+
/*
|
|
374
|
+
module.exports.ifNotExists = async function ifNotExists(filePaths, fnIfFailed) {
|
|
375
|
+
const filesNotFound = FileUtil.checkFile(filePaths);
|
|
376
|
+
|
|
377
|
+
let results;
|
|
378
|
+
|
|
379
|
+
if (filesNotFound) {
|
|
380
|
+
results = await fnIfFailed(filesNotFound);
|
|
381
|
+
} else {
|
|
382
|
+
results = null;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return results;
|
|
386
|
+
};
|
|
387
|
+
*/
|
package/src/format.js
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* * formatting Numbers
|
|
10
10
|
* * {@link module:format.zeroFill|format.zeroFill} - Pads a number to a specific length
|
|
11
11
|
* * {@link module:format.divideR|format.divideR} - Divides a number to provide { integer, remainder } - ex: 5/3 as ( 1, remainder 2 )
|
|
12
|
+
* * Formatting Strings
|
|
13
|
+
* * {@link module:format.capitalize|format.capitalize} - Capitalizes only the first character in the string (ex: 'John paul');
|
|
14
|
+
* * {@link module:format.capitalizeAll|format.capitalizeAll} - Capitalizes all the words in a string (ex: 'John Paul')
|
|
12
15
|
* * Formatting Time
|
|
13
16
|
* * {@link module:format.millisecondDuration|format.millisecondDuration}
|
|
14
17
|
* * Mapping Values
|
|
@@ -454,3 +457,40 @@ module.exports.clampDomain = function clampDomain(value, [minimum, maximum]) {
|
|
|
454
457
|
}
|
|
455
458
|
return value;
|
|
456
459
|
};
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Capitalizes the first character of the string.
|
|
463
|
+
*
|
|
464
|
+
* @param {String} str - String to capitalize the first letter only
|
|
465
|
+
* @returns {String} - ex: 'John paul'
|
|
466
|
+
* @see {@link module:format.capitalizeAll|capitalizeAll} - to capitalize all words in a string
|
|
467
|
+
* @example
|
|
468
|
+
* utils.format.capitalize('john'); // 'John'
|
|
469
|
+
* utils.format.capitalize('john doe'); // 'John doe'
|
|
470
|
+
*/
|
|
471
|
+
module.exports.capitalize = function capitalize(str) {
|
|
472
|
+
if (!str || str.length === 0) {
|
|
473
|
+
return '';
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
//-- charAt does not work for unicode
|
|
477
|
+
const [first, ...rest] = str;
|
|
478
|
+
return first.toLocaleUpperCase() + rest.join('');
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Capitalizes all words in a string.
|
|
483
|
+
*
|
|
484
|
+
* @param {String} str - String to capitalize
|
|
485
|
+
* @returns {String} - ex: 'John-Paul'
|
|
486
|
+
* @see {@link module:format.capitalizeAll|capitalizeAll} - to capitalize all words in a string
|
|
487
|
+
* @example
|
|
488
|
+
* utils.format.capitalize('john'); // 'John'
|
|
489
|
+
* utils.format.capitalize('john doe'); // 'John Doe'
|
|
490
|
+
* utils.format.capitalize('john-paul'); // 'John-Paul'
|
|
491
|
+
*/
|
|
492
|
+
module.exports.capitalizeAll = function capitalizeAll(str) {
|
|
493
|
+
return (str || '').split(/\b/)
|
|
494
|
+
.map(FormatUtils.capitalize)
|
|
495
|
+
.join('');
|
|
496
|
+
};
|
package/src/ijs.js
CHANGED
|
@@ -135,7 +135,7 @@ module.exports.await = async function ijsAsync(fn) {
|
|
|
135
135
|
context.$$.async();
|
|
136
136
|
|
|
137
137
|
try {
|
|
138
|
-
const results = fn(context.$$, context.console);
|
|
138
|
+
const results = await fn(context.$$, context.console);
|
|
139
139
|
context.$$.sendResult(results);
|
|
140
140
|
} catch (err) {
|
|
141
141
|
context.console.error('error occurred');
|
package/src/object.js
CHANGED
|
@@ -9,6 +9,9 @@ const schemaGenerator = require('generate-schema');
|
|
|
9
9
|
* * {@link module:object.keys|keys()} - Safely get the keys of an object or list of objects
|
|
10
10
|
* * {@link module:object.getObjectPropertyTypes|getObjectPropertyTypes()} - describe the properties of a list of objects
|
|
11
11
|
* * {@link module:object.generateSchema|generateSchema()} - generate a schema / describe properties of a list of objects
|
|
12
|
+
* * {@link module:object.findWithoutProperties|findWithoutProperties()} - find objects without ALL the properties specified
|
|
13
|
+
* * {@link module:object.findWithoutProperties|findWithProperties()} - find objects with any of the properties specified
|
|
14
|
+
* * {@link module:object.setPropertyDefaults|setPropertyDefaults()} - sets values for objects that don't currently have the property
|
|
12
15
|
* * Manipulating objects
|
|
13
16
|
* * {@link module:object.objAssign|objAssign()} -
|
|
14
17
|
* * {@link module:object.objAssignEntities|objAssignEntities()} -
|
|
@@ -634,3 +637,154 @@ module.exports.joinProperties = function join(objectArray, indexField, targetMap
|
|
|
634
637
|
|
|
635
638
|
return ObjectUtils.join(objectArray, indexField, targetMap, joinFn);
|
|
636
639
|
};
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Finds objects that do not have ALL the properties specified.
|
|
643
|
+
*
|
|
644
|
+
* This can be very helpful in ensuring all objects actually meet a specification and are not missing values.
|
|
645
|
+
*
|
|
646
|
+
* ```
|
|
647
|
+
* const students = [
|
|
648
|
+
* { first: 'john', last: 'doe', age: 23 }, { first: 'jane', last: 'doe', age: 23 }, { first: 'jack', last: 'white', failure: 401 }
|
|
649
|
+
* ];
|
|
650
|
+
*
|
|
651
|
+
* utils.findWithoutProperties(students, 'first', 'last', 'age');
|
|
652
|
+
* // [{ first: 'jack', last: 'white', failure: 401 }]
|
|
653
|
+
*
|
|
654
|
+
* utils.findWithoutProperties(students, 'failure');
|
|
655
|
+
* // [{ first: 'john', last: 'doe', age: 23 }, { first: 'jane', last: 'doe', age: 23 }]
|
|
656
|
+
* ```
|
|
657
|
+
*
|
|
658
|
+
* Please note, that we can check a single object:
|
|
659
|
+
*
|
|
660
|
+
* ```
|
|
661
|
+
* utils.findWithoutProperties(students[0], 'failure');
|
|
662
|
+
* // []
|
|
663
|
+
* ```
|
|
664
|
+
*
|
|
665
|
+
* @param {Object[]} objectsToCheck - the array of objects to check for the properties.
|
|
666
|
+
* @param {...String} propertiesToFind - the list of properties to find within the collection.
|
|
667
|
+
* @returns {Object[]} - Array of objects that are missing at least one of those properties
|
|
668
|
+
* @see {@link module:file.findWithProperties|findWithProperties} - if you want objects that do not have all properties
|
|
669
|
+
**/
|
|
670
|
+
module.exports.findWithoutProperties = function findWithoutProperties(targetObj, ...propertiesToFind) {
|
|
671
|
+
const cleanProperties = propertiesToFind.length > 0 && Array.isArray(propertiesToFind[0])
|
|
672
|
+
? propertiesToFind[0]
|
|
673
|
+
: propertiesToFind;
|
|
674
|
+
|
|
675
|
+
const cleanTargets = Array.isArray(targetObj)
|
|
676
|
+
? targetObj
|
|
677
|
+
: [targetObj];
|
|
678
|
+
|
|
679
|
+
const results = [];
|
|
680
|
+
|
|
681
|
+
cleanTargets.forEach((target) => {
|
|
682
|
+
if (cleanProperties.find((prop) => (typeof target[prop]) === 'undefined')) {
|
|
683
|
+
results.push(target);
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
return results;
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Finds objects that have any of the properties specified.
|
|
692
|
+
*
|
|
693
|
+
* This can be very helpful when working with datasets that include mixed data (such as JSON)
|
|
694
|
+
*
|
|
695
|
+
* ```
|
|
696
|
+
* const students = [
|
|
697
|
+
* { first: 'john', last: 'doe' }, { first: 'jane', last: 'doe' }, { first: 'jack', last: 'white', failure: 401 }
|
|
698
|
+
* ];
|
|
699
|
+
*
|
|
700
|
+
* utils.findWithProperties(students, 'failure');
|
|
701
|
+
* // { first: 'jack', last: 'white', failure: 401 }
|
|
702
|
+
* ```
|
|
703
|
+
*
|
|
704
|
+
* Please note, that we can check a single object:
|
|
705
|
+
*
|
|
706
|
+
* ```
|
|
707
|
+
* utils.findWithProperties({ first: 'john', last: 'doe' }, 'failure');
|
|
708
|
+
* // []
|
|
709
|
+
* ```
|
|
710
|
+
*
|
|
711
|
+
* @param {Object[]} objectsToCheck - the array of objects to check for the properties.
|
|
712
|
+
* @param {...String} propertiesToFind - the list of properties to find within the collection.
|
|
713
|
+
* @returns {Object[]} - Array of objects that have at least one of those properties
|
|
714
|
+
* @see {@link module:file.findWithoutProperties|findWithoutProperties} - if you want objects that do not have all properties
|
|
715
|
+
**/
|
|
716
|
+
module.exports.findWithProperties = function findWithProperties(targetObj, ...propertiesToFind) {
|
|
717
|
+
const cleanProperties = propertiesToFind.length > 0 && Array.isArray(propertiesToFind[0])
|
|
718
|
+
? propertiesToFind[0]
|
|
719
|
+
: propertiesToFind;
|
|
720
|
+
|
|
721
|
+
const cleanTargets = Array.isArray(targetObj)
|
|
722
|
+
? targetObj
|
|
723
|
+
: [targetObj];
|
|
724
|
+
|
|
725
|
+
const results = [];
|
|
726
|
+
|
|
727
|
+
cleanTargets.forEach((target) => {
|
|
728
|
+
if (cleanProperties.find((prop) => (typeof target[prop]) !== 'undefined')) {
|
|
729
|
+
results.push(target);
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
return results;
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Sets values for objects that don't currently have the property
|
|
738
|
+
*
|
|
739
|
+
* This is very helpful for ensuring that all objects have a property,
|
|
740
|
+
* or setting a value to make it easier to identify that it is 'N/A'
|
|
741
|
+
*
|
|
742
|
+
* Note, that only the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty|ownProperties}
|
|
743
|
+
* on the default object are checked.
|
|
744
|
+
*
|
|
745
|
+
* And values are applied to the target object, only if the property is not on the object (property is undefined)
|
|
746
|
+
*
|
|
747
|
+
* @param {Object[] | Object} targetObject - Object to apply the properties to <br />
|
|
748
|
+
* but ONLY if the object does not have that property (ex: undefined)
|
|
749
|
+
* @param {Object} defaultObj - Object with the properties and defaults applied
|
|
750
|
+
* @param {any} defaultObj.property - the property to check, with the default value assigned
|
|
751
|
+
* @see {@link module:file.findWithoutProperties|findWithoutProperties} - to determine if any objects do not have a set of properties
|
|
752
|
+
* @see {@link module:file.keys|keys} - to get a list of unique properties of all objects in a list.
|
|
753
|
+
* @example
|
|
754
|
+
* const students = [
|
|
755
|
+
* { first: 'john', last: 'doe', birthday: '2002-04-01' },
|
|
756
|
+
* { first: 'jane', last: 'doe', birthday: '2003-05-01' },
|
|
757
|
+
* { first: 'jack', last: 'white', failure: 401 }
|
|
758
|
+
* ];
|
|
759
|
+
*
|
|
760
|
+
* utils.object.setPropertyDefaults(students, {
|
|
761
|
+
* first: '',
|
|
762
|
+
* last: '',
|
|
763
|
+
* birthday: ''
|
|
764
|
+
* });
|
|
765
|
+
*
|
|
766
|
+
* // [
|
|
767
|
+
* // { first: 'john', last: 'doe', birthday: '2002-04-01' },
|
|
768
|
+
* // { first: 'jane', last: 'doe', birthday: '2003-05-01' },
|
|
769
|
+
* // { first: 'jack', last: 'white', birthday: '', failure: 401 }
|
|
770
|
+
* // ];
|
|
771
|
+
*/
|
|
772
|
+
module.exports.setPropertyDefaults = function setPropertyDefaults(targetObject, defaultObj) {
|
|
773
|
+
const cleanTargets = Array.isArray(targetObject)
|
|
774
|
+
? targetObject
|
|
775
|
+
: [targetObject];
|
|
776
|
+
|
|
777
|
+
if (!defaultObj || typeof defaultObj !== 'object') {
|
|
778
|
+
throw Error('object.setPropertyDefaults(targetObject, defaultObject): defaultObject is expected to be an object with properties set to the defaults to apply');
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const defaultKeys = Object.getOwnPropertyNames(defaultObj);
|
|
782
|
+
|
|
783
|
+
cleanTargets.forEach((target) => {
|
|
784
|
+
defaultKeys.forEach((prop) => {
|
|
785
|
+
if (typeof target[prop] === 'undefined') {
|
|
786
|
+
target[prop] = defaultObj[prop];
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
};
|