proca 1.4.0 → 1.5.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.
package/README.md CHANGED
@@ -8,17 +8,17 @@ Proca is an open-source campaign toolkit designed to empower activists and organ
8
8
 
9
9
  One of Proca's standout features is its robust support for coalition campaigns, allowing multiple organisations to collaborate seamlessly on shared initiatives. This coalition functionality enables partners to pool resources, amplify their collective voice, and reach a broader audience whilst maintaining individual branding and supporter relationships. By facilitating data sharing and joint campaign management, Proca helps coalitions to maximise their impact, streamline operations, and present a united front on critical issues, all whilst ensuring compliance with data protection regulations.
10
10
 
11
-
12
11
  ## usage
13
12
 
14
13
  ### global installation
14
+
15
15
  <!-- usage -->
16
16
  ```sh-session
17
17
  $ npm install -g proca
18
18
  $ proca COMMAND
19
19
  running command...
20
20
  $ proca (--version)
21
- proca/1.4.0 linux-x64 node-v20.12.2
21
+ proca/1.5.0 linux-x64 node-v20.12.2
22
22
  $ proca --help [COMMAND]
23
23
  USAGE
24
24
  $ proca COMMAND
@@ -28,33 +28,50 @@ USAGE
28
28
 
29
29
  ### local development
30
30
 
31
- ```sh-session
31
+ ````sh-session
32
32
  $ git clone https://github.com/fixthestatusquo/proca-cli.git
33
- $ git install
34
33
  $ cd proca-cli
35
- $./proca-cli --help
34
+ $ npm install
35
+ $ npm link # let the proca widget and other use the local version
36
+ $./proca-cli config add --env=local --url=http://localhost:4000/api
37
+ $./proca-cli config server --env=local #check if the config is working
38
+ $./proca-cli config user #check if the config is working
36
39
  ...
37
- ```
40
+
41
+ you should also use the local proca-api in your [widget generator](https://github.com/fixthestatusquo/proca)
42
+
43
+ ```sh-session
44
+ $ cd /your/path/to/proca
45
+ $ npm link proca-api
46
+ $ npm link proca # use the local proca-cli repo
47
+ ...
48
+
49
+
50
+ ````
38
51
 
39
52
  ### TOPICS
40
- - campaign Handle campaigns
53
+
54
+ - campaign Handle campaigns
41
55
  - org
42
- - config create setting to access the server authentication
56
+ - config create setting to access the server authentication
43
57
  - widget
44
58
  - supporters (counter)
45
59
 
46
60
  # Commands
61
+
47
62
  <!-- commands -->
48
63
  * [`proca action add`](#proca-action-add)
49
64
  * [`proca action count`](#proca-action-count)
50
65
  * [`proca action list [TITLE]`](#proca-action-list-title)
51
66
  * [`proca action replay`](#proca-action-replay)
52
67
  * [`proca campaign add [TITLE]`](#proca-campaign-add-title)
53
- * [`proca campaign close [TITLE]`](#proca-campaign-close-title)
68
+ * [`proca campaign close`](#proca-campaign-close)
54
69
  * [`proca campaign delete`](#proca-campaign-delete)
55
70
  * [`proca campaign get`](#proca-campaign-get)
56
71
  * [`proca campaign list [TITLE]`](#proca-campaign-list-title)
72
+ * [`proca campaign status`](#proca-campaign-status)
57
73
  * [`proca config add [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY]`](#proca-config-add-env-human-json-csv-simplify)
74
+ * [`proca config folder`](#proca-config-folder)
58
75
  * [`proca config init [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY]`](#proca-config-init-env-human-json-csv-simplify)
59
76
  * [`proca config server`](#proca-config-server)
60
77
  * [`proca config set [KEY] [VALUE]`](#proca-config-set-key-value)
@@ -81,6 +98,8 @@ USAGE
81
98
  * [`proca user get`](#proca-user-get)
82
99
  * [`proca user leave`](#proca-user-leave)
83
100
  * [`proca user list`](#proca-user-list)
101
+ * [`proca user reset [USER]`](#proca-user-reset-user)
102
+ * [`proca user whoami`](#proca-user-whoami)
84
103
  * [`proca widget add`](#proca-widget-add)
85
104
  * [`proca widget get`](#proca-widget-get)
86
105
  * [`proca widget list`](#proca-widget-list)
@@ -234,22 +253,17 @@ EXAMPLES
234
253
  $ proca campaign add -n <new_campaign> the full name of the campaign
235
254
  ```
236
255
 
237
- ## `proca campaign close [TITLE]`
256
+ ## `proca campaign close`
238
257
 
239
258
  ```
240
259
  USAGE
241
- $ proca campaign close [TITLE] -n <campaign name> -o <org name> --status
242
- closed|ignored|live [--json | --human | --csv] [--env <value>] [--simplify]
243
-
244
- ARGUMENTS
245
- TITLE title of the campaign
260
+ $ proca campaign close [ID_NAME_DXID] --status draft|live|closed|ignored [--json |
261
+ --human | --csv] [--env <value>] [--simplify]
246
262
 
247
263
  FLAGS
248
- -n, --name=<campaign name> (required) name of the campaign
249
- -o, --org=<org name> (required) name of the coordinator
250
- --env=<value> [default: default] allow to switch between configurations (server or users)
251
- --status=<option> (required) [default: closed] status
252
- <options: closed|ignored|live>
264
+ --env=<value> [default: default] allow to switch between configurations (server or users)
265
+ --status=<option> (required) Status to set
266
+ <options: draft|live|closed|ignored>
253
267
 
254
268
  OUTPUT FLAGS
255
269
  --csv Format output as csv
@@ -257,8 +271,13 @@ OUTPUT FLAGS
257
271
  --json Format output as json
258
272
  --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
259
273
 
274
+ ALIASES
275
+ $ proca campaign close
276
+
260
277
  EXAMPLES
261
278
  $ proca campaign close -name <campaign>
279
+
280
+ $ proca campaign close -i <campaign_id>
262
281
  ```
263
282
 
264
283
  ## `proca campaign delete`
@@ -350,14 +369,41 @@ EXAMPLES
350
369
  $ proca campaign list %pizza%
351
370
  ```
352
371
 
372
+ ## `proca campaign status`
373
+
374
+ ```
375
+ USAGE
376
+ $ proca campaign status [ID_NAME_DXID] --status draft|live|closed|ignored [--json |
377
+ --human | --csv] [--env <value>] [--simplify]
378
+
379
+ FLAGS
380
+ --env=<value> [default: default] allow to switch between configurations (server or users)
381
+ --status=<option> (required) Status to set
382
+ <options: draft|live|closed|ignored>
383
+
384
+ OUTPUT FLAGS
385
+ --csv Format output as csv
386
+ --human Format output to be read on screen by a human [default]
387
+ --json Format output as json
388
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
389
+
390
+ ALIASES
391
+ $ proca campaign close
392
+
393
+ EXAMPLES
394
+ $ proca campaign status -name <campaign>
395
+
396
+ $ proca campaign status -i <campaign_id>
397
+ ```
398
+
353
399
  ## `proca config add [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY]`
354
400
 
355
- create setting to access the server authentication
401
+ create setting to access to a server
356
402
 
357
403
  ```
358
404
  USAGE
359
- $ proca config add [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY] --token <API-token> [--json
360
- | --human | --csv] [--env <value>] [--simplify] [--force] [--url <url>]
405
+ $ proca config add [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY] [--json | --human | --csv]
406
+ [--env <value>] [--simplify] [--url <url>] [--token <API-token>] [--folder /var/www/proca]
361
407
 
362
408
  ARGUMENTS
363
409
  ENV [default: default] allow to switch between configurations (server or users)
@@ -367,10 +413,10 @@ ARGUMENTS
367
413
  SIMPLIFY flatten and filter to output only the most important attributes, mostly relevant for json
368
414
 
369
415
  FLAGS
370
- --env=<value> [default: default] allow to switch between configurations (server or users)
371
- --force write over an existing configuration
372
- --token=<API-token> (required) user token on proca server
373
- --url=<url> [default: https://api.proca.app/api] url of the proca server api
416
+ --env=<value> [default: default] allow to switch between configurations (server or users)
417
+ --folder=/var/www/proca config folder (in the proca widget generator)
418
+ --token=<API-token> user token on proca server
419
+ --url=<url> [default: https://api.proca.app/api] url of the proca server api
374
420
 
375
421
  OUTPUT FLAGS
376
422
  --csv Format output as csv
@@ -379,7 +425,7 @@ OUTPUT FLAGS
379
425
  --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
380
426
 
381
427
  DESCRIPTION
382
- create setting to access the server authentication
428
+ create setting to access to a server
383
429
 
384
430
  ALIASES
385
431
  $ proca config setup
@@ -389,14 +435,37 @@ EXAMPLES
389
435
  $ proca config add --user=xavier@example.org --token=API-12345789
390
436
  ```
391
437
 
438
+ ## `proca config folder`
439
+
440
+ Check and create config folders
441
+
442
+ ```
443
+ USAGE
444
+ $ proca config folder [--json | --human | --csv] [--env <value>] [--simplify]
445
+
446
+ FLAGS
447
+ --env=<value> [default: default] allow to switch between configurations (server or users)
448
+
449
+ OUTPUT FLAGS
450
+ --csv Format output as csv
451
+ --human Format output to be read on screen by a human [default]
452
+ --json Format output as json
453
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
454
+
455
+ DESCRIPTION
456
+ Check and create config folders
457
+
458
+ Check if the PROCA_CONFIG_FOLDER is set up, if it is, check if the required subfolders exists and create if not
459
+ ```
460
+
392
461
  ## `proca config init [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY]`
393
462
 
394
- create setting to access the server authentication
463
+ create setting to access to a server
395
464
 
396
465
  ```
397
466
  USAGE
398
- $ proca config init [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY] --token <API-token> [--json
399
- | --human | --csv] [--env <value>] [--simplify] [--force] [--url <url>]
467
+ $ proca config init [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY] [--json | --human | --csv]
468
+ [--env <value>] [--simplify] [--url <url>] [--token <API-token>] [--folder /var/www/proca]
400
469
 
401
470
  ARGUMENTS
402
471
  ENV [default: default] allow to switch between configurations (server or users)
@@ -406,10 +475,10 @@ ARGUMENTS
406
475
  SIMPLIFY flatten and filter to output only the most important attributes, mostly relevant for json
407
476
 
408
477
  FLAGS
409
- --env=<value> [default: default] allow to switch between configurations (server or users)
410
- --force write over an existing configuration
411
- --token=<API-token> (required) user token on proca server
412
- --url=<url> [default: https://api.proca.app/api] url of the proca server api
478
+ --env=<value> [default: default] allow to switch between configurations (server or users)
479
+ --folder=/var/www/proca config folder (in the proca widget generator)
480
+ --token=<API-token> user token on proca server
481
+ --url=<url> [default: https://api.proca.app/api] url of the proca server api
413
482
 
414
483
  OUTPUT FLAGS
415
484
  --csv Format output as csv
@@ -418,7 +487,7 @@ OUTPUT FLAGS
418
487
  --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
419
488
 
420
489
  DESCRIPTION
421
- create setting to access the server authentication
490
+ create setting to access to a server
422
491
 
423
492
  ALIASES
424
493
  $ proca config setup
@@ -488,12 +557,12 @@ EXAMPLES
488
557
 
489
558
  ## `proca config setup [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY]`
490
559
 
491
- create setting to access the server authentication
560
+ create setting to access to a server
492
561
 
493
562
  ```
494
563
  USAGE
495
- $ proca config setup [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY] --token <API-token> [--json
496
- | --human | --csv] [--env <value>] [--simplify] [--force] [--url <url>]
564
+ $ proca config setup [ENV] [HUMAN] [JSON] [CSV] [SIMPLIFY] [--json | --human | --csv]
565
+ [--env <value>] [--simplify] [--url <url>] [--token <API-token>] [--folder /var/www/proca]
497
566
 
498
567
  ARGUMENTS
499
568
  ENV [default: default] allow to switch between configurations (server or users)
@@ -503,10 +572,10 @@ ARGUMENTS
503
572
  SIMPLIFY flatten and filter to output only the most important attributes, mostly relevant for json
504
573
 
505
574
  FLAGS
506
- --env=<value> [default: default] allow to switch between configurations (server or users)
507
- --force write over an existing configuration
508
- --token=<API-token> (required) user token on proca server
509
- --url=<url> [default: https://api.proca.app/api] url of the proca server api
575
+ --env=<value> [default: default] allow to switch between configurations (server or users)
576
+ --folder=/var/www/proca config folder (in the proca widget generator)
577
+ --token=<API-token> user token on proca server
578
+ --url=<url> [default: https://api.proca.app/api] url of the proca server api
510
579
 
511
580
  OUTPUT FLAGS
512
581
  --csv Format output as csv
@@ -515,7 +584,7 @@ OUTPUT FLAGS
515
584
  --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
516
585
 
517
586
  DESCRIPTION
518
- create setting to access the server authentication
587
+ create setting to access to a server
519
588
 
520
589
  ALIASES
521
590
  $ proca config setup
@@ -545,6 +614,9 @@ OUTPUT FLAGS
545
614
  DESCRIPTION
546
615
  fetch the information about the current user (based on the token)
547
616
 
617
+ ALIASES
618
+ $ proca user whoami
619
+
548
620
  EXAMPLES
549
621
  $ proca config user
550
622
  ```
@@ -638,12 +710,13 @@ _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.2
638
710
  ```
639
711
  USAGE
640
712
  $ proca org add [--json | --human | --csv] [--env <value>] [--simplify] [--twitter
641
- <screen name>] [-n <org name>]
713
+ <screen name>] [-n <org acronym/name>] [-t <org full name>]
642
714
 
643
715
  FLAGS
644
- -n, --name=<org name> name of the org
645
- --env=<value> [default: default] allow to switch between configurations (server or users)
646
- --twitter=<screen name> twitter account
716
+ -n, --name=<org acronym/name> short name of the org
717
+ -t, --title=<org full name> title/full name of the org
718
+ --env=<value> [default: default] allow to switch between configurations (server or users)
719
+ --twitter=<screen name> twitter account
647
720
 
648
721
  OUTPUT FLAGS
649
722
  --csv Format output as csv
@@ -652,6 +725,8 @@ OUTPUT FLAGS
652
725
  --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
653
726
 
654
727
  EXAMPLES
728
+ $ proca org add --name <twitter of the organisation> --title='this is an organisation'
729
+
655
730
  $ proca org add --twitter <twitter of the organisation>
656
731
  ```
657
732
 
@@ -709,7 +784,7 @@ view a org
709
784
  ```
710
785
  USAGE
711
786
  $ proca org get [ID_NAME_DXID] [--json | --human | --csv] [--env <value>]
712
- [--simplify] [-n <org name>] [--config] [--keys] [--campaigns] [--widgets] [--users]
787
+ [--simplify] [-n <org name>] [--config] [--keys] [--campaigns] [--users]
713
788
 
714
789
  FLAGS
715
790
  -n, --name=<org name> name of the org
@@ -718,7 +793,6 @@ FLAGS
718
793
  --env=<value> [default: default] allow to switch between configurations (server or users)
719
794
  --[no-]keys
720
795
  --[no-]users
721
- --[no-]widgets
722
796
 
723
797
  OUTPUT FLAGS
724
798
  --csv Format output as csv
@@ -1133,6 +1207,60 @@ EXAMPLES
1133
1207
  $ proca user list %pizza%
1134
1208
  ```
1135
1209
 
1210
+ ## `proca user reset [USER]`
1211
+
1212
+ Reset user API token
1213
+
1214
+ ```
1215
+ USAGE
1216
+ $ proca user reset [USER] [--json | --human | --csv] [--env <value>] [--simplify]
1217
+ [--password <value>] [--url <value>]
1218
+
1219
+ ARGUMENTS
1220
+ USER Username (email)
1221
+
1222
+ FLAGS
1223
+ --env=<value> [default: default] allow to switch between configurations (server or users)
1224
+ --password=<value> Password
1225
+ --url=<value> URL of the Proca server API
1226
+
1227
+ OUTPUT FLAGS
1228
+ --csv Format output as csv
1229
+ --human Format output to be read on screen by a human [default]
1230
+ --json Format output as json
1231
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
1232
+
1233
+ DESCRIPTION
1234
+ Reset user API token
1235
+ ```
1236
+
1237
+ ## `proca user whoami`
1238
+
1239
+ fetch the information about the current user (based on the token)
1240
+
1241
+ ```
1242
+ USAGE
1243
+ $ proca user whoami [--json | --human | --csv] [--env <value>] [--simplify]
1244
+
1245
+ FLAGS
1246
+ --env=<value> [default: default] allow to switch between configurations (server or users)
1247
+
1248
+ OUTPUT FLAGS
1249
+ --csv Format output as csv
1250
+ --human Format output to be read on screen by a human [default]
1251
+ --json Format output as json
1252
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
1253
+
1254
+ DESCRIPTION
1255
+ fetch the information about the current user (based on the token)
1256
+
1257
+ ALIASES
1258
+ $ proca user whoami
1259
+
1260
+ EXAMPLES
1261
+ $ proca user whoami
1262
+ ```
1263
+
1136
1264
  ## `proca widget add`
1137
1265
 
1138
1266
  ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "proca",
3
3
  "description": "Access the proca api",
4
- "version": "1.4.0",
4
+ "version": "1.5.0",
5
5
  "author": "Xavier",
6
6
  "bin": {
7
7
  "proca": "proca-cli"
@@ -19,7 +19,8 @@
19
19
  "fast-csv": "^5.0.1",
20
20
  "graphql": "^16.10.0",
21
21
  "typescript": "^5.7.3",
22
- "urql": "^4.1.0"
22
+ "urql": "^4.1.0",
23
+ "prompts": "^2.4.2"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@biomejs/biome": "^1.9.3",
@@ -0,0 +1,63 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { error, stdout, ux } from "@oclif/core/ux";
3
+ import Command from "#src/procaCommand.mjs";
4
+ import { gql, mutation } from "#src/urql.mjs";
5
+
6
+ export default class CampaignStatus extends Command {
7
+ static args = this.multiid();
8
+ static aliases = ["campaign:close"];
9
+
10
+ static examples = [
11
+ "<%= config.bin %> <%= command.id %> -name <campaign>",
12
+ "<%= config.bin %> <%= command.id %> -i <campaign_id>",
13
+ ];
14
+
15
+ static isCloseCommand =
16
+ process.argv.includes("close") ||
17
+ this.commandPath?.includes("close") ||
18
+ this.id?.includes("close");
19
+
20
+ static flags = {
21
+ status: Flags.string({
22
+ ...this.flagify({ multiid: true }),
23
+ description: "Status to set",
24
+ required: true,
25
+ default: this.isCloseCommand ? "close" : undefined,
26
+ options: ["draft", "live", "closed", "ignored"],
27
+ }),
28
+ };
29
+
30
+ updateStatus = async (props) => {
31
+ const Query = gql`
32
+ mutation (
33
+ $id: Int,
34
+ $name: String
35
+ $status: String!
36
+ ) {
37
+ updateCampaign (id:$id, input: { name: $name,status: $status }) {
38
+ name
39
+ org {name}
40
+ status
41
+ title
42
+ }
43
+ }
44
+ `;
45
+
46
+ const result = await mutation(Query, {
47
+ // org: props.org,
48
+ id: props.id,
49
+ name: props.name,
50
+ status: props.status.toUpperCase(),
51
+ });
52
+
53
+ console.log("result", result);
54
+ return result.updateCampaign;
55
+ };
56
+
57
+ async run() {
58
+ const { args, flags } = await this.parse();
59
+
60
+ const data = await this.updateStatus(flags);
61
+ return this.output(data);
62
+ }
63
+ }
@@ -1,18 +1,19 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
- import { error, stdout, ux } from "@oclif/core/ux";
3
- import { get as getConfig, getFilename, write } from "#src/config.mjs";
2
+ import { error, stdout } from "@oclif/core/ux";
3
+ import prompts from "prompts";
4
+ import { format, get as getConfig, getFilename, write } from "#src/config.mjs";
4
5
  import Command from "#src/procaCommand.mjs";
5
6
 
6
- export default class CampaignList extends Command {
7
+ export default class ConfigAdd extends Command {
7
8
  static enableJsonFlag = true;
8
9
  static aliases = ["config:setup", "config:init"];
9
- static deprecateAliases = true;
10
+ // static deprecateAliases = true;
10
11
 
11
12
  static args = {
12
13
  ...this.flagify({ multiid: false }),
13
14
  };
14
15
 
15
- static description = "create setting to access the server authentication";
16
+ static description = "create setting to access to a server";
16
17
 
17
18
  static examples = [
18
19
  "<%= config.bin %> <%= command.id %> --user=xavier@example.org --token=API-12345789",
@@ -21,11 +22,6 @@ export default class CampaignList extends Command {
21
22
  static flags = {
22
23
  // flag with no value (-f, --force)
23
24
  ...super.globalFlags,
24
- force: Flags.boolean({
25
- description: "write over an existing configuration",
26
- default: false,
27
- helpValue: "(default false)",
28
- }),
29
25
  url: Flags.string({
30
26
  description: "url of the proca server api",
31
27
  default: "https://api.proca.app/api",
@@ -34,7 +30,10 @@ export default class CampaignList extends Command {
34
30
  token: Flags.string({
35
31
  description: "user token on proca server",
36
32
  helpValue: "<API-token>",
37
- required: true,
33
+ }),
34
+ folder: Flags.string({
35
+ description: "config folder (in the proca widget generator)",
36
+ helpValue: "/var/www/proca",
38
37
  }),
39
38
  // n8n: Flags.string({ description: "api access on the n8n server", helpValue: "<n8n api>", }),
40
39
  // supabase: Flags.string({description: "url of the supabase",helpValue: "<url>"}),
@@ -42,46 +41,53 @@ export default class CampaignList extends Command {
42
41
  // "supabase-secrey-key": Flags.string({ description: "secret service key", }),
43
42
  };
44
43
 
45
- format = (obj) => {
46
- const content = ["# generated by proca-cli"];
47
- for (const [key, value] of Object.entries(obj)) {
48
- if (value) {
49
- content.push(`${key}='${value.replace(/'/g, "''")}'`);
50
- } else {
51
- content.push(`#${key}= `);
52
- }
53
- }
54
- return content.join("\n");
55
- };
56
-
57
- generate = function () {
44
+ generate = (flags) => {
58
45
  const mapping = {
59
46
  REACT_APP_NAME: "proca",
60
- REACT_APP_API_URL: this.flags.url,
61
- PROCA_TOKEN: this.flags.token,
62
- N8N_TOKEN: this.flags.n8n,
63
- REACT_APP_SUPABASE_URL: this.flags.supabase,
64
- REACT_APP_SUPABASE_ANON_KEY: this.flags.supabase_anon_key,
65
- SUPABASE_SECRET_KEY: this.flags.supabase_secret_key,
47
+ REACT_APP_API_URL: flags.url,
48
+ PROCA_TOKEN: flags.token,
49
+ PROCA_CONFIG_FOLDER: flags.folder,
50
+ N8N_TOKEN: flags.n8n,
51
+ REACT_APP_SUPABASE_URL: flags.supabase,
52
+ REACT_APP_SUPABASE_ANON_KEY: flags.supabase_anon_key,
53
+ SUPABASE_SECRET_KEY: flags.supabase_secret_key,
66
54
  };
67
55
 
68
- return this.format(mapping);
56
+ return format(mapping);
69
57
  };
70
58
 
71
59
  async run() {
72
- const { args, flags } = await this.parse();
60
+ const { args, flags } = await this.parse(this.constructor);
61
+
73
62
  const file = getFilename(this.config.configDir, flags.env);
74
- const userConfig = getConfig(file);
75
- if (userConfig && !this.flags.force) {
76
- this.error("config file exists already", {
77
- code: "CONFIG_EXISTS",
78
- _ref: "README.md#",
79
- suggestions: [
80
- `edit ${file}`,
81
- "add --force flag\nWARNING, it will delete the existing file",
82
- ],
63
+ const userConfig = getConfig(file, true) || {};
64
+
65
+ if (Object.keys(userConfig).length > 0) {
66
+ this.log(`Config file ${file} exists. Using it to pre-fill values.`);
67
+ }
68
+
69
+ if (!flags.token) {
70
+ const response = await prompts({
71
+ type: "text",
72
+ name: "token",
73
+ message: this.constructor.flags.token.description,
74
+ initial: userConfig.PROCA_TOKEN || "API-",
75
+ });
76
+ flags.token = response.token;
77
+ }
78
+ if (!flags.folder) {
79
+ const response = await prompts({
80
+ type: "text",
81
+ name: "folder",
82
+ message: this.constructor.flags.folder.description,
83
+ initial: userConfig.PROCA_FOLDER,
83
84
  });
85
+ flags.folder = response.folder;
86
+ }
87
+
88
+ if (!flags.token || !flags.token.startsWith("API-")) {
89
+ return error("Token must start with API-, config file not saved");
84
90
  }
85
- write(file, this.generate());
91
+ write(file, this.generate(flags));
86
92
  }
87
93
  }
@@ -0,0 +1,42 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { Command } from "#src/procaCommand.mjs";
4
+
5
+ export default class FolderConfig extends Command {
6
+ static summary = "Check and create config folders";
7
+ static description =
8
+ "Check if the PROCA_CONFIG_FOLDER is set up, if it is, check if the required subfolders exists and create if not";
9
+
10
+ async run() {
11
+ const configFolder = process.env.PROCA_CONFIG_FOLDER;
12
+
13
+ if (!configFolder) {
14
+ this.error("PROCA_CONFIG_FOLDER environment variable is not set.");
15
+ }
16
+
17
+ const subfolders = [
18
+ "org",
19
+ "target/source",
20
+ "target/server",
21
+ "target/public",
22
+ "campaign",
23
+ "email/actionpage",
24
+ "email/html",
25
+ "email/mjml",
26
+ ];
27
+
28
+ this.log(`Checking config folder at ${configFolder}`);
29
+
30
+ subfolders.forEach((subfolder) => {
31
+ const fullPath = path.join(configFolder, subfolder);
32
+ if (!fs.existsSync(fullPath)) {
33
+ fs.mkdirSync(fullPath, { recursive: true });
34
+ this.log(`🆕 ${fullPath}`);
35
+ } else {
36
+ this.log(`✅ ${fullPath}`);
37
+ }
38
+ });
39
+
40
+ this.log("Config folder check complete.");
41
+ }
42
+ }
@@ -4,6 +4,7 @@ import Command from "#src/procaCommand.mjs";
4
4
  import { gql, query } from "#src/urql.mjs";
5
5
 
6
6
  export default class UserList extends Command {
7
+ static aliases = ["user:whoami"];
7
8
  static description =
8
9
  "fetch the information about the current user (based on the token)";
9
10
 
@@ -8,6 +8,7 @@ export default class OrgAdd extends Command {
8
8
  static args = {};
9
9
 
10
10
  static examples = [
11
+ "<%= config.bin %> <%= command.id %> --name <twitter of the organisation> --title='this is an organisation'",
11
12
  "<%= config.bin %> <%= command.id %> --twitter <twitter of the organisation>",
12
13
  ];
13
14
 
@@ -20,8 +21,13 @@ export default class OrgAdd extends Command {
20
21
  }),
21
22
  name: Flags.string({
22
23
  char: "n",
23
- description: "name of the org",
24
- helpValue: "<org name>",
24
+ description: "short name of the org",
25
+ helpValue: "<org acronym/name>",
26
+ }),
27
+ title: Flags.string({
28
+ char: "t",
29
+ description: "title/full name of the org",
30
+ helpValue: "<org full name>",
25
31
  }),
26
32
  };
27
33
 
@@ -54,7 +60,11 @@ mutation ($org: OrgInput!) {
54
60
  this.error("You must provide either --name or --twitter");
55
61
  }
56
62
 
57
- const org = { name: flags.twitter || flags.name, config: {} };
63
+ const org = {
64
+ name: flags.twitter || flags.name,
65
+ title: flags.title || flags.name,
66
+ config: {},
67
+ };
58
68
 
59
69
  if (flags.twitter) {
60
70
  await getTwitter(org);
@@ -33,10 +33,6 @@ export default class OrgGet extends Command {
33
33
  default: false,
34
34
  allowNo: true,
35
35
  }),
36
- widgets: Flags.boolean({
37
- default: true,
38
- allowNo: true,
39
- }),
40
36
  users: Flags.boolean({
41
37
  default: true,
42
38
  allowNo: true,
@@ -45,19 +41,56 @@ export default class OrgGet extends Command {
45
41
 
46
42
  fetch = async (params) => {
47
43
  const GetOrgDocument = gql`
48
- query GetOrg($name: String!, $withCampaigns: Boolean = true) {
44
+ query GetOrg($name: String!, $withCampaigns: Boolean = true, $withKeys: Boolean = true) {
49
45
  org (name: $name) {
50
46
  id name title
51
47
  config
48
+ keys @include(if: $withKeys) {id, name, expired, expiredAt, public}
49
+
52
50
  campaigns @include(if: $withCampaigns) {id, name, title, org {name}}
51
+ personalData {
52
+ contactSchema
53
+ doiThankYou
54
+ highSecurity
55
+ replyEnabled
56
+ supporterConfirm
57
+ supporterConfirmTemplate
58
+ }
59
+ processing {
60
+ customActionConfirm
61
+ customActionDeliver
62
+ customEventDeliver
63
+ customSupporterConfirm
64
+ detailBackend
65
+ doiThankYou
66
+ emailBackend
67
+ emailFrom
68
+ emailTemplates
69
+ eventBackend
70
+ pushBackend
71
+ storageBackend
72
+ supporterConfirm
73
+ supporterConfirmTemplate
74
+ }
75
+
76
+ services {
77
+ host
78
+ id
79
+ name
80
+ path
81
+ user
82
+ }
53
83
  }
54
84
  }
55
85
  `;
86
+
56
87
  const result = await query(GetOrgDocument, {
57
88
  name: params.name,
58
89
  withCampaigns: params.campaigns,
90
+ withKeys: params.keys || true,
59
91
  });
60
92
  // result.org.config = JSON.parse (result.org.config);
93
+ console.log(result.org);
61
94
  return result.org;
62
95
  };
63
96
 
@@ -66,6 +99,10 @@ export default class OrgGet extends Command {
66
99
  id: d.id,
67
100
  Name: d.name,
68
101
  Title: d.title,
102
+ "can targets reply?": d.replyEnabled ? true : undefined,
103
+ "confirm actions?": d.supporterConfirm
104
+ ? d.supporterConfirmTemplate
105
+ : undefined,
69
106
  };
70
107
  if (this.flags.stats) {
71
108
  result["#Supporters"] = d.stats.supporterCount;
@@ -0,0 +1,83 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { error, stdout } from "@oclif/core/ux";
3
+ import prompts from "prompts";
4
+ import { format, get as getConfig, getFilename, write } from "#src/config.mjs";
5
+ import Command from "#src/procaCommand.mjs";
6
+
7
+ export default class UserReset extends Command {
8
+ static description = "Reset user API token";
9
+
10
+ static args = {
11
+ user: Args.string({ description: "Username (email)" }),
12
+ };
13
+
14
+ static flags = {
15
+ ...super.globalFlags,
16
+ password: Flags.string({ description: "Password" }),
17
+ url: Flags.string({ description: "URL of the Proca server API" }),
18
+ };
19
+
20
+ async run() {
21
+ const { args, flags } = await this.parse(UserReset);
22
+
23
+ const file = getFilename(this.config.configDir, flags.env);
24
+ const userConfig = getConfig(file, true) || {};
25
+
26
+ if (!args.user) {
27
+ const response = await prompts({
28
+ type: "text",
29
+ name: "user",
30
+ message: "Username:",
31
+ });
32
+ args.user = response.user;
33
+ }
34
+
35
+ if (!flags.password) {
36
+ const response = await prompts({
37
+ type: "password",
38
+ name: "password",
39
+ message: "Password:",
40
+ });
41
+ flags.password = response.password;
42
+ }
43
+
44
+ const url =
45
+ flags.url || userConfig.REACT_APP_API_URL || "https://api.proca.app/api";
46
+
47
+ if (!args.user || !flags.password) {
48
+ return error("User and password are required.");
49
+ }
50
+
51
+ const query = `mutation {
52
+ resetApiToken
53
+ }`;
54
+
55
+ const auth = `Basic ${Buffer.from(`${args.user}:${flags.password}`).toString("base64")}`;
56
+
57
+ try {
58
+ const response = await fetch(url, {
59
+ method: "POST",
60
+ headers: {
61
+ "Content-Type": "application/json",
62
+ Authorization: auth,
63
+ },
64
+ body: JSON.stringify({ query }),
65
+ });
66
+
67
+ const data = await response.json();
68
+
69
+ if (data.errors) {
70
+ return error(data.errors.map((e) => e.message).join("\n"));
71
+ }
72
+
73
+ const newToken = data.data.resetApiToken;
74
+ this.log(`New API token: ${newToken}`);
75
+
76
+ userConfig.PROCA_TOKEN = newToken;
77
+ write(file, format(userConfig));
78
+ this.log(`Token saved to ${file}`);
79
+ } catch (e) {
80
+ error(e.message);
81
+ }
82
+ }
83
+ }
@@ -72,7 +72,7 @@ export default class WidgetAdd extends Command {
72
72
 
73
73
  try {
74
74
  const r = await mutation(addWidgetDocument, flag);
75
- return r;
75
+ return { id: r.addActionPage.id };
76
76
  } catch (e) {
77
77
  const errors = e.graphQLErrors;
78
78
  console.log(errors, flag, addWidgetDocument);
package/src/config.mjs CHANGED
@@ -8,6 +8,7 @@ export const getFilename = (folder, env = "default") =>
8
8
  export const load = (folder, env = "default") => {
9
9
  const file = getFilename(folder, env);
10
10
  const config = dotenv({ path: file });
11
+
11
12
  return {
12
13
  token: config.parsed.PROCA_TOKEN,
13
14
  url: config.parsed.REACT_APP_API_URL,
@@ -34,3 +35,15 @@ export const get = (file, parsed = false) => {
34
35
  export const write = (file, content) => {
35
36
  writeFileSync(file, content);
36
37
  };
38
+
39
+ export const format = (obj) => {
40
+ const content = ["# generated by proca-cli"];
41
+ for (const [key, value] of Object.entries(obj)) {
42
+ if (value) {
43
+ content.push(`${key}='${value.replace(/'/g, "''")}'`);
44
+ } else {
45
+ content.push(`#${key}= `);
46
+ }
47
+ }
48
+ return content.join("\n");
49
+ };
@@ -1,81 +0,0 @@
1
- import { Args, Flags } from "@oclif/core";
2
- import { error, stdout, ux } from "@oclif/core/ux";
3
- import OrgGet from "#src/commands/org/get.mjs";
4
- import Command from "#src/procaCommand.mjs";
5
- import { gql, mutation } from "#src/urql.mjs";
6
- import { getTwitter } from "#src/util/twitter.mjs";
7
-
8
- export default class CampaignClose extends Command {
9
- static args = {
10
- title: Args.string({
11
- description: "title of the campaign",
12
- multiple: true,
13
- }),
14
- };
15
- // static strict = false;
16
-
17
- static examples = ["<%= config.bin %> <%= command.id %> -name <campaign>"];
18
-
19
- static flags = {
20
- // flag with no value (-f, --force)
21
- ...super.globalFlags,
22
- name: Flags.string({
23
- char: "n",
24
- description: "name of the campaign",
25
- helpValue: "<campaign name>",
26
- required: true,
27
- }),
28
- org: Flags.string({
29
- char: "o",
30
- description: "name of the coordinator",
31
- helpValue: "<org name>",
32
- required: true,
33
- }),
34
- status: Flags.string({
35
- description: "status",
36
- required: true,
37
- options: ["closed", "ignored", "live"],
38
- default: "closed",
39
- }),
40
- };
41
-
42
- updateStatus = async (props) => {
43
- const org = await this.getOrg(props.org);
44
-
45
- const Query = gql`
46
- mutation ($org: String!
47
- $name: String!
48
- $status: String!
49
- ) {
50
- upsertCampaign (input: { name: $name, status: $status }, orgName: $org) {
51
- name
52
- title
53
- status
54
- config
55
- }
56
- }
57
- `;
58
- const result = await mutation(Query, {
59
- org: props.org,
60
- name: props.name,
61
- status: props.status.toUpperCase(),
62
- });
63
-
64
- console.log("result", result);
65
- return result;
66
- };
67
-
68
- async getOrg(orgName) {
69
- const { config } = this;
70
- const orgGet = new OrgGet({}, this.config);
71
- const org = await orgGet.fetch({ name: orgName });
72
- return org;
73
- }
74
-
75
- async run() {
76
- const { args, flags } = await this.parse();
77
-
78
- const data = await this.updateStatus(flags);
79
- return this.output(data);
80
- }
81
- }