datagrok-tools 4.7.10 → 4.8.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.
package/README.md CHANGED
@@ -17,7 +17,7 @@ npm install datagrok-tools -g
17
17
  ```
18
18
 
19
19
  Enter developer keys and set the default server. The developer key can be retrieved from your user profile (for
20
- example, see https://public.datagrok.ai/u).
20
+ example, see <https://public.datagrok.ai/u>).
21
21
  2. Create a new package by running this command:
22
22
 
23
23
  ```shell
@@ -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
@@ -98,3 +98,24 @@ Read more about package development in [Datagrok's documentation](https://datagr
98
98
  - `--suffix`: a string containing package version hash
99
99
 
100
100
  Running `grok publish` is the same as running `grok publish defaultHost --build --debug`.
101
+ - `check` checks package content (function signatures, import statements of external modules,
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`).
105
+ - `test` runs package tests. First, it builds a package and publishes it (these
106
+ steps can be skipped with flags `--skip-build` and `--skip-publish`
107
+ correspondingly).
108
+
109
+ ```shell
110
+ cd <package-name>
111
+ grok test
112
+ ```
113
+
114
+ The default host from the `config.yaml` file is used. You
115
+ can specify another server alias via the `--host` option (e.g., `grok test
116
+ --host=dev`). The results are printed to the terminal. To see tests execution,
117
+ pass the `--gui` flag that disables the headless browser mode. If you want to
118
+ save a test run result, add the `--csv` flag (the report will be saved in a
119
+ CSV file in the package folder). You can find more details in [local package testing
120
+ instructions](https://datagrok.ai/help/develop/how-to/test-packages#local-testing).
121
+ - `link` / `unlink` commands are used for public plugins development to (un)link `datagrok-api` and libraries.
@@ -15,6 +15,8 @@ exports.extractExternals = extractExternals;
15
15
 
16
16
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
17
17
 
18
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
19
+
18
20
  var _fs = _interopRequireDefault(require("fs"));
19
21
 
20
22
  var _path = _interopRequireDefault(require("path"));
@@ -37,29 +39,44 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
37
39
 
38
40
  function check(args) {
39
41
  var nOptions = Object.keys(args).length - 1;
40
- if (args['_'].length !== 1 || nOptions > 0 && (!args.dir || typeof args.dir !== 'string') || nOptions > 1) return false;
42
+ if (args['_'].length !== 1 || nOptions > 2 || nOptions > 0 && !args.r && !args.recursive) return false;
41
43
  var curDir = process.cwd();
42
44
 
43
- if (args.dir && typeof args.dir === 'string') {
44
- var packagesDir = _path["default"].isAbsolute(args.dir) ? args.dir : _path["default"].join(curDir, args.dir);
45
+ if (args.recursive) {
46
+ var runChecksRec = function runChecksRec(dir) {
47
+ var files = _fs["default"].readdirSync(dir);
48
+
49
+ var _iterator = _createForOfIteratorHelper(files),
50
+ _step;
51
+
52
+ try {
53
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
54
+ var file = _step.value;
45
55
 
46
- _fs["default"].readdirSync(packagesDir).forEach(function (file) {
47
- var filepath = _path["default"].join(packagesDir, file);
56
+ var filepath = _path["default"].join(dir, file);
48
57
 
49
- var stats = _fs["default"].statSync(filepath);
58
+ var stats = _fs["default"].statSync(filepath);
50
59
 
51
- if (stats.isDirectory() && utils.isPackageDir(filepath)) {
52
- console.log("Checking package ".concat(file, "..."));
53
- runChecks(filepath);
60
+ if (stats.isDirectory()) {
61
+ if (utils.isPackageDir(filepath)) runChecks(filepath);else {
62
+ if (file !== 'node_modules' && !file.startsWith('.')) runChecksRec(_path["default"].join(dir, file));
63
+ }
64
+ }
65
+ }
66
+ } catch (err) {
67
+ _iterator.e(err);
68
+ } finally {
69
+ _iterator.f();
54
70
  }
55
- });
71
+ };
72
+
73
+ runChecksRec(curDir);
56
74
  } else {
57
75
  if (!utils.isPackageDir(curDir)) {
58
76
  color.error('File `package.json` not found. Run the command from the package directory');
59
77
  return false;
60
78
  }
61
79
 
62
- console.log("Checking package ".concat(_path["default"].basename(curDir), "..."));
63
80
  runChecks(curDir);
64
81
  }
65
82
 
@@ -76,6 +93,7 @@ function check(args) {
76
93
  var funcFiles = jsTsFiles.filter(function (f) {
77
94
  return packageFiles.includes(f);
78
95
  });
96
+ var warnings = [];
79
97
 
80
98
  var webpackConfigPath = _path["default"].join(packagePath, 'webpack.config.js');
81
99
 
@@ -87,11 +105,16 @@ function check(args) {
87
105
  });
88
106
 
89
107
  var externals = extractExternals(content);
90
- if (externals) warn(checkImportStatements(packagePath, jsTsFiles, externals));
108
+ if (externals) warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkImportStatements(packagePath, jsTsFiles, externals)));
91
109
  }
92
110
 
93
- warn(checkFuncSignatures(packagePath, funcFiles));
94
- warn(checkPackageFile(packagePath));
111
+ warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkFuncSignatures(packagePath, funcFiles)));
112
+ warnings.push.apply(warnings, (0, _toConsumableArray2["default"])(checkPackageFile(packagePath)));
113
+
114
+ if (warnings.length) {
115
+ console.log("Checking package ".concat(_path["default"].basename(packagePath), "..."));
116
+ warn(warnings);
117
+ } else console.log("Checking package ".concat(_path["default"].basename(packagePath), "...\t\t\t\u2713 OK"));
95
118
  }
96
119
 
97
120
  return true;
@@ -137,12 +160,12 @@ function checkImportStatements(packagePath, files, externals) {
137
160
  };
138
161
  }
139
162
 
140
- var _iterator = _createForOfIteratorHelper(files),
141
- _step;
163
+ var _iterator2 = _createForOfIteratorHelper(files),
164
+ _step2;
142
165
 
143
166
  try {
144
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
145
- var file = _step.value;
167
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
168
+ var file = _step2.value;
146
169
 
147
170
  var content = _fs["default"].readFileSync(_path["default"].join(packagePath, file), {
148
171
  encoding: 'utf-8'
@@ -151,26 +174,26 @@ function checkImportStatements(packagePath, files, externals) {
151
174
  var matchedImports = content.match(importRegex);
152
175
 
153
176
  if (matchedImports) {
154
- var _iterator2 = _createForOfIteratorHelper(matchedImports),
155
- _step2;
177
+ var _iterator3 = _createForOfIteratorHelper(matchedImports),
178
+ _step3;
156
179
 
157
180
  try {
158
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
159
- var match = _step2.value;
181
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
182
+ var match = _step3.value;
160
183
  var vr = validateImport(file, match);
161
184
  if (!vr.value) warnings.push(vr.message);
162
185
  }
163
186
  } catch (err) {
164
- _iterator2.e(err);
187
+ _iterator3.e(err);
165
188
  } finally {
166
- _iterator2.f();
189
+ _iterator3.f();
167
190
  }
168
191
  }
169
192
  }
170
193
  } catch (err) {
171
- _iterator.e(err);
194
+ _iterator2.e(err);
172
195
  } finally {
173
- _iterator.f();
196
+ _iterator2.f();
174
197
  }
175
198
 
176
199
  return warnings;
@@ -179,9 +202,33 @@ function checkImportStatements(packagePath, files, externals) {
179
202
  function checkFuncSignatures(packagePath, files) {
180
203
  var warnings = [];
181
204
  var checkFunctions = {
182
- semTypeDetector: function semTypeDetector(_ref) {
183
- var inputs = _ref.inputs,
184
- outputs = _ref.outputs;
205
+ app: function app(_ref) {
206
+ var name = _ref.name;
207
+ var value = true;
208
+ var message = '';
209
+
210
+ if (name && typeof name === 'string') {
211
+ var lowerCaseName = name.toLocaleLowerCase();
212
+
213
+ if (lowerCaseName.startsWith('app')) {
214
+ value = false;
215
+ message += 'Prefix "App" is not needed. Consider removing it.\n';
216
+ }
217
+
218
+ if (lowerCaseName.endsWith('app')) {
219
+ value = false;
220
+ message += 'Postfix "App" is not needed. Consider removing it.\n';
221
+ }
222
+ }
223
+
224
+ return {
225
+ value: value,
226
+ message: message
227
+ };
228
+ },
229
+ semTypeDetector: function semTypeDetector(_ref2) {
230
+ var inputs = _ref2.inputs,
231
+ outputs = _ref2.outputs;
185
232
  var value = true;
186
233
  var message = '';
187
234
 
@@ -200,9 +247,9 @@ function checkFuncSignatures(packagePath, files) {
200
247
  message: message
201
248
  };
202
249
  },
203
- cellRenderer: function cellRenderer(_ref2) {
204
- var inputs = _ref2.inputs,
205
- outputs = _ref2.outputs;
250
+ cellRenderer: function cellRenderer(_ref3) {
251
+ var inputs = _ref3.inputs,
252
+ outputs = _ref3.outputs;
206
253
  var value = true;
207
254
  var message = '';
208
255
 
@@ -221,9 +268,9 @@ function checkFuncSignatures(packagePath, files) {
221
268
  message: message
222
269
  };
223
270
  },
224
- viewer: function viewer(_ref3) {
225
- var inputs = _ref3.inputs,
226
- outputs = _ref3.outputs;
271
+ viewer: function viewer(_ref4) {
272
+ var inputs = _ref4.inputs,
273
+ outputs = _ref4.outputs;
227
274
  var value = true;
228
275
  var message = '';
229
276
 
@@ -242,10 +289,10 @@ function checkFuncSignatures(packagePath, files) {
242
289
  message: message
243
290
  };
244
291
  },
245
- fileViewer: function fileViewer(_ref4) {
246
- var inputs = _ref4.inputs,
247
- outputs = _ref4.outputs,
248
- tags = _ref4.tags;
292
+ fileViewer: function fileViewer(_ref5) {
293
+ var inputs = _ref5.inputs,
294
+ outputs = _ref5.outputs,
295
+ tags = _ref5.tags;
249
296
  var value = true;
250
297
  var message = '';
251
298
 
@@ -271,8 +318,8 @@ function checkFuncSignatures(packagePath, files) {
271
318
  message: message
272
319
  };
273
320
  },
274
- fileExporter: function fileExporter(_ref5) {
275
- var description = _ref5.description;
321
+ fileExporter: function fileExporter(_ref6) {
322
+ var description = _ref6.description;
276
323
  var value = true;
277
324
  var message = '';
278
325
 
@@ -286,8 +333,8 @@ function checkFuncSignatures(packagePath, files) {
286
333
  message: message
287
334
  };
288
335
  },
289
- packageSettingsEditor: function packageSettingsEditor(_ref6) {
290
- var outputs = _ref6.outputs;
336
+ packageSettingsEditor: function packageSettingsEditor(_ref7) {
337
+ var outputs = _ref7.outputs;
291
338
  var value = true;
292
339
  var message = '';
293
340
 
@@ -304,12 +351,12 @@ function checkFuncSignatures(packagePath, files) {
304
351
  };
305
352
  var functionRoles = Object.keys(checkFunctions);
306
353
 
307
- var _iterator3 = _createForOfIteratorHelper(files),
308
- _step3;
354
+ var _iterator4 = _createForOfIteratorHelper(files),
355
+ _step4;
309
356
 
310
357
  try {
311
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
312
- var file = _step3.value;
358
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
359
+ var file = _step4.value;
313
360
 
314
361
  var content = _fs["default"].readFileSync(_path["default"].join(packagePath, file), {
315
362
  encoding: 'utf-8'
@@ -317,12 +364,12 @@ function checkFuncSignatures(packagePath, files) {
317
364
 
318
365
  var functions = getFuncMetadata(content);
319
366
 
320
- var _iterator4 = _createForOfIteratorHelper(functions),
321
- _step4;
367
+ var _iterator5 = _createForOfIteratorHelper(functions),
368
+ _step5;
322
369
 
323
370
  try {
324
371
  var _loop = function _loop() {
325
- var f = _step4.value;
372
+ var f = _step5.value;
326
373
  var roles = functionRoles.filter(function (role) {
327
374
  var _f$tags;
328
375
 
@@ -337,19 +384,19 @@ function checkFuncSignatures(packagePath, files) {
337
384
  }
338
385
  };
339
386
 
340
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
387
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
341
388
  _loop();
342
389
  }
343
390
  } catch (err) {
344
- _iterator4.e(err);
391
+ _iterator5.e(err);
345
392
  } finally {
346
- _iterator4.f();
393
+ _iterator5.f();
347
394
  }
348
395
  }
349
396
  } catch (err) {
350
- _iterator3.e(err);
397
+ _iterator4.e(err);
351
398
  } finally {
352
- _iterator3.f();
399
+ _iterator4.f();
353
400
  }
354
401
 
355
402
  return warnings;
@@ -367,18 +414,18 @@ function checkPackageFile(packagePath) {
367
414
  if (!json.description) warnings.push('File "package.json": "description" field is empty. Provide a package description.');
368
415
 
369
416
  if (Array.isArray(json.properties) && json.properties.length > 0) {
370
- var _iterator5 = _createForOfIteratorHelper(json.properties),
371
- _step5;
417
+ var _iterator6 = _createForOfIteratorHelper(json.properties),
418
+ _step6;
372
419
 
373
420
  try {
374
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
375
- var propInfo = _step5.value;
421
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
422
+ var propInfo = _step6.value;
376
423
  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, "."));
377
424
  }
378
425
  } catch (err) {
379
- _iterator5.e(err);
426
+ _iterator6.e(err);
380
427
  } finally {
381
- _iterator5.f();
428
+ _iterator6.f();
382
429
  }
383
430
  }
384
431
 
@@ -386,21 +433,21 @@ function checkPackageFile(packagePath) {
386
433
  if (json.author == null && isPublicPackage) warnings.push('File "package.json": add the "author" field.');
387
434
 
388
435
  if (Array.isArray(json.sources) && json.sources.length > 0) {
389
- var _iterator6 = _createForOfIteratorHelper(json.sources),
390
- _step6;
436
+ var _iterator7 = _createForOfIteratorHelper(json.sources),
437
+ _step7;
391
438
 
392
439
  try {
393
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
394
- var source = _step6.value;
440
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
441
+ var source = _step7.value;
395
442
  if (typeof source !== 'string') warnings.push("File \"package.json\": Only file paths and URLs are allowed in sources. Modify the source ".concat(source));
396
443
  if (source.startsWith('common/') || utils.absUrlRegex.test(source)) continue;
397
444
  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."));
398
445
  if (!_fs["default"].existsSync(_path["default"].join(packagePath, source))) warnings.push("Source ".concat(source, " not found in the package."));
399
446
  }
400
447
  } catch (err) {
401
- _iterator6.e(err);
448
+ _iterator7.e(err);
402
449
  } finally {
403
- _iterator6.f();
450
+ _iterator7.f();
404
451
  }
405
452
  }
406
453
 
@@ -422,12 +469,12 @@ function getFuncMetadata(script) {
422
469
  outputs: []
423
470
  };
424
471
 
425
- var _iterator7 = _createForOfIteratorHelper(script.split('\n')),
426
- _step7;
472
+ var _iterator8 = _createForOfIteratorHelper(script.split('\n')),
473
+ _step8;
427
474
 
428
475
  try {
429
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
430
- var line = _step7.value;
476
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
477
+ var line = _step8.value;
431
478
  if (!line) continue;
432
479
  var match = line.match(utils.paramRegex);
433
480
 
@@ -459,9 +506,9 @@ function getFuncMetadata(script) {
459
506
  }
460
507
  }
461
508
  } catch (err) {
462
- _iterator7.e(err);
509
+ _iterator8.e(err);
463
510
  } finally {
464
- _iterator7.f();
511
+ _iterator8.f();
465
512
  }
466
513
 
467
514
  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
+ }
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
+ }
@@ -1,3 +1,3 @@
1
1
  # #{PACKAGE_NAME}
2
2
 
3
- #{PACKAGE_NAME} is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform.
3
+ `#{PACKAGE_NAME}` is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform
@@ -15,7 +15,7 @@ module.exports = {
15
15
  { test: /\.tsx?$/, loader: 'ts-loader' }
16
16
  ],
17
17
  },
18
- devtool: 'inline-source-map',
18
+ devtool: 'source-map',
19
19
  externals: {
20
20
  'datagrok-api/dg': 'DG',
21
21
  'datagrok-api/grok': 'grok',
@@ -12,7 +12,7 @@
12
12
  // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
13
13
  // "declaration": true, /* Generates corresponding '.d.ts' file. */
14
14
  // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15
- // "sourceMap": true, /* Generates corresponding '.map' file. */
15
+ "sourceMap": true, /* Generates corresponding '.map' file. */
16
16
  // "outFile": "./", /* Concatenate and emit output to single file. */
17
17
  // "outDir": "./", /* Redirect output structure to the directory. */
18
18
  // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
@@ -6,7 +6,7 @@ module.exports = {
6
6
  entry: {
7
7
  package: './src/package.js'
8
8
  },
9
- devtool: 'inline-source-map',
9
+ devtool: 'source-map',
10
10
  externals: {
11
11
  'datagrok-api/dg': 'DG',
12
12
  'datagrok-api/grok': 'grok',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datagrok-tools",
3
- "version": "4.7.10",
3
+ "version": "4.8.0",
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": {