proca 1.1.5 → 1.2.1

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
@@ -18,7 +18,7 @@ $ npm install -g proca
18
18
  $ proca COMMAND
19
19
  running command...
20
20
  $ proca (--version)
21
- proca/1.1.5 linux-x64 node-v20.12.2
21
+ proca/1.2.1 linux-x64 node-v20.12.2
22
22
  $ proca --help [COMMAND]
23
23
  USAGE
24
24
  $ proca COMMAND
@@ -58,6 +58,8 @@ USAGE
58
58
  * [`proca config setup [ENVIRONMENT]`](#proca-config-setup-environment)
59
59
  * [`proca config token`](#proca-config-token)
60
60
  * [`proca config user`](#proca-config-user)
61
+ * [`proca contact count`](#proca-contact-count)
62
+ * [`proca contact list [TITLE]`](#proca-contact-list-title)
61
63
  * [`proca help [COMMAND]`](#proca-help-command)
62
64
  * [`proca org add`](#proca-org-add)
63
65
  * [`proca org crm`](#proca-org-crm)
@@ -74,7 +76,6 @@ USAGE
74
76
  * [`proca plugins uninstall [PLUGIN]`](#proca-plugins-uninstall-plugin)
75
77
  * [`proca plugins unlink [PLUGIN]`](#proca-plugins-unlink-plugin)
76
78
  * [`proca plugins update`](#proca-plugins-update)
77
- * [`proca supporter count`](#proca-supporter-count)
78
79
  * [`proca user get`](#proca-user-get)
79
80
  * [`proca user leave`](#proca-user-leave)
80
81
  * [`proca user list`](#proca-user-list)
@@ -448,6 +449,68 @@ EXAMPLES
448
449
  $ proca config user
449
450
  ```
450
451
 
452
+ ## `proca contact count`
453
+
454
+ counter of supporters
455
+
456
+ ```
457
+ USAGE
458
+ $ proca contact count [ID_NAME_DXID] [--json | --human | --csv] [--simplify] [-i <value>
459
+ | -n <the_short_name> | -x <value>]
460
+
461
+ FLAGS
462
+ -i, --id=<value>
463
+ -n, --name=<the_short_name> name
464
+ -x, --dxid=<value> dxid
465
+
466
+ OUTPUT FLAGS
467
+ --csv Format output as csv
468
+ --human Format output to be read on screen by a human [default]
469
+ --json Format output as json
470
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
471
+
472
+ DESCRIPTION
473
+ counter of supporters
474
+
475
+ EXAMPLES
476
+ $ proca contact count --id <id of the campaign>
477
+
478
+ $ proca contact count --name <name of the campaign>
479
+ ```
480
+
481
+ ## `proca contact list [TITLE]`
482
+
483
+ ```
484
+ USAGE
485
+ $ proca contact list [TITLE] -o <organisation name> [--json | --human | --csv] [-c
486
+ <campaign title>] [-n <value>] [--today | --after 2025-04-09] [--optin] [--testing] [--doi] [--utm | --simplify]
487
+ [--comment | ]
488
+
489
+ ARGUMENTS
490
+ TITLE name of the campaign, % for wildchar
491
+
492
+ FLAGS
493
+ -c, --campaign=<campaign title> name of the campaign, % for wildchar
494
+ -n, --limit=<value> max number of actions
495
+ -o, --org=<organisation name> (required) campaigns of the organisation (coordinator or partner)
496
+ --after=2025-04-09 only actions after a date
497
+ --[no-]comment display the comment
498
+ --doi only export the double optin actions
499
+ --optin only export the optin actions
500
+ --testing also export the test actions
501
+ --today only actions today
502
+ --[no-]utm display the utm tracking parameters
503
+
504
+ OUTPUT FLAGS
505
+ --csv Format output as csv
506
+ --human Format output to be read on screen by a human [default]
507
+ --json Format output as json
508
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
509
+
510
+ EXAMPLES
511
+ $ proca contact list %pizza%
512
+ ```
513
+
451
514
  ## `proca help [COMMAND]`
452
515
 
453
516
  Display help for proca.
@@ -882,39 +945,6 @@ DESCRIPTION
882
945
 
883
946
  _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.25/src/commands/plugins/update.ts)_
884
947
 
885
- ## `proca supporter count`
886
-
887
- counter of supporters
888
-
889
- ```
890
- USAGE
891
- $ proca supporter count [ID_NAME_DXID] [--json | --human | --csv] [--simplify] [-i <value>
892
- | -n <the_short_name> | -x <value>] [--org] [--area] [--number --without <value>]
893
-
894
- FLAGS
895
- -i, --id=<value>
896
- -n, --name=<the_short_name> name
897
- -x, --dxid=<value> dxid
898
- --area segment by area
899
- --number just return the number to add to the partner's counter
900
- --org segment by partner
901
- --without=<value> total to add to the partner's counter
902
-
903
- OUTPUT FLAGS
904
- --csv Format output as csv
905
- --human Format output to be read on screen by a human [default]
906
- --json Format output as json
907
- --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
908
-
909
- DESCRIPTION
910
- counter of supporters
911
-
912
- EXAMPLES
913
- $ proca supporter count --id <id of the campaign>
914
-
915
- $ proca supporter count --name <name of the campaign>
916
- ```
917
-
918
948
  ## `proca user get`
919
949
 
920
950
  fetch the information about a user
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "proca",
3
3
  "description": "Access the proca api",
4
- "version": "1.1.5",
4
+ "version": "1.2.1",
5
5
  "author": "Xavier",
6
6
  "bin": {
7
7
  "proca": "proca-cli"
@@ -8,7 +8,7 @@ import {
8
8
  } from "#src/queries/campaign.mjs";
9
9
  import { gql, query } from "#src/urql.mjs";
10
10
 
11
- export default class CampaignList extends Command {
11
+ export default class List extends Command {
12
12
  actionTypes = new Set();
13
13
 
14
14
  static args = {
@@ -85,7 +85,7 @@ export default class CampaignList extends Command {
85
85
  $orgName: String!
86
86
  $start: Int
87
87
  ) {
88
- exportActions(
88
+ actions (
89
89
  after: $after
90
90
  campaignId: $campaignId
91
91
  campaignName: $campaignName
@@ -142,7 +142,7 @@ export default class CampaignList extends Command {
142
142
  orgName: flags.org,
143
143
  start: flags.start,
144
144
  });
145
- return result.exportActions.map((d) => {
145
+ return result.actions.map((d) => {
146
146
  d.customFields = JSON.parse(d.customFields);
147
147
  if (!d.contact.publicKey) {
148
148
  const ref = d.contactRef;
@@ -0,0 +1,42 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import Command from "#src/procaCommand.mjs";
3
+ import { gql, query } from "#src/urql.mjs";
4
+
5
+ export default class CounterGet extends Command {
6
+ static description = "counter of supporters";
7
+
8
+ static examples = [
9
+ "<%= config.bin %> <%= command.id %> --id <id of the campaign>",
10
+ "<%= config.bin %> <%= command.id %> --name <name of the campaign>",
11
+ ];
12
+
13
+ static args = this.multiid();
14
+ static flags = {
15
+ // flag with no value (-f, --force)
16
+ ...this.flagify({ multiid: true }),
17
+ };
18
+
19
+ fetch = async (params) => {
20
+ const GetCounterDocument = gql`
21
+ query GetCounter($name: String, $id: Int) {
22
+ campaign(name: $name, id: $id) {
23
+ stats {
24
+ supporterCount
25
+ }
26
+ }
27
+ }
28
+ `;
29
+ const result = await query(GetCounterDocument, params);
30
+ return result.campaign.stats;
31
+ };
32
+
33
+ table = (r) => {
34
+ super.table(r, null, null);
35
+ };
36
+
37
+ async run() {
38
+ const { args, flags } = await this.parse();
39
+ const data = await this.fetch(flags);
40
+ return this.output(data);
41
+ }
42
+ }
@@ -0,0 +1,205 @@
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 {
5
+ FragmentOrg,
6
+ FragmentStats,
7
+ FragmentSummary,
8
+ } from "#src/queries/campaign.mjs";
9
+ import { gql, query } from "#src/urql.mjs";
10
+
11
+ export default class List extends Command {
12
+ actionTypes = new Set();
13
+
14
+ static args = {
15
+ title: Args.string({ description: "name of the campaign, % for wildchar" }),
16
+ };
17
+
18
+ static examples = ["<%= config.bin %> <%= command.id %> %pizza%"];
19
+
20
+ static flags = {
21
+ // flag with no value (-f, --force)
22
+ ...super.globalFlags,
23
+ org: Flags.string({
24
+ char: "o",
25
+ description: "campaigns of the organisation (coordinator or partner)",
26
+ required: true,
27
+ // exactlyOne: ["org", "title"],
28
+ helpValue: "<organisation name>",
29
+ }),
30
+ campaign: Flags.string({
31
+ char: "c",
32
+ description: "name of the campaign, % for wildchar",
33
+ helpValue: "<campaign title>",
34
+ }),
35
+ limit: Flags.string({
36
+ char: "n",
37
+ description: "max number of actions",
38
+ parse: (input) => Number.parseInt(input, 10),
39
+ }),
40
+ after: Flags.string({
41
+ description: "only actions after a date",
42
+ helpValue: "2025-04-09",
43
+ parse: (input) => new Date(input).toISOString(),
44
+ }),
45
+ today: Flags.boolean({
46
+ description: "only actions today",
47
+ exclusive: ["after"],
48
+ parse: (input) => `${new Date().toISOString().split("T")[0]}T00:00:00Z`,
49
+ }),
50
+ optin: Flags.boolean({
51
+ description: "only export the optin actions",
52
+ default: false,
53
+ }),
54
+ testing: Flags.boolean({
55
+ description: "also export the test actions",
56
+ default: false,
57
+ }),
58
+ doi: Flags.boolean({
59
+ description: "only export the double optin actions",
60
+ default: false,
61
+ }),
62
+ utm: Flags.boolean({
63
+ description: "display the utm tracking parameters",
64
+ default: true,
65
+ allowNo: true,
66
+ exclusive: ["simplify"],
67
+ }),
68
+ comment: Flags.boolean({
69
+ description: "display the comment",
70
+ default: true,
71
+ allowNo: true,
72
+ exclusive: ["simplify"],
73
+ }),
74
+ };
75
+
76
+ fetch = async (flags) => {
77
+ const Document = gql`
78
+ query (
79
+ $after: DateTime
80
+ $campaignId: Int
81
+ $campaignName: String
82
+ $includeTesting: Boolean
83
+ $limit: Int
84
+ $onlyDoubleOptIn: Boolean
85
+ $onlyOptIn: Boolean
86
+ $orgName: String!
87
+ $start: Int
88
+ ) {
89
+ contacts(
90
+ after: $after
91
+ campaignId: $campaignId
92
+ campaignName: $campaignName
93
+ includeTesting: $includeTesting
94
+ limit: $limit
95
+ onlyDoubleOptIn: $onlyDoubleOptIn
96
+ onlyOptIn: $onlyOptIn
97
+ orgName: $orgName
98
+ start: $start
99
+ ) {
100
+ actionId
101
+ actionPage {
102
+ locale
103
+ name
104
+ }
105
+ actionType
106
+ campaign {
107
+ name
108
+ }
109
+ contact {
110
+ contactRef
111
+ payload
112
+ nonce
113
+ publicKey {
114
+ public
115
+ }
116
+ }
117
+ createdAt
118
+ customFields
119
+ privacy {
120
+ emailStatus
121
+ emailStatusChanged
122
+ givenAt
123
+ optIn
124
+ withConsent
125
+ }
126
+ tracking {
127
+ campaign
128
+ content
129
+ medium
130
+ source
131
+ }
132
+ }
133
+ }
134
+ `;
135
+ const result = await query(Document, {
136
+ after: flags.after,
137
+ // "campaignId": 42,
138
+ campaignName: flags.campaign,
139
+ includeTesting: flags.testing,
140
+ limit: flags.limit,
141
+ onlyDoubleOptIn: flags.doi,
142
+ onlyOptIn: flags.optin,
143
+ orgName: flags.org,
144
+ start: flags.start,
145
+ });
146
+ return result.contacts.map((d) => {
147
+ d.customFields = JSON.parse(d.customFields);
148
+ if (!d.contact.publicKey) {
149
+ const ref = d.contactRef;
150
+ d.contact = JSON.parse(d.contact.payload);
151
+ d.contact.contactRef = ref;
152
+ } else {
153
+ this.error(
154
+ `encrypted contact we need the private key for ${d.contact.publicKey.public}`,
155
+ );
156
+ }
157
+ return d;
158
+ });
159
+ // return result.exportActions;
160
+ };
161
+
162
+ simplify = (d) => {
163
+ const result = {
164
+ id: d.actionId,
165
+ firstname: d.contact.firstName,
166
+ country: d.contact.country,
167
+ email: d.contact.email,
168
+ type: d.actionType,
169
+ date: d.createdAt,
170
+ campaign: d.campaign.name,
171
+ widget_id: d.actionPage.id,
172
+ widget: d.actionPage.name,
173
+ // customFields
174
+ };
175
+ if (this.flags.comment && d.customFields?.comment)
176
+ result.comment = d.customFields.comment;
177
+ if (d.customFields?.emailProvider)
178
+ result.provider = d.customFields.emailProvider;
179
+ if (this.flags.utm && d.tracking) {
180
+ result.utm_medium =
181
+ d.tracking.medium === "unknown" ? undefined : d.tracking.medium;
182
+ result.utm_source =
183
+ d.tracking.source === "unknown" ? undefined : d.tracking.source;
184
+ result.utm_campaign =
185
+ d.tracking.campaign === "unknown" ? undefined : d.tracking.campaign;
186
+ if (d.tracking.content)
187
+ result.utm_content =
188
+ d.tracking.content === "unknown" ? undefined : d.tracking.content;
189
+ }
190
+ return result;
191
+ };
192
+
193
+ _table = (r) => {
194
+ super.table(r, null, (table) => table.sort(["id|des"]).toString());
195
+ };
196
+
197
+ async run() {
198
+ const { args, flags } = await this.parse();
199
+ if (flags.today) flags.after = flags.today;
200
+ let data = [];
201
+
202
+ data = await this.fetch(flags);
203
+ return this.output(data);
204
+ }
205
+ }
@@ -1,96 +0,0 @@
1
- import { Args, Flags } from "@oclif/core";
2
- import Command from "#src/procaCommand.mjs";
3
- import { gql, query } from "#src/urql.mjs";
4
-
5
- export default class CounterGet extends Command {
6
- static description = "counter of supporters";
7
-
8
- static examples = [
9
- "<%= config.bin %> <%= command.id %> --id <id of the campaign>",
10
- "<%= config.bin %> <%= command.id %> --name <name of the campaign>",
11
- ];
12
-
13
- static args = this.multiid();
14
- static flags = {
15
- // flag with no value (-f, --force)
16
- ...this.flagify({ multiid: true }),
17
- org: Flags.boolean({
18
- description: "segment by partner",
19
- default: false,
20
- }),
21
- area: Flags.boolean({
22
- description: "segment by area",
23
- default: false,
24
- }),
25
- without: Flags.string({
26
- description: "total to add to the partner's counter",
27
- }),
28
- number: Flags.boolean({
29
- description: "just return the number to add to the partner's counter",
30
- dependsOn: ["without"],
31
- }),
32
- };
33
-
34
- fetchExcluding = async (params) => {
35
- const GetCounterDocument = gql`
36
- query GetCounter($name: String, $id: Int, $without: String!) {
37
- campaign(name: $name, id: $id) {
38
- stats {
39
- supporterCount
40
- supporterCountByOthers (orgName: $without)
41
- }
42
- }
43
- }`;
44
-
45
- const result = await query(GetCounterDocument, params);
46
- return result.campaign.stats;
47
- };
48
-
49
- fetch = async (params) => {
50
- const GetCounterDocument = gql`
51
- query GetCounter($name: String, $id: Int, $org: Boolean = false, $area: Boolean = false) {
52
- campaign(name: $name, id: $id) {
53
- stats {
54
- supporterCount
55
- supporterCountByOrg @include(if: $org) { org { name } count }
56
- supporterCountByArea @include(if: $area) { area count }
57
- }
58
- }
59
- }`;
60
-
61
- const result = await query(GetCounterDocument, params);
62
- return result.campaign.stats;
63
- };
64
-
65
- simplify = (d) => {
66
- const result = { total: d.supporterCount };
67
- d.supporterCountByOrg
68
- ?.sort((a, b) => b.count - a.count)
69
- .forEach((org) => {
70
- result[org.org.name] = org.count;
71
- });
72
- d.supporterCountByArea
73
- ?.sort((a, b) => b.count - a.count)
74
- .forEach((area) => {
75
- result[area.area] = area.count;
76
- });
77
- if (d.supporterCountByOthers) {
78
- result[`without ${this.flags.without}`] = d.supporterCountByOthers;
79
- }
80
- return result;
81
- };
82
- table = (r) => {
83
- super.table(r, null, null);
84
- };
85
-
86
- async run() {
87
- const { args, flags } = await this.parse();
88
- if (flags.without) {
89
- const data = await this.fetchExcluding(flags);
90
- if (flags.number) return console.log(data.supporterCountByOthers);
91
- return this.output(data);
92
- }
93
- const data = await this.fetch(flags);
94
- return this.output(data);
95
- }
96
- }