datagrok-tools 4.14.17 → 4.14.19

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,13 @@
1
1
  # Datagrok-tools changelog
2
2
 
3
+ ## 4.14.19 (2025-06-23)
4
+
5
+ ### Features
6
+
7
+ * Grok Check added header tag validation
8
+ * Grok Api added optional parameters
9
+
10
+
3
11
  ## 4.14.14 (2025-06-16)
4
12
 
5
13
  ### Features
@@ -43,7 +43,7 @@ function generateQueryWrappers() {
43
43
  const name = utils.getScriptName(q, utils.commentMap[utils.queryExtension]);
44
44
  if (!name) continue;
45
45
  checkNameColision(name);
46
- const tb = new utils.TemplateBuilder(utils.queryWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package?.name ?? '');
46
+ const tb = new utils.TemplateBuilder(utils.queryWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package?.friendlyName ?? '');
47
47
  const description = utils.getScriptDescription(q, utils.commentMap[utils.queryExtension]);
48
48
  const inputs = utils.getScriptInputs(q, utils.commentMap[utils.queryExtension]);
49
49
  const outputType = utils.getScriptOutputType(q, utils.commentMap[utils.queryExtension]);
@@ -78,7 +78,7 @@ function generateScriptWrappers() {
78
78
  if (!name) continue;
79
79
  const description = utils.getScriptDescription(script);
80
80
  checkNameColision(name);
81
- const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package.name);
81
+ const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package?.friendlyName ?? '');
82
82
  const inputs = utils.getScriptInputs(script);
83
83
  const outputType = utils.getScriptOutputType(script);
84
84
  tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs).replace('FUNC_DESCRIPTION', description).replace('OUTPUT_TYPE', outputType);
@@ -111,7 +111,7 @@ function generateFunctionWrappers() {
111
111
  outputType = utils.dgToTsTypeMap[outputAnnotation[1]] ?? 'any';
112
112
  }
113
113
  checkNameColision(name);
114
- const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package?.name ?? '').replace('PARAMS_OBJECT', annotationInputs).replace('FUNC_DESCRIPTION', description).replace('TYPED_PARAMS', annotationInputs).replace('OUTPUT_TYPE', outputType);
114
+ const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package?.friendlyName ?? '').replace('PARAMS_OBJECT', annotationInputs).replace('FUNC_DESCRIPTION', description).replace('TYPED_PARAMS', annotationInputs).replace('OUTPUT_TYPE', outputType);
115
115
  wrappers.push(tb.build(1));
116
116
  }
117
117
  }
@@ -138,6 +138,7 @@ function api(args) {
138
138
  _package = JSON.parse(_fs.default.readFileSync(packagePath, {
139
139
  encoding: 'utf-8'
140
140
  }));
141
+ if (_package.friendlyName) _package.friendlyName = _package.friendlyName.replaceAll(' ', '');
141
142
  const nOptions = Object.keys(args).length - 1;
142
143
  if (args['_'].length !== 1 || nOptions > 0) return false;
143
144
  if (!utils.isPackageDir(process.cwd())) {
@@ -308,7 +308,7 @@ function checkFuncSignatures(packagePath, files) {
308
308
  encoding: 'utf-8'
309
309
  });
310
310
  const functions = getFuncMetadata(content, file.split('.').pop() ?? 'ts');
311
- for (const f of functions) {
311
+ for (const f of functions.meta) {
312
312
  const paramsCheck = checkFunctions.params(f);
313
313
  if (!paramsCheck.value) warnings.push(`File ${file}, function ${f.name}:\n${paramsCheck.message}`);
314
314
  const roles = functionRoles.filter(role => f.tags?.includes(role));
@@ -327,6 +327,9 @@ function checkFuncSignatures(packagePath, files) {
327
327
  if (f.cache) if (!utils.cacheValues.includes(f.cache)) errors.push(`File ${file}, function ${f.name}: unsupposed variable for cache : ${f.cache}`);
328
328
  if (f.invalidateOn) if (!utils.isValidCron(f.invalidateOn)) errors.push(`File ${file}, function ${f.name}: unsupposed variable for invalidateOn : ${f.invalidateOn}`);
329
329
  }
330
+ functions.warnings.forEach(e => {
331
+ warnings.push(`${e} In the file: ${file}.`);
332
+ });
330
333
  }
331
334
  for (const [name, files] of namesInFiles) {
332
335
  if (files.length > 1) errors.push(`Duplicate names ('${name}'): \n ${files.join('\n ')}`);
@@ -515,6 +518,7 @@ function warn(warnings) {
515
518
  }
516
519
  function getFuncMetadata(script, fileExtention) {
517
520
  const funcData = [];
521
+ const warnings = [];
518
522
  let isHeader = false;
519
523
  let data = {
520
524
  name: '',
@@ -528,6 +532,10 @@ function getFuncMetadata(script, fileExtention) {
528
532
  if (match) {
529
533
  if (!isHeader) isHeader = true;
530
534
  const param = match[1];
535
+ if (!utils.headerTags.includes(param) && !param.includes('meta.')) {
536
+ warnings.push(`Unknown header tag: ${param},`);
537
+ continue;
538
+ }
531
539
  if (param === 'name') data.name = line.match(utils.nameAnnRegex)?.[2]?.toLocaleLowerCase();else if (param === 'description') data.description = match[2];else if (param === 'input') {
532
540
  data.inputs.push({
533
541
  type: match[2],
@@ -560,5 +568,8 @@ function getFuncMetadata(script, fileExtention) {
560
568
  }
561
569
  }
562
570
  }
563
- return funcData;
571
+ return {
572
+ meta: funcData,
573
+ warnings
574
+ };
564
575
  }
@@ -106,7 +106,8 @@ Options:
106
106
  const HELP_PUBLISH = `
107
107
  Usage: grok publish [host]
108
108
 
109
- Upload a package
109
+ Uploads a package
110
+ Checks for errors before publishing — the package won't be published if there are any.
110
111
 
111
112
  Options:
112
113
  [--build|--rebuild] [--debug|--release] [-k | --key] [--suffix] [--all] [--refresh] [--link]
@@ -114,6 +115,7 @@ Options:
114
115
  --all Publish all available packages
115
116
  --refresh Publish all available already loaded packages
116
117
  --link Link the package to local utils
118
+ --skip-check Skip check stage
117
119
 
118
120
  Running \`grok publish\` is the same as running \`grok publish defaultHost --build --debug\`
119
121
  `;
@@ -124,6 +126,7 @@ Options:
124
126
  [-r | --recursive]
125
127
 
126
128
  --recursive Check all packages in the current directory
129
+ --soft Even if an error occurs, it doesn't throw an exception
127
130
 
128
131
  Check package content (function signatures, import statements of external modules, etc.)
129
132
  `;
@@ -109,7 +109,7 @@ const replacers = exports.replacers = {
109
109
  FUNC_NAME_LOWERCASE: (s, name) => s.replace(/#{FUNC_NAME_LOWERCASE}/g, friendlyNameToName(name, false)),
110
110
  PARAMS_OBJECT: (s, params) => s.replace(/#{PARAMS_OBJECT}/g, params.length ? `{ ${params.map(p => p.name).join(', ')} }` : `{}`),
111
111
  OUTPUT_TYPE: (s, type) => s.replace(/#{OUTPUT_TYPE}/g, type),
112
- TYPED_PARAMS: (s, params) => s.replace(/#{TYPED_PARAMS}/g, params.map(p => `${p.name}: ${p.type}`).join(', '))
112
+ TYPED_PARAMS: (s, params) => s.replace(/#{TYPED_PARAMS}/g, params.map(p => `${p.name}${p.isOptional ? '?' : ''}: ${p.type}`).join(', '))
113
113
  };
114
114
  class TemplateBuilder {
115
115
  static sep = '\n';
@@ -185,10 +185,10 @@ const dgToTsTypeMap = exports.dgToTsTypeMap = {
185
185
  const propertyTypes = exports.propertyTypes = ['bool', 'int', 'double', 'string', 'datetime', 'object', 'column', 'dataframe', 'bitset', 'cell', 'string_list', 'map'];
186
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
- py: new RegExp(`^\#\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
189
- ts: new RegExp(`^\/\/\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
190
- js: new RegExp(`^\/\/\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
191
- sql: new RegExp(`^--\\s*((?:${headerTags.join('|')})[^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`)
188
+ py: new RegExp(`^\#\\s*([^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
189
+ ts: new RegExp(`^\/\/\\s*([^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
190
+ js: new RegExp(`^\/\/\\s*([^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`),
191
+ sql: new RegExp(`^--\\s*([^:]*): *([^\\s\\[\\{]+) ?([^\\s\\[\\{]+)?[^\\n]*$`)
192
192
  };
193
193
  const nameAnnRegex = exports.nameAnnRegex = /\s*(name[^:]*): ([^\n\r\[\{]+)/;
194
194
  const nameRegex = exports.nameRegex = /(?:|(?:static)(?:export )(?:async ))\s+function\s+([a-zA-Z_][a-zA-Z0-9_$]*)\s*\((.*?).*/;
@@ -201,14 +201,16 @@ function getScriptOutputType(script, comment = '#') {
201
201
  }
202
202
  ;
203
203
  function getScriptInputs(script, comment = '#') {
204
- const regex = new RegExp(`${comment}\\s*input:\\s?([a-z_]+)\\s+(\\w+)`, 'g');
204
+ const regex = new RegExp(`${comment}\\s*input:\\s?([a-z_]+)\\s+(\\w+)(?:[^{\\n]*{[^}\\n]*})?`, 'g');
205
205
  const inputs = [];
206
206
  for (const match of script.matchAll(regex)) {
207
+ const isOptional = /isOptional\s*:\s*true/.test(match[0]);
207
208
  const type = dgToTsTypeMap[match[1]] || 'any';
208
209
  const name = match[2];
209
210
  inputs.push({
210
211
  type,
211
- name
212
+ name,
213
+ isOptional
212
214
  });
213
215
  }
214
216
  return inputs;
@@ -10,7 +10,7 @@
10
10
  "@datagrok-libraries/utils": "^4.5.7"
11
11
  },
12
12
  "devDependencies": {
13
- "datagrok-tools": "^4.14.10",
13
+ "datagrok-tools": "^4.14.18",
14
14
  "webpack": "^5.95.0",
15
15
  "webpack-cli": "^5.1.4"
16
16
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datagrok-tools",
3
- "version": "4.14.17",
3
+ "version": "4.14.19",
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": {