datagrok-tools 4.1.18 → 4.2.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.
Files changed (45) hide show
  1. package/README.md +84 -84
  2. package/bin/_deprecated/migrate.js +83 -83
  3. package/bin/_deprecated/upload.js +161 -161
  4. package/bin/commands/config.js +11 -6
  5. package/bin/commands/create.js +2 -0
  6. package/bin/commands/help.js +1 -1
  7. package/bin/commands/publish.js +31 -25
  8. package/bin/grok.js +26 -26
  9. package/bin/utils/utils.js +1 -7
  10. package/config-template.yaml +11 -11
  11. package/entity-template/app.js +6 -6
  12. package/entity-template/connection.json +17 -17
  13. package/entity-template/function.js +9 -9
  14. package/entity-template/function.ts +9 -9
  15. package/entity-template/init.js +4 -4
  16. package/entity-template/panel.js +11 -11
  17. package/entity-template/panel.ts +11 -11
  18. package/entity-template/queries.sql +7 -7
  19. package/entity-template/sem-type-detector.js +11 -11
  20. package/entity-template/view-class.js +60 -60
  21. package/entity-template/view-class.ts +64 -64
  22. package/entity-template/view.js +10 -10
  23. package/entity-template/viewer-class.js +23 -23
  24. package/entity-template/viewer-class.ts +23 -23
  25. package/entity-template/viewer.js +8 -8
  26. package/package-template/.eslintrc.json +37 -35
  27. package/package-template/.vscode/launch.json +15 -15
  28. package/package-template/.vscode/tasks.json +9 -9
  29. package/package-template/README.md +2 -2
  30. package/package-template/detectors.js +9 -9
  31. package/package-template/gitignore +29 -29
  32. package/package-template/package.json +23 -22
  33. package/package-template/src/package-test.js +13 -0
  34. package/package-template/src/package-test.ts +13 -0
  35. package/package-template/src/package.js +2 -2
  36. package/package-template/ts.webpack.config.js +3 -1
  37. package/package-template/webpack.config.js +27 -26
  38. package/package.json +51 -51
  39. package/script-template/javascript.js +6 -6
  40. package/script-template/julia.jl +8 -8
  41. package/script-template/node.js +8 -8
  42. package/script-template/octave.m +8 -8
  43. package/script-template/python.py +8 -8
  44. package/script-template/r.R +8 -8
  45. package/tsconfig.json +71 -71
package/README.md CHANGED
@@ -1,84 +1,84 @@
1
- # Datagrok-tools
2
-
3
- Utility to upload and publish [packages](https://datagrok.ai/help/develop/develop#packages) to Datagrok.
4
-
5
- ## Installation
6
-
7
- ```
8
- npm install datagrok-tools -g
9
- ```
10
-
11
- ## Usage
12
-
13
- 1. Configure your environment with the following command:
14
- ```
15
- grok config
16
- ```
17
- Enter developer keys and set the default server. The developer key can be retrieved from your user profile (for example, see https://public.datagrok.ai/u).
18
- 2. Create a new package by running this command:
19
- ```
20
- grok create <package-name>
21
- ```
22
- A new folder `<package-name>` will be created automatically as well as its contents.
23
- 3. Run `npm install` in your package directory to get the required dependencies.
24
- 4. Start working on the functionality of your package. Use ` grok add` to create function templates.
25
- 5. Once you have completed the work on your package, upload it by running:
26
- ```
27
- grok publish
28
- ```
29
-
30
- Run `grok` for instructions and `grok <command> --help` to get help on a particular command.
31
-
32
- Read more about package development in [Datagrok's documentation](https://datagrok.ai/help/develop/develop).
33
-
34
- ## Commands
35
-
36
- - `config` creates or updates a configuration file.
37
- The command shows the location of the config file with the developer keys and offers to interactively change them.
38
- 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.
40
- The directory must be empty:
41
- ```
42
- grok create
43
- ```
44
- When called with an argument, the command creates a package in a folder with the specified name:
45
- ```
46
- grok create <package-name>
47
- ```
48
- Package name may only include letters, numbers, underscores, or hyphens.
49
- Read more about naming conventions [here](https://datagrok.ai/help/develop/develop#naming-conventions).
50
- Options:
51
- - `--eslint` adds a basic configuration for `eslint`
52
- - `--ide` adds an IDE-specific configuration for debugging (vscode)
53
- - `--ts` creates a TypeScript package template
54
- - `add` puts an object template to your package:
55
- ```
56
- cd <package-name>
57
- grok add app <name>
58
- grok add connection <name>
59
- grok add detector <semantic-type-name>
60
- grok add function [tag] <name>
61
- grok add query <name>
62
- grok add script [tag] <language> <name>
63
- grok add view <name>
64
- grok add viewer <name>
65
- ```
66
- In general, entity names follow naming rules for functions. Views and viewers should have class names,
67
- we recommend that you postfix them with 'View' and 'Viewer' respectively.
68
- Supported languages for scripts are `javascript`, `julia`, `node`, `octave`, `python`, `r`.
69
- Available function tags: `panel`, `init`.
70
- - `api` creates wrapper functions for package scripts and queries. The output is stored in files `/src/scripts-api.ts` and `/src/queries-api.ts` respectively.
71
- - `publish` uploads a package to the specified server (pass either a URL or a server alias from the `config.yaml` file).
72
- ```
73
- cd <package-name>
74
- grok publish [host]
75
- ```
76
- Options:
77
- - `--build` or `--rebuild`: boolean flags that indicate whether a local webpack bundle should be used
78
- or it should be generated on the server side
79
- - `--debug` or `--release`: boolean flags that determine whether to publish a debug version of the package
80
- visible only to the developer or a release version accessible by all eligible users and user groups
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
- - `--suffix`: a string containing package version hash
83
-
84
- Running `grok publish` is the same as running `grok publish defaultHost --build --debug`.
1
+ # Datagrok-tools
2
+
3
+ Utility to upload and publish [packages](https://datagrok.ai/help/develop/develop#packages) to Datagrok.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ npm install datagrok-tools -g
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ 1. Configure your environment with the following command:
14
+ ```
15
+ grok config
16
+ ```
17
+ Enter developer keys and set the default server. The developer key can be retrieved from your user profile (for example, see https://public.datagrok.ai/u).
18
+ 2. Create a new package by running this command:
19
+ ```
20
+ grok create <package-name>
21
+ ```
22
+ A new folder `<package-name>` will be created automatically as well as its contents.
23
+ 3. Run `npm install` in your package directory to get the required dependencies.
24
+ 4. Start working on the functionality of your package. Use ` grok add` to create function templates.
25
+ 5. Once you have completed the work on your package, upload it by running:
26
+ ```
27
+ grok publish
28
+ ```
29
+
30
+ Run `grok` for instructions and `grok <command> --help` to get help on a particular command.
31
+
32
+ Read more about package development in [Datagrok's documentation](https://datagrok.ai/help/develop/develop).
33
+
34
+ ## Commands
35
+
36
+ - `config` creates or updates a configuration file.
37
+ The command shows the location of the config file with the developer keys and offers to interactively change them.
38
+ 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.
40
+ The directory must be empty:
41
+ ```
42
+ grok create
43
+ ```
44
+ When called with an argument, the command creates a package in a folder with the specified name:
45
+ ```
46
+ grok create <package-name>
47
+ ```
48
+ Package name may only include letters, numbers, underscores, or hyphens.
49
+ Read more about naming conventions [here](https://datagrok.ai/help/develop/develop#naming-conventions).
50
+ Options:
51
+ - `--eslint` adds a basic configuration for `eslint`
52
+ - `--ide` adds an IDE-specific configuration for debugging (vscode)
53
+ - `--ts` creates a TypeScript package template
54
+ - `add` puts an object template to your package:
55
+ ```
56
+ cd <package-name>
57
+ grok add app <name>
58
+ grok add connection <name>
59
+ grok add detector <semantic-type-name>
60
+ grok add function [tag] <name>
61
+ grok add query <name>
62
+ grok add script [tag] <language> <name>
63
+ grok add view <name>
64
+ grok add viewer <name>
65
+ ```
66
+ In general, entity names follow naming rules for functions. Views and viewers should have class names,
67
+ we recommend that you postfix them with 'View' and 'Viewer' respectively.
68
+ Supported languages for scripts are `javascript`, `julia`, `node`, `octave`, `python`, `r`.
69
+ Available function tags: `panel`, `init`.
70
+ - `api` creates wrapper functions for package scripts and queries. The output is stored in files `/src/scripts-api.ts` and `/src/queries-api.ts` respectively.
71
+ - `publish` uploads a package to the specified server (pass either a URL or a server alias from the `config.yaml` file).
72
+ ```
73
+ cd <package-name>
74
+ grok publish [host]
75
+ ```
76
+ Options:
77
+ - `--build` or `--rebuild`: boolean flags that indicate whether a local webpack bundle should be used
78
+ or it should be generated on the server side
79
+ - `--debug` or `--release`: boolean flags that determine whether to publish a debug version of the package
80
+ visible only to the developer or a release version accessible by all eligible users and user groups
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
+ - `--suffix`: a string containing package version hash
83
+
84
+ Running `grok publish` is the same as running `grok publish defaultHost --build --debug`.
@@ -1,83 +1,83 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const os = require('os');
4
- const yaml = require('js-yaml');
5
- const utils = require('../utils/utils.js');
6
-
7
- module.exports = {
8
- migrate: migrate
9
- };
10
-
11
- const curDir = process.cwd();
12
- const keysDir = path.join(curDir, 'upload.keys.json');
13
- const packDir = path.join(curDir, 'package.json');
14
- const grokDir = path.join(os.homedir(), '.grok');
15
- const confPath = path.join(grokDir, 'config.yaml');
16
- const confTemplateDir = path.join(path.dirname(path.dirname(__dirname)), 'config-template.yaml');
17
- const confTemplate = yaml.load(fs.readFileSync(confTemplateDir));
18
-
19
- const grokMap = {
20
- 'datagrok-upload': 'grok publish',
21
- 'debug': '',
22
- 'deploy': '--release',
23
- 'build': '',
24
- 'rebuild': '--rebuild'
25
- };
26
-
27
- const replRegExp = new RegExp(Object.keys(grokMap).join("|"), "g");
28
-
29
- function migrate(args) {
30
- const nOptions = Object.keys(args).length - 1;
31
- const nArgs = args['_'].length;
32
-
33
- if (nArgs > 1 || nOptions > 0) return false;
34
-
35
- // Create `config.yaml` if it doesn't exist yet
36
- if (!fs.existsSync(grokDir)) fs.mkdirSync(grokDir);
37
- if (!fs.existsSync(confPath)) fs.writeFileSync(confPath, yaml.dump(confTemplate));
38
-
39
- let config = yaml.load(fs.readFileSync(confPath));
40
-
41
- // Copy keys to the `config.yaml` file
42
- if (fs.existsSync(keysDir)) {
43
- try {
44
- const keys = JSON.parse(fs.readFileSync(keysDir));
45
- let urls = utils.mapURL(config);
46
- for (const url in keys) {
47
- try {
48
- let hostname = (new URL(url)).hostname;
49
- if (url in urls) hostname = urls[url];
50
- config['servers'][hostname] = {};
51
- config['servers'][hostname]['url'] = url;
52
- config['servers'][hostname]['key'] = keys[url];
53
- } catch (error) {
54
- console.log(`Skipping an invalid URL in \`upload.keys.json\`: ${url}`);
55
- }
56
- }
57
- fs.writeFileSync(confPath, yaml.dump(config));
58
- console.log(`Migrated data from local \`upload.keys.json\` to ${confPath}`);
59
- fs.unlinkSync(keysDir);
60
- console.log('Successfully deleted the file');
61
- } catch (error) {
62
- console.error(error);
63
- }
64
- } else {
65
- console.log('Unable to locate `upload.keys.json`');
66
- }
67
-
68
- // Rewrite scripts in `package.json`
69
- if (!fs.existsSync(packDir)) return console.log('`package.json` doesn\'t exist');
70
- try {
71
- let _package = JSON.parse(fs.readFileSync(packDir));
72
- for (let script in _package.scripts) {
73
- if (!_package['scripts'][script].includes('datagrok-upload')) continue;
74
- _package['scripts'][script] = _package['scripts'][script].replace(replRegExp, (match) => grokMap[match]);
75
- }
76
- fs.writeFileSync(packDir, JSON.stringify(_package, null, '\t'));
77
- console.log('Converting scripts in `package.json`... Done!');
78
- } catch (error) {
79
- console.error(error);
80
- }
81
-
82
- return true;
83
- }
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+ const yaml = require('js-yaml');
5
+ const utils = require('../utils/utils.js');
6
+
7
+ module.exports = {
8
+ migrate: migrate
9
+ };
10
+
11
+ const curDir = process.cwd();
12
+ const keysDir = path.join(curDir, 'upload.keys.json');
13
+ const packDir = path.join(curDir, 'package.json');
14
+ const grokDir = path.join(os.homedir(), '.grok');
15
+ const confPath = path.join(grokDir, 'config.yaml');
16
+ const confTemplateDir = path.join(path.dirname(path.dirname(__dirname)), 'config-template.yaml');
17
+ const confTemplate = yaml.load(fs.readFileSync(confTemplateDir));
18
+
19
+ const grokMap = {
20
+ 'datagrok-upload': 'grok publish',
21
+ 'debug': '',
22
+ 'deploy': '--release',
23
+ 'build': '',
24
+ 'rebuild': '--rebuild'
25
+ };
26
+
27
+ const replRegExp = new RegExp(Object.keys(grokMap).join("|"), "g");
28
+
29
+ function migrate(args) {
30
+ const nOptions = Object.keys(args).length - 1;
31
+ const nArgs = args['_'].length;
32
+
33
+ if (nArgs > 1 || nOptions > 0) return false;
34
+
35
+ // Create `config.yaml` if it doesn't exist yet
36
+ if (!fs.existsSync(grokDir)) fs.mkdirSync(grokDir);
37
+ if (!fs.existsSync(confPath)) fs.writeFileSync(confPath, yaml.dump(confTemplate));
38
+
39
+ let config = yaml.load(fs.readFileSync(confPath));
40
+
41
+ // Copy keys to the `config.yaml` file
42
+ if (fs.existsSync(keysDir)) {
43
+ try {
44
+ const keys = JSON.parse(fs.readFileSync(keysDir));
45
+ let urls = utils.mapURL(config);
46
+ for (const url in keys) {
47
+ try {
48
+ let hostname = (new URL(url)).hostname;
49
+ if (url in urls) hostname = urls[url];
50
+ config['servers'][hostname] = {};
51
+ config['servers'][hostname]['url'] = url;
52
+ config['servers'][hostname]['key'] = keys[url];
53
+ } catch (error) {
54
+ console.log(`Skipping an invalid URL in \`upload.keys.json\`: ${url}`);
55
+ }
56
+ }
57
+ fs.writeFileSync(confPath, yaml.dump(config));
58
+ console.log(`Migrated data from local \`upload.keys.json\` to ${confPath}`);
59
+ fs.unlinkSync(keysDir);
60
+ console.log('Successfully deleted the file');
61
+ } catch (error) {
62
+ console.error(error);
63
+ }
64
+ } else {
65
+ console.log('Unable to locate `upload.keys.json`');
66
+ }
67
+
68
+ // Rewrite scripts in `package.json`
69
+ if (!fs.existsSync(packDir)) return console.log('`package.json` doesn\'t exist');
70
+ try {
71
+ let _package = JSON.parse(fs.readFileSync(packDir));
72
+ for (let script in _package.scripts) {
73
+ if (!_package['scripts'][script].includes('datagrok-upload')) continue;
74
+ _package['scripts'][script] = _package['scripts'][script].replace(replRegExp, (match) => grokMap[match]);
75
+ }
76
+ fs.writeFileSync(packDir, JSON.stringify(_package, null, '\t'));
77
+ console.log('Converting scripts in `package.json`... Done!');
78
+ } catch (error) {
79
+ console.error(error);
80
+ }
81
+
82
+ return true;
83
+ }
@@ -1,162 +1,162 @@
1
- #!/usr/bin/env node
2
- const argv = require('minimist')(process.argv.slice(2));
3
- const getFiles = require('node-recursive-directory');
4
- const fs = require('fs');
5
- const fetch = require('node-fetch');
6
- const path = require('path');
7
- const archiver = require('archiver-promise');
8
- const walk = require('ignore-walk')
9
-
10
- // The script is no longer supported
11
- console.log(`\`datagrok-upload\` is not available, please use \`grok publish\` instead.
12
- Run \`grok migrate\` to convert your scripts in \`package.json\` and to copy your keys to \`config.yaml\``);
13
- console.log(`Exiting with code 1`);
14
- process.exit(1);
15
-
16
- process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
17
-
18
- let mode = argv['_'][1];
19
- let host = argv['_'][0];
20
- let rebuild = argv['_'].includes('rebuild');
21
-
22
- if (mode !== 'debug' && mode !== 'deploy')
23
- return console.log('Mode must be either debug or deploy');
24
-
25
- let debug = mode === 'debug';
26
-
27
- let keys = {
28
- [host]: ''
29
- };
30
-
31
- //get key from keys file
32
- if (fs.existsSync('upload.keys.json')) {
33
- keys = JSON.parse(fs.readFileSync('upload.keys.json'));
34
- } else {
35
- fs.writeFileSync('upload.keys.json', JSON.stringify(keys));
36
- }
37
- let devKey = keys[host];
38
- if (devKey === undefined) {
39
- devKey = '';
40
- keys[host] = devKey;
41
- fs.writeFileSync('upload.keys.json', JSON.stringify(keys));
42
- }
43
-
44
- if (devKey === '')
45
- return console.log('Empty developer key. See upload.keys.json file.');
46
-
47
-
48
- //check if package.json exists, get package name
49
- let packageName = '';
50
- if (!fs.existsSync('package.json'))
51
- return console.log('package.js doesn\'t exists');
52
- else {
53
- let packageJson = JSON.parse(fs.readFileSync('package.json'));
54
- packageName = packageJson['name'];
55
- }
56
-
57
- process.on('beforeExit', async () => {
58
- let code = 0;
59
- try {
60
- code = await processPackage()
61
-
62
- } catch (err) {
63
- console.log(err);
64
- code = 1;
65
- }
66
- console.log(`Exiting with code ${code}`);
67
- process.exit(code);
68
- });
69
-
70
- async function processPackage() {
71
- //get server timestamps
72
- let timestamps = {};
73
- if (debug) {
74
- try {
75
- timestamps = await (await fetch(`${host}/packages/dev/${devKey}/${packageName}/timestamps`)).json();
76
- if (timestamps['#type'] === 'ApiError') {
77
- console.log(timestamps.message);
78
- return 1;
79
- }
80
- } catch (error) {
81
- console.log(error);
82
- return 1;
83
- }
84
- }
85
-
86
- let zip = archiver('zip', {store: false});
87
-
88
- //gather files
89
- let localTimestamps = {};
90
- let files = await walk({
91
- path: '.',
92
- ignoreFiles: ['.npmignore', '.gitignore'],
93
- includeEmpty: true,
94
- follow: true
95
- });
96
-
97
- if (!rebuild) {
98
- const distFiles = await walk({
99
- path: './dist',
100
- ignoreFiles: [],
101
- includeEmpty: true,
102
- follow: true
103
- });
104
- distFiles.forEach((df) => {
105
- files.push(`dist/${df}`);
106
- })
107
- }
108
- files.forEach((file) => {
109
- let fullPath = file;
110
- let relativePath = path.relative(process.cwd(), fullPath);
111
- let canonicalRelativePath = relativePath.replace(/\\/g, '/');
112
- if (canonicalRelativePath.includes('/.'))
113
- return;
114
- if (canonicalRelativePath.startsWith('.'))
115
- return;
116
- if (relativePath.startsWith('node_modules'))
117
- return;
118
- if (relativePath.startsWith('dist') && rebuild)
119
- return;
120
- if (relativePath.startsWith('upload.keys.json'))
121
- return;
122
- if (relativePath === 'zip')
123
- return;
124
- let t = fs.statSync(fullPath).mtime.toUTCString();
125
- localTimestamps[canonicalRelativePath] = t;
126
- if (debug && timestamps[canonicalRelativePath] === t) {
127
- console.log(`Skipping ${canonicalRelativePath}`);
128
- return;
129
- }
130
- zip.append(fs.createReadStream(fullPath), {name: relativePath});
131
- console.log(`Adding ${relativePath}...`);
132
- });
133
- zip.append(JSON.stringify(localTimestamps), {name: 'timestamps.json'});
134
-
135
- //upload
136
- let uploadPromise = new Promise((resolve, reject) => {
137
- fetch(`${host}/packages/dev/${devKey}/${packageName}?debug=${debug.toString()}&rebuild=${rebuild.toString()}`, {
138
- method: 'POST',
139
- body: zip
140
- }).then(body => body.json()).then(j => resolve(j)).catch(err => {
141
- reject(err);
142
- });
143
- }
144
- )
145
- await zip.finalize();
146
-
147
- try {
148
- let log = await uploadPromise;
149
-
150
- fs.unlinkSync('zip');
151
- if (log['#type'] === 'ApiError') {
152
- console.log(log['message']);
153
- console.log(log['innerMessage']);
154
- return 1;
155
- } else
156
- console.log(log);
157
- } catch (error) {
158
- console.log(error);
159
- return 1;
160
- }
161
- return 0;
1
+ #!/usr/bin/env node
2
+ const argv = require('minimist')(process.argv.slice(2));
3
+ const getFiles = require('node-recursive-directory');
4
+ const fs = require('fs');
5
+ const fetch = require('node-fetch');
6
+ const path = require('path');
7
+ const archiver = require('archiver-promise');
8
+ const walk = require('ignore-walk')
9
+
10
+ // The script is no longer supported
11
+ console.log(`\`datagrok-upload\` is not available, please use \`grok publish\` instead.
12
+ Run \`grok migrate\` to convert your scripts in \`package.json\` and to copy your keys to \`config.yaml\``);
13
+ console.log(`Exiting with code 1`);
14
+ process.exit(1);
15
+
16
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
17
+
18
+ let mode = argv['_'][1];
19
+ let host = argv['_'][0];
20
+ let rebuild = argv['_'].includes('rebuild');
21
+
22
+ if (mode !== 'debug' && mode !== 'deploy')
23
+ return console.log('Mode must be either debug or deploy');
24
+
25
+ let debug = mode === 'debug';
26
+
27
+ let keys = {
28
+ [host]: ''
29
+ };
30
+
31
+ //get key from keys file
32
+ if (fs.existsSync('upload.keys.json')) {
33
+ keys = JSON.parse(fs.readFileSync('upload.keys.json'));
34
+ } else {
35
+ fs.writeFileSync('upload.keys.json', JSON.stringify(keys));
36
+ }
37
+ let devKey = keys[host];
38
+ if (devKey === undefined) {
39
+ devKey = '';
40
+ keys[host] = devKey;
41
+ fs.writeFileSync('upload.keys.json', JSON.stringify(keys));
42
+ }
43
+
44
+ if (devKey === '')
45
+ return console.log('Empty developer key. See upload.keys.json file.');
46
+
47
+
48
+ //check if package.json exists, get package name
49
+ let packageName = '';
50
+ if (!fs.existsSync('package.json'))
51
+ return console.log('package.js doesn\'t exists');
52
+ else {
53
+ let packageJson = JSON.parse(fs.readFileSync('package.json'));
54
+ packageName = packageJson['name'];
55
+ }
56
+
57
+ process.on('beforeExit', async () => {
58
+ let code = 0;
59
+ try {
60
+ code = await processPackage()
61
+
62
+ } catch (err) {
63
+ console.log(err);
64
+ code = 1;
65
+ }
66
+ console.log(`Exiting with code ${code}`);
67
+ process.exit(code);
68
+ });
69
+
70
+ async function processPackage() {
71
+ //get server timestamps
72
+ let timestamps = {};
73
+ if (debug) {
74
+ try {
75
+ timestamps = await (await fetch(`${host}/packages/dev/${devKey}/${packageName}/timestamps`)).json();
76
+ if (timestamps['#type'] === 'ApiError') {
77
+ console.log(timestamps.message);
78
+ return 1;
79
+ }
80
+ } catch (error) {
81
+ console.log(error);
82
+ return 1;
83
+ }
84
+ }
85
+
86
+ let zip = archiver('zip', {store: false});
87
+
88
+ //gather files
89
+ let localTimestamps = {};
90
+ let files = await walk({
91
+ path: '.',
92
+ ignoreFiles: ['.npmignore', '.gitignore'],
93
+ includeEmpty: true,
94
+ follow: true
95
+ });
96
+
97
+ if (!rebuild) {
98
+ const distFiles = await walk({
99
+ path: './dist',
100
+ ignoreFiles: [],
101
+ includeEmpty: true,
102
+ follow: true
103
+ });
104
+ distFiles.forEach((df) => {
105
+ files.push(`dist/${df}`);
106
+ })
107
+ }
108
+ files.forEach((file) => {
109
+ let fullPath = file;
110
+ let relativePath = path.relative(process.cwd(), fullPath);
111
+ let canonicalRelativePath = relativePath.replace(/\\/g, '/');
112
+ if (canonicalRelativePath.includes('/.'))
113
+ return;
114
+ if (canonicalRelativePath.startsWith('.'))
115
+ return;
116
+ if (relativePath.startsWith('node_modules'))
117
+ return;
118
+ if (relativePath.startsWith('dist') && rebuild)
119
+ return;
120
+ if (relativePath.startsWith('upload.keys.json'))
121
+ return;
122
+ if (relativePath === 'zip')
123
+ return;
124
+ let t = fs.statSync(fullPath).mtime.toUTCString();
125
+ localTimestamps[canonicalRelativePath] = t;
126
+ if (debug && timestamps[canonicalRelativePath] === t) {
127
+ console.log(`Skipping ${canonicalRelativePath}`);
128
+ return;
129
+ }
130
+ zip.append(fs.createReadStream(fullPath), {name: relativePath});
131
+ console.log(`Adding ${relativePath}...`);
132
+ });
133
+ zip.append(JSON.stringify(localTimestamps), {name: 'timestamps.json'});
134
+
135
+ //upload
136
+ let uploadPromise = new Promise((resolve, reject) => {
137
+ fetch(`${host}/packages/dev/${devKey}/${packageName}?debug=${debug.toString()}&rebuild=${rebuild.toString()}`, {
138
+ method: 'POST',
139
+ body: zip
140
+ }).then(body => body.json()).then(j => resolve(j)).catch(err => {
141
+ reject(err);
142
+ });
143
+ }
144
+ )
145
+ await zip.finalize();
146
+
147
+ try {
148
+ let log = await uploadPromise;
149
+
150
+ fs.unlinkSync('zip');
151
+ if (log['#type'] === 'ApiError') {
152
+ console.log(log['message']);
153
+ console.log(log['innerMessage']);
154
+ return 1;
155
+ } else
156
+ console.log(log);
157
+ } catch (error) {
158
+ console.log(error);
159
+ return 1;
160
+ }
161
+ return 0;
162
162
  }