datagrok-tools 4.2.1 → 4.4.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 +21 -21
- package/bin/commands/create.js +21 -3
- package/bin/commands/help.js +1 -1
- package/bin/commands/publish.js +1 -1
- package/package-template/jest.config.js +33 -0
- package/package-template/npmignore +26 -0
- package/package-template/package.json +2 -1
- package/package-template/src/__jest__/remote.test.ts +49 -0
- package/package-template/src/__jest__/test-node.ts +96 -0
- package/package-template/src/package-test.js +0 -1
- package/package-template/src/package-test.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,16 +10,17 @@ npm install datagrok-tools -g
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
1. Configure your environment with the following command:
|
|
13
|
+
1. Configure your environment with the following command:
|
|
14
14
|
```
|
|
15
15
|
grok config
|
|
16
16
|
```
|
|
17
|
-
|
|
17
|
+
Enter developer keys and set the default server. The developer key can be retrieved from your user profile (for
|
|
18
|
+
example, see https://public.datagrok.ai/u).
|
|
18
19
|
2. Create a new package by running this command:
|
|
19
20
|
```
|
|
20
21
|
grok create <package-name>
|
|
21
22
|
```
|
|
22
|
-
|
|
23
|
+
A new folder `<package-name>` will be created automatically as well as its contents.
|
|
23
24
|
3. Run `npm install` in your package directory to get the required dependencies.
|
|
24
25
|
4. Start working on the functionality of your package. Use ` grok add` to create function templates.
|
|
25
26
|
5. Once you have completed the work on your package, upload it by running:
|
|
@@ -33,11 +34,10 @@ Read more about package development in [Datagrok's documentation](https://datagr
|
|
|
33
34
|
|
|
34
35
|
## Commands
|
|
35
36
|
|
|
36
|
-
- `config` creates or updates a configuration file.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
The directory must be empty:
|
|
37
|
+
- `config` creates or updates a configuration file. The command shows the location of the config file with the developer
|
|
38
|
+
keys and offers to interactively change them. It is also possible to reset the current configuration.
|
|
39
|
+
- `create` adds a package template to the current working directory when used without the `name` argument. The directory
|
|
40
|
+
must be empty:
|
|
41
41
|
```
|
|
42
42
|
grok create
|
|
43
43
|
```
|
|
@@ -45,12 +45,12 @@ Read more about package development in [Datagrok's documentation](https://datagr
|
|
|
45
45
|
```
|
|
46
46
|
grok create <package-name>
|
|
47
47
|
```
|
|
48
|
-
Package name may only include letters, numbers, underscores, or hyphens.
|
|
49
|
-
|
|
50
|
-
Options:
|
|
48
|
+
Package name may only include letters, numbers, underscores, or hyphens. Read more about naming
|
|
49
|
+
conventions [here](https://datagrok.ai/help/develop/develop#naming-conventions). Options:
|
|
51
50
|
- `--eslint` adds a basic configuration for `eslint`
|
|
52
51
|
- `--ide` adds an IDE-specific configuration for debugging (vscode)
|
|
53
52
|
- `--ts` creates a TypeScript package template
|
|
53
|
+
- `--jest` adds a basic configuration for `jest`
|
|
54
54
|
- `add` puts an object template to your package:
|
|
55
55
|
```
|
|
56
56
|
cd <package-name>
|
|
@@ -63,22 +63,22 @@ Read more about package development in [Datagrok's documentation](https://datagr
|
|
|
63
63
|
grok add view <name>
|
|
64
64
|
grok add viewer <name>
|
|
65
65
|
```
|
|
66
|
-
In general, entity names follow naming rules for functions. Views and viewers should have class names,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
In general, entity names follow naming rules for functions. Views and viewers should have class names, we recommend
|
|
67
|
+
that you postfix them with 'View' and 'Viewer' respectively. Supported languages for scripts are `javascript`, `julia`
|
|
68
|
+
, `node`, `octave`, `python`, `r`. Available function tags: `panel`, `init`.
|
|
69
|
+
- `api` creates wrapper functions for package scripts and queries. The output is stored in files `/src/scripts-api.ts`
|
|
70
|
+
and `/src/queries-api.ts` respectively.
|
|
71
71
|
- `publish` uploads a package to the specified server (pass either a URL or a server alias from the `config.yaml` file).
|
|
72
72
|
```
|
|
73
73
|
cd <package-name>
|
|
74
74
|
grok publish [host]
|
|
75
75
|
```
|
|
76
76
|
Options:
|
|
77
|
-
- `--build` or `--rebuild`: boolean flags that indicate whether a local webpack bundle should be used
|
|
78
|
-
|
|
79
|
-
- `--debug` or `--release`: boolean flags that determine whether to publish a debug version of the package
|
|
80
|
-
|
|
77
|
+
- `--build` or `--rebuild`: boolean flags that indicate whether a local webpack bundle should be used or it should
|
|
78
|
+
be generated on the server side
|
|
79
|
+
- `--debug` or `--release`: boolean flags that determine whether to publish a debug version of the package visible
|
|
80
|
+
only to the developer or a release version accessible by all eligible users and user groups
|
|
81
81
|
- `--key`: a string containing a developer key that is not listed in the config file, e.g., the key for a new server
|
|
82
82
|
- `--suffix`: a string containing package version hash
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
Running `grok publish` is the same as running `grok publish defaultHost --build --debug`.
|
package/bin/commands/create.js
CHANGED
|
@@ -55,6 +55,7 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
|
|
|
55
55
|
var ide = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
|
|
56
56
|
var ts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
57
57
|
var eslint = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
|
|
58
|
+
var jest = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
|
|
58
59
|
|
|
59
60
|
var filesToCreate = _fs["default"].readdirSync(templateDir);
|
|
60
61
|
|
|
@@ -108,6 +109,20 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
|
|
|
108
109
|
'lint': "eslint src".concat(ts ? ' --ext .ts' : ''),
|
|
109
110
|
'lint-fix': "eslint src".concat(ts ? ' --ext .ts' : '', " --fix")
|
|
110
111
|
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (jest) {
|
|
115
|
+
Object.assign(_package.devDependencies, {
|
|
116
|
+
'jest': 'latest',
|
|
117
|
+
'jest-html-reporter': 'latest',
|
|
118
|
+
'@types/jest': 'latest',
|
|
119
|
+
'puppeteer': 'latest'
|
|
120
|
+
}, ts ? {
|
|
121
|
+
'ts-jest': 'latest'
|
|
122
|
+
} : {});
|
|
123
|
+
Object.assign(_package.scripts, {
|
|
124
|
+
'test': 'jest'
|
|
125
|
+
});
|
|
111
126
|
} // Save module names for installation prompt
|
|
112
127
|
|
|
113
128
|
|
|
@@ -127,6 +142,9 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
|
|
|
127
142
|
if (file === 'package-test.ts' && !ts) return false;
|
|
128
143
|
if (file === 'tsconfig.json' && !ts) return false;
|
|
129
144
|
if (file === 'ts.webpack.config.js') return false;
|
|
145
|
+
if (file === 'remote.test.ts' && (!ts || !jest)) return false;
|
|
146
|
+
if (file === 'test-node.ts' && (!ts || !jest)) return false;
|
|
147
|
+
if (file === 'jest.config.js' && !jest) return false;
|
|
130
148
|
|
|
131
149
|
if (file === '.eslintrc.json') {
|
|
132
150
|
if (!eslint) return false;
|
|
@@ -151,7 +169,7 @@ function createDirectoryContents(name, config, templateDir, packageDir) {
|
|
|
151
169
|
_fs["default"].mkdirSync(copyFilePath); // recursive call
|
|
152
170
|
|
|
153
171
|
|
|
154
|
-
createDirectoryContents(name, config, origFilePath, copyFilePath, ide, ts);
|
|
172
|
+
createDirectoryContents(name, config, origFilePath, copyFilePath, ide, ts, eslint, jest);
|
|
155
173
|
}
|
|
156
174
|
});
|
|
157
175
|
}
|
|
@@ -161,7 +179,7 @@ function create(args) {
|
|
|
161
179
|
var nArgs = args['_'].length;
|
|
162
180
|
if (nArgs > 2 || nOptions > 3) return false;
|
|
163
181
|
if (nOptions && !Object.keys(args).slice(1).every(function (op) {
|
|
164
|
-
return ['ide', 'ts', 'eslint'].includes(op);
|
|
182
|
+
return ['ide', 'ts', 'eslint', 'jest'].includes(op);
|
|
165
183
|
})) return false; // Create `config.yaml` if it doesn't exist yet
|
|
166
184
|
|
|
167
185
|
if (!_fs["default"].existsSync(grokDir)) _fs["default"].mkdirSync(grokDir);
|
|
@@ -198,7 +216,7 @@ function create(args) {
|
|
|
198
216
|
return false;
|
|
199
217
|
}
|
|
200
218
|
|
|
201
|
-
createDirectoryContents(name, config, templateDir, packageDir, args.ide, args.ts, args.eslint);
|
|
219
|
+
createDirectoryContents(name, config, templateDir, packageDir, args.ide, args.ts, args.eslint, args.jest);
|
|
202
220
|
console.log(_entHelpers.help["package"](name, args.ts));
|
|
203
221
|
console.log("\nThe package has the following dependencies:\n".concat(dependencies.join(' '), "\n"));
|
|
204
222
|
console.log('Running `npm install` to get the required dependencies...\n');
|
package/bin/commands/help.js
CHANGED
|
@@ -8,7 +8,7 @@ var HELP = "\nUsage: grok <command>\n\nDatagrok's package management tool\n\nCom
|
|
|
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>\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
9
|
var HELP_API = "\nUsage: grok api\n\nCreate wrapper functions for package scripts and queries\n";
|
|
10
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] [--ts]\n\n--eslint Add a configuration for eslint\n--ide Add an IDE-specific configuration for debugging (vscode)\n--ts Create a TypeScript package\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] [--ts] [--jest]\n\n--eslint Add a configuration for eslint\n--ide Add an IDE-specific configuration for debugging (vscode)\n--ts Create a TypeScript package\n--jest Add a configuration for jest\n";
|
|
12
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
13
|
var HELP_MIGRATE = "\nUsage: grok migrate\n\nSwitch to `grok` tools by copying your keys to the config\nfile and converting your scripts in the `package.json` file\n";
|
|
14
14
|
var help = {
|
package/bin/commands/publish.js
CHANGED
|
@@ -163,7 +163,7 @@ function _processPackage() {
|
|
|
163
163
|
if (relativePath.startsWith('dist') && rebuild) return;
|
|
164
164
|
|
|
165
165
|
if (relativePath.startsWith('src') && !rebuild && isWebpack) {
|
|
166
|
-
if (!relativePath.startsWith('src/package')) return;
|
|
166
|
+
if (!relativePath.startsWith('src/package') && !relativePath.startsWith('src\\package')) return;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
if (relativePath.startsWith('upload.keys.json')) return;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
"roots": [
|
|
3
|
+
"<rootDir>/src"
|
|
4
|
+
],
|
|
5
|
+
"testMatch": [
|
|
6
|
+
"**/__jest__/**/*.test.+(ts|tsx)"
|
|
7
|
+
],
|
|
8
|
+
moduleFileExtensions: [
|
|
9
|
+
'ts',
|
|
10
|
+
'js',
|
|
11
|
+
],
|
|
12
|
+
"transform": {
|
|
13
|
+
"^.+\\.(ts|tsx)$": "ts-jest"
|
|
14
|
+
},
|
|
15
|
+
transformIgnorePatterns: ['^.+\\.js$'],
|
|
16
|
+
globals: {
|
|
17
|
+
'ts-jest': {
|
|
18
|
+
'tsconfig': {
|
|
19
|
+
"target": "es6",
|
|
20
|
+
"module": "es2020",
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
reporters: [
|
|
25
|
+
"default",
|
|
26
|
+
[
|
|
27
|
+
"./node_modules/jest-html-reporter",
|
|
28
|
+
{
|
|
29
|
+
"includeConsoleLog": true
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
]
|
|
33
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Developer keys
|
|
2
|
+
upload.keys.json
|
|
3
|
+
|
|
4
|
+
# Dependency directories
|
|
5
|
+
node_modules/
|
|
6
|
+
|
|
7
|
+
# IDEs
|
|
8
|
+
# VS Code (https://github.com/github/gitignore/blob/master/Global/VisualStudioCode.gitignore)
|
|
9
|
+
.vscode/*
|
|
10
|
+
!.vscode/settings.json
|
|
11
|
+
!.vscode/tasks.json
|
|
12
|
+
!.vscode/launch.json
|
|
13
|
+
!.vscode/extensions.json
|
|
14
|
+
*.code-workspace
|
|
15
|
+
.history/
|
|
16
|
+
|
|
17
|
+
# Intellij IDEA/WebStorm (https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore)
|
|
18
|
+
.idea/inspectionProfiles/
|
|
19
|
+
.idea/**/compiler.xml
|
|
20
|
+
.idea/**/encodings.xml
|
|
21
|
+
.idea/**/workspace.xml
|
|
22
|
+
.idea/**/tasks.xml
|
|
23
|
+
.idea/**/usage.statistics.xml
|
|
24
|
+
.idea/**/dictionaries
|
|
25
|
+
.idea/**/shelf
|
|
26
|
+
.idea/codeStyles/
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as utils from './test-node';
|
|
6
|
+
import puppeteer from 'puppeteer';
|
|
7
|
+
|
|
8
|
+
const P_START_TIMEOUT: number = 100000;
|
|
9
|
+
let browser: puppeteer.Browser;
|
|
10
|
+
let page: puppeteer.Page;
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
let out = await utils.getBrowserPage(puppeteer);
|
|
14
|
+
browser = out.browser;
|
|
15
|
+
page = out.page;
|
|
16
|
+
}, P_START_TIMEOUT);
|
|
17
|
+
|
|
18
|
+
afterAll(async () => {
|
|
19
|
+
await browser.close();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('TEST', async () => {
|
|
23
|
+
const target_package:string = process.env.TARGET_PACKAGE;
|
|
24
|
+
console.log(`Testing ${target_package} package`);
|
|
25
|
+
|
|
26
|
+
//console.log(require('root-require')('package.json').version);
|
|
27
|
+
let r = await page.evaluate((target_package):Promise<object> => {
|
|
28
|
+
return new Promise<object>((resolve, reject) => {
|
|
29
|
+
(<any>window).grok.functions.eval(target_package + ':test()').then((df: any) => {
|
|
30
|
+
let cStatus = df.columns.byName('success');
|
|
31
|
+
let cMessage = df.columns.byName('result');
|
|
32
|
+
let cCat = df.columns.byName('category');
|
|
33
|
+
let cName = df.columns.byName('name');
|
|
34
|
+
let failed = false;
|
|
35
|
+
let report = '';
|
|
36
|
+
for (let i = 0; i < df.rowCount; i++)
|
|
37
|
+
if (!cStatus.get(i)) {
|
|
38
|
+
report += `${cCat.get(i)}.${cName.get(i)}: ${cMessage.get(i)}\n`;
|
|
39
|
+
failed = true;
|
|
40
|
+
}
|
|
41
|
+
resolve({report, failed});
|
|
42
|
+
}).catch((e: any) => reject(e));
|
|
43
|
+
});
|
|
44
|
+
}, target_package);
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
console.log(r.report);
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
expect(r.failed).toBe(false);
|
|
49
|
+
}, 100000);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import * as yaml from 'js-yaml';
|
|
6
|
+
const fetch = require('node-fetch');
|
|
7
|
+
|
|
8
|
+
export async function getToken(url: string, key: string) {
|
|
9
|
+
let response = await fetch(`${url}/users/login/dev/${key}`, {method: 'POST'});
|
|
10
|
+
let json = await response.json();
|
|
11
|
+
if (json.isSuccess == true)
|
|
12
|
+
return json.token;
|
|
13
|
+
else
|
|
14
|
+
throw 'Unable to login to server. Check your dev key';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function getWebUrl(url: string, token: string) {
|
|
18
|
+
let response = await fetch(`${url}/admin/plugins/admin/settings`, {headers: {Authorization: token}});
|
|
19
|
+
let json = await response.json();
|
|
20
|
+
return json.settings.webRoot;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const grokDir = path.join(os.homedir(), '.grok');
|
|
24
|
+
const confPath = path.join(grokDir, 'config.yaml');
|
|
25
|
+
|
|
26
|
+
function mapURL(conf: Config): Indexable {
|
|
27
|
+
let urls: Indexable = {};
|
|
28
|
+
for (let server in conf.servers) {
|
|
29
|
+
urls[conf['servers'][server]['url']] = conf['servers'][server];
|
|
30
|
+
}
|
|
31
|
+
return urls;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getDevKey(hostKey: string): {url: string, key: string} {
|
|
35
|
+
let config = yaml.load(fs.readFileSync(confPath, 'utf8')) as any;
|
|
36
|
+
let host = hostKey == '' ? config.default : hostKey;
|
|
37
|
+
host = host.trim();
|
|
38
|
+
let urls = mapURL(config);
|
|
39
|
+
let key = '';
|
|
40
|
+
let url = '';
|
|
41
|
+
try {
|
|
42
|
+
let url = new URL(host).href;
|
|
43
|
+
if (url.endsWith('/')) url = url.slice(0, -1);
|
|
44
|
+
if (url in urls) key = config['servers'][urls[url]]['key'];
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (config['servers'][host] == null)
|
|
47
|
+
throw `Unknown server alias. Please add it to ${confPath}`;
|
|
48
|
+
url = config['servers'][host]['url'];
|
|
49
|
+
key = config['servers'][host]['key'];
|
|
50
|
+
}
|
|
51
|
+
return {url, key};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function getBrowserPage(puppeteer: any): Promise<{browser: any, page: any}> {
|
|
55
|
+
let url:string = process.env.HOST ?? '';
|
|
56
|
+
let cfg = getDevKey(url);
|
|
57
|
+
url = cfg.url;
|
|
58
|
+
|
|
59
|
+
let key = cfg.key;
|
|
60
|
+
let token = await getToken(url, key);
|
|
61
|
+
url = await getWebUrl(url, token);
|
|
62
|
+
console.log(`Using web root: ${url}`);
|
|
63
|
+
|
|
64
|
+
let browser = await puppeteer.launch({
|
|
65
|
+
args: ['--disable-dev-shm-usage', '--disable-features=site-per-process'],
|
|
66
|
+
ignoreHTTPSErrors: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
let page = await browser.newPage();
|
|
70
|
+
await page.goto(`${url}/oauth/`);
|
|
71
|
+
await page.setCookie({name: 'auth', value: token});
|
|
72
|
+
await page.evaluate((token: any) => {
|
|
73
|
+
window.localStorage.setItem('auth', token);
|
|
74
|
+
}, token);
|
|
75
|
+
await page.goto(url);
|
|
76
|
+
try {
|
|
77
|
+
await page.waitForSelector('.grok-preloader');
|
|
78
|
+
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 100000});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
return {browser, page};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
interface Config {
|
|
87
|
+
servers: {
|
|
88
|
+
[alias: string]: {
|
|
89
|
+
url: string,
|
|
90
|
+
key: string
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
default: string,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface Indexable { [key: string]: any }
|
package/package.json
CHANGED