@faable/faable 1.33.0 → 1.35.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.
@@ -28,6 +28,7 @@ const actions_get = {
28
28
  log.info(` Trigger: ${action.trigger ?? '-'}`);
29
29
  log.info(` Enabled: ${yes_no(action.enabled)}`);
30
30
  log.info(` Order: ${action.order ?? 0}`);
31
+ log.info(` Revision: ${action.revision ?? 1} (updated ${action.updatedAt ?? '-'})`);
31
32
  log.info(` Created: ${action.createdAt ?? '-'}`);
32
33
  if (args.code) {
33
34
  log.info(' Code:');
@@ -55,7 +55,7 @@ const actions_update = {
55
55
  const action = await api.actionUpdate(args.action_id, patch);
56
56
  if (args.json)
57
57
  return print_json(action);
58
- log.info(`✅ Updated action ${action.id} (${action.name}, trigger ${action.trigger}, enabled: ${action.enabled ? '✓' : '✗'})`);
58
+ log.info(`✅ Updated action ${action.id} (${action.name}, trigger ${action.trigger}, enabled: ${action.enabled ? '✓' : '✗'}, revision ${action.revision ?? '-'})`);
59
59
  })
60
60
  };
61
61
 
@@ -1,14 +1,16 @@
1
1
  import { users_get } from './get.js';
2
2
  import { users_list } from './list.js';
3
+ import { users_reinstate } from './reinstate.js';
3
4
  import { users_suspend } from './suspend.js';
4
5
 
5
6
  const users = {
6
7
  command: 'users',
7
- describe: 'List, inspect and suspend users',
8
+ describe: 'List, inspect, suspend and reinstate users',
8
9
  builder: yargs => yargs
9
10
  .command(users_list)
10
11
  .command(users_get)
11
12
  .command(users_suspend)
13
+ .command(users_reinstate)
12
14
  .demandCommand(1)
13
15
  .showHelpOnFail(false),
14
16
  handler: () => { }
@@ -0,0 +1,78 @@
1
+ import prompts from 'prompts';
2
+ import { withAuthHints, requireAuthAdmin } from '../../../api/auth_admin.js';
3
+ import { log } from '../../../log.js';
4
+ import { json_option, tenant_options } from '../options.js';
5
+ import { print_json } from '../render.js';
6
+ import { wants_stdin, read_stdin, parse_user_ids } from './ids.js';
7
+
8
+ const users_reinstate = {
9
+ command: 'reinstate [user_ids..]',
10
+ describe: 'Reinstate one or more suspended users (re-enables logins and tokens)',
11
+ builder: yargs => json_option(tenant_options(yargs))
12
+ .positional('user_ids', {
13
+ type: 'string',
14
+ array: true,
15
+ description: 'User ids (user_…); omit them to read ids from stdin'
16
+ })
17
+ .option('yes', {
18
+ alias: 'y',
19
+ type: 'boolean',
20
+ default: false,
21
+ description: 'Skip the confirmation prompt'
22
+ })
23
+ .example('$0 auth users reinstate user_abc123', 'Reinstate one user')
24
+ .example('faable auth users list --suspended --json | jq -r ".[].id" | $0 auth users reinstate -y', 'Bulk-reinstate ids piped from a filtered listing')
25
+ .showHelpOnFail(false),
26
+ handler: withAuthHints(async (args) => {
27
+ const argv_ids = args.user_ids ?? [];
28
+ const stdin = wants_stdin(argv_ids, !!process.stdin.isTTY)
29
+ ? await read_stdin()
30
+ : null;
31
+ const ids = parse_user_ids(argv_ids, stdin);
32
+ if (!args.yes) {
33
+ const preview = ids.slice(0, 5).join(', ') + (ids.length > 5 ? ', …' : '');
34
+ // In a non-TTY run without --yes, prompts resolves undefined → cancel.
35
+ const { confirm } = await prompts({
36
+ type: 'toggle',
37
+ name: 'confirm',
38
+ message: `Reinstate ${ids.length} user(s) (${preview})?`,
39
+ initial: false,
40
+ active: 'yes',
41
+ inactive: 'no'
42
+ });
43
+ if (!confirm) {
44
+ log.info('Cancelled.');
45
+ return;
46
+ }
47
+ }
48
+ const api = await requireAuthAdmin(args);
49
+ const results = [];
50
+ for (const id of ids) {
51
+ try {
52
+ const user = await api.userUpdate(id, { suspended: false });
53
+ results.push({ id, suspended: !!user.suspended });
54
+ // Progress lines stay off stdout in --json mode (machine-clean pipe).
55
+ if (!args.json) {
56
+ log.info(`🟢 Reinstated ${id}${user.email ? ` (${user.email})` : ''}`);
57
+ }
58
+ }
59
+ catch (e) {
60
+ const message = e instanceof Error ? e.message : String(e);
61
+ results.push({ id, suspended: true, error: message });
62
+ if (!args.json)
63
+ log.error(`❌ Failed to reinstate ${id}: ${message}`);
64
+ }
65
+ }
66
+ if (args.json)
67
+ print_json(results);
68
+ const failed = results.filter(r => r.error);
69
+ if (failed.length > 0) {
70
+ throw new Error(`${failed.length} of ${ids.length} reinstatement(s) failed${args.json ? '' : ' — see errors above'}`);
71
+ }
72
+ if (!args.json) {
73
+ log.info(`✅ ${ids.length} user(s) reinstated.`);
74
+ }
75
+ })
76
+ };
77
+
78
+ export { users_reinstate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faable/faable",
3
- "version": "1.33.0",
3
+ "version": "1.35.0",
4
4
  "main": "dist/index.js",
5
5
  "license": "MIT",
6
6
  "author": "Marc Pomar <marc@faable.com>",