datagrok-tools 6.7.6 → 6.7.7

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > datagrok-tools@6.7.6 build /home/runner/work/public/public/tools
2
+ > datagrok-tools@6.7.7 build /home/runner/work/public/public/tools
3
3
  > node build.js
4
4
 
5
5
  Successfully compiled 51 files with Babel.
package/CHANGELOG.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Datagrok-tools changelog
2
2
 
3
- ## v.next
3
+ ## 6.7.7 (2026-10-09)
4
4
 
5
+ * GROK-21156: `grok s users invite [<email>] [--prefix <P>] [--send-email]`: invites a user and prints a link that logs them in (no email sent; the email may be omitted); `--prefix` starts the code with `<P>`; `--send-email` mails the invitation instead
5
6
  * `grok test --skip-gc` launches the browser without `--expose-gc`, so the test runner skips its garbage collection after every test; a suite of small unit tests runs several times faster (ComputeUtils driver tests: 92 s to 19 s)
6
7
  * `grok setup` installs corepack when it is missing instead of asking for it by hand: Node 25 no longer bundles corepack, so every fresh checkout on current Node stopped at that step
7
8
  * `grok setup` also removes the `.js`/`.d.ts` files the npm-era tsc emitted beside js-api and library sources: the workspace emits into `dist/`, and a leftover `js-api/grok.js` shadowed the `grok` command in cmd.exe
package/GROK_S.md CHANGED
@@ -16,6 +16,7 @@ browser or a logged-in session.
16
16
  |-------------------------------------------------------------|--------------------------------------------------------|
17
17
  | Create / update a user | `grok s users save --json user.json` |
18
18
  | Block / unblock a user | `grok s users block <login>` / `users unblock <login>` |
19
+ | Invite a user, get a login link | `grok s users invite [<email>] [--prefix <P>]` |
19
20
  | Create / update a group | `grok s groups save --json group.json` |
20
21
  | Add or remove users in a group | `grok s groups add-members <group> <user>...` |
21
22
  | List members of a group | `grok s groups list-members <group>` |
@@ -165,8 +166,17 @@ personal groups.
165
166
  ```bash
166
167
  grok s users block alice.mendel # accept login, UUID, or namespace:name
167
168
  grok s users unblock alice.mendel
169
+ grok s users invite alice@corp.com # prints a login link; no email is sent
170
+ grok s users invite # same, for an account with no email
171
+ grok s users invite --prefix ALEX- # code starts with ALEX- (letters, digits, - and _, up to 32)
172
+ grok s users invite alice@corp.com --send-email # mail the invitation instead
168
173
  ```
169
174
 
175
+ `users invite` creates the user in state `new` and prints `<server>?inviteCode=<code>`. The
176
+ link logs straight in as that user, every time, for a year. Inviting the same email again
177
+ prints a new link, and the earlier ones keep working. An account that has already been used
178
+ cannot be sent a link.
179
+
170
180
  Both commands resolve the argument to a full user record first, so the server receives
171
181
  the entire object (matching the Python client's `grok.users.block(user)`). Blocking
172
182
  flips `status` to `Blocked` and terminates active sessions; unblocking restores `Active`.
@@ -111,6 +111,7 @@ async function server(argv) {
111
111
  if (entity === 'groups' && (verb === 'list-members' || verb === 'list-memberships')) return await handleGroupListMembers(dapi, verb, rest, argv, output);
112
112
  if (entity === 'users' && verb === 'block') return await handleUserBlock(dapi, rest, output);
113
113
  if (entity === 'users' && verb === 'unblock') return await handleUserUnblock(dapi, rest, output);
114
+ if (entity === 'users' && verb === 'invite') return await handleUserInvite(dapi, rest, argv, output);
114
115
  if (entity === 'tables' && verb === 'download') return await handleTablesDownload(dapi, rest, argv, output);
115
116
  if (entity === 'tables' && verb === 'upload') return await handleTablesUpload(dapi, rest, output);
116
117
  if (entity === 'packages' && verb === 'install') return await handlePackagesInstall(dapi, rest, argv, output);
@@ -214,6 +215,20 @@ async function handleUserUnblock(dapi, rest, output) {
214
215
  if (output !== 'quiet') console.log(`Unblocked ${user?.login ?? rest[0]}`);
215
216
  return true;
216
217
  }
218
+ async function handleUserInvite(dapi, rest, argv, output) {
219
+ const email = rest[0] !== undefined ? String(rest[0]) : undefined;
220
+ const prefix = argv.prefix !== undefined ? String(argv.prefix) : undefined;
221
+ if (argv['send-email'] && (!email || prefix !== undefined)) {
222
+ (0, _serverOutput.printError)(new Error('Usage: grok s users invite <email> --send-email (no --prefix: only a link has a code)'));
223
+ return false;
224
+ }
225
+ const link = await dapi.users.invite(email, !!argv['send-email'], prefix);
226
+ if (output === 'json') (0, _serverOutput.printOutput)({
227
+ email: email ?? null,
228
+ link: link || null
229
+ }, output);else if (link) console.log(link);else if (output !== 'quiet') console.log(`Invitation sent to ${email}`);
230
+ return true;
231
+ }
217
232
  async function handleTablesDownload(dapi, rest, argv, output) {
218
233
  const name = rest[0];
219
234
  if (!name) {
@@ -949,6 +964,10 @@ Special commands:
949
964
  List parent groups
950
965
  grok s users block <id-or-login> Block a user from the platform
951
966
  grok s users unblock <id-or-login> Unblock a previously blocked user
967
+ grok s users invite [<email>] [--prefix <P>] [--send-email]
968
+ Invite a user; prints a login link (no email sent).
969
+ --prefix starts the code with <P> (e.g. ALEX-);
970
+ --send-email mails the invitation instead
952
971
  grok s tables upload <name> <file.csv|file.d42> Upload a CSV or d42 binary as a Datagrok table
953
972
  grok s tables download <name|Project:Table|id> [-O <file>]
954
973
  Download a table as CSV (stdout by default)
package/bin/grok.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  const argv = require('minimist')(process.argv.slice(2), {
3
3
  alias: {k: 'key', h: 'help', r: 'recursive'},
4
- boolean: ['dartium'],
4
+ boolean: ['dartium', 'send-email'],
5
5
  // keep versions verbatim — minimist would coerce '1.10' to the number 1.1
6
- string: ['version'],
6
+ string: ['version', 'prefix'],
7
7
  });
8
8
  // minimist maps `--no-retry` to `{retry: false}`, so the `args['no-retry']` checks in
9
9
  // test.ts / playwright-runner.ts never fired and `--no-retry` was silently ignored
@@ -595,6 +595,20 @@ class NodeUsersDataSource extends NodeHttpDataSource {
595
595
  async unblock(user) {
596
596
  await this.client.post('/public/v1/users/unblock', user);
597
597
  }
598
+
599
+ /**
600
+ * Creates the invitee (status `new`) and returns a link that logs them in, sending no email; the
601
+ * email may be omitted, and [prefix] goes in front of the link's code. With [sendEmail] the
602
+ * server mails the invitation and returns '' instead.
603
+ */
604
+ async invite(email, sendEmail = false, prefix) {
605
+ return this.client.post(`/users/invite${buildQuery({
606
+ email: email ?? '',
607
+ target: 'Datagrok',
608
+ link: sendEmail ? undefined : true,
609
+ prefix
610
+ })}`);
611
+ }
598
612
  }
599
613
  exports.NodeUsersDataSource = NodeUsersDataSource;
600
614
  class NodeConnectionsDataSource extends NodeHttpDataSource {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/datagrok-ai/public.git"
6
6
  },
7
- "version": "6.7.6",
7
+ "version": "6.7.7",
8
8
  "description": "Utility to upload and publish packages to Datagrok",
9
9
  "homepage": "https://github.com/datagrok-ai/public/tree/master/tools#readme",
10
10
  "dependencies": {