@reventlessdev/reventless-aws 3.0.0-alpha.354 → 3.0.0-alpha.356

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.
@@ -52,36 +52,19 @@ type args = {
52
52
  `--email` that parsed as "absent" would be caught by the required-argument check
53
53
  below, but a typo'd `--provider-id` would fall through to the environment and
54
54
  create the administrator in a *different pool* than the operator named. */
55
- let parseArgs = (argv: array<string>): result<args, string> => {
56
- let acc = ref(Ok({providerId: None, stack: None, email: None, help: false}))
57
- let i = ref(0)
58
- let count = argv->Array.length
59
- while i.contents < count {
60
- let flag = argv->Array.getUnsafe(i.contents)
61
- let value = argv->Array.get(i.contents + 1)
62
- switch (acc.contents, flag, value) {
63
- | (Error(_), _, _) => i := count
64
- | (Ok(a), "--provider-id", Some(v)) =>
65
- acc := Ok({...a, providerId: Some(v)})
66
- i := i.contents + 2
67
- | (Ok(a), "--stack", Some(v)) =>
68
- acc := Ok({...a, stack: Some(v)})
69
- i := i.contents + 2
70
- | (Ok(a), "--email", Some(v)) =>
71
- acc := Ok({...a, email: Some(v)})
72
- i := i.contents + 2
73
- | (Ok(a), "--help", _) | (Ok(a), "-h", _) =>
74
- acc := Ok({...a, help: true})
75
- i := i.contents + 1
76
- | (Ok(_), "--provider-id", None) | (Ok(_), "--email", None) | (Ok(_), "--stack", None) =>
77
- acc := Error(`${flag} needs a value`)
78
- | (Ok(_), unknown, _) => acc := Error(`unknown argument "${unknown}"`)
79
- }
80
- }
81
- acc.contents
82
- }
55
+ let parseArgs = (argv: array<string>): result<args, string> =>
56
+ Reventless.CliArgs.parse(~strings=["provider-id", "stack", "email"], argv)
57
+ ->Result.flatMap(Reventless.CliArgs.noPositionals)
58
+ ->Result.map(a => {
59
+ providerId: a->Reventless.CliArgs.string("provider-id"),
60
+ stack: a->Reventless.CliArgs.string("stack"),
61
+ email: a->Reventless.CliArgs.string("email"),
62
+ help: a->Reventless.CliArgs.help,
63
+ })
83
64
 
84
65
  let usage = `
66
+ Usage: provision-admin --email <address> [--provider-id <id>] [--stack <name>]
67
+
85
68
  Make the first administrator of a Reventless deployment.
86
69
 
87
70
  --provider-id <id> The identity provider to create the account in. Usually
@@ -217,57 +200,59 @@ made through a signed-in session because there is no signed-in session yet. The
217
200
  rest of the cast is a list rather than a command: declare it in
218
201
  .reventless/users.yaml and run \`pnpm exec provision-accounts\`.`
219
202
 
220
- let run = async (): result<unit, string> =>
221
- // argv[0] is node, argv[1] this script.
222
- switch parseArgs(NodeProcess.argv->Array.slice(~start=2, ~end=NodeProcess.argv->Array.length)) {
223
- | Error(_) as e => e
224
- | Ok(args) if args.help =>
225
- Console.log(usage)
226
- Ok()
227
- | Ok(args) =>
228
- // The address is checked before the provider is resolved: it costs nothing,
229
- // while resolving may shell out to Pulumi, and a run missing both arguments
230
- // should say the cheap thing rather than fail on a stack lookup it never
231
- // needed.
232
- switch args.email {
203
+ type request = {email: string, providerId: option<string>, stack: option<string>}
204
+
205
+ /** The address is required before anything else is looked at: it costs nothing,
206
+ while resolving the provider may shell out to Pulumi, and a run missing both
207
+ arguments should say the cheap thing rather than fail on a stack lookup it
208
+ never needed. */
209
+ let parseRequest = (argv: array<string>): result<request, string> =>
210
+ parseArgs(argv)->Result.flatMap(({email, providerId, stack}) =>
211
+ switch email {
233
212
  | None => Error("--email is required — it is the address the administrator signs in with")
234
- | Some(email) =>
235
- switch ProvisionProvider.resolve(~given=args.providerId, ~stack=args.stack) {
236
- | Error(_) as e => e
237
- | Ok((providerId, source)) =>
238
- Console.log(`provider ${providerId} (from ${source->ProvisionProvider.describe})`)
239
- switch await checkPoolAcceptsEmail(~providerId) {
240
- | Error(_) as e => e
241
- | Ok() =>
242
- let group = Reventless.AdminGroup.name
243
- let password = Reventless.Util_Password.generate()
244
- await ensureGroup(~providerId, ~group)
245
- await ensureUser(~providerId, ~email)
246
- await setPassword(~providerId, ~email, ~password)
247
- await addToGroup(~providerId, ~email, ~group)
248
- Console.log(signInDetails(~providerId, ~email, ~password, ~group))
249
- Ok()
250
- }
251
- }
213
+ | Some(email) => Ok({email, providerId, stack})
214
+ }
215
+ )
216
+
217
+ let run = async ({email, providerId, stack}: request): result<unit, string> =>
218
+ switch ProvisionProvider.resolve(~given=providerId, ~stack) {
219
+ | Error(_) as e => e
220
+ | Ok((providerId, source)) =>
221
+ Console.log(`provider ${providerId} (from ${source->ProvisionProvider.describe})`)
222
+ switch await checkPoolAcceptsEmail(~providerId) {
223
+ | Error(_) as e => e
224
+ | Ok() =>
225
+ let group = Reventless.AdminGroup.name
226
+ let password = Reventless.Util_Password.generate()
227
+ await ensureGroup(~providerId, ~group)
228
+ await ensureUser(~providerId, ~email)
229
+ await setPassword(~providerId, ~email, ~password)
230
+ await addToGroup(~providerId, ~email, ~group)
231
+ Console.log(signInDetails(~providerId, ~email, ~password, ~group))
232
+ Ok()
252
233
  }
253
234
  }
254
235
 
236
+ let cli: Reventless.CliArgs.cli<request> = {bin: "provision-admin", usage, parse: parseRequest}
237
+
255
238
  /**
256
239
  🚨 **Catches thrown exceptions, not only `Error` results** — the reason
257
240
  [ProvisionIdentity.main] gives. Without it an SDK failure escapes an async
258
241
  function nothing awaits and Node reports `UnhandledPromiseRejection ...
259
242
  "#<Object>"`, naming neither the call that failed nor why.
260
243
  */
261
- let main = async () =>
262
- switch await run() {
263
- | Ok() => ()
264
- | Error(message) =>
265
- Console.error(`provision-admin: ${message}`)
266
- NodeProcess.exit(1)
267
- | exception exn =>
268
- Console.error(`provision-admin: ${Util_AwsError.describe(exn)}`)
269
- NodeProcess.exit(1)
270
- }
244
+ let main = () =>
245
+ Reventless.CliArgs.run(cli, async request =>
246
+ switch await run(request) {
247
+ | Ok() => ()
248
+ | Error(message) =>
249
+ Console.error(`provision-admin: ${message}`)
250
+ NodeProcess.exit(1)
251
+ | exception exn =>
252
+ Console.error(`provision-admin: ${Util_AwsError.describe(exn)}`)
253
+ NodeProcess.exit(1)
254
+ }
255
+ )
271
256
 
272
257
  // 🚨 **No top-level call.** `../run-provision-admin.mjs` invokes [main]; this
273
258
  // module only defines it. A module that ran itself on import could not be
@@ -1,5 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
4
+ import * as CliArgs$Reventless from "@reventlessdev/reventless-spec/src/CliArgs.res.mjs";
3
5
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
4
6
  import * as AdminGroup$Reventless from "@reventlessdev/reventless-spec/src/types/AdminGroup.res.mjs";
5
7
  import * as Util_Password$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Password.res.mjs";
@@ -8,110 +10,21 @@ import * as ProvisionCognito$ReventlessAws from "./ProvisionCognito.res.mjs";
8
10
  import * as ProvisionProvider$ReventlessAws from "./ProvisionProvider.res.mjs";
9
11
 
10
12
  function parseArgs(argv) {
11
- let acc = {
12
- TAG: "Ok",
13
- _0: {
14
- providerId: undefined,
15
- stack: undefined,
16
- email: undefined,
17
- help: false
18
- }
19
- };
20
- let i = 0;
21
- let count = argv.length;
22
- while (i < count) {
23
- let flag = argv[i];
24
- let value = argv[i + 1 | 0];
25
- let match = acc;
26
- let exit = 0;
27
- if (match.TAG === "Ok") {
28
- let a = match._0;
29
- let exit$1 = 0;
30
- switch (flag) {
31
- case "--email" :
32
- if (value !== undefined) {
33
- acc = {
34
- TAG: "Ok",
35
- _0: {
36
- providerId: a.providerId,
37
- stack: a.stack,
38
- email: value,
39
- help: a.help
40
- }
41
- };
42
- i = i + 2 | 0;
43
- } else {
44
- exit = 1;
45
- }
46
- break;
47
- case "--provider-id" :
48
- if (value !== undefined) {
49
- acc = {
50
- TAG: "Ok",
51
- _0: {
52
- providerId: value,
53
- stack: a.stack,
54
- email: a.email,
55
- help: a.help
56
- }
57
- };
58
- i = i + 2 | 0;
59
- } else {
60
- exit = 1;
61
- }
62
- break;
63
- case "--stack" :
64
- if (value !== undefined) {
65
- acc = {
66
- TAG: "Ok",
67
- _0: {
68
- providerId: a.providerId,
69
- stack: value,
70
- email: a.email,
71
- help: a.help
72
- }
73
- };
74
- i = i + 2 | 0;
75
- } else {
76
- exit = 1;
77
- }
78
- break;
79
- case "--help" :
80
- case "-h" :
81
- exit$1 = 2;
82
- break;
83
- default:
84
- acc = {
85
- TAG: "Error",
86
- _0: `unknown argument "` + flag + `"`
87
- };
88
- }
89
- if (exit$1 === 2) {
90
- acc = {
91
- TAG: "Ok",
92
- _0: {
93
- providerId: a.providerId,
94
- stack: a.stack,
95
- email: a.email,
96
- help: true
97
- }
98
- };
99
- i = i + 1 | 0;
100
- }
101
- } else {
102
- i = count;
103
- }
104
- if (exit === 1) {
105
- acc = {
106
- TAG: "Error",
107
- _0: flag + ` needs a value`
108
- };
109
- }
110
- };
111
- return acc;
13
+ return Stdlib_Result.map(Stdlib_Result.flatMap(CliArgs$Reventless.parse([
14
+ "provider-id",
15
+ "stack",
16
+ "email"
17
+ ], undefined, undefined, undefined, argv), CliArgs$Reventless.noPositionals), a => ({
18
+ providerId: CliArgs$Reventless.string(a, "provider-id"),
19
+ stack: CliArgs$Reventless.string(a, "stack"),
20
+ email: CliArgs$Reventless.string(a, "email"),
21
+ help: CliArgs$Reventless.help(a)
22
+ }));
112
23
  }
113
24
 
114
25
  let usage = `
26
+ Usage: provision-admin --email <address> [--provider-id <id>] [--stack <name>]
27
+
115
28
  Make the first administrator of a Reventless deployment.
116
29
 
117
30
  --provider-id <id> The identity provider to create the account in. Usually
@@ -209,36 +122,39 @@ rest of the cast is a list rather than a command: declare it in
209
122
  .reventless/users.yaml and run \`pnpm exec provision-accounts\`.`;
210
123
  }
211
124
 
212
- async function run() {
213
- let e = parseArgs(process.argv.slice(2, process.argv.length));
125
+ function parseRequest(argv) {
126
+ return Stdlib_Result.flatMap(parseArgs(argv), param => {
127
+ let email = param.email;
128
+ if (email !== undefined) {
129
+ return {
130
+ TAG: "Ok",
131
+ _0: {
132
+ email: email,
133
+ providerId: param.providerId,
134
+ stack: param.stack
135
+ }
136
+ };
137
+ } else {
138
+ return {
139
+ TAG: "Error",
140
+ _0: "--email is required — it is the address the administrator signs in with"
141
+ };
142
+ }
143
+ });
144
+ }
145
+
146
+ async function run(param) {
147
+ let email = param.email;
148
+ let e = ProvisionProvider$ReventlessAws.resolve(param.providerId, param.stack);
214
149
  if (e.TAG !== "Ok") {
215
150
  return e;
216
151
  }
217
- let args = e._0;
218
- if (args.help) {
219
- console.log(usage);
220
- return {
221
- TAG: "Ok",
222
- _0: undefined
223
- };
224
- }
225
- let email = args.email;
226
- if (email === undefined) {
227
- return {
228
- TAG: "Error",
229
- _0: "--email is required — it is the address the administrator signs in with"
230
- };
231
- }
232
- let e$1 = ProvisionProvider$ReventlessAws.resolve(args.providerId, args.stack);
233
- if (e$1.TAG !== "Ok") {
234
- return e$1;
235
- }
236
- let match = e$1._0;
152
+ let match = e._0;
237
153
  let providerId = match[0];
238
154
  console.log(`provider ` + providerId + ` (from ` + ProvisionProvider$ReventlessAws.describe(match[1]) + `)`);
239
- let e$2 = await checkPoolAcceptsEmail(providerId);
240
- if (e$2.TAG !== "Ok") {
241
- return e$2;
155
+ let e$1 = await checkPoolAcceptsEmail(providerId);
156
+ if (e$1.TAG !== "Ok") {
157
+ return e$1;
242
158
  }
243
159
  let password = Util_Password$Reventless.generate();
244
160
  await ensureGroup(providerId, AdminGroup$Reventless.name);
@@ -252,21 +168,29 @@ async function run() {
252
168
  };
253
169
  }
254
170
 
255
- async function main() {
256
- let message;
257
- try {
258
- message = await run();
259
- } catch (raw_exn) {
260
- let exn = Primitive_exceptions.internalToException(raw_exn);
261
- console.error(`provision-admin: ` + Util_AwsError$ReventlessAws.describe(exn));
171
+ let cli = {
172
+ bin: "provision-admin",
173
+ usage: usage,
174
+ parse: parseRequest
175
+ };
176
+
177
+ function main() {
178
+ return CliArgs$Reventless.run(cli, undefined, undefined, async request => {
179
+ let message;
180
+ try {
181
+ message = await run(request);
182
+ } catch (raw_exn) {
183
+ let exn = Primitive_exceptions.internalToException(raw_exn);
184
+ console.error(`provision-admin: ` + Util_AwsError$ReventlessAws.describe(exn));
185
+ process.exit(1);
186
+ return;
187
+ }
188
+ if (message.TAG === "Ok") {
189
+ return;
190
+ }
191
+ console.error(`provision-admin: ` + message._0);
262
192
  process.exit(1);
263
- return;
264
- }
265
- if (message.TAG === "Ok") {
266
- return;
267
- }
268
- console.error(`provision-admin: ` + message._0);
269
- process.exit(1);
193
+ });
270
194
  }
271
195
 
272
196
  let Cognito;
@@ -283,7 +207,9 @@ export {
283
207
  addToGroup,
284
208
  passwordNote,
285
209
  signInDetails,
210
+ parseRequest,
286
211
  run,
212
+ cli,
287
213
  main,
288
214
  }
289
- /* Util_Password-Reventless Not a pure module */
215
+ /* CliArgs-Reventless Not a pure module */
@@ -48,52 +48,34 @@ let defaultPoolName = "ReventlessIdentity"
48
48
  /** Parsed rather than positional, and unknown flags are an error: a typo'd
49
49
  `--provider-id` that parsed as "absent" would create a *second* pool beside the
50
50
  one the operator meant to extend. */
51
- let parseArgs = (argv: array<string>): result<args, string> => {
52
- let acc = ref(
53
- Ok({
54
- poolName: defaultPoolName,
55
- providerId: None,
56
- loginIdentifier: Auth_LoginIdentifier.default,
57
- signUpMode: Auth_SignUpMode.default,
58
- help: false,
59
- }),
51
+ let parseArgs = (argv: array<string>): result<args, string> =>
52
+ Reventless.CliArgs.parse(
53
+ ~strings=["name", "provider-id", "login-identifier", "sign-up-mode"],
54
+ argv,
60
55
  )
61
- let i = ref(0)
62
- let count = argv->Array.length
63
- while i.contents < count {
64
- let flag = argv->Array.getUnsafe(i.contents)
65
- let value = argv->Array.get(i.contents + 1)
66
- switch (acc.contents, flag, value) {
67
- | (Error(_), _, _) => i := count
68
- | (Ok(a), "--name", Some(v)) =>
69
- acc := Ok({...a, poolName: v})
70
- i := i.contents + 2
71
- | (Ok(a), "--provider-id", Some(v)) =>
72
- acc := Ok({...a, providerId: Some(v)})
73
- i := i.contents + 2
74
- | (Ok(a), "--login-identifier", Some(v)) =>
75
- acc :=
76
- Auth_LoginIdentifier.parse(Some(v))->Result.map(loginIdentifier => {
77
- ...a,
78
- loginIdentifier,
79
- })
80
- i := i.contents + 2
81
- | (Ok(a), "--sign-up-mode", Some(v)) =>
82
- acc := Auth_SignUpMode.parse(Some(v))->Result.map(signUpMode => {...a, signUpMode})
83
- i := i.contents + 2
84
- | (Ok(a), "--help", _) | (Ok(a), "-h", _) =>
85
- acc := Ok({...a, help: true})
86
- i := i.contents + 1
87
- | (Ok(_), "--name", None)
88
- | (Ok(_), "--provider-id", None)
89
- | (Ok(_), "--login-identifier", None)
90
- | (Ok(_), "--sign-up-mode", None) =>
91
- acc := Error(`${flag} needs a value`)
92
- | (Ok(_), unknown, _) => acc := Error(`unknown argument "${unknown}"`)
56
+ ->Result.flatMap(Reventless.CliArgs.noPositionals)
57
+ ->Result.flatMap(a => {
58
+ let given = name => a->Reventless.CliArgs.string(name)
59
+ let loginIdentifier = switch given("login-identifier") {
60
+ | None => Ok(Auth_LoginIdentifier.default)
61
+ | Some(_) as v => Auth_LoginIdentifier.parse(v)
93
62
  }
94
- }
95
- acc.contents
96
- }
63
+ let signUpMode = switch given("sign-up-mode") {
64
+ | None => Ok(Auth_SignUpMode.default)
65
+ | Some(_) as v => Auth_SignUpMode.parse(v)
66
+ }
67
+ switch (loginIdentifier, signUpMode) {
68
+ | (Error(_) as e, _) | (_, Error(_) as e) => e
69
+ | (Ok(loginIdentifier), Ok(signUpMode)) =>
70
+ Ok({
71
+ poolName: given("name")->Option.getOr(defaultPoolName),
72
+ providerId: given("provider-id"),
73
+ loginIdentifier,
74
+ signUpMode,
75
+ help: a->Reventless.CliArgs.help,
76
+ })
77
+ }
78
+ })
97
79
 
98
80
  let _loginIdentifiers =
99
81
  Auth_LoginIdentifier.all->Array.map(Auth_LoginIdentifier.toString)->Array.join(" | ")
@@ -105,6 +87,8 @@ let _signUpModes = Auth_SignUpMode.all->Array.map(Auth_SignUpMode.toString)->Arr
105
87
  let _defaultSignUpMode = Auth_SignUpMode.toString(Auth_SignUpMode.default)
106
88
 
107
89
  let usage = `
90
+ Usage: provision-identity [--name <name>] [--provider-id <id>] [--login-identifier <a>] [--sign-up-mode <m>]
91
+
108
92
  Provision a Reventless identity provider and its active-role store.
109
93
 
110
94
  --name <name> Pool name to create or adopt (default: ${defaultPoolName})
@@ -327,27 +311,21 @@ That is a separate bin because it provisions nothing a stack owns, and because i
327
311
  is needed on a pool created here and on one a stack created for itself alike. See
328
312
  [ProvisionAdmin].`
329
313
 
330
- let run = async (): result<unit, string> =>
331
- // argv[0] is node, argv[1] this script.
332
- switch parseArgs(NodeProcess.argv->Array.slice(~start=2, ~end=NodeProcess.argv->Array.length)) {
314
+ let run = async (args: args): result<unit, string> =>
315
+ switch await resolvePool(~args) {
333
316
  | Error(_) as e => e
334
- | Ok(args) if args.help =>
335
- Console.log(usage)
336
- Ok()
337
- | Ok(args) =>
338
- switch await resolvePool(~args) {
317
+ | Ok(providerId) =>
318
+ let tableName = Schema.derivedStoreName(~identityProviderId=providerId)
319
+ switch await provisionStore(~tableName) {
339
320
  | Error(_) as e => e
340
- | Ok(providerId) =>
341
- let tableName = Schema.derivedStoreName(~identityProviderId=providerId)
342
- switch await provisionStore(~tableName) {
343
- | Error(_) as e => e
344
- | Ok() =>
345
- Console.log(nextSteps(~providerId))
346
- Ok()
347
- }
321
+ | Ok() =>
322
+ Console.log(nextSteps(~providerId))
323
+ Ok()
348
324
  }
349
325
  }
350
326
 
327
+ let cli: Reventless.CliArgs.cli<args> = {bin: "provision-identity", usage, parse: parseArgs}
328
+
351
329
  /**
352
330
  🚨 **Catches thrown exceptions, not only `Error` results.**
353
331
 
@@ -356,16 +334,18 @@ reports `UnhandledPromiseRejection ... "#<Object>"` — which names neither the
356
334
  that failed nor why. Every AWS call in this script can throw, so the top level has
357
335
  to turn any of them into something an operator can read.
358
336
  */
359
- let main = async () =>
360
- switch await run() {
361
- | Ok() => ()
362
- | Error(message) =>
363
- Console.error(`provision-identity: ${message}`)
364
- NodeProcess.exit(1)
365
- | exception exn =>
366
- Console.error(`provision-identity: ${Util_AwsError.describe(exn)}`)
367
- NodeProcess.exit(1)
368
- }
337
+ let main = () =>
338
+ Reventless.CliArgs.run(cli, async args =>
339
+ switch await run(args) {
340
+ | Ok() => ()
341
+ | Error(message) =>
342
+ Console.error(`provision-identity: ${message}`)
343
+ NodeProcess.exit(1)
344
+ | exception exn =>
345
+ Console.error(`provision-identity: ${Util_AwsError.describe(exn)}`)
346
+ NodeProcess.exit(1)
347
+ }
348
+ )
369
349
 
370
350
  // 🚨 **No top-level call.** `../run-provision-identity.mjs` invokes [main]; this
371
351
  // module only defines it. A module that ran itself on import could not be