proca 2.2.1 → 2.3.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 +134 -27
- package/package.json +2 -1
- package/src/commands/campaign/get.mjs +4 -2
- package/src/commands/campaign/status.mjs +37 -12
- package/src/commands/contact/delete.mjs +43 -0
- package/src/commands/contact/get.mjs +137 -0
- package/src/commands/contact/list.mjs +2 -11
- package/src/commands/org/get.mjs +5 -11
- package/src/commands/org/logo.js +116 -0
- package/src/commands/user/join.mjs +8 -11
- package/src/commands/widget/external/index.mjs +109 -0
- package/src/procaCommand.mjs +14 -5
- package/src/queries/campaign.mjs +1 -1
- package/src/urql.mjs +0 -1
package/README.md
CHANGED
|
@@ -74,6 +74,8 @@ you should also use the local proca-api in your [widget generator](https://githu
|
|
|
74
74
|
* [`proca config user`](#proca-config-user)
|
|
75
75
|
* [`proca contact area count`](#proca-contact-area-count)
|
|
76
76
|
* [`proca contact count`](#proca-contact-count)
|
|
77
|
+
* [`proca contact delete`](#proca-contact-delete)
|
|
78
|
+
* [`proca contact get`](#proca-contact-get)
|
|
77
79
|
* [`proca contact list`](#proca-contact-list)
|
|
78
80
|
* [`proca help [COMMAND]`](#proca-help-command)
|
|
79
81
|
* [`proca org add`](#proca-org-add)
|
|
@@ -81,6 +83,7 @@ you should also use the local proca-api in your [widget generator](https://githu
|
|
|
81
83
|
* [`proca org delete`](#proca-org-delete)
|
|
82
84
|
* [`proca org email`](#proca-org-email)
|
|
83
85
|
* [`proca org get`](#proca-org-get)
|
|
86
|
+
* [`proca org logo`](#proca-org-logo)
|
|
84
87
|
* [`proca org user get`](#proca-org-user-get)
|
|
85
88
|
* [`proca plugins`](#proca-plugins)
|
|
86
89
|
* [`proca plugins add PLUGIN`](#proca-plugins-add-plugin)
|
|
@@ -107,6 +110,7 @@ you should also use the local proca-api in your [widget generator](https://githu
|
|
|
107
110
|
* [`proca user whoami`](#proca-user-whoami)
|
|
108
111
|
* [`proca widget add`](#proca-widget-add)
|
|
109
112
|
* [`proca widget delete`](#proca-widget-delete)
|
|
113
|
+
* [`proca widget external`](#proca-widget-external)
|
|
110
114
|
* [`proca widget get`](#proca-widget-get)
|
|
111
115
|
* [`proca widget list`](#proca-widget-list)
|
|
112
116
|
* [`proca widget rebuild`](#proca-widget-rebuild)
|
|
@@ -337,12 +341,15 @@ EXAMPLES
|
|
|
337
341
|
```
|
|
338
342
|
USAGE
|
|
339
343
|
$ proca campaign close [ID_NAME_DXID] --status draft|live|closed|ignored [--json | --csv
|
|
340
|
-
| --markdown] [--env <value>] [--simplify]
|
|
344
|
+
| --markdown] [--env <value>] [--simplify] [-n <campaign>] [--start YYYY-MM-DD] [--end YYYY-MM-DD]
|
|
341
345
|
|
|
342
346
|
FLAGS
|
|
343
|
-
--
|
|
344
|
-
|
|
345
|
-
|
|
347
|
+
-n, --name=<campaign> name (technical short name, also called slug)
|
|
348
|
+
--end=YYYY-MM-DD end date of the campaign
|
|
349
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
350
|
+
--start=YYYY-MM-DD start date of the campaign
|
|
351
|
+
--status=<option> (required) Status to set
|
|
352
|
+
<options: draft|live|closed|ignored>
|
|
346
353
|
|
|
347
354
|
OUTPUT FLAGS
|
|
348
355
|
--csv Format output as csv
|
|
@@ -354,9 +361,7 @@ ALIASES
|
|
|
354
361
|
$ proca campaign close
|
|
355
362
|
|
|
356
363
|
EXAMPLES
|
|
357
|
-
$ proca campaign close -name <campaign>
|
|
358
|
-
|
|
359
|
-
$ proca campaign close -i <campaign_id>
|
|
364
|
+
$ proca campaign close -name <campaign> --end=2025-01-02 --status=close
|
|
360
365
|
```
|
|
361
366
|
|
|
362
367
|
## `proca campaign copy`
|
|
@@ -526,12 +531,15 @@ EXAMPLES
|
|
|
526
531
|
```
|
|
527
532
|
USAGE
|
|
528
533
|
$ proca campaign status [ID_NAME_DXID] --status draft|live|closed|ignored [--json | --csv
|
|
529
|
-
| --markdown] [--env <value>] [--simplify]
|
|
534
|
+
| --markdown] [--env <value>] [--simplify] [-n <campaign>] [--start YYYY-MM-DD] [--end YYYY-MM-DD]
|
|
530
535
|
|
|
531
536
|
FLAGS
|
|
532
|
-
--
|
|
533
|
-
|
|
534
|
-
|
|
537
|
+
-n, --name=<campaign> name (technical short name, also called slug)
|
|
538
|
+
--end=YYYY-MM-DD end date of the campaign
|
|
539
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
540
|
+
--start=YYYY-MM-DD start date of the campaign
|
|
541
|
+
--status=<option> (required) Status to set
|
|
542
|
+
<options: draft|live|closed|ignored>
|
|
535
543
|
|
|
536
544
|
OUTPUT FLAGS
|
|
537
545
|
--csv Format output as csv
|
|
@@ -543,9 +551,7 @@ ALIASES
|
|
|
543
551
|
$ proca campaign close
|
|
544
552
|
|
|
545
553
|
EXAMPLES
|
|
546
|
-
$ proca campaign status -name <campaign>
|
|
547
|
-
|
|
548
|
-
$ proca campaign status -i <campaign_id>
|
|
554
|
+
$ proca campaign status -name <campaign> --end=2025-01-02 --status=close
|
|
549
555
|
```
|
|
550
556
|
|
|
551
557
|
## `proca campaign widget archive`
|
|
@@ -961,18 +967,58 @@ EXAMPLES
|
|
|
961
967
|
$ proca contact count --name <name of the campaign>
|
|
962
968
|
```
|
|
963
969
|
|
|
970
|
+
## `proca contact delete`
|
|
971
|
+
|
|
972
|
+
```
|
|
973
|
+
USAGE
|
|
974
|
+
$ proca contact delete -c from contact get [--json | --csv | --markdown] [--env <value>]
|
|
975
|
+
[--simplify] [-n <org>]
|
|
976
|
+
|
|
977
|
+
FLAGS
|
|
978
|
+
-c, --ref=from contact get (required) contact reference
|
|
979
|
+
-n, --name=<org> name (technical short name, also called slug)
|
|
980
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
981
|
+
|
|
982
|
+
OUTPUT FLAGS
|
|
983
|
+
--csv Format output as csv
|
|
984
|
+
--json Format output as json
|
|
985
|
+
--markdown Format output as markdown table
|
|
986
|
+
--[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
## `proca contact get`
|
|
990
|
+
|
|
991
|
+
```
|
|
992
|
+
USAGE
|
|
993
|
+
$ proca contact get -e <supporter@example.org> [--json | --csv | --markdown] [--env
|
|
994
|
+
<value>] [-n <org>] [--utm | --simplify] [--comment | ]
|
|
995
|
+
|
|
996
|
+
FLAGS
|
|
997
|
+
-e, --email=<supporter@example.org> (required) email of the supporter
|
|
998
|
+
-n, --name=<org> name (technical short name, also called slug)
|
|
999
|
+
--[no-]comment display the comment
|
|
1000
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
1001
|
+
--[no-]utm display the utm tracking parameters
|
|
1002
|
+
|
|
1003
|
+
OUTPUT FLAGS
|
|
1004
|
+
--csv Format output as csv
|
|
1005
|
+
--json Format output as json
|
|
1006
|
+
--markdown Format output as markdown table
|
|
1007
|
+
--[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
|
|
1008
|
+
```
|
|
1009
|
+
|
|
964
1010
|
## `proca contact list`
|
|
965
1011
|
|
|
966
1012
|
```
|
|
967
1013
|
USAGE
|
|
968
|
-
$ proca contact list
|
|
969
|
-
<
|
|
970
|
-
|
|
1014
|
+
$ proca contact list [--json | --csv | --markdown] [--env <value>] [-n <org>] [-c
|
|
1015
|
+
<campaign title>] [-n <value>] [--today | --after 2025-04-09] [--optin] [--testing] [--doi] [--utm | --simplify]
|
|
1016
|
+
[--comment | ]
|
|
971
1017
|
|
|
972
1018
|
FLAGS
|
|
973
1019
|
-c, --campaign=<campaign title> name of the campaign, % for wildchar
|
|
974
1020
|
-n, --limit=<value> max number of actions
|
|
975
|
-
-
|
|
1021
|
+
-n, --name=<org> name (technical short name, also called slug)
|
|
976
1022
|
--after=2025-04-09 only actions after a date
|
|
977
1023
|
--[no-]comment display the comment
|
|
978
1024
|
--doi only export the double optin actions
|
|
@@ -987,9 +1033,6 @@ OUTPUT FLAGS
|
|
|
987
1033
|
--json Format output as json
|
|
988
1034
|
--markdown Format output as markdown table
|
|
989
1035
|
--[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
|
|
990
|
-
|
|
991
|
-
EXAMPLES
|
|
992
|
-
$ proca contact list %pizza%
|
|
993
1036
|
```
|
|
994
1037
|
|
|
995
1038
|
## `proca help [COMMAND]`
|
|
@@ -1126,10 +1169,10 @@ view a org
|
|
|
1126
1169
|
```
|
|
1127
1170
|
USAGE
|
|
1128
1171
|
$ proca org get [ID_NAME_DXID] [--json | --csv | --markdown] [--env <value>]
|
|
1129
|
-
[--simplify] [-n <org
|
|
1172
|
+
[--simplify] [-n <org>] [--config] [--personaldata] [--processing] [--keys] [--campaigns] [--users]
|
|
1130
1173
|
|
|
1131
1174
|
FLAGS
|
|
1132
|
-
-n, --name=<org
|
|
1175
|
+
-n, --name=<org> name (technical short name, also called slug)
|
|
1133
1176
|
--[no-]campaigns
|
|
1134
1177
|
--[no-]config display the config
|
|
1135
1178
|
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
@@ -1151,6 +1194,36 @@ EXAMPLES
|
|
|
1151
1194
|
$ proca org get <name of the ngo>
|
|
1152
1195
|
```
|
|
1153
1196
|
|
|
1197
|
+
## `proca org logo`
|
|
1198
|
+
|
|
1199
|
+
add a logo to the org
|
|
1200
|
+
|
|
1201
|
+
```
|
|
1202
|
+
USAGE
|
|
1203
|
+
$ proca org logo [ID_NAME_DXID] [--json | --csv | --markdown] [--env <value>]
|
|
1204
|
+
[--simplify] [-n <org>] [--url <value>] [--update]
|
|
1205
|
+
|
|
1206
|
+
FLAGS
|
|
1207
|
+
-n, --name=<org> name (technical short name, also called slug)
|
|
1208
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
1209
|
+
--[no-]update use that url (and update it)
|
|
1210
|
+
--url=<value> use that url (and update it)
|
|
1211
|
+
|
|
1212
|
+
OUTPUT FLAGS
|
|
1213
|
+
--csv Format output as csv
|
|
1214
|
+
--json Format output as json
|
|
1215
|
+
--markdown Format output as markdown table
|
|
1216
|
+
--[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
|
|
1217
|
+
|
|
1218
|
+
DESCRIPTION
|
|
1219
|
+
add a logo to the org
|
|
1220
|
+
|
|
1221
|
+
EXAMPLES
|
|
1222
|
+
$ proca org logo <name of the ngo>
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
_See code: [src/commands/org/logo.ts](https://github.com/fixthestatusquo/proca-cli/blob/v2.3.1/src/commands/org/logo.ts)_
|
|
1226
|
+
|
|
1154
1227
|
## `proca org user get`
|
|
1155
1228
|
|
|
1156
1229
|
list all the users
|
|
@@ -1654,12 +1727,12 @@ let a user join an organisation with a role
|
|
|
1654
1727
|
|
|
1655
1728
|
```
|
|
1656
1729
|
USAGE
|
|
1657
|
-
$ proca user join
|
|
1658
|
-
[--simplify] [--role owner|campaigner|coordinator|translator] [-u <user email>]
|
|
1730
|
+
$ proca user join [ID_NAME_DXID] [--json | --csv | --markdown] [--env <value>]
|
|
1731
|
+
[--simplify] [-n <org>] [--role owner|campaigner|coordinator|translator] [-u <user email>]
|
|
1659
1732
|
|
|
1660
1733
|
FLAGS
|
|
1661
|
-
-
|
|
1662
|
-
-u, --user=<user email> email
|
|
1734
|
+
-n, --name=<org> name (technical short name, also called slug)
|
|
1735
|
+
-u, --user=<user email> email, default current user
|
|
1663
1736
|
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
1664
1737
|
--role=<option> [default: campaigner] permission level in that org
|
|
1665
1738
|
<options: owner|campaigner|coordinator|translator>
|
|
@@ -1863,6 +1936,40 @@ DESCRIPTION
|
|
|
1863
1936
|
Delete a widget
|
|
1864
1937
|
```
|
|
1865
1938
|
|
|
1939
|
+
## `proca widget external`
|
|
1940
|
+
|
|
1941
|
+
Pull external counter and save it into a widget extra Supporter
|
|
1942
|
+
|
|
1943
|
+
```
|
|
1944
|
+
USAGE
|
|
1945
|
+
$ proca widget external [ID_NAME_DXID] [--json | --csv | --markdown] [--env <value>]
|
|
1946
|
+
[--simplify] [-i <value> | -n <the_short_name> | -x <value>] [-u <value>] [--path object.sub-object.total] [--total
|
|
1947
|
+
<value>] [--timeout <value>] [--dry-run]
|
|
1948
|
+
|
|
1949
|
+
FLAGS
|
|
1950
|
+
-i, --id=<value>
|
|
1951
|
+
-n, --name=<the_short_name> name (technical short name, also called slug)
|
|
1952
|
+
-u, --url=<value> API endpoint URL to pull from
|
|
1953
|
+
-x, --dxid=<value> dxid
|
|
1954
|
+
--dry-run just fetch, don't update
|
|
1955
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
1956
|
+
--path=object.sub-object.total dot notation path to the counter field in the json returned by the url
|
|
1957
|
+
--timeout=<value> [default: 10000] Request timeout in milliseconds
|
|
1958
|
+
--total=<value> number to add to the total
|
|
1959
|
+
|
|
1960
|
+
OUTPUT FLAGS
|
|
1961
|
+
--csv Format output as csv
|
|
1962
|
+
--json Format output as json
|
|
1963
|
+
--markdown Format output as markdown table
|
|
1964
|
+
--[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
|
|
1965
|
+
|
|
1966
|
+
DESCRIPTION
|
|
1967
|
+
Pull external counter and save it into a widget extra Supporter
|
|
1968
|
+
|
|
1969
|
+
EXAMPLES
|
|
1970
|
+
$ proca widget external --url https://mitmachen.wwf.de/node/506/polling
|
|
1971
|
+
```
|
|
1972
|
+
|
|
1866
1973
|
## `proca widget get`
|
|
1867
1974
|
|
|
1868
1975
|
view a widget
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "proca",
|
|
3
3
|
"description": "Access the proca api",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.3.1",
|
|
5
5
|
"author": "Xavier",
|
|
6
6
|
"bin": {
|
|
7
7
|
"proca": "proca-cli"
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"fast-csv": "^5.0.1",
|
|
20
20
|
"graphql": "^16.10.0",
|
|
21
21
|
"merge-anything": "^6.0.6",
|
|
22
|
+
"object-path": "^0.11.8",
|
|
22
23
|
"prompts": "^2.4.2",
|
|
23
24
|
"typescript": "^5.7.3",
|
|
24
25
|
"urql": "^4.1.0"
|
|
@@ -74,6 +74,8 @@ export default class CampaignGet extends Command {
|
|
|
74
74
|
Status: d.status,
|
|
75
75
|
locales: d.config.locales && Object.keys(d.config.locales).join(" "),
|
|
76
76
|
journey: d.config.journey?.join(" → "),
|
|
77
|
+
from: d.start?.substring(0, 10),
|
|
78
|
+
to: d.end?.substring(0, 10),
|
|
77
79
|
};
|
|
78
80
|
if (d.mtt) {
|
|
79
81
|
// we have an mtt
|
|
@@ -83,8 +85,8 @@ export default class CampaignGet extends Command {
|
|
|
83
85
|
minute: "2-digit",
|
|
84
86
|
hour12: false,
|
|
85
87
|
});
|
|
86
|
-
result
|
|
87
|
-
result
|
|
88
|
+
result["mtt from"] = d.mtt.startAt.substring(0, 10);
|
|
89
|
+
result["mttt to"] = d.mtt.endAt.substring(0, 10);
|
|
88
90
|
result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
|
|
89
91
|
result["test email"] = d.mtt.testEmail;
|
|
90
92
|
result["mtt template"] = d.mtt.template;
|
|
@@ -8,8 +8,7 @@ export default class CampaignStatus extends Command {
|
|
|
8
8
|
static aliases = ["campaign:close"];
|
|
9
9
|
|
|
10
10
|
static examples = [
|
|
11
|
-
"<%= config.bin %> <%= command.id %> -name <campaign>",
|
|
12
|
-
"<%= config.bin %> <%= command.id %> -i <campaign_id>",
|
|
11
|
+
"<%= config.bin %> <%= command.id %> -name <campaign> --end=2025-01-02 --status=close",
|
|
13
12
|
];
|
|
14
13
|
|
|
15
14
|
static isCloseCommand =
|
|
@@ -18,46 +17,72 @@ export default class CampaignStatus extends Command {
|
|
|
18
17
|
this.id?.includes("close");
|
|
19
18
|
|
|
20
19
|
static flags = {
|
|
20
|
+
...this.flagify({ name: "campaign" }),
|
|
21
21
|
status: Flags.string({
|
|
22
|
-
...this.flagify({ multiid: true }),
|
|
23
22
|
description: "Status to set",
|
|
24
23
|
required: true,
|
|
25
24
|
default: this.isCloseCommand ? "close" : undefined,
|
|
26
25
|
options: ["draft", "live", "closed", "ignored"],
|
|
27
26
|
}),
|
|
27
|
+
start: Flags.string({
|
|
28
|
+
description: "start date of the campaign",
|
|
29
|
+
helpValue: "YYYY-MM-DD",
|
|
30
|
+
parse: async (input) => {
|
|
31
|
+
const date = new Date(input);
|
|
32
|
+
if (Number.isNaN(date.getTime())) {
|
|
33
|
+
throw new Error(`Invalid date: ${input}`);
|
|
34
|
+
}
|
|
35
|
+
return date;
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
end: Flags.string({
|
|
39
|
+
description: "end date of the campaign",
|
|
40
|
+
helpValue: "YYYY-MM-DD",
|
|
41
|
+
parse: async (input) => {
|
|
42
|
+
const date = new Date(input);
|
|
43
|
+
if (Number.isNaN(date.getTime())) {
|
|
44
|
+
throw new Error(`Invalid date: ${input}`);
|
|
45
|
+
}
|
|
46
|
+
return date;
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
28
49
|
};
|
|
29
50
|
|
|
30
51
|
updateStatus = async (props) => {
|
|
31
52
|
const Query = gql`
|
|
32
53
|
mutation (
|
|
33
|
-
$id: Int
|
|
54
|
+
$id: Int
|
|
34
55
|
$name: String
|
|
35
|
-
$
|
|
56
|
+
$input: CampaignInput!
|
|
36
57
|
) {
|
|
37
|
-
updateCampaign (id:$id,
|
|
58
|
+
updateCampaign (id:$id, name: $name, input: $input) {
|
|
38
59
|
name
|
|
39
60
|
org {name}
|
|
40
61
|
status
|
|
62
|
+
start
|
|
63
|
+
end
|
|
41
64
|
title
|
|
42
65
|
}
|
|
43
|
-
}
|
|
44
|
-
|
|
66
|
+
}`;
|
|
67
|
+
const input = {
|
|
68
|
+
status: props.status.toUpperCase(),
|
|
69
|
+
};
|
|
45
70
|
|
|
46
71
|
const result = await mutation(Query, {
|
|
47
72
|
// org: props.org,
|
|
48
73
|
id: props.id,
|
|
49
74
|
name: props.name,
|
|
50
|
-
|
|
75
|
+
input: input,
|
|
51
76
|
});
|
|
52
77
|
|
|
53
|
-
console.log("result", result);
|
|
54
78
|
return result.updateCampaign;
|
|
55
79
|
};
|
|
56
80
|
|
|
57
81
|
async run() {
|
|
58
|
-
const {
|
|
82
|
+
const { flags } = await this.parse();
|
|
59
83
|
|
|
60
84
|
const data = await this.updateStatus(flags);
|
|
61
|
-
|
|
85
|
+
|
|
86
|
+
return this.output(data, { single: true });
|
|
62
87
|
}
|
|
63
88
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { error, stdout, ux } from "@oclif/core/ux";
|
|
3
|
+
import { formatDistanceToNowStrict } from "date-fns";
|
|
4
|
+
import Command from "#src/procaCommand.mjs";
|
|
5
|
+
import {
|
|
6
|
+
FragmentOrg,
|
|
7
|
+
FragmentStats,
|
|
8
|
+
FragmentSummary,
|
|
9
|
+
} from "#src/queries/campaign.mjs";
|
|
10
|
+
import { gql, mutation } from "#src/urql.mjs";
|
|
11
|
+
|
|
12
|
+
export default class Delete extends Command {
|
|
13
|
+
static flags = {
|
|
14
|
+
...this.flagify({ name: "org", char: "o" }),
|
|
15
|
+
ref: Flags.string({
|
|
16
|
+
char: "c",
|
|
17
|
+
required: true,
|
|
18
|
+
description: "contact reference",
|
|
19
|
+
helpValue: "from contact get",
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
delete = async (ref, org) => {
|
|
24
|
+
const DeleteDocument = gql`mutation delete($ref: String!, $org: String!) {
|
|
25
|
+
deleteContact (contactRef: $ref, orgName: $org)
|
|
26
|
+
}`;
|
|
27
|
+
|
|
28
|
+
const r = await mutation(DeleteDocument, {
|
|
29
|
+
ref,
|
|
30
|
+
org,
|
|
31
|
+
});
|
|
32
|
+
if (r.errors) {
|
|
33
|
+
throw new Error(r.errors[0].message || "can't delete");
|
|
34
|
+
}
|
|
35
|
+
return r;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
async run() {
|
|
39
|
+
const { flags } = await this.parse();
|
|
40
|
+
const data = await this.delete(flags.ref, flags.name);
|
|
41
|
+
return this.output(data);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Args, Flags } from "@oclif/core";
|
|
2
|
+
import { error, stdout, ux } from "@oclif/core/ux";
|
|
3
|
+
import { formatDistanceToNowStrict } from "date-fns";
|
|
4
|
+
import Command from "#src/procaCommand.mjs";
|
|
5
|
+
import {
|
|
6
|
+
FragmentOrg,
|
|
7
|
+
FragmentStats,
|
|
8
|
+
FragmentSummary,
|
|
9
|
+
} from "#src/queries/campaign.mjs";
|
|
10
|
+
import { gql, query } from "#src/urql.mjs";
|
|
11
|
+
|
|
12
|
+
export default class Get extends Command {
|
|
13
|
+
static flags = {
|
|
14
|
+
...this.flagify({ name: "org", char: "o" }),
|
|
15
|
+
email: Flags.string({
|
|
16
|
+
char: "e",
|
|
17
|
+
required: true,
|
|
18
|
+
description: "email of the supporter",
|
|
19
|
+
helpValue: "<supporter@example.org>",
|
|
20
|
+
}),
|
|
21
|
+
utm: Flags.boolean({
|
|
22
|
+
description: "display the utm tracking parameters",
|
|
23
|
+
default: true,
|
|
24
|
+
allowNo: true,
|
|
25
|
+
exclusive: ["simplify"],
|
|
26
|
+
}),
|
|
27
|
+
comment: Flags.boolean({
|
|
28
|
+
description: "display the comment",
|
|
29
|
+
default: true,
|
|
30
|
+
allowNo: true,
|
|
31
|
+
exclusive: ["simplify"],
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
fetch = async (flags) => {
|
|
36
|
+
const Document = gql`
|
|
37
|
+
query (
|
|
38
|
+
$orgName: String!
|
|
39
|
+
$email: String!
|
|
40
|
+
) {
|
|
41
|
+
contacts(
|
|
42
|
+
orgName: $orgName
|
|
43
|
+
email: $email
|
|
44
|
+
) {
|
|
45
|
+
actionId
|
|
46
|
+
actionPage {
|
|
47
|
+
id
|
|
48
|
+
locale
|
|
49
|
+
name
|
|
50
|
+
}
|
|
51
|
+
actionType
|
|
52
|
+
campaign {
|
|
53
|
+
name
|
|
54
|
+
}
|
|
55
|
+
contact {
|
|
56
|
+
contactRef
|
|
57
|
+
payload
|
|
58
|
+
nonce
|
|
59
|
+
publicKey {
|
|
60
|
+
public
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
createdAt
|
|
64
|
+
customFields
|
|
65
|
+
privacy {
|
|
66
|
+
emailStatus
|
|
67
|
+
emailStatusChanged
|
|
68
|
+
givenAt
|
|
69
|
+
optIn
|
|
70
|
+
withConsent
|
|
71
|
+
}
|
|
72
|
+
tracking {
|
|
73
|
+
campaign
|
|
74
|
+
content
|
|
75
|
+
medium
|
|
76
|
+
source
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
const result = await query(Document, {
|
|
82
|
+
orgName: flags.name,
|
|
83
|
+
email: flags.email,
|
|
84
|
+
});
|
|
85
|
+
return result.contacts.map((d) => {
|
|
86
|
+
d.customFields = JSON.parse(d.customFields);
|
|
87
|
+
if (!d.contact.publicKey) {
|
|
88
|
+
const ref = d.contact.contactRef;
|
|
89
|
+
d.contact = JSON.parse(d.contact.payload);
|
|
90
|
+
d.contact.contactRef = ref;
|
|
91
|
+
} else {
|
|
92
|
+
this.error(
|
|
93
|
+
`encrypted contact we need the private key for ${d.contact.publicKey.public}`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return d;
|
|
97
|
+
});
|
|
98
|
+
// return result.exportActions;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
simplify = (d) => {
|
|
102
|
+
const result = {
|
|
103
|
+
contactRef: d.contact.contactRef,
|
|
104
|
+
firstname: d.contact.firstName,
|
|
105
|
+
country: d.contact.country,
|
|
106
|
+
email: d.contact.email,
|
|
107
|
+
type: d.actionType,
|
|
108
|
+
date: formatDistanceToNowStrict(d.createdAt),
|
|
109
|
+
campaign: !this.flags.campaign && d.campaign.name,
|
|
110
|
+
widget_id: d.actionPage.id,
|
|
111
|
+
widget: d.actionPage.name,
|
|
112
|
+
// customFields
|
|
113
|
+
};
|
|
114
|
+
if (this.flags.comment && d.customFields?.comment)
|
|
115
|
+
result.comment = d.customFields.comment;
|
|
116
|
+
if (this.flags.utm && d.tracking) {
|
|
117
|
+
result.utm_medium =
|
|
118
|
+
d.tracking.medium === "unknown" ? undefined : d.tracking.medium;
|
|
119
|
+
result.utm_source =
|
|
120
|
+
d.tracking.source === "unknown" ? undefined : d.tracking.source;
|
|
121
|
+
result.utm_campaign =
|
|
122
|
+
d.tracking.campaign === "unknown" ? undefined : d.tracking.campaign;
|
|
123
|
+
if (d.tracking.content)
|
|
124
|
+
result.utm_content =
|
|
125
|
+
d.tracking.content === "unknown" ? undefined : d.tracking.content;
|
|
126
|
+
}
|
|
127
|
+
if (d.customFields?.emailProvider)
|
|
128
|
+
result.provider = d.customFields.emailProvider;
|
|
129
|
+
return result;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
async run() {
|
|
133
|
+
const { flags } = await this.parse();
|
|
134
|
+
const data = await this.fetch(flags);
|
|
135
|
+
return this.output(data, { single: true });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -12,18 +12,9 @@ import { gql, query } from "#src/urql.mjs";
|
|
|
12
12
|
export default class List extends Command {
|
|
13
13
|
actionTypes = new Set();
|
|
14
14
|
|
|
15
|
-
static examples = ["<%= config.bin %> <%= command.id %> %pizza%"];
|
|
16
|
-
|
|
17
15
|
static flags = {
|
|
18
16
|
// flag with no value (-f, --force)
|
|
19
|
-
...
|
|
20
|
-
org: Flags.string({
|
|
21
|
-
char: "o",
|
|
22
|
-
description: "campaigns of the organisation (coordinator or partner)",
|
|
23
|
-
required: true,
|
|
24
|
-
// exactlyOne: ["org", "title"],
|
|
25
|
-
helpValue: "<organisation name>",
|
|
26
|
-
}),
|
|
17
|
+
...this.flagify({ name: "org", char: "o" }),
|
|
27
18
|
campaign: Flags.string({
|
|
28
19
|
char: "c",
|
|
29
20
|
description: "name of the campaign, % for wildchar",
|
|
@@ -138,7 +129,7 @@ export default class List extends Command {
|
|
|
138
129
|
limit: flags.limit,
|
|
139
130
|
onlyDoubleOptIn: flags.doi,
|
|
140
131
|
onlyOptIn: flags.optin,
|
|
141
|
-
orgName: flags.
|
|
132
|
+
orgName: flags.name,
|
|
142
133
|
start: flags.start,
|
|
143
134
|
});
|
|
144
135
|
return result.contacts.map((d) => {
|
package/src/commands/org/get.mjs
CHANGED
|
@@ -18,13 +18,7 @@ export default class OrgGet extends Command {
|
|
|
18
18
|
|
|
19
19
|
static flags = {
|
|
20
20
|
// flag with no value (-f, --force)
|
|
21
|
-
...this.flagify({ multiid: false }),
|
|
22
|
-
name: Flags.string({
|
|
23
|
-
char: "n",
|
|
24
|
-
charAliases: ["o"],
|
|
25
|
-
description: "name of the org",
|
|
26
|
-
helpValue: "<org name>",
|
|
27
|
-
}),
|
|
21
|
+
...this.flagify({ multiid: false, name: "org", char: "o" }),
|
|
28
22
|
config: Flags.boolean({
|
|
29
23
|
description: "display the config",
|
|
30
24
|
default: false,
|
|
@@ -113,8 +107,10 @@ export default class OrgGet extends Command {
|
|
|
113
107
|
simplify = (d) => {
|
|
114
108
|
const result = {
|
|
115
109
|
id: d.id,
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
name: d.name,
|
|
111
|
+
title: d.title,
|
|
112
|
+
url: d.config?.url,
|
|
113
|
+
logo: d.config?.logo,
|
|
118
114
|
"can targets reply?": d.replyEnabled ? true : undefined,
|
|
119
115
|
"confirm actions?": d.supporterConfirm
|
|
120
116
|
? d.supporterConfirmTemplate
|
|
@@ -142,9 +138,7 @@ export default class OrgGet extends Command {
|
|
|
142
138
|
};
|
|
143
139
|
|
|
144
140
|
async run() {
|
|
145
|
-
console.log("starting");
|
|
146
141
|
const { flags } = await this.parse();
|
|
147
|
-
console.log("flags", this.Flags);
|
|
148
142
|
|
|
149
143
|
const data = await this.fetch(flags);
|
|
150
144
|
return this.output(data);
|
|
@@ -0,0 +1,116 @@
|
|
|
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 {FragmentSummary,} from "#src/queries/org.mjs";
|
|
5
|
+
import { gql, mutation } from "#src/urql.mjs";
|
|
6
|
+
import { getOrg } from "./get.mjs";
|
|
7
|
+
|
|
8
|
+
export default class OrgLogo extends Command {
|
|
9
|
+
static description = "add a logo to the org";
|
|
10
|
+
|
|
11
|
+
static examples = ["<%= config.bin %> <%= command.id %> <name of the ngo>"];
|
|
12
|
+
|
|
13
|
+
static args = this.multiid();
|
|
14
|
+
|
|
15
|
+
static flags = {
|
|
16
|
+
// flag with no value (-f, --force)
|
|
17
|
+
...this.flagify({ multiid: false, name: "org", char: "o" }),
|
|
18
|
+
url: Flags.string({
|
|
19
|
+
description: "use that url (and update it)",
|
|
20
|
+
}),
|
|
21
|
+
update: Flags.boolean({
|
|
22
|
+
default: true,
|
|
23
|
+
allowNo: true,
|
|
24
|
+
description: "use that url (and update it)",
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
toProxyUrl = (pic) => {
|
|
29
|
+
const url = new URL(pic);
|
|
30
|
+
if (!url.hostname.endsWith("gstatic.com")) return googleUrl;
|
|
31
|
+
const sub = url.hostname.split(".")[0];
|
|
32
|
+
const domain = new URL(url.searchParams.get("url")).hostname;
|
|
33
|
+
return `https://pic.proca.app/favicon/${sub}/${domain}`;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
fetchLogoUrl = async (domain) => {
|
|
37
|
+
const res = await fetch(
|
|
38
|
+
`https://www.google.com/s2/favicons?sz=128&domain=${domain}`,
|
|
39
|
+
{ redirect: "manual" }, // don't follow — we want the Location header
|
|
40
|
+
);
|
|
41
|
+
const location = res.headers.get("location");
|
|
42
|
+
if (!location) throw new Error(`No redirect for ${domain}`);
|
|
43
|
+
return this.toProxyUrl(location);
|
|
44
|
+
};
|
|
45
|
+
update = async ({ name, config }) => {
|
|
46
|
+
const input = {};
|
|
47
|
+
|
|
48
|
+
input.config = typeof config === "string" ? config : JSON.stringify(config);
|
|
49
|
+
|
|
50
|
+
const Document = gql`
|
|
51
|
+
mutation update(
|
|
52
|
+
$orgName: String!
|
|
53
|
+
$input: OrgInput!
|
|
54
|
+
) {
|
|
55
|
+
updateOrg(
|
|
56
|
+
name: $orgName
|
|
57
|
+
input: $input
|
|
58
|
+
) {
|
|
59
|
+
id, name, config
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
console.log({
|
|
66
|
+
orgName: name,
|
|
67
|
+
input,
|
|
68
|
+
});
|
|
69
|
+
const r = await mutation(Document, {
|
|
70
|
+
orgName: name,
|
|
71
|
+
input,
|
|
72
|
+
});
|
|
73
|
+
return { id: r.updateOrg };
|
|
74
|
+
} catch (e) {
|
|
75
|
+
const err = e.graphQLErrors?.[0];
|
|
76
|
+
|
|
77
|
+
if (err?.extensions?.code === "permission_denied") {
|
|
78
|
+
this.error(`permission denied to update org ${name}`);
|
|
79
|
+
}
|
|
80
|
+
throw new Error(err?.message ?? "failed to update org");
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
table = (r) => {
|
|
85
|
+
super.table(r, null, null);
|
|
86
|
+
if (this.flags.config) {
|
|
87
|
+
r.config.locales = undefined;
|
|
88
|
+
this.prettyJson(r.config);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
async run() {
|
|
93
|
+
const { flags } = await this.parse();
|
|
94
|
+
let logo;
|
|
95
|
+
let org;
|
|
96
|
+
if (flags.url) {
|
|
97
|
+
logo = await this.fetchLogoUrl(flags.url);
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
org = await getOrg(flags);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
this.output({ error: "user not a member of org", org: flags.name, logo });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (!logo) logo = await this.fetchLogoUrl(org.config.url);
|
|
106
|
+
org.config.logo = logo;
|
|
107
|
+
if (flags.update) {
|
|
108
|
+
if (!org.config.url) {
|
|
109
|
+
org.config.url = flags.url;
|
|
110
|
+
}
|
|
111
|
+
const r = this.update({ name: flags.name, config: org.config });
|
|
112
|
+
return this.output(r);
|
|
113
|
+
}
|
|
114
|
+
return this.output({ logo, name: flags.name });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -8,22 +8,19 @@ export default class UserJoinOrg extends Command {
|
|
|
8
8
|
|
|
9
9
|
static examples = ["<%= config.bin %> <%= command.id %>"];
|
|
10
10
|
|
|
11
|
+
static args = this.multiid();
|
|
12
|
+
|
|
11
13
|
static flags = {
|
|
12
|
-
|
|
14
|
+
// flag with no value (-f, --force)
|
|
15
|
+
...this.flagify({ multiid: false, name: "org", char: "o" }),
|
|
13
16
|
role: Flags.string({
|
|
14
17
|
description: "permission level in that org",
|
|
15
18
|
default: "campaigner",
|
|
16
19
|
options: ["owner", "campaigner", "coordinator", "translator"],
|
|
17
20
|
}),
|
|
18
|
-
org: Flags.string({
|
|
19
|
-
char: "o",
|
|
20
|
-
required: true,
|
|
21
|
-
description: "name of the org",
|
|
22
|
-
helpValue: "<org name>",
|
|
23
|
-
}),
|
|
24
21
|
user: Flags.string({
|
|
25
22
|
char: "u",
|
|
26
|
-
description: "email",
|
|
23
|
+
description: "email, default current user",
|
|
27
24
|
helpValue: "<user email>",
|
|
28
25
|
}),
|
|
29
26
|
};
|
|
@@ -58,7 +55,7 @@ mutation ($org: String!, $user: String!, $role: String = "campaigner") {
|
|
|
58
55
|
`;
|
|
59
56
|
const result = await mutation(Document, {
|
|
60
57
|
user: params.user,
|
|
61
|
-
org: params.
|
|
58
|
+
org: params.name,
|
|
62
59
|
role: params.role,
|
|
63
60
|
});
|
|
64
61
|
return result.addOrgUser;
|
|
@@ -69,10 +66,10 @@ mutation ($org: String!, $user: String!, $role: String = "campaigner") {
|
|
|
69
66
|
};
|
|
70
67
|
|
|
71
68
|
async run() {
|
|
72
|
-
const {
|
|
69
|
+
const { flags } = await this.parse();
|
|
73
70
|
let data = undefined;
|
|
74
71
|
if (!flags.user) {
|
|
75
|
-
data = await this.join(flags.
|
|
72
|
+
data = await this.join(flags.name);
|
|
76
73
|
} else {
|
|
77
74
|
data = await this.mutate(flags);
|
|
78
75
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { Flags } from "@oclif/core";
|
|
3
|
+
import oPath from "object-path";
|
|
4
|
+
import { updateCounter } from "#src/commands/widget/update/external.mjs";
|
|
5
|
+
import Command from "#src/procaCommand.mjs";
|
|
6
|
+
|
|
7
|
+
export default class CounterExternal extends Command {
|
|
8
|
+
static description =
|
|
9
|
+
"Pull external counter and save it into a widget extra Supporter";
|
|
10
|
+
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> <%= command.id %> --url https://mitmachen.wwf.de/node/506/polling",
|
|
13
|
+
];
|
|
14
|
+
static args = this.multiid();
|
|
15
|
+
|
|
16
|
+
static flags = {
|
|
17
|
+
...this.flagify({ multiid: true }),
|
|
18
|
+
url: Flags.string({
|
|
19
|
+
char: "u",
|
|
20
|
+
description: "API endpoint URL to pull from",
|
|
21
|
+
relationships: [{ type: "some", flags: ["path", "dry-run"] }],
|
|
22
|
+
}),
|
|
23
|
+
path: Flags.string({
|
|
24
|
+
helpValue: "object.sub-object.total",
|
|
25
|
+
description:
|
|
26
|
+
"dot notation path to the counter field in the json returned by the url",
|
|
27
|
+
}),
|
|
28
|
+
total: Flags.integer({
|
|
29
|
+
description: "number to add to the total",
|
|
30
|
+
relationships: [
|
|
31
|
+
// define complex relationships between flags
|
|
32
|
+
{ type: "none", flags: ["url", "path"] },
|
|
33
|
+
],
|
|
34
|
+
}),
|
|
35
|
+
timeout: Flags.integer({
|
|
36
|
+
description: "Request timeout in milliseconds",
|
|
37
|
+
default: 10000,
|
|
38
|
+
}),
|
|
39
|
+
"dry-run": Flags.boolean({
|
|
40
|
+
description: "just fetch, don't update",
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
async fetchCounter({ url, path, timeout, "dry-run": verbose }) {
|
|
45
|
+
const response = await fetch(url, {
|
|
46
|
+
timeout,
|
|
47
|
+
headers: {
|
|
48
|
+
"User-Agent": "proca",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
this.error(`API request failed with status ${response.status}`, {
|
|
54
|
+
exit: 1,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
if (verbose) {
|
|
60
|
+
this.log(JSON.stringify(data, null, 2));
|
|
61
|
+
}
|
|
62
|
+
const counter = oPath.get(data, path);
|
|
63
|
+
if (Number.isNaN(Number.parseFloat(counter)) || !Number.isFinite(counter)) {
|
|
64
|
+
this.error(`Could not extract value from ${counter} at ${path}`, {
|
|
65
|
+
exit: 1,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return Number.parseFloat(counter);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async getCounterConfig(id) {
|
|
72
|
+
const folder = this.procaConfig.folder;
|
|
73
|
+
const filePath = `${folder}/${id}.json`;
|
|
74
|
+
|
|
75
|
+
const data = await readFile(filePath, "utf8");
|
|
76
|
+
const jsonData = JSON.parse(data);
|
|
77
|
+
return jsonData.component.counter;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async run() {
|
|
81
|
+
const { flags } = await this.parse(CounterExternal);
|
|
82
|
+
let counter = undefined;
|
|
83
|
+
if (!flags.url) {
|
|
84
|
+
const config = await this.getCounterConfig(flags.id);
|
|
85
|
+
flags.url = config.url;
|
|
86
|
+
flags.path = config.path;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (flags.url) {
|
|
90
|
+
counter = await this.fetchCounter(flags);
|
|
91
|
+
}
|
|
92
|
+
if (flags.total) {
|
|
93
|
+
counter = flags.total;
|
|
94
|
+
}
|
|
95
|
+
if (flags["dry-run"]) {
|
|
96
|
+
return this.output(
|
|
97
|
+
{
|
|
98
|
+
counter,
|
|
99
|
+
url: flags.url,
|
|
100
|
+
// response: JSON.stringify(data, null, 2),
|
|
101
|
+
},
|
|
102
|
+
{ single: true },
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const updated = await updateCounter(flags.id, counter);
|
|
107
|
+
return this.output(updated, { single: true });
|
|
108
|
+
}
|
|
109
|
+
}
|
package/src/procaCommand.mjs
CHANGED
|
@@ -50,16 +50,18 @@ class ProcaCommand extends Command {
|
|
|
50
50
|
return args;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
static flagify({ multiid = false, name = false } = {}) {
|
|
53
|
+
static flagify({ multiid = false, name = false, char } = {}) {
|
|
54
54
|
const flags = Object.assign({}, ProcaCommand.baseFlags);
|
|
55
55
|
if (name || multiid) {
|
|
56
56
|
flags.name = Flags.string({
|
|
57
57
|
char: "n",
|
|
58
|
+
charAliases: char ? ["n", char] : undefined,
|
|
58
59
|
description: "name (technical short name, also called slug)",
|
|
59
60
|
helpValue: typeof name === "string" ? `<${name}>` : "<the_short_name>",
|
|
60
61
|
parse: (input) => ProcaCommand.safeName(input),
|
|
61
62
|
});
|
|
62
63
|
}
|
|
64
|
+
|
|
63
65
|
if (multiid) {
|
|
64
66
|
flags.id = Flags.string({
|
|
65
67
|
char: "i",
|
|
@@ -157,6 +159,10 @@ class ProcaCommand extends Command {
|
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
if (err.networkError) {
|
|
162
|
+
if (err.response.status === 500) {
|
|
163
|
+
this.error("500 Internal Server Error", { exit: err.code || 1 });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
160
166
|
this.info("Looks like there’s a problem with your internet connection");
|
|
161
167
|
this.error(err.networkError.cause, { exit: err.code || 1 });
|
|
162
168
|
}
|
|
@@ -286,7 +292,7 @@ class ProcaCommand extends Command {
|
|
|
286
292
|
table(data, transformRow, print = (table) => table.toString()) {
|
|
287
293
|
if (!transformRow) {
|
|
288
294
|
if (this.flags.simplify !== false) {
|
|
289
|
-
transformRow = (d, cell
|
|
295
|
+
transformRow = (d, cell) => {
|
|
290
296
|
const r = this.simplify(d);
|
|
291
297
|
if (r === null) return null;
|
|
292
298
|
for (const [key, value] of Object.entries(r)) {
|
|
@@ -295,7 +301,7 @@ class ProcaCommand extends Command {
|
|
|
295
301
|
return true;
|
|
296
302
|
};
|
|
297
303
|
} else {
|
|
298
|
-
transformRow = (d, cell
|
|
304
|
+
transformRow = (d, cell) => {
|
|
299
305
|
for (const [key, value] of Object.entries(this.flatten(d))) {
|
|
300
306
|
cell(key, value);
|
|
301
307
|
}
|
|
@@ -316,15 +322,18 @@ class ProcaCommand extends Command {
|
|
|
316
322
|
}, this);
|
|
317
323
|
return this.newRow();
|
|
318
324
|
};
|
|
319
|
-
|
|
320
325
|
this.log(Table.print(data, transformRow, print));
|
|
321
326
|
}
|
|
322
327
|
|
|
323
328
|
single = (r) => {
|
|
324
|
-
this.table(r, null, null);
|
|
329
|
+
return this.table(r[0], null, null);
|
|
325
330
|
};
|
|
326
331
|
|
|
327
332
|
async output(data, { single = false } = {}) {
|
|
333
|
+
if (!Array.isArray(data)) {
|
|
334
|
+
data = [data];
|
|
335
|
+
single = true;
|
|
336
|
+
}
|
|
328
337
|
if (this.format === "json") {
|
|
329
338
|
if (this.flags.simplify)
|
|
330
339
|
return data?.map(this.simplify) || this.simplify(data);
|
package/src/queries/campaign.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { gql } from "#src/urql.mjs";
|
|
2
2
|
|
|
3
|
-
export const FragmentSummary = gql`fragment Summary on Campaign {id name title externalId status}`;
|
|
3
|
+
export const FragmentSummary = gql`fragment Summary on Campaign {id name title externalId status start end}`;
|
|
4
4
|
|
|
5
5
|
export const FragmentMtt = gql`
|
|
6
6
|
fragment Mtt on PrivateCampaign {
|
package/src/urql.mjs
CHANGED
|
@@ -51,7 +51,6 @@ export const query = async (query, payload) => {
|
|
|
51
51
|
export const mutation = async (mutation, payload) => {
|
|
52
52
|
const result = await client.mutation(mutation, payload).toPromise();
|
|
53
53
|
if (result.error) {
|
|
54
|
-
console.log("error", result.error);
|
|
55
54
|
throw result.error;
|
|
56
55
|
}
|
|
57
56
|
return result.data;
|