datagrok-tools 4.14.68 → 4.14.70

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.70 (2026-01-10)
4
+
5
+ ### Bug Fixes
6
+
7
+ * Grok Check: Fixed `--recursive` flag to check all packages instead of stopping after the first package
8
+ * Grok Check: Fixed process exit behavior in recursive mode to continue checking remaining packages even when errors are found
9
+
10
+
3
11
  ## 4.14.26 (2025-07-10)
4
12
 
5
13
  ### Features
package/CLAUDE.md ADDED
@@ -0,0 +1,208 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Overview
6
+
7
+ This is **datagrok-tools**, a CLI utility for creating, validating, testing, and publishing packages to Datagrok. The tool is distributed as `grok` command globally via npm.
8
+
9
+ ## Build & Development Commands
10
+
11
+ ### Build the CLI
12
+ ```bash
13
+ npm run build # Transpile TypeScript to JavaScript using Babel
14
+ npm run debug-source-map # Build with source maps for debugging
15
+ ```
16
+
17
+ The build process uses Babel with `@babel/preset-typescript` to transpile TypeScript files from `bin/` (TypeScript source) to `bin/` (JavaScript output). The source TypeScript files are transpiled in-place.
18
+
19
+ ### Link for Local Development
20
+ ```bash
21
+ npm link # Make 'grok' command available globally for testing
22
+ ```
23
+
24
+ ### Testing
25
+ While this CLI tool manages testing for Datagrok packages, it doesn't have its own test suite. To test changes:
26
+ 1. Build the tool: `npm run build`
27
+ 2. Link it: `npm link`
28
+ 3. Test commands manually: `grok create test-package`, `grok check`, etc.
29
+
30
+ ## Code Architecture
31
+
32
+ ### Command Structure (`bin/commands/`)
33
+
34
+ The CLI uses a modular command pattern. Each command is a separate module that:
35
+ - Exports a default function taking `argv` (parsed arguments)
36
+ - Returns `boolean` (true for success, false for failure)
37
+ - Is imported and mapped in `bin/grok.js`
38
+
39
+ **Available commands:**
40
+ - `config.ts` - Manage server configuration (`~/.grok/config.yaml`)
41
+ - `create.ts` - Create new packages from templates
42
+ - `add.ts` - Add entities (functions, scripts, queries, etc.) to packages
43
+ - `publish.ts` - Upload and deploy packages to Datagrok servers
44
+ - `check.ts` - Validate package structure, signatures, imports
45
+ - `test.ts` - Run Puppeteer-based tests for a single package
46
+ - `test-all.ts` - Run tests across multiple packages
47
+ - `api.ts` - Auto-generate TypeScript wrappers for scripts/queries
48
+ - `link.ts` - Link libraries for plugin development
49
+ - `migrate.ts` - Update legacy packages
50
+ - `init.ts` - Apply configuration to existing packages
51
+
52
+ ### Template System
53
+
54
+ **Package Templates** (`package-template/`)
55
+ - Supports TypeScript (default) and JavaScript packages
56
+ - Uses placeholder replacement: `#{PACKAGE_NAME}`, `#{PACKAGE_NAME_LOWERCASE}`, `#{CURRENT_DATE}`, etc.
57
+ - Includes webpack config, tsconfig, package.json, and optional IDE/ESLint configs
58
+
59
+ **Entity Templates** (`entity-template/`)
60
+ Supports 8 entity types:
61
+ - Code: `function`, `app`, `script`, `detector`, `view`, `viewer`
62
+ - Data: `connection`, `query`
63
+ - Test template with `package-test.ts`
64
+
65
+ **Script Templates** (`script-template/`)
66
+ Language-specific templates for: JavaScript, Node.js, Python, R, Julia, Octave
67
+
68
+ ### Utilities (`bin/utils/`)
69
+
70
+ **utils.ts** - Core utilities:
71
+ - Case converters: `kebabToCamelCase()`, `camelCaseToKebab()`, `spaceToCamelCase()`
72
+ - Validators: `isPackageDir()`, `isValidCron()`, `isEmpty()`
73
+ - Template placeholder replacement system
74
+ - Constants: `scriptLangExtMap`, `cacheValues`, `propertyTypes`
75
+
76
+ **test-utils.ts** - Testing infrastructure:
77
+ - Puppeteer browser automation: `getBrowserPage()`
78
+ - Authentication: `getToken()`, `getDevKey()`
79
+ - Test loading and CSV export utilities
80
+
81
+ **color-utils.ts** - Console styling: `error()`, `warn()`, `success()`, `info()`
82
+
83
+ **func-generation.ts** - Auto-generates TypeScript wrappers with type signatures
84
+
85
+ **ent-helpers.ts** - User-friendly help messages for entity types
86
+
87
+ ### Validation System (`bin/validators/`)
88
+
89
+ **check.ts** (~695 lines) performs comprehensive validation:
90
+ - Function signatures match implementation
91
+ - Imports match webpack externals (prevent bundle bloat)
92
+ - Package.json structure and fields
93
+ - CHANGELOG.md format and version matching
94
+ - Script naming conventions (alphanumeric only)
95
+ - Parameter validation (types, names, optional/nullable)
96
+ - Cache and cron schedule validation
97
+
98
+ **config-validator.ts** validates `~/.grok/config.yaml`:
99
+ - Checks for required fields (default server, servers object, URLs, keys)
100
+ - Returns structured result: `{value: boolean, message: string, warnings: string[]}`
101
+
102
+ ### Publishing Workflow
103
+
104
+ The `publish` command executes these steps:
105
+ 1. Gather files using `ignore-walk` (respects .npmignore/.gitignore/.grokignore)
106
+ 2. Run validation checks (signatures, imports, package.json, changelog)
107
+ 3. Process environment variables in `/connections/*.json` files (replace `${VAR}`)
108
+ 4. Create ZIP archive with archiver-promise
109
+ 5. Upload to server: `POST ${host}/packages/dev/${devKey}/${packageName}`
110
+
111
+ **Key flags:**
112
+ - `--debug` (default) - Package visible only to developer
113
+ - `--release` - Public package
114
+ - `--build` / `--rebuild` - Control webpack bundling
115
+ - `--skip-check` - Skip validation
116
+
117
+ ### Testing Framework
118
+
119
+ Tests use Puppeteer for headless browser automation:
120
+
121
+ **Test execution flow:**
122
+ 1. Build package (skip with `--skip-build`)
123
+ 2. Publish package (skip with `--skip-publish`)
124
+ 3. Load test list from `package-test.ts`
125
+ 4. Launch Puppeteer browser
126
+ 5. Execute tests with optional recording (`--record`) or GUI mode (`--gui`)
127
+ 6. Report results (console, CSV with `--csv`, or submit with `--report`)
128
+
129
+ **Important flags:**
130
+ - `--gui` - Visual debugging (headless=false)
131
+ - `--verbose` - Detailed test output
132
+ - `--catchUnhandled` - Catch unhandled exceptions
133
+ - `--debug` - Debug breakpoints (requires `--gui`)
134
+
135
+ ## Key Patterns and Conventions
136
+
137
+ ### Naming Conventions
138
+
139
+ **Package names:** Letters, numbers, underscores, hyphens only (`^([A-Za-z\-_\d])+$`)
140
+ **Entity names:** Start with letter, alphanumeric thereafter (`^([A-Za-z])+([A-Za-z\d])*$`)
141
+ **Developer keys:** Alphanumeric + hyphens (`^([A-Za-z\d-])+$`)
142
+
143
+ ### Versioning
144
+
145
+ Semantic versioning enforced: `X.Y.Z` or `X.Y.Z-rc` or `X.Y.Z-rc.N`
146
+
147
+ CHANGELOG.md format:
148
+ ```markdown
149
+ ## X.Y.Z (YYYY-MM-DD | WIP)
150
+ ```
151
+
152
+ Latest version in CHANGELOG must match package.json version (enforced for packages v1.0+).
153
+
154
+ ### Function Metadata Pattern
155
+
156
+ Functions use JSDoc-style metadata comments:
157
+ ```javascript
158
+ //name: functionName
159
+ //description: What it does
160
+ //input: type paramName {optional: true, nullable: true}
161
+ //output: type returnName
162
+ //meta.role: panel | viewer | app
163
+ //meta.cache: global | session | client | none
164
+ //meta.invalidateOn: 0 */5 * * * * (cron schedule)
165
+ ```
166
+
167
+ ### Environment Variable Substitution
168
+
169
+ Connection files (`/connections/*.json`) support `${VAR_NAME}` placeholders, replaced at publish time with environment variables.
170
+
171
+ ### Configuration File
172
+
173
+ Location: `~/.grok/config.yaml`
174
+
175
+ Structure:
176
+ ```yaml
177
+ default: 'public'
178
+ servers:
179
+ public:
180
+ url: 'https://public.datagrok.ai/api'
181
+ key: 'developer-key-here'
182
+ dev:
183
+ url: 'https://dev.datagrok.ai/api'
184
+ key: ''
185
+ ```
186
+
187
+ ### Webpack Externals
188
+
189
+ The CLI validates that imports match webpack externals to prevent bundling datagrok-api and other provided libraries. Common externals:
190
+ - `datagrok-api`
191
+ - `rxjs`
192
+ - `cash-dom`
193
+ - `dayjs`
194
+ - `openchemlib/full`
195
+ - `wu`
196
+
197
+ ## File References
198
+
199
+ When working with commands, key entry points are:
200
+ - `bin/grok.js` - Main CLI router
201
+ - `bin/commands/<command>.ts` - Individual command implementations
202
+ - `bin/utils/utils.ts` - Core utility functions
203
+ - `bin/validators/check.ts` - Package validation logic
204
+
205
+ When modifying templates:
206
+ - `package-template/` - Full package scaffolding
207
+ - `entity-template/` - Individual entity templates
208
+ - `script-template/` - Language-specific script templates
@@ -86,16 +86,17 @@ function add(args) {
86
86
 
87
87
  // Create the folder `scripts` if it doesn't exist yet
88
88
  if (!_fs.default.existsSync(scriptsDir)) _fs.default.mkdirSync(scriptsDir);
89
- const scriptPath = _path.default.join(scriptsDir, name + '.' + utils.scriptLangExtMap[lang]);
89
+ const scriptPath = _path.default.join(scriptsDir, `${name}.${utils.scriptLangExtMap[lang]}`);
90
90
  if (_fs.default.existsSync(scriptPath)) return color.error(`The file with the script already exists: ${scriptPath}`);
91
91
 
92
92
  // Copy the script template
93
- let templatePath = _path.default.join(templateDir, 'script-template');
94
- templatePath = _path.default.join(templatePath, lang + '.' + utils.scriptLangExtMap[lang]);
93
+ const templatePath = _path.default.join(templateDir, 'script-template', `${lang}.${utils.scriptLangExtMap[lang]}`);
95
94
  contents = _fs.default.readFileSync(templatePath, 'utf8');
96
95
  if (tag) {
97
- const ind = contents.indexOf('tags: ') + 6;
98
- contents = contents.slice(0, ind) + 'panel, ' + contents.slice(ind);
96
+ const isJs = ['javascript', 'nodejs'].includes(lang);
97
+ const comment = isJs ? '//meta.role: panel' : '#meta.role: panel';
98
+ const nameLineRe = /^(#|\/\/)\s*name:.*$/m;
99
+ if (nameLineRe.test(contents)) contents = contents.replace(nameLineRe, match => `${match}\n${comment}`);else contents = `${comment}\n${contents}`;
99
100
  }
100
101
  _fs.default.writeFileSync(scriptPath, insertName(name, contents), 'utf8');
101
102