datagrok-tools 4.7.11 → 4.8.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.
package/README.md CHANGED
@@ -61,7 +61,7 @@ Read more about package development in [Datagrok's documentation](https://datagr
61
61
  - `--ide` adds an IDE-specific configuration for debugging (vscode)
62
62
  - `--js` creates a JavaScript package template
63
63
  - `--ts` creates a TypeScript package template (default)
64
- - `--jest` adds a basic configuration for `jest`
64
+ - `--test` adds tests support to package
65
65
  - `add` puts an object template to your package:
66
66
 
67
67
  ```shell
@@ -100,6 +100,8 @@ Read more about package development in [Datagrok's documentation](https://datagr
100
100
  Running `grok publish` is the same as running `grok publish defaultHost --build --debug`.
101
101
  - `check` checks package content (function signatures, import statements of external modules,
102
102
  etc.). The check is also run during package publication.
103
+ - `init` modifies a package template by adding config files for linters, IDE, and so on
104
+ (applies the same options as `create`).
103
105
  - `test` runs package tests. First, it builds a package and publishes it (these
104
106
  steps can be skipped with flags `--skip-build` and `--skip-publish`
105
107
  correspondingly).
@@ -13,6 +13,8 @@ exports.checkImportStatements = checkImportStatements;
13
13
  exports.checkPackageFile = checkPackageFile;
14
14
  exports.extractExternals = extractExternals;
15
15
 
16
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
17
+
16
18
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
17
19
 
18
20
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
@@ -39,19 +41,38 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
39
41
 
40
42
  function check(args) {
41
43
  var nOptions = Object.keys(args).length - 1;
42
- if (args['_'].length !== 1 || nOptions > 0 && (!args.dir || typeof args.dir !== 'string') || nOptions > 1) return false;
44
+ if (args['_'].length !== 1 || nOptions > 2 || nOptions > 0 && !args.r && !args.recursive) return false;
43
45
  var curDir = process.cwd();
44
46
 
45
- if (args.dir && typeof args.dir === 'string') {
46
- var packagesDir = _path["default"].isAbsolute(args.dir) ? args.dir : _path["default"].join(curDir, args.dir);
47
+ if (args.recursive) {
48
+ var runChecksRec = function runChecksRec(dir) {
49
+ var files = _fs["default"].readdirSync(dir);
50
+
51
+ var _iterator = _createForOfIteratorHelper(files),
52
+ _step;
47
53
 
48
- _fs["default"].readdirSync(packagesDir).forEach(function (file) {
49
- var filepath = _path["default"].join(packagesDir, file);
54
+ try {
55
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
56
+ var file = _step.value;
50
57
 
51
- var stats = _fs["default"].statSync(filepath);
58
+ var filepath = _path["default"].join(dir, file);
52
59
 
53
- if (stats.isDirectory() && utils.isPackageDir(filepath)) runChecks(filepath);
54
- });
60
+ var stats = _fs["default"].statSync(filepath);
61
+
62
+ if (stats.isDirectory()) {
63
+ if (utils.isPackageDir(filepath)) runChecks(filepath);else {
64
+ if (file !== 'node_modules' && !file.startsWith('.')) runChecksRec(_path["default"].join(dir, file));
65
+ }
66
+ }
67
+ }
68
+ } catch (err) {
69
+ _iterator.e(err);
70
+ } finally {
71
+ _iterator.f();
72
+ }
73
+ };
74
+
75
+ runChecksRec(curDir);
55
76
  } else {
56
77
  if (!utils.isPackageDir(curDir)) {
57
78
  color.error('File `package.json` not found. Run the command from the package directory');
@@ -80,17 +101,22 @@ function check(args) {
80
101
 
81
102
  var isWebpack = _fs["default"].existsSync(webpackConfigPath);
82
103
 
104
+ var externals = null;
105
+
83
106
  if (isWebpack) {
84
107
  var content = _fs["default"].readFileSync(webpackConfigPath, {
85
108
  encoding: 'utf-8'
86
109
  });
87
110
 
88
- var externals = extractExternals(content);
111
+ externals = extractExternals(content);
89
112
  if (externals) warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkImportStatements(packagePath, jsTsFiles, externals)));
90
113
  }
91
114
 
92
115
  warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkFuncSignatures(packagePath, funcFiles)));
93
- warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkPackageFile(packagePath)));
116
+ warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkPackageFile(packagePath, {
117
+ isWebpack: isWebpack,
118
+ externals: externals
119
+ })));
94
120
 
95
121
  if (warnings.length) {
96
122
  console.log("Checking package ".concat(_path["default"].basename(packagePath), "..."));
@@ -102,12 +128,12 @@ function check(args) {
102
128
  }
103
129
 
104
130
  function extractExternals(config) {
105
- var externalsRegex = /(?<=externals\s*:\s*)(\{[\S\s]*?\})/;
131
+ var externalsRegex = /(?<=externals)\s*:\s*(\{[\S\s]*?\})/;
106
132
  var match = config.match(externalsRegex);
107
133
 
108
134
  if (match) {
109
- // Replace single quotes and a trailing comma to make a string JSON-like
110
- var externalStr = match[1].replace(/'/g, '"').replace(/(?<=[\S\s]),(?=\s*\})/, '');
135
+ // Replace single quotes, comments, and a trailing comma to make a string JSON-like
136
+ var externalStr = match[1].replace(/'/g, '"').replace(/\/\/.*(\r\n|\r|\n)/, '').replace(/(?<=[\S\s]),(?=\s*\})/, '');
111
137
 
112
138
  try {
113
139
  var externals = JSON.parse(externalStr);
@@ -123,9 +149,9 @@ function extractExternals(config) {
123
149
  function checkImportStatements(packagePath, files, externals) {
124
150
  var modules = [];
125
151
 
126
- for (var key in externals) {
127
- modules.push(key);
128
- if (key.includes('/')) modules.push(key.split('/', 1)[0]);
152
+ for (var _key in externals) {
153
+ modules.push(_key);
154
+ if (_key.includes('/')) modules.push(_key.split('/', 1)[0]);
129
155
  }
130
156
 
131
157
  var importRegex = new RegExp("^(?!\\/{2})\\s*import\\s+.*(".concat(modules.join('|'), ").*(?=\\s+?)"), 'g');
@@ -141,12 +167,12 @@ function checkImportStatements(packagePath, files, externals) {
141
167
  };
142
168
  }
143
169
 
144
- var _iterator = _createForOfIteratorHelper(files),
145
- _step;
170
+ var _iterator2 = _createForOfIteratorHelper(files),
171
+ _step2;
146
172
 
147
173
  try {
148
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
149
- var file = _step.value;
174
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
175
+ var file = _step2.value;
150
176
 
151
177
  var content = _fs["default"].readFileSync(_path["default"].join(packagePath, file), {
152
178
  encoding: 'utf-8'
@@ -155,26 +181,26 @@ function checkImportStatements(packagePath, files, externals) {
155
181
  var matchedImports = content.match(importRegex);
156
182
 
157
183
  if (matchedImports) {
158
- var _iterator2 = _createForOfIteratorHelper(matchedImports),
159
- _step2;
184
+ var _iterator3 = _createForOfIteratorHelper(matchedImports),
185
+ _step3;
160
186
 
161
187
  try {
162
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
163
- var match = _step2.value;
188
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
189
+ var match = _step3.value;
164
190
  var vr = validateImport(file, match);
165
191
  if (!vr.value) warnings.push(vr.message);
166
192
  }
167
193
  } catch (err) {
168
- _iterator2.e(err);
194
+ _iterator3.e(err);
169
195
  } finally {
170
- _iterator2.f();
196
+ _iterator3.f();
171
197
  }
172
198
  }
173
199
  }
174
200
  } catch (err) {
175
- _iterator.e(err);
201
+ _iterator2.e(err);
176
202
  } finally {
177
- _iterator.f();
203
+ _iterator2.f();
178
204
  }
179
205
 
180
206
  return warnings;
@@ -183,9 +209,33 @@ function checkImportStatements(packagePath, files, externals) {
183
209
  function checkFuncSignatures(packagePath, files) {
184
210
  var warnings = [];
185
211
  var checkFunctions = {
186
- semTypeDetector: function semTypeDetector(_ref) {
187
- var inputs = _ref.inputs,
188
- outputs = _ref.outputs;
212
+ app: function app(_ref) {
213
+ var name = _ref.name;
214
+ var value = true;
215
+ var message = '';
216
+
217
+ if (name && typeof name === 'string') {
218
+ var lowerCaseName = name.toLocaleLowerCase();
219
+
220
+ if (lowerCaseName.startsWith('app')) {
221
+ value = false;
222
+ message += 'Prefix "App" is not needed. Consider removing it.\n';
223
+ }
224
+
225
+ if (lowerCaseName.endsWith('app')) {
226
+ value = false;
227
+ message += 'Postfix "App" is not needed. Consider removing it.\n';
228
+ }
229
+ }
230
+
231
+ return {
232
+ value: value,
233
+ message: message
234
+ };
235
+ },
236
+ semTypeDetector: function semTypeDetector(_ref2) {
237
+ var inputs = _ref2.inputs,
238
+ outputs = _ref2.outputs;
189
239
  var value = true;
190
240
  var message = '';
191
241
 
@@ -204,9 +254,9 @@ function checkFuncSignatures(packagePath, files) {
204
254
  message: message
205
255
  };
206
256
  },
207
- cellRenderer: function cellRenderer(_ref2) {
208
- var inputs = _ref2.inputs,
209
- outputs = _ref2.outputs;
257
+ cellRenderer: function cellRenderer(_ref3) {
258
+ var inputs = _ref3.inputs,
259
+ outputs = _ref3.outputs;
210
260
  var value = true;
211
261
  var message = '';
212
262
 
@@ -225,9 +275,9 @@ function checkFuncSignatures(packagePath, files) {
225
275
  message: message
226
276
  };
227
277
  },
228
- viewer: function viewer(_ref3) {
229
- var inputs = _ref3.inputs,
230
- outputs = _ref3.outputs;
278
+ viewer: function viewer(_ref4) {
279
+ var inputs = _ref4.inputs,
280
+ outputs = _ref4.outputs;
231
281
  var value = true;
232
282
  var message = '';
233
283
 
@@ -246,10 +296,10 @@ function checkFuncSignatures(packagePath, files) {
246
296
  message: message
247
297
  };
248
298
  },
249
- fileViewer: function fileViewer(_ref4) {
250
- var inputs = _ref4.inputs,
251
- outputs = _ref4.outputs,
252
- tags = _ref4.tags;
299
+ fileViewer: function fileViewer(_ref5) {
300
+ var inputs = _ref5.inputs,
301
+ outputs = _ref5.outputs,
302
+ tags = _ref5.tags;
253
303
  var value = true;
254
304
  var message = '';
255
305
 
@@ -275,8 +325,8 @@ function checkFuncSignatures(packagePath, files) {
275
325
  message: message
276
326
  };
277
327
  },
278
- fileExporter: function fileExporter(_ref5) {
279
- var description = _ref5.description;
328
+ fileExporter: function fileExporter(_ref6) {
329
+ var description = _ref6.description;
280
330
  var value = true;
281
331
  var message = '';
282
332
 
@@ -290,8 +340,8 @@ function checkFuncSignatures(packagePath, files) {
290
340
  message: message
291
341
  };
292
342
  },
293
- packageSettingsEditor: function packageSettingsEditor(_ref6) {
294
- var outputs = _ref6.outputs;
343
+ packageSettingsEditor: function packageSettingsEditor(_ref7) {
344
+ var outputs = _ref7.outputs;
295
345
  var value = true;
296
346
  var message = '';
297
347
 
@@ -308,12 +358,12 @@ function checkFuncSignatures(packagePath, files) {
308
358
  };
309
359
  var functionRoles = Object.keys(checkFunctions);
310
360
 
311
- var _iterator3 = _createForOfIteratorHelper(files),
312
- _step3;
361
+ var _iterator4 = _createForOfIteratorHelper(files),
362
+ _step4;
313
363
 
314
364
  try {
315
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
316
- var file = _step3.value;
365
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
366
+ var file = _step4.value;
317
367
 
318
368
  var content = _fs["default"].readFileSync(_path["default"].join(packagePath, file), {
319
369
  encoding: 'utf-8'
@@ -321,12 +371,12 @@ function checkFuncSignatures(packagePath, files) {
321
371
 
322
372
  var functions = getFuncMetadata(content);
323
373
 
324
- var _iterator4 = _createForOfIteratorHelper(functions),
325
- _step4;
374
+ var _iterator5 = _createForOfIteratorHelper(functions),
375
+ _step5;
326
376
 
327
377
  try {
328
378
  var _loop = function _loop() {
329
- var f = _step4.value;
379
+ var f = _step5.value;
330
380
  var roles = functionRoles.filter(function (role) {
331
381
  var _f$tags;
332
382
 
@@ -341,25 +391,43 @@ function checkFuncSignatures(packagePath, files) {
341
391
  }
342
392
  };
343
393
 
344
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
394
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
345
395
  _loop();
346
396
  }
347
397
  } catch (err) {
348
- _iterator4.e(err);
398
+ _iterator5.e(err);
349
399
  } finally {
350
- _iterator4.f();
400
+ _iterator5.f();
351
401
  }
352
402
  }
353
403
  } catch (err) {
354
- _iterator3.e(err);
404
+ _iterator4.e(err);
355
405
  } finally {
356
- _iterator3.f();
406
+ _iterator4.f();
357
407
  }
358
408
 
359
409
  return warnings;
360
410
  }
361
411
 
362
- function checkPackageFile(packagePath) {
412
+ var sharedLibExternals = {
413
+ 'common/html2canvas.min.js': {
414
+ 'exceljs': 'ExcelJS'
415
+ },
416
+ 'common/exceljs.min.js': {
417
+ 'html2canvas': 'html2canvas'
418
+ },
419
+ 'common/ngl_viewer/ngl.js': {
420
+ 'NGL': 'NGL'
421
+ },
422
+ 'common/openchemlib-full.js': {
423
+ 'openchemlib/full': 'OCL'
424
+ },
425
+ 'common/codemirror/codemirror.js': {
426
+ 'codemirror': 'CodeMirror'
427
+ }
428
+ };
429
+
430
+ function checkPackageFile(packagePath, options) {
363
431
  var warnings = [];
364
432
 
365
433
  var packageFilePath = _path["default"].join(packagePath, 'package.json');
@@ -371,18 +439,18 @@ function checkPackageFile(packagePath) {
371
439
  if (!json.description) warnings.push('File "package.json": "description" field is empty. Provide a package description.');
372
440
 
373
441
  if (Array.isArray(json.properties) && json.properties.length > 0) {
374
- var _iterator5 = _createForOfIteratorHelper(json.properties),
375
- _step5;
442
+ var _iterator6 = _createForOfIteratorHelper(json.properties),
443
+ _step6;
376
444
 
377
445
  try {
378
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
379
- var propInfo = _step5.value;
446
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
447
+ var propInfo = _step6.value;
380
448
  if ((0, _typeof2["default"])(propInfo) !== 'object') warnings.push('File "package.json": Invalid property annotation in the "properties" field.');else if (!propInfo.name) warnings.push('File "package.json": Add a property name for each property in the "properties" field.');else if (!utils.propertyTypes.includes(propInfo.propertyType)) warnings.push("File \"package.json\": Invalid property type for property ".concat(propInfo.name, "."));
381
449
  }
382
450
  } catch (err) {
383
- _iterator5.e(err);
451
+ _iterator6.e(err);
384
452
  } finally {
385
- _iterator5.f();
453
+ _iterator6.f();
386
454
  }
387
455
  }
388
456
 
@@ -390,21 +458,44 @@ function checkPackageFile(packagePath) {
390
458
  if (json.author == null && isPublicPackage) warnings.push('File "package.json": add the "author" field.');
391
459
 
392
460
  if (Array.isArray(json.sources) && json.sources.length > 0) {
393
- var _iterator6 = _createForOfIteratorHelper(json.sources),
394
- _step6;
461
+ var _iterator7 = _createForOfIteratorHelper(json.sources),
462
+ _step7;
395
463
 
396
464
  try {
397
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
398
- var source = _step6.value;
465
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
466
+ var source = _step7.value;
399
467
  if (typeof source !== 'string') warnings.push("File \"package.json\": Only file paths and URLs are allowed in sources. Modify the source ".concat(source));
400
- if (source.startsWith('common/') || utils.absUrlRegex.test(source)) continue;
468
+ if (utils.absUrlRegex.test(source)) continue;
469
+
470
+ if (source.startsWith('common/')) {
471
+ if (options !== null && options !== void 0 && options.isWebpack && source.endsWith('.js')) {
472
+ if (options !== null && options !== void 0 && options.externals) {
473
+ if (source in sharedLibExternals) {
474
+ var _Object$entries$ = (0, _slicedToArray2["default"])(Object.entries(sharedLibExternals[source])[0], 2),
475
+ _lib = _Object$entries$[0],
476
+ name = _Object$entries$[1];
477
+
478
+ if (!(_lib in options.externals && options.externals[_lib] === name)) {
479
+ warnings.push("Webpack config parsing: Consider adding source \"".concat(source, "\" to webpack externals:\n") + "'".concat(_lib, "': '").concat(name, "'\n"));
480
+ }
481
+ } else {
482
+ warnings.push("File \"package.json\": source \"".concat(source, "\" not in the list of shared libraries"));
483
+ }
484
+ } else {
485
+ warnings.push('Webpack config parsing: External modules not found.\n' + "Consider adding source \"".concat(source, "\" to webpack externals") + (source in sharedLibExternals ? ':\n' + "'".concat(Object.keys(sharedLibExternals[source])[0], "': '").concat(Object.values(sharedLibExternals[source])[0], "'\n") : ''));
486
+ }
487
+ }
488
+
489
+ continue;
490
+ }
491
+
401
492
  if (source.startsWith('src/') && _fs["default"].existsSync(_path["default"].join(packagePath, 'webpack.config.js'))) warnings.push('File "package.json": Sources cannot include files from the \`src/\` directory. ' + "Move file ".concat(source, " to another folder."));
402
493
  if (!_fs["default"].existsSync(_path["default"].join(packagePath, source))) warnings.push("Source ".concat(source, " not found in the package."));
403
494
  }
404
495
  } catch (err) {
405
- _iterator6.e(err);
496
+ _iterator7.e(err);
406
497
  } finally {
407
- _iterator6.f();
498
+ _iterator7.f();
408
499
  }
409
500
  }
410
501
 
@@ -426,12 +517,12 @@ function getFuncMetadata(script) {
426
517
  outputs: []
427
518
  };
428
519
 
429
- var _iterator7 = _createForOfIteratorHelper(script.split('\n')),
430
- _step7;
520
+ var _iterator8 = _createForOfIteratorHelper(script.split('\n')),
521
+ _step8;
431
522
 
432
523
  try {
433
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
434
- var line = _step7.value;
524
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
525
+ var line = _step8.value;
435
526
  if (!line) continue;
436
527
  var match = line.match(utils.paramRegex);
437
528
 
@@ -463,9 +554,9 @@ function getFuncMetadata(script) {
463
554
  }
464
555
  }
465
556
  } catch (err) {
466
- _iterator7.e(err);
557
+ _iterator8.e(err);
467
558
  } finally {
468
- _iterator7.f();
559
+ _iterator8.f();
469
560
  }
470
561
 
471
562
  return funcData;
@@ -57,7 +57,7 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
57
57
  var ide = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
58
58
  var ts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
59
59
  var eslint = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
60
- var jest = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
60
+ var test = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
61
61
 
62
62
  var filesToCreate = _fs["default"].readdirSync(templateDir);
63
63
 
@@ -114,7 +114,7 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
114
114
  });
115
115
  }
116
116
 
117
- if (jest) {
117
+ if (test) {
118
118
  Object.assign(_package.dependencies, {
119
119
  '@datagrok-libraries/utils': 'latest'
120
120
  });
@@ -168,13 +168,13 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
168
168
  _fs["default"].mkdirSync(copyFilePath); // recursive call
169
169
 
170
170
 
171
- createDirectoryContents(name, config, origFilePath, copyFilePath, ide, ts, eslint, jest);
171
+ createDirectoryContents(name, config, origFilePath, copyFilePath, ide, ts, eslint, test);
172
172
  }
173
173
  });
174
174
  }
175
175
 
176
176
  function create(args) {
177
- var options = ['ide', 'js', 'ts', 'eslint', 'jest'];
177
+ var options = ['ide', 'js', 'ts', 'eslint', 'test'];
178
178
  var nOptions = Object.keys(args).length - 1;
179
179
  var nArgs = args['_'].length;
180
180
  if (nArgs > 2 || nOptions > 4) return false;
@@ -253,7 +253,7 @@ function create(args) {
253
253
 
254
254
  process.exit();
255
255
  });
256
- createDirectoryContents(name, config, templateDir, packageDir, args.ide, ts, !!args.eslint, !!args.jest);
256
+ createDirectoryContents(name, config, templateDir, packageDir, args.ide, ts, !!args.eslint, !!args.test);
257
257
  color.success('Successfully created package ' + name);
258
258
  console.log(_entHelpers.help["package"](ts));
259
259
  console.log("\nThe package has the following dependencies:\n".concat(dependencies.join(' '), "\n"));
@@ -4,13 +4,14 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.help = void 0;
7
- var HELP = "\nUsage: grok <command>\n\nDatagrok's package management tool\n\nCommands:\n add Add an object template\n api Create wrapper functions\n check Check package content (function signatures, etc.)\n config Create and manage config files\n create Create a package\n link Link `datagrok-api` and libraries for local development\n unlink Revert `grok link`\n publish Upload a package\n test Run package tests\n\nTo get help on a particular command, use:\n grok <command> --help\n\nRead more about the package development workflow:\nhttps://datagrok.ai/help/develop/develop\n";
7
+ var HELP = "\nUsage: grok <command>\n\nDatagrok's package management tool\n\nCommands:\n add Add an object template\n api Create wrapper functions\n check Check package content (function signatures, etc.)\n config Create and manage config files\n create Create a package\n init Modify a package template\n link Link `datagrok-api` and libraries for local development\n unlink Revert `grok link`\n publish Upload a package\n test Run package tests\n\nTo get help on a particular command, use:\n grok <command> --help\n\nRead more about the package development workflow:\nhttps://datagrok.ai/help/develop/develop\n";
8
8
  var HELP_ADD = "\nUsage: grok add <entity> <name>\n\nAdd an object template to your package:\n\ngrok add app <name>\ngrok add connection <name>\ngrok add detector <semantic-type-name>\ngrok add function [tag] <name>\ngrok add query <name>\ngrok add script [tag] <language> <name>\ngrok add view <name>\ngrok add viewer <name>\ngrok add tests\n\nPlease note that entity names may only include letters and numbers\n\nSupported languages for scripts:\njavascript, julia, node, octave, python, r\n\nAvailable tags:\npanel, init\n";
9
+ var HELP_INIT = "\nUsage: grok init\n\nModify a package template by adding config files for linters, IDE, etc.\n\nOptions:\n[--eslint] [--ide] [--test] [--ts]\n\n--eslint Add a configuration for eslint\n--ide Add an IDE-specific configuration for debugging (vscode)\n--test Add tests support (TypeScript packages only)\n--ts Convert a JavaScript package to TypeScript\n";
9
10
  var HELP_API = "\nUsage: grok api\n\nCreate wrapper functions for package scripts and queries\n";
10
- var HELP_CONFIG = "\nUsage: grok config\n\nCreate or update a configuration file\n\nOptions:\n[--reset] [--server] [--alias] [--key]\n\n--reset Restore the default config file template\n--server Use to add a server to the config (`grok config add --alias alias --server url --key key`)\n--alias Use in conjunction with the `server` option to set the server name\n--key Use in conjunction with the `server` option to set the developer key\n--default Use in conjunction with the `server` option to set the added server as default\n";
11
- var HELP_CREATE = "\nUsage: grok create [name]\n\nCreate a package:\n\ngrok create Create a package in the current working directory\ngrok create <name> Create a package in a folder with the specified name\n\nPlease note that the package name may only include letters, numbers, underscores, or hyphens\n\nOptions:\n[--eslint] [--ide] [--js|--ts]\n\n--eslint Add a configuration for eslint\n--ide Add an IDE-specific configuration for debugging (vscode)\n--js Create a JavaScript package\n--ts Create a TypeScript package (default)\n";
12
- var HELP_PUBLISH = "\nUsage: grok publish [host]\n\nUpload a package\n\nOptions:\n[--build|--rebuild] [--debug|--release] [--key] [--suffix]\n\nRunning `grok publish` is the same as running `grok publish defaultHost --build --debug`\n";
13
- var HELP_CHECK = "\nUsage: grok check\n\nOptions:\n[--dir]\n\n--dir Check all packages in a specified directory\n\nCheck package content (function signatures, import statements of external modules, etc.)\n";
11
+ var HELP_CONFIG = "\nUsage: grok config\n\nCreate or update a configuration file\n\nOptions:\n[--reset] [--server] [--alias] [-k | --key]\n\n--reset Restore the default config file template\n--server Use to add a server to the config (`grok config add --alias alias --server url --key key`)\n--alias Use in conjunction with the `server` option to set the server name\n--key Use in conjunction with the `server` option to set the developer key\n--default Use in conjunction with the `server` option to set the added server as default\n";
12
+ var HELP_CREATE = "\nUsage: grok create [name]\n\nCreate a package:\n\ngrok create Create a package in the current working directory\ngrok create <name> Create a package in a folder with the specified name\n\nPlease note that the package name may only include letters, numbers, underscores, or hyphens\n\nOptions:\n[--eslint] [--ide] [--js | --ts] [--test]\n\n--eslint Add a configuration for eslint\n--ide Add an IDE-specific configuration for debugging (vscode)\n--js Create a JavaScript package\n--ts Create a TypeScript package (default)\n--test Add tests support (TypeScript packages only)\n";
13
+ var HELP_PUBLISH = "\nUsage: grok publish [host]\n\nUpload a package\n\nOptions:\n[--build|--rebuild] [--debug|--release] [-k | --key] [--suffix]\n\nRunning `grok publish` is the same as running `grok publish defaultHost --build --debug`\n";
14
+ var HELP_CHECK = "\nUsage: grok check\n\nOptions:\n[-r | --recursive]\n\n--recursive Check all packages in the current directory\n\nCheck package content (function signatures, import statements of external modules, etc.)\n";
14
15
  var HELP_TEST = "\nUsage: grok test\n\nOptions:\n[--host] [--csv]\n\n--host Host alias as in the config file\n--csv Save the test report in a CSV file\n--gui Launch graphical interface (non-headless mode)\n--skip-build Skip the package build step\n--skip-publish Skip the package publication step\n\nRun package tests\n\nSee instructions:\nhttps://datagrok.ai/help/develop/how-to/test-packages#local-testing\n";
15
16
  var HELP_LINK = "\nUsage: grok link\n\nLink `datagrok-api` and libraries for local development\n";
16
17
  var HELP_UNLINK = "\nUsage: grok unlink\n\nRevert `grok link`\n";
@@ -21,6 +22,7 @@ var help = {
21
22
  check: HELP_CHECK,
22
23
  config: HELP_CONFIG,
23
24
  create: HELP_CREATE,
25
+ init: HELP_INIT,
24
26
  link: HELP_LINK,
25
27
  unlink: HELP_UNLINK,
26
28
  publish: HELP_PUBLISH,
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports.init = init;
11
+
12
+ var _fs = _interopRequireDefault(require("fs"));
13
+
14
+ var _os = _interopRequireDefault(require("os"));
15
+
16
+ var _path = _interopRequireDefault(require("path"));
17
+
18
+ var _jsYaml = _interopRequireDefault(require("js-yaml"));
19
+
20
+ var utils = _interopRequireWildcard(require("../utils/utils"));
21
+
22
+ var color = _interopRequireWildcard(require("../utils/color-utils"));
23
+
24
+ var _configValidator = require("../validators/config-validator");
25
+
26
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
27
+
28
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
+
30
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
31
+
32
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
33
+
34
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
35
+
36
+ var curDir = process.cwd();
37
+
38
+ var platform = _os["default"].platform();
39
+
40
+ var grokDir = _path["default"].join(_os["default"].homedir(), '.grok');
41
+
42
+ var confPath = _path["default"].join(grokDir, 'config.yaml');
43
+
44
+ var packageJsonPath = _path["default"].join(curDir, 'package.json');
45
+
46
+ var tsConfigPath = _path["default"].join(curDir, 'tsconfig.json');
47
+
48
+ var webpackConfigPath = _path["default"].join(curDir, 'webpack.config.js');
49
+
50
+ var templateDir = _path["default"].join(_path["default"].dirname(_path["default"].dirname(__dirname)), 'package-template');
51
+
52
+ function init(args) {
53
+ var options = ['ide', 'eslint', 'test', 'ts'];
54
+ var nOptions = Object.keys(args).length - 1;
55
+ var nArgs = args['_'].length;
56
+
57
+ if (nArgs > 1 || nOptions > options.length) {
58
+ color.error('Incorrect number of arguments and options.');
59
+ return false;
60
+ }
61
+
62
+ var passedOptions = Object.keys(args).slice(1);
63
+
64
+ if (nOptions) {
65
+ var hasUnknownOpt = false;
66
+
67
+ var _iterator = _createForOfIteratorHelper(passedOptions),
68
+ _step;
69
+
70
+ try {
71
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
72
+ var op = _step.value;
73
+
74
+ if (!options.includes(op)) {
75
+ if (op !== 'h' && op !== 'help') color.error("Unknown option: ".concat(op));
76
+ hasUnknownOpt = true;
77
+ }
78
+ }
79
+ } catch (err) {
80
+ _iterator.e(err);
81
+ } finally {
82
+ _iterator.f();
83
+ }
84
+
85
+ if (hasUnknownOpt) return false;
86
+ }
87
+
88
+ if (!utils.isPackageDir(curDir)) {
89
+ color.error('File `package.json` not found. Run the command from the package directory');
90
+ return false;
91
+ }
92
+
93
+ if (args.ts) {
94
+ _fs["default"].writeFileSync(webpackConfigPath, _fs["default"].readFileSync(_path["default"].join(templateDir, 'ts.webpack.config.js')));
95
+
96
+ _fs["default"].writeFileSync(tsConfigPath, _fs["default"].readFileSync(_path["default"].join(templateDir, 'tsconfig.json')));
97
+
98
+ var packageJsPath = _path["default"].join(curDir, 'src', 'package.js');
99
+
100
+ _fs["default"].writeFileSync(_path["default"].join(curDir, 'src', 'package.ts'), _fs["default"].existsSync(packageJsPath) ? _fs["default"].readFileSync(packageJsPath) : _fs["default"].readFileSync(_path["default"].join(templateDir, 'src', 'package.ts')));
101
+
102
+ var packageData = JSON.parse(_fs["default"].readFileSync(packageJsonPath, 'utf-8'));
103
+ Object.assign(packageData.devDependencies, {
104
+ 'ts-loader': 'latest',
105
+ 'typescript': 'latest'
106
+ });
107
+ if ('eslint' in packageData.devDependencies) Object.assign(packageData.devDependencies, {
108
+ '@typescript-eslint/eslint-plugin': 'latest',
109
+ '@typescript-eslint/parser': 'latest'
110
+ });
111
+
112
+ _fs["default"].writeFileSync(packageJsonPath, JSON.stringify(packageData, null, 2), 'utf-8');
113
+
114
+ color.success('TypeScript support has been added.');
115
+ }
116
+
117
+ if (args.ide) {
118
+ var config = _jsYaml["default"].load(_fs["default"].readFileSync(confPath, {
119
+ encoding: 'utf-8'
120
+ }));
121
+
122
+ var confTest = (0, _configValidator.validateConf)(config);
123
+
124
+ if (!confTest.value) {
125
+ color.warn('Invalid configuration. Skipping `ide`...');
126
+ color.error(confTest.message);
127
+ }
128
+
129
+ if (args.ide === 'vscode') {
130
+ var ideConfPath = _path["default"].join(curDir, '.vscode');
131
+
132
+ var templateConfPath = _path["default"].join(templateDir, '.vscode');
133
+
134
+ if (!_fs["default"].existsSync(ideConfPath)) _fs["default"].mkdirSync(ideConfPath);
135
+
136
+ var files = _fs["default"].readdirSync(templateConfPath);
137
+
138
+ var _iterator2 = _createForOfIteratorHelper(files),
139
+ _step2;
140
+
141
+ try {
142
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
143
+ var file = _step2.value;
144
+
145
+ var contents = _fs["default"].readFileSync(_path["default"].join(templateConfPath, file), 'utf-8');
146
+
147
+ if (file === 'tasks.json' && platform !== 'win32') contents = contents.replace(/(?<="command": ").*(?=")/, 'webpack && grok publish #{GROK_HOST_ALIAS}');
148
+ contents = contents.replace(/#{GROK_HOST_ALIAS}/g, config["default"]);
149
+ contents = contents.replace(/#{GROK_HOST}/g, /localhost|127\.0\.0\.1/.test(config['servers'][config["default"]]['url']) ? 'http://localhost:63343/login.html' : new URL(config['servers'][config["default"]]['url']).origin);
150
+
151
+ _fs["default"].writeFileSync(_path["default"].join(ideConfPath, file), contents, 'utf-8');
152
+ }
153
+ } catch (err) {
154
+ _iterator2.e(err);
155
+ } finally {
156
+ _iterator2.f();
157
+ }
158
+
159
+ color.success('IDE configuration has been added.');
160
+ }
161
+ }
162
+
163
+ if (args.eslint) {
164
+ var _packageData = JSON.parse(_fs["default"].readFileSync(packageJsonPath, 'utf-8'));
165
+
166
+ Object.assign(_packageData.devDependencies, {
167
+ 'eslint': 'latest',
168
+ 'eslint-config-google': 'latest'
169
+ });
170
+
171
+ var ts = _fs["default"].existsSync(tsConfigPath);
172
+
173
+ if (ts) {
174
+ Object.assign(_packageData.devDependencies, {
175
+ '@typescript-eslint/eslint-plugin': 'latest',
176
+ '@typescript-eslint/parser': 'latest'
177
+ });
178
+ }
179
+
180
+ Object.assign(_packageData.scripts, {
181
+ 'lint': "eslint src".concat(ts ? ' --ext .ts' : ''),
182
+ 'lint-fix': "eslint src".concat(ts ? ' --ext .ts' : '', " --fix")
183
+ });
184
+
185
+ _fs["default"].writeFileSync(packageJsonPath, JSON.stringify(_packageData, null, 2), 'utf-8');
186
+
187
+ var eslintConfigPath = _path["default"].join(curDir, '.eslintrc.json');
188
+
189
+ var eslintTemplatePath = _path["default"].join(templateDir, '.eslintrc.json');
190
+
191
+ if (ts) {
192
+ var _contents = _fs["default"].readFileSync(eslintTemplatePath, 'utf-8');
193
+
194
+ var eslintConf = JSON.parse(_contents);
195
+ eslintConf.parser = '@typescript-eslint/parser';
196
+ eslintConf.plugins = ['@typescript-eslint'];
197
+ _contents = JSON.stringify(eslintConf, null, 2);
198
+
199
+ _fs["default"].writeFileSync(eslintConfigPath, _contents, 'utf-8');
200
+ } else _fs["default"].writeFileSync(eslintConfigPath, eslintTemplatePath);
201
+
202
+ color.success('Linter configuration has been added.');
203
+ }
204
+
205
+ if (args.test) {
206
+ var tsPath = _path["default"].join(curDir, 'src', 'package.ts');
207
+
208
+ if (!_fs["default"].existsSync(tsPath)) {
209
+ color.warn('Tests can only be added to TypeScript packages. Skipping `test`...');
210
+ } else if (!_fs["default"].existsSync(webpackConfigPath)) {
211
+ color.warn('Webpack configuration not found. Skipping `test`...');
212
+ } else {
213
+ var _config = _fs["default"].readFileSync(webpackConfigPath, 'utf-8');
214
+
215
+ if (!/(?<=entry:\s*{\s*(\r\n|\r|\n))[^}]*test:/.test(_config)) {
216
+ var entryIdx = _config.search(/(?<=entry:\s*{\s*(\r\n|\r|\n)).*/);
217
+
218
+ if (entryIdx === -1) color.error('Entry point not found during webpack config parsing');else {
219
+ var testEntry = " test: {filename: 'package-test.js', library: " + "{type: 'var', name:`${packageName}_test`}, import: './src/package-test.ts'},";
220
+
221
+ _fs["default"].writeFileSync(webpackConfigPath, _config.slice(0, entryIdx) + testEntry + _config.slice(entryIdx), 'utf-8');
222
+ }
223
+ }
224
+
225
+ var _packageData2 = JSON.parse(_fs["default"].readFileSync(packageJsonPath, 'utf-8'));
226
+
227
+ Object.assign(_packageData2.dependencies, {
228
+ '@datagrok-libraries/utils': 'latest'
229
+ });
230
+ Object.assign(_packageData2.scripts, {
231
+ 'test': 'grok test'
232
+ });
233
+
234
+ _fs["default"].writeFileSync(packageJsonPath, JSON.stringify(_packageData2, null, 2), 'utf-8');
235
+
236
+ var packageTestPath = _path["default"].join(curDir, 'src', 'package-test.ts');
237
+
238
+ if (!_fs["default"].existsSync(packageTestPath)) _fs["default"].writeFileSync(packageTestPath, _fs["default"].readFileSync(_path["default"].join(templateDir, 'src', 'package-test.ts')));
239
+
240
+ var testsDir = _path["default"].join(curDir, 'src', 'tests');
241
+
242
+ if (!_fs["default"].existsSync(testsDir)) _fs["default"].mkdirSync(testsDir);
243
+
244
+ _fs["default"].writeFileSync(_path["default"].join(testsDir, 'test-examples.ts'), _fs["default"].readFileSync(_path["default"].join(_path["default"].dirname(templateDir), 'entity-template', 'test.ts')));
245
+
246
+ _fs["default"].writeFileSync(packageTestPath, "import './tests/test-examples';\n" + _fs["default"].readFileSync(packageTestPath, 'utf-8'), 'utf-8');
247
+
248
+ color.success('Tests support has been added.');
249
+ }
250
+ }
251
+
252
+ return true;
253
+ }
@@ -121,16 +121,15 @@ function link(args) {
121
121
  var lib = _step2.value;
122
122
 
123
123
  if ("".concat(libScope, "/").concat(lib.name) in dependencies) {
124
- if (lib.isSymbolicLink()) {
125
- console.log("Package \"".concat(lib.name, "\" is linked. Skipping..."));
126
- } else {
127
- console.log("Linking \"".concat(lib.name, "\"..."));
128
- (0, _child_process.exec)('npm install && npm run build && npm link', {
129
- cwd: _path["default"].join(paths[libScope], lib.name)
130
- }, function (err, stdout, stderr) {
131
- if (err) throw err;else console.log(stderr, stdout);
132
- });
133
- }
124
+ var libPath = _path["default"].join(paths[libScope], lib.name);
125
+
126
+ var isLinked = lib.isSymbolicLink();
127
+ console.log(isLinked ? "Package \"".concat(lib.name, "\" is linked. Updating dependencies and running the build script...") : "Linking \"".concat(lib.name, "\"..."));
128
+ (0, _child_process.exec)(isLinked ? 'npm update && npm run build' : 'npm install && npm run build && npm link', {
129
+ cwd: libPath
130
+ }, function (err, stdout, stderr) {
131
+ if (err) throw err;else console.log(stderr, stdout);
132
+ });
134
133
  }
135
134
  }
136
135
  } catch (err) {
@@ -145,43 +144,38 @@ function link(args) {
145
144
  return m.name === 'utils';
146
145
  }), 1)[0];
147
146
 
148
- if (utilsModule.isSymbolicLink()) {
149
- console.log("Package \"".concat(utilsModule.name, "\" is linked. Skipping..."));
150
- } else {
151
- console.log("Linking \"".concat(utilsModule.name, "\"..."));
152
- (0, _child_process.exec)('npm install && npm run build && npm link', {
153
- cwd: _path["default"].join(paths[libScope], 'utils')
154
- }, function (err, stdout, stderr) {
155
- if (err) throw err;else {
156
- console.log(stderr, stdout);
157
- f();
158
- }
159
- });
160
- }
161
- } else {
162
- f();
163
- }
164
- }
147
+ var libPath = _path["default"].join(paths[libScope], 'utils');
165
148
 
166
- if (apiModule != null) {
167
- if (apiModule.isSymbolicLink()) {
168
- console.log("Package \"".concat(apiModule.name, "\" is linked. Skipping..."));
169
- installLibs(libs);
170
- } else {
171
- console.log("Linking \"".concat(apiModule.name, "\"..."));
172
- (0, _child_process.exec)("npm install && npm run build && npm link", {
173
- cwd: paths[apiPackageName]
149
+ var isLinked = utilsModule.isSymbolicLink();
150
+ console.log(isLinked ? "Package \"".concat(utilsModule.name, "\" is linked. Updating dependencies and running the build script...") : "Linking \"".concat(utilsModule.name, "\"..."));
151
+ (0, _child_process.exec)(isLinked ? 'npm update && npm run build' : 'npm install && npm run build && npm link', {
152
+ cwd: libPath
174
153
  }, function (err, stdout, stderr) {
175
154
  if (err) throw err;else {
176
155
  console.log(stderr, stdout);
177
- installLibs(libs);
178
- var packageNames = Object.keys(dependencies).join(' ');
179
- (0, _child_process.exec)("npm link ".concat(packageNames));
156
+ f();
180
157
  }
181
158
  });
159
+ } else {
160
+ f();
182
161
  }
183
162
  }
184
163
 
164
+ if (apiModule != null) {
165
+ var isLinked = apiModule.isSymbolicLink();
166
+ console.log(isLinked ? "Package \"".concat(apiModule.name, "\" is linked. Updating dependencies and running the build script...") : "Linking \"".concat(apiModule.name, "\"..."));
167
+ (0, _child_process.exec)(isLinked ? "npm update && npm run build" : "npm install && npm run build && npm link", {
168
+ cwd: paths[apiPackageName]
169
+ }, function (err, stdout, stderr) {
170
+ if (err) throw err;else {
171
+ console.log(stderr, stdout);
172
+ installLibs(libs);
173
+ var packageNames = Object.keys(dependencies).join(' ');
174
+ (0, _child_process.exec)("npm link ".concat(packageNames));
175
+ }
176
+ });
177
+ }
178
+
185
179
  return true;
186
180
  }
187
181
  /** Unlinks local packages and runs `npm i`. */
package/bin/grok.js CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
- const argv = require('minimist')(process.argv.slice(2), {alias: {k: 'key'}});
2
+ const argv = require('minimist')(process.argv.slice(2), {
3
+ alias: { k: 'key', h: 'help', r: 'recursive' },
4
+ });
3
5
  const help = require('./commands/help').help;
4
6
 
5
7
  const commands = {
@@ -8,6 +10,7 @@ const commands = {
8
10
  check: require('./commands/check').check,
9
11
  config: require('./commands/config').config,
10
12
  create: require('./commands/create').create,
13
+ init: require('./commands/init').init,
11
14
  link: require('./commands/link').link,
12
15
  unlink: require('./commands/link').unlink,
13
16
  publish: require('./commands/publish').publish,
@@ -3,8 +3,8 @@
3
3
  "tasks": [
4
4
  {
5
5
  "type": "shell",
6
- "command": "cmd.exe /c 'call webpack && call grok publish {GROK_HOST_ALIAS}'",
6
+ "command": "cmd.exe /c 'call webpack && call grok publish #{GROK_HOST_ALIAS}'",
7
7
  "label": "rebuild"
8
8
  }
9
9
  ]
10
- }
10
+ }
@@ -27,6 +27,7 @@ module.exports = {
27
27
  'dayjs': 'dayjs',
28
28
  'wu': 'wu',
29
29
  'exceljs': 'ExcelJS',
30
+ 'html2canvas': 'html2canvas',
30
31
  },
31
32
  output: {
32
33
  filename: '[name].js',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datagrok-tools",
3
- "version": "4.7.11",
3
+ "version": "4.8.1",
4
4
  "description": "Utility to upload and publish packages to Datagrok",
5
5
  "homepage": "https://github.com/datagrok-ai/public/tree/master/tools#readme",
6
6
  "dependencies": {