datagrok-tools 4.14.6 → 4.14.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Datagrok-tools changelog
2
2
 
3
+ ## 4.14.6 (2025-06-06)
4
+
5
+ ### Features
6
+
7
+ * Grok Check added collision checks
8
+ * Grok Publish runs check before invocation
9
+ * Grok Api creates api for the scripts in the python directory.
10
+
11
+
3
12
  ## 4.14.6 (2025-05-29)
4
13
 
5
14
  ### Features
@@ -55,31 +55,37 @@ function generateQueryWrappers() {
55
55
  }
56
56
  function generateScriptWrappers() {
57
57
  const scriptsDir = _path.default.join(curDir, 'scripts');
58
+ const pythonDir = _fs.default.existsSync(srcDir) ? _path.default.join(srcDir, 'python') : _path.default.join(curDir, 'python');
58
59
  if (!_fs.default.existsSync(scriptsDir)) {
59
60
  color.warn(`Directory ${scriptsDir} not found`);
60
61
  console.log('Skipping API generation for scripts...');
61
62
  return;
62
63
  }
63
- const files = _ignoreWalk.default.sync({
64
- path: scriptsDir,
65
- ignoreFiles: ['.npmignore', '.gitignore']
66
- });
67
64
  const wrappers = [];
68
- for (const file of files) {
69
- let extension;
70
- if (!utils.scriptExtensions.some(ext => (extension = ext, file.endsWith(ext)))) continue;
71
- const filepath = _path.default.join(scriptsDir, file);
72
- const script = _fs.default.readFileSync(filepath, 'utf8');
73
- if (!script) continue;
74
- const name = utils.getScriptName(script, utils.commentMap[extension]);
75
- if (!name) continue;
76
- const description = utils.getScriptDescription(script);
77
- checkNameColision(name);
78
- const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package.name);
79
- const inputs = utils.getScriptInputs(script);
80
- const outputType = utils.getScriptOutputType(script);
81
- tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs).replace('FUNC_DESCRIPTION', description).replace('OUTPUT_TYPE', outputType);
82
- wrappers.push(tb.build(1));
65
+ for (let dir of [scriptsDir, pythonDir]) {
66
+ const files = _ignoreWalk.default.sync({
67
+ path: dir,
68
+ ignoreFiles: ['.npmignore', '.gitignore']
69
+ });
70
+ console.log(files);
71
+ for (const file of files) {
72
+ let extension;
73
+ if (!utils.scriptExtensions.some(ext => (extension = ext, file.endsWith(ext)))) continue;
74
+ const filepath = _path.default.join(dir, file);
75
+ const script = _fs.default.readFileSync(filepath, 'utf8');
76
+ if (!script) continue;
77
+ console.log(filepath);
78
+ console.log(script);
79
+ const name = utils.getScriptName(script, utils.commentMap[extension]);
80
+ if (!name) continue;
81
+ const description = utils.getScriptDescription(script);
82
+ checkNameColision(name);
83
+ const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package.name);
84
+ const inputs = utils.getScriptInputs(script);
85
+ const outputType = utils.getScriptOutputType(script);
86
+ tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs).replace('FUNC_DESCRIPTION', description).replace('OUTPUT_TYPE', outputType);
87
+ wrappers.push(tb.build(1));
88
+ }
83
89
  }
84
90
  saveWrappersToFile('scripts', wrappers);
85
91
  }
@@ -21,20 +21,21 @@ var testUtils = _interopRequireWildcard(require("../utils/test-utils"));
21
21
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
22
22
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
23
23
  const warns = ['Latest package version', 'Datagrok API version should contain'];
24
- const forbidenNames = ['function', 'class', 'export'];
24
+ const forbiddenNames = ['function', 'class', 'export'];
25
+ const namesInFiles = new Map();
25
26
  function check(args) {
26
27
  const nOptions = Object.keys(args).length - 1;
27
28
  if (args['_'].length !== 1 || nOptions > 2 || nOptions > 0 && !args.r && !args.recursive) return false;
28
29
  const curDir = process.cwd();
29
- if (args.recursive) return runChecksRec(curDir);else {
30
+ if (args.recursive) return runChecksRec(curDir, args.soft ?? false);else {
30
31
  if (!utils.isPackageDir(curDir)) {
31
32
  color.error('File `package.json` not found. Run the command from the package directory');
32
33
  return false;
33
34
  }
34
- return runChecks(curDir);
35
+ return runChecks(curDir, args.soft ?? false);
35
36
  }
36
37
  }
37
- function runChecks(packagePath) {
38
+ function runChecks(packagePath, soft = false) {
38
39
  const files = _ignoreWalk.default.sync({
39
40
  path: packagePath,
40
41
  ignoreFiles: ['.npmignore', '.gitignore']
@@ -77,20 +78,20 @@ function runChecks(packagePath) {
77
78
  if (errors.length) {
78
79
  console.log(`Checking package ${_path.default.basename(packagePath)}...`);
79
80
  showError(errors);
80
- if (json.version.startsWith('0') || errors.every(w => warns.some(ww => w.includes(ww)))) return true;
81
+ if (soft || json.version.startsWith('0') || errors.every(w => warns.some(ww => w.includes(ww)))) return true;
81
82
  testUtils.exitWithCode(1);
82
83
  }
83
84
  console.log(`Checking package ${_path.default.basename(packagePath)}...\t\t\t\u2713 OK`);
84
85
  return true;
85
86
  }
86
- function runChecksRec(dir) {
87
+ function runChecksRec(dir, soft = false) {
87
88
  const files = _fs.default.readdirSync(dir);
88
89
  for (const file of files) {
89
90
  const filepath = _path.default.join(dir, file);
90
91
  const stats = _fs.default.statSync(filepath);
91
92
  if (stats.isDirectory()) {
92
- if (utils.isPackageDir(filepath)) return runChecks(filepath);else {
93
- if (file !== 'node_modules' && !file.startsWith('.')) runChecksRec(_path.default.join(dir, file));
93
+ if (utils.isPackageDir(filepath)) return runChecks(filepath, soft);else {
94
+ if (file !== 'node_modules' && !file.startsWith('.')) runChecksRec(_path.default.join(dir, file), soft);
94
95
  }
95
96
  }
96
97
  }
@@ -315,13 +316,19 @@ function checkFuncSignatures(packagePath, files) {
315
316
  warnings.push(`File ${file}, function ${f.name}:\n${vr.message}`);
316
317
  }
317
318
  }
318
- let wrongInputNames = f.inputs.filter(e => forbidenNames.includes(e?.name ?? ''));
319
+ let wrongInputNames = f.inputs.filter(e => forbiddenNames.includes(e?.name ?? ''));
320
+ if (f.name) {
321
+ if (namesInFiles.has(f.name)) namesInFiles.get(f.name)?.push(file);else namesInFiles.set(f.name, [file]);
322
+ }
319
323
  if (wrongInputNames.length > 0) warnings.push(`File ${file}, function ${f.name}: Wrong input names: (${wrongInputNames.map(e => e.name).join(', ')})`);
320
324
  if (f.isInvalidateOnWithoutCache) warnings.push(`File ${file}, function ${f.name}: Can't use invalidateOn without cache, please follow this example: 'meta.cache.invalidateOn'`);
321
- if (f.cache) if (!utils.cahceValues.includes(f.cache)) warnings.push(`File ${file}, function ${f.name}: unsupposed variable for cache : ${f.cache}`);
325
+ if (f.cache) if (!utils.cacheValues.includes(f.cache)) warnings.push(`File ${file}, function ${f.name}: unsupposed variable for cache : ${f.cache}`);
322
326
  if (f.invalidateOn) if (!utils.isValidCron(f.invalidateOn)) warnings.push(`File ${file}, function ${f.name}: unsupposed variable for invalidateOn : ${f.invalidateOn}`);
323
327
  }
324
328
  }
329
+ for (const [name, files] of namesInFiles) {
330
+ if (files.length > 1) warnings.push(`Duplicate names ('${name}'): \n ${files.join('\n ')}`);
331
+ }
325
332
  return warnings;
326
333
  }
327
334
  const sharedLibExternals = {
@@ -519,7 +526,7 @@ function getFuncMetadata(script, fileExtention) {
519
526
  if (match) {
520
527
  if (!isHeader) isHeader = true;
521
528
  const param = match[1];
522
- if (param === 'name') data.name = line.match(utils.nameAnnRegex)?.[2];else if (param === 'description') data.description = match[2];else if (param === 'input') {
529
+ if (param === 'name') data.name = line.match(utils.nameAnnRegex)?.[2]?.toLocaleLowerCase();else if (param === 'description') data.description = match[2];else if (param === 'input') {
523
530
  data.inputs.push({
524
531
  type: match[2],
525
532
  name: match[3]
@@ -539,8 +546,8 @@ function getFuncMetadata(script, fileExtention) {
539
546
  }
540
547
  if (isHeader) {
541
548
  const nm = line.match(utils.nameRegex);
542
- if (nm && !match) {
543
- data.name = data.name || nm[1];
549
+ if (nm) data.name = nm[1]?.toLocaleLowerCase();
550
+ if (data.name && !match) {
544
551
  funcData.push(data);
545
552
  data = {
546
553
  name: '',
@@ -14,9 +14,9 @@ var _path = _interopRequireDefault(require("path"));
14
14
  var _ignoreWalk = _interopRequireDefault(require("ignore-walk"));
15
15
  var _jsYaml = _interopRequireDefault(require("js-yaml"));
16
16
  var _testUtils = require("../utils/test-utils");
17
- var _check = require("./check");
18
17
  var utils = _interopRequireWildcard(require("../utils/utils"));
19
18
  var color = _interopRequireWildcard(require("../utils/color-utils"));
19
+ var _check = require("./check");
20
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
21
21
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
22
22
  // @ts-ignore
@@ -81,7 +81,8 @@ async function processPackage(debug, rebuild, host, devKey, packageName, suffix)
81
81
  rebuild = true;
82
82
  }
83
83
  }
84
- let contentValidationLog = '';
84
+
85
+ // let contentValidationLog = '';
85
86
  console.log('Starting package checks...');
86
87
  const checkStart = Date.now();
87
88
  const jsTsFiles = files.filter(f => !f.startsWith('dist/') && (f.endsWith('.js') || f.endsWith('.ts')));
@@ -94,19 +95,19 @@ async function processPackage(debug, rebuild, host, devKey, packageName, suffix)
94
95
  const content = _fs.default.readFileSync(webpackConfigPath, {
95
96
  encoding: 'utf-8'
96
97
  });
97
- const externals = (0, _check.extractExternals)(content);
98
- if (externals) {
99
- const importWarnings = (0, _check.checkImportStatements)(curDir, jsTsFiles, externals);
100
- contentValidationLog += importWarnings.join('\n') + (importWarnings.length ? '\n' : '');
101
- }
98
+ // const externals = extractExternals(content);
99
+ // if (externals) {
100
+ // const importWarnings = checkImportStatements(curDir, jsTsFiles, externals);
101
+ // contentValidationLog += importWarnings.join('\n') + (importWarnings.length ? '\n' : '');
102
+ // }
102
103
  }
103
104
  const funcFiles = jsTsFiles.filter(f => packageFiles.includes(f));
104
- const funcWarnings = (0, _check.checkFuncSignatures)(curDir, funcFiles);
105
- contentValidationLog += funcWarnings.join('\n') + (funcWarnings.length ? '\n' : '');
106
- const packageWarnings = (0, _check.checkPackageFile)(curDir, json);
107
- contentValidationLog += packageWarnings.join('\n') + (packageWarnings.length ? '\n' : '');
108
- const changelogWarnings = (0, _check.checkChangelog)(curDir, json);
109
- contentValidationLog += changelogWarnings.join('\n') + (packageWarnings.length ? '\n' : '');
105
+ // const funcWarnings = checkFuncSignatures(curDir, funcFiles);
106
+ // contentValidationLog += funcWarnings.join('\n') + (funcWarnings.length ? '\n' : '');
107
+ // const packageWarnings = checkPackageFile(curDir, json);
108
+ // contentValidationLog += packageWarnings.join('\n') + (packageWarnings.length ? '\n' : '');
109
+ // const changelogWarnings = checkChangelog(curDir, json);
110
+ // contentValidationLog += changelogWarnings.join('\n') + '';
110
111
  console.log(`Checks finished in ${Date.now() - checkStart} ms`);
111
112
  const reg = new RegExp(/\${(\w*)}/g);
112
113
  const errs = [];
@@ -123,9 +124,10 @@ async function processPackage(debug, rebuild, host, devKey, packageName, suffix)
123
124
  }
124
125
  if (relativePath.startsWith('upload.keys.json')) return;
125
126
  if (relativePath === 'zip') return;
126
- if (!utils.checkScriptLocation(canonicalRelativePath)) {
127
- contentValidationLog += `Warning: file \`${canonicalRelativePath}\`` + ` should be in directory \`${_path.default.basename(curDir)}/scripts/\`\n`;
128
- }
127
+ // if (!utils.checkScriptLocation(canonicalRelativePath)) {
128
+ // contentValidationLog += `Warning: file \`${canonicalRelativePath}\`` +
129
+ // ` should be in directory \`${path.basename(curDir)}/scripts/\`\n`;
130
+ // }
129
131
  const t = _fs.default.statSync(fullPath).mtime.toUTCString();
130
132
  localTimestamps[canonicalRelativePath] = t;
131
133
  if (debug && timestamps[canonicalRelativePath] === t) {
@@ -196,7 +198,7 @@ async function processPackage(debug, rebuild, host, devKey, packageName, suffix)
196
198
  return 1;
197
199
  } else {
198
200
  console.log(log);
199
- color.warn(contentValidationLog);
201
+ // color.warn(contentValidationLog);
200
202
  }
201
203
  } catch (error) {
202
204
  console.error(error);
@@ -205,6 +207,9 @@ async function processPackage(debug, rebuild, host, devKey, packageName, suffix)
205
207
  return 0;
206
208
  }
207
209
  async function publish(args) {
210
+ if (!args['skip-check']) (0, _check.check)({
211
+ _: ['check']
212
+ });
208
213
  config = _jsYaml.default.load(_fs.default.readFileSync(confPath, {
209
214
  encoding: 'utf-8'
210
215
  }));
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.cahceValues = exports.absUrlRegex = exports.TemplateBuilder = void 0;
7
+ exports.cacheValues = exports.absUrlRegex = exports.TemplateBuilder = void 0;
8
8
  exports.camelCaseToKebab = camelCaseToKebab;
9
9
  exports.checkScriptLocation = checkScriptLocation;
10
10
  exports.commentMap = void 0;
@@ -149,7 +149,7 @@ const queryExtension = exports.queryExtension = '.sql';
149
149
  const jsExtention = exports.jsExtention = '.js';
150
150
  const scriptExtensions = exports.scriptExtensions = ['.jl', '.m', '.py', '.R'];
151
151
  function checkScriptLocation(filepath) {
152
- if (!(filepath.startsWith('scripts/') || filepath.startsWith('projects/') || filepath.startsWith('dockerfiles/')) && scriptExtensions.some(ext => filepath.endsWith(ext))) return false;
152
+ if (!(filepath.startsWith('scripts/') || filepath.startsWith('projects/') || filepath.startsWith('dockerfiles/') || filepath.startsWith('python/')) && scriptExtensions.some(ext => filepath.endsWith(ext))) return false;
153
153
  return true;
154
154
  }
155
155
  ;
@@ -165,7 +165,7 @@ function getParam(name, script, comment = '#') {
165
165
  return match ? match[1]?.trim() : null;
166
166
  }
167
167
  ;
168
- const cahceValues = exports.cahceValues = ['all', 'server', 'client', 'true'];
168
+ const cacheValues = exports.cacheValues = ['all', 'server', 'client', 'true'];
169
169
  function isValidCron(cronExpression) {
170
170
  const cronRegex = /^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))$/;
171
171
  return cronRegex.test(cronExpression);
@@ -183,15 +183,15 @@ const dgToTsTypeMap = exports.dgToTsTypeMap = {
183
183
  view: 'DG.View'
184
184
  };
185
185
  const propertyTypes = exports.propertyTypes = ['bool', 'int', 'double', 'string', 'datetime', 'object', 'column', 'dataframe', 'bitset', 'cell', 'string_list', 'map'];
186
- const headerTags = exports.headerTags = ['name', 'description', 'help-url', 'input', 'output', 'tags', 'sample', 'language', 'returns', 'test', 'sidebar', 'condition', 'top-menu', 'environment', 'require', 'editor-for', 'schedule', 'reference', 'editor', 'meta'];
186
+ const headerTags = exports.headerTags = ['name', 'description', 'help-url', 'input', 'output', 'tags', 'sample', 'language', 'returns', 'test', 'sidebar', 'condition', 'top-menu', 'environment', 'require', 'editor-for', 'schedule', 'reference', 'editor', 'meta', 'connection', 'friendlyName'];
187
187
  const fileParamRegex = exports.fileParamRegex = {
188
188
  py: new RegExp(`^\#\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
189
189
  ts: new RegExp(`^\/\/\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
190
190
  js: new RegExp(`^\/\/\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
191
191
  sql: new RegExp(`^--\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`)
192
192
  };
193
- const nameAnnRegex = exports.nameAnnRegex = /\/\/\s*(name[^:]*): ([^\n\r\[\{]+)/;
194
- const nameRegex = exports.nameRegex = /(?:|(?:static)(?:export )(?:async )function )\s+([a-zA-Z_][a-zA-Z0-9_$]*)\s*\((.*?).*/;
193
+ const nameAnnRegex = exports.nameAnnRegex = /\s*(name[^:]*): ([^\n\r\[\{]+)/;
194
+ const nameRegex = exports.nameRegex = /(?:|(?:static)(?:export )(?:async ))\s+function\s+([a-zA-Z_][a-zA-Z0-9_$]*)\s*\((.*?).*/;
195
195
  const absUrlRegex = exports.absUrlRegex = new RegExp('^(?:[a-z+]+:)?//', 'i');
196
196
  function getScriptOutputType(script, comment = '#') {
197
197
  const regex = new RegExp(`${comment}\\s*output:\\s?([a-z_]+)\\s*`);
@@ -245,7 +245,7 @@ async function runScript(script, path, verbose = false) {
245
245
  }
246
246
  } catch (error) {
247
247
  console.error(`Execution failed: ${error.message}`);
248
- throw new Error(`Cant run script ${script}`);
248
+ throw new Error(`Error executing '${script}'. Error message: ${error.message}`);
249
249
  }
250
250
  }
251
251
  function setHost(host, configFile) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datagrok-tools",
3
- "version": "4.14.6",
3
+ "version": "4.14.8",
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": {