proca 1.1.5 → 1.2.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
@@ -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.0 linux-x64 node-v20.12.2
22
22
  $ proca --help [COMMAND]
23
23
  USAGE
24
24
  $ proca COMMAND
@@ -58,6 +58,7 @@ 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 list [TITLE]`](#proca-contact-list-title)
61
62
  * [`proca help [COMMAND]`](#proca-help-command)
62
63
  * [`proca org add`](#proca-org-add)
63
64
  * [`proca org crm`](#proca-org-crm)
@@ -74,7 +75,6 @@ USAGE
74
75
  * [`proca plugins uninstall [PLUGIN]`](#proca-plugins-uninstall-plugin)
75
76
  * [`proca plugins unlink [PLUGIN]`](#proca-plugins-unlink-plugin)
76
77
  * [`proca plugins update`](#proca-plugins-update)
77
- * [`proca supporter count`](#proca-supporter-count)
78
78
  * [`proca user get`](#proca-user-get)
79
79
  * [`proca user leave`](#proca-user-leave)
80
80
  * [`proca user list`](#proca-user-list)
@@ -448,6 +448,39 @@ EXAMPLES
448
448
  $ proca config user
449
449
  ```
450
450
 
451
+ ## `proca contact list [TITLE]`
452
+
453
+ ```
454
+ USAGE
455
+ $ proca contact list [TITLE] -o <organisation name> [--json | --human | --csv] [-c
456
+ <campaign title>] [--limit <value>] [--today | --after 2025-04-09] [--optin] [--testing] [--doi] [--utm |
457
+ --simplify] [--comment | ]
458
+
459
+ ARGUMENTS
460
+ TITLE name of the campaign, % for wildchar
461
+
462
+ FLAGS
463
+ -c, --campaign=<campaign title> name of the campaign, % for wildchar
464
+ -o, --org=<organisation name> (required) campaigns of the organisation (coordinator or partner)
465
+ --after=2025-04-09 only actions after a date
466
+ --[no-]comment display the comment
467
+ --doi only export the double optin actions
468
+ --limit=<value> max number of actions
469
+ --optin only export the optin actions
470
+ --testing also export the test actions
471
+ --today only actions today
472
+ --[no-]utm display the utm tracking parameters
473
+
474
+ OUTPUT FLAGS
475
+ --csv Format output as csv
476
+ --human Format output to be read on screen by a human [default]
477
+ --json Format output as json
478
+ --[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
479
+
480
+ EXAMPLES
481
+ $ proca contact list %pizza%
482
+ ```
483
+
451
484
  ## `proca help [COMMAND]`
452
485
 
453
486
  Display help for proca.
@@ -882,39 +915,6 @@ DESCRIPTION
882
915
 
883
916
  _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.25/src/commands/plugins/update.ts)_
884
917
 
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
918
  ## `proca user get`
919
919
 
920
920
  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.0",
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,204 @@
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
+ description: "max number of actions",
37
+ parse: (input) => Number.parseInt(input, 10),
38
+ }),
39
+ after: Flags.string({
40
+ description: "only actions after a date",
41
+ helpValue: "2025-04-09",
42
+ parse: (input) => new Date(input).toISOString(),
43
+ }),
44
+ today: Flags.boolean({
45
+ description: "only actions today",
46
+ exclusive: ["after"],
47
+ parse: (input) => `${new Date().toISOString().split("T")[0]}T00:00:00Z`,
48
+ }),
49
+ optin: Flags.boolean({
50
+ description: "only export the optin actions",
51
+ default: false,
52
+ }),
53
+ testing: Flags.boolean({
54
+ description: "also export the test actions",
55
+ default: false,
56
+ }),
57
+ doi: Flags.boolean({
58
+ description: "only export the double optin actions",
59
+ default: false,
60
+ }),
61
+ utm: Flags.boolean({
62
+ description: "display the utm tracking parameters",
63
+ default: true,
64
+ allowNo: true,
65
+ exclusive: ["simplify"],
66
+ }),
67
+ comment: Flags.boolean({
68
+ description: "display the comment",
69
+ default: true,
70
+ allowNo: true,
71
+ exclusive: ["simplify"],
72
+ }),
73
+ };
74
+
75
+ fetch = async (flags) => {
76
+ const Document = gql`
77
+ query (
78
+ $after: DateTime
79
+ $campaignId: Int
80
+ $campaignName: String
81
+ $includeTesting: Boolean
82
+ $limit: Int
83
+ $onlyDoubleOptIn: Boolean
84
+ $onlyOptIn: Boolean
85
+ $orgName: String!
86
+ $start: Int
87
+ ) {
88
+ contacts(
89
+ after: $after
90
+ campaignId: $campaignId
91
+ campaignName: $campaignName
92
+ includeTesting: $includeTesting
93
+ limit: $limit
94
+ onlyDoubleOptIn: $onlyDoubleOptIn
95
+ onlyOptIn: $onlyOptIn
96
+ orgName: $orgName
97
+ start: $start
98
+ ) {
99
+ actionId
100
+ actionPage {
101
+ locale
102
+ name
103
+ }
104
+ actionType
105
+ campaign {
106
+ name
107
+ }
108
+ contact {
109
+ contactRef
110
+ payload
111
+ nonce
112
+ publicKey {
113
+ public
114
+ }
115
+ }
116
+ createdAt
117
+ customFields
118
+ privacy {
119
+ emailStatus
120
+ emailStatusChanged
121
+ givenAt
122
+ optIn
123
+ withConsent
124
+ }
125
+ tracking {
126
+ campaign
127
+ content
128
+ medium
129
+ source
130
+ }
131
+ }
132
+ }
133
+ `;
134
+ const result = await query(Document, {
135
+ after: flags.after,
136
+ // "campaignId": 42,
137
+ campaignName: flags.campaign,
138
+ includeTesting: flags.testing,
139
+ limit: flags.limit,
140
+ onlyDoubleOptIn: flags.doi,
141
+ onlyOptIn: flags.optin,
142
+ orgName: flags.org,
143
+ start: flags.start,
144
+ });
145
+ return result.contacts.map((d) => {
146
+ d.customFields = JSON.parse(d.customFields);
147
+ if (!d.contact.publicKey) {
148
+ const ref = d.contactRef;
149
+ d.contact = JSON.parse(d.contact.payload);
150
+ d.contact.contactRef = ref;
151
+ } else {
152
+ this.error(
153
+ `encrypted contact we need the private key for ${d.contact.publicKey.public}`,
154
+ );
155
+ }
156
+ return d;
157
+ });
158
+ // return result.exportActions;
159
+ };
160
+
161
+ simplify = (d) => {
162
+ const result = {
163
+ id: d.actionId,
164
+ firstname: d.contact.firstName,
165
+ country: d.contact.country,
166
+ email: d.contact.email,
167
+ type: d.actionType,
168
+ date: d.createdAt,
169
+ campaign: d.campaign.name,
170
+ widget_id: d.actionPage.id,
171
+ widget: d.actionPage.name,
172
+ // customFields
173
+ };
174
+ if (this.flags.comment && d.customFields?.comment)
175
+ result.comment = d.customFields.comment;
176
+ if (d.customFields?.emailProvider)
177
+ result.provider = d.customFields.emailProvider;
178
+ if (this.flags.utm && d.tracking) {
179
+ result.utm_medium =
180
+ d.tracking.medium === "unknown" ? undefined : d.tracking.medium;
181
+ result.utm_source =
182
+ d.tracking.source === "unknown" ? undefined : d.tracking.source;
183
+ result.utm_campaign =
184
+ d.tracking.campaign === "unknown" ? undefined : d.tracking.campaign;
185
+ if (d.tracking.content)
186
+ result.utm_content =
187
+ d.tracking.content === "unknown" ? undefined : d.tracking.content;
188
+ }
189
+ return result;
190
+ };
191
+
192
+ _table = (r) => {
193
+ super.table(r, null, (table) => table.sort(["id|des"]).toString());
194
+ };
195
+
196
+ async run() {
197
+ const { args, flags } = await this.parse();
198
+ if (flags.today) flags.after = flags.today;
199
+ let data = [];
200
+
201
+ data = await this.fetch(flags);
202
+ return this.output(data);
203
+ }
204
+ }
@@ -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
- }