proca 0.1.3 → 0.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.
@@ -0,0 +1,186 @@
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 CampaignList 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
+ optin: Flags.boolean({
40
+ description: "only export the optin actions",
41
+ default: true,
42
+ }),
43
+ testing: Flags.boolean({
44
+ description: "also export the test actions",
45
+ default: false,
46
+ }),
47
+ doi: Flags.boolean({
48
+ description: "only export the double optin actions",
49
+ default: false,
50
+ }),
51
+ utm: Flags.boolean({
52
+ description: "display the utm tracking parameters",
53
+ default: true,
54
+ allowNo: true,
55
+ }),
56
+ };
57
+
58
+ fetch = async (flags) => {
59
+ const Document = gql`
60
+ query (
61
+ $after: DateTime
62
+ $campaignId: Int
63
+ $campaignName: String
64
+ $includeTesting: Boolean
65
+ $limit: Int
66
+ $onlyDoubleOptIn: Boolean
67
+ $onlyOptIn: Boolean
68
+ $orgName: String!
69
+ $start: Int
70
+ ) {
71
+ exportActions(
72
+ after: $after
73
+ campaignId: $campaignId
74
+ campaignName: $campaignName
75
+ includeTesting: $includeTesting
76
+ limit: $limit
77
+ onlyDoubleOptIn: $onlyDoubleOptIn
78
+ onlyOptIn: $onlyOptIn
79
+ orgName: $orgName
80
+ start: $start
81
+ ) {
82
+ actionId
83
+ actionPage {
84
+ locale
85
+ name
86
+ }
87
+ actionType
88
+ campaign {
89
+ name
90
+ }
91
+ contact {
92
+ contactRef
93
+ payload
94
+ nonce
95
+ publicKey {
96
+ public
97
+ }
98
+ }
99
+ createdAt
100
+ customFields
101
+ privacy {
102
+ emailStatus
103
+ emailStatusChanged
104
+ givenAt
105
+ optIn
106
+ withConsent
107
+ }
108
+ tracking {
109
+ campaign
110
+ content
111
+ medium
112
+ source
113
+ }
114
+ }
115
+ }
116
+ `;
117
+ const result = await query(Document, {
118
+ after: flags.after,
119
+ // "campaignId": 42,
120
+ campaignName: flags.campaign,
121
+ includeTesting: flags.testing,
122
+ limit: flags.limit,
123
+ onlyDoubleOptIn: flags.doi,
124
+ onlyOptIn: flags.optin,
125
+ orgName: flags.org,
126
+ start: flags.start,
127
+ });
128
+ console.log(result);
129
+ return result.exportActions.map((d) => {
130
+ d.customFields = JSON.parse(d.customFields);
131
+ if (!d.contact.publicKey) {
132
+ const ref = d.contactRef;
133
+ d.contact = JSON.parse(d.contact.payload);
134
+ d.contact.contactRef = ref;
135
+ } else {
136
+ this.error(
137
+ `encrypted contact we need the private key for ${d.contact.publicKey.public}`,
138
+ );
139
+ }
140
+ return d;
141
+ });
142
+ // return result.exportActions;
143
+ };
144
+
145
+ simplify = (d) => {
146
+ const result = {
147
+ id: d.actionId,
148
+ firstname: d.contact.firstName,
149
+ country: d.contact.country,
150
+ email: d.contact.email,
151
+ widget: d.actionPage.name,
152
+ type: d.actionType,
153
+ date: d.createdAt,
154
+ campaign: d.campaign.name,
155
+ widget_id: d.actionPage.id,
156
+ // customFields
157
+ };
158
+ if (d.customFields?.comment) result.comment = d.customFields.comment;
159
+ if (d.customFields?.emailProvider)
160
+ result.provider = d.customFields.emailProvider;
161
+ if (this.flags.utm && d.tracking) {
162
+ result.utm_medium =
163
+ d.tracking.medium === "unknown" ? undefined : d.tracking.medium;
164
+ result.utm_source =
165
+ d.tracking.source === "unknown" ? undefined : d.tracking.source;
166
+ result.utm_campaign =
167
+ d.tracking.campaign === "unknown" ? undefined : d.tracking.campaign;
168
+ if (d.tracking.content)
169
+ result.utm_content =
170
+ d.tracking.content === "unknown" ? undefined : d.tracking.content;
171
+ }
172
+ return result;
173
+ };
174
+
175
+ _table = (r) => {
176
+ super.table(r, null, (table) => table.sort(["id|des"]).toString());
177
+ };
178
+
179
+ async run() {
180
+ const { args, flags } = await this.parse();
181
+ let data = [];
182
+
183
+ data = await this.fetch(flags);
184
+ return this.output(data);
185
+ }
186
+ }
@@ -0,0 +1,61 @@
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, mutation } from "#src/urql.mjs";
10
+
11
+ export default class CampaignDelete extends Command {
12
+ actionTypes = new Set();
13
+
14
+ static args = {};
15
+
16
+ static description = "delete a campaign";
17
+
18
+ static examples = ["<%= config.bin %> <%= command.id %> -i 42"];
19
+
20
+ static flags = {
21
+ // flag with no value (-f, --force)
22
+ ...super.globalFlags,
23
+ id: Flags.string({
24
+ char: "i",
25
+ parse: (input) => {
26
+ return Number.parseInt(input, 10);
27
+ },
28
+ description: "id of the campaign",
29
+ exactlyOne: ["id", "name"],
30
+ helpValue: "<organisation name>",
31
+ }),
32
+ name: Flags.string({
33
+ char: "n",
34
+ description: "name of the campaign",
35
+ helpValue: "<campaign name>",
36
+ }),
37
+ };
38
+
39
+ mutate = async ({ id, name }) => {
40
+ const Document = gql`
41
+ mutation ($id: Int, $name: String) {
42
+ deleteCampaign(id: $id, name: $name)
43
+ }`;
44
+ const result = await mutation(Document, {
45
+ id: id,
46
+ name: name,
47
+ });
48
+ return result.deleteCampaign;
49
+ };
50
+
51
+ table = (r) => {
52
+ super.table(r, null, null);
53
+ };
54
+
55
+ async run() {
56
+ const { args, flags } = await this.parse();
57
+
58
+ const data = await this.mutate({ id: flags.id, name: flags.name });
59
+ return this.output(data);
60
+ }
61
+ }
@@ -49,7 +49,7 @@ export default class CampaignGet extends Command {
49
49
  }),
50
50
  };
51
51
 
52
- Get = async (id, name) => {
52
+ fetch = async ({ id, name }) => {
53
53
  const GetCampaignDocument = gql`
54
54
  query GetCampaign($id: Int, $name: String, $withStats: Boolean = false) {
55
55
  campaign (name: $name, id: $id) {
@@ -96,9 +96,9 @@ export default class CampaignGet extends Command {
96
96
 
97
97
  table = (r) => {
98
98
  r.config = JSON.parse(r.config);
99
- super.table(this.simplify(r), null, null);
99
+ super.table(r, null, null);
100
100
  if (this.flags.locale) {
101
- this.prettyJson(r.config.locales[this.flags.locale]);
101
+ this.prettyJson(r.config?.locales[this.flags.locale]);
102
102
  }
103
103
  if (this.flags.config) {
104
104
  r.config.locales = undefined;
@@ -109,7 +109,7 @@ export default class CampaignGet extends Command {
109
109
  async run() {
110
110
  const { args, flags } = await this.parse();
111
111
 
112
- const data = await this.Get(flags.id, flags.name);
112
+ const data = await this.fetch({ id: flags.id, name: flags.name });
113
113
  if (this.flags.stats) {
114
114
  data.stats.actionCount.forEach((d) => {
115
115
  //skip share_confirmed?
@@ -25,13 +25,12 @@ export default class CampaignList extends Command {
25
25
  org: Flags.string({
26
26
  char: "o",
27
27
  description: "campaigns of the organisation (coordinator or partner)",
28
- exclusive: ["title"],
28
+ exactlyOne: ["org", "title"],
29
29
  helpValue: "<organisation name>",
30
30
  }),
31
31
  title: Flags.string({
32
32
  char: "t",
33
33
  description: "name of the campaign, % for wildchar",
34
- exclusive: ["org"],
35
34
  helpValue: "<campaign title>",
36
35
  }),
37
36
  stats: Flags.boolean({
@@ -85,7 +84,7 @@ export default class CampaignList extends Command {
85
84
  //return result.campaigns.map (d => {d.config = JSON.parse(d.config); return d});
86
85
  };
87
86
 
88
- simplify = (d, context) => {
87
+ simplify = (d) => {
89
88
  const result = {
90
89
  id: d.id,
91
90
  Name: d.name,
@@ -107,15 +106,7 @@ export default class CampaignList extends Command {
107
106
  };
108
107
 
109
108
  table = (r) => {
110
- super.table(
111
- r,
112
- (d, cell) => {
113
- for (const [key, value] of Object.entries(this.simplify(d))) {
114
- cell(key, value);
115
- }
116
- },
117
- (table) => table.sort(["ID"]).toString(),
118
- );
109
+ super.table(r, null, (table) => table.sort(["id|des"]).toString());
119
110
  };
120
111
 
121
112
  async run() {
@@ -68,8 +68,6 @@ export default class CampaignList extends Command {
68
68
  };
69
69
 
70
70
  generate = function () {
71
- console.log(this.flags);
72
-
73
71
  const mapping = {
74
72
  REACT_APP_NAME: "proca",
75
73
  REACT_APP_API_URL: this.flags.url,
@@ -86,14 +84,9 @@ export default class CampaignList extends Command {
86
84
  async run() {
87
85
  const { args, flags } = await this.parse();
88
86
  const file = getFilename(this.config.configDir);
89
- let exists = true;
90
- const userConfig = getConfig({
91
- folder: this.config.configDir,
92
- onMissing: (missingFile) => {
93
- exists = false;
94
- },
95
- });
96
- if (exists && !this.flags.force) {
87
+
88
+ const userConfig = getConfig(file);
89
+ if (userConfig && !this.flags.force) {
97
90
  this.error("config file exists already", {
98
91
  code: "CONFIG_ERR",
99
92
  _ref: "README.md#",
@@ -0,0 +1,33 @@
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/widget.mjs";
5
+ import { gql, query } from "#src/urql.mjs";
6
+
7
+ export default class ConfigServer extends Command {
8
+ static description = "get the server config";
9
+
10
+ fetch = async () => {
11
+ const Document = gql`
12
+ query {
13
+ application {
14
+ logLevel
15
+ name
16
+ version
17
+ }
18
+ }`;
19
+ const result = await query(Document, {});
20
+ return result.application;
21
+ };
22
+
23
+ table = (r) => {
24
+ super.table(r, null, null);
25
+ };
26
+
27
+ async run() {
28
+ // const { args, flags } = await this.parse();
29
+
30
+ const data = await this.fetch();
31
+ return this.output(data);
32
+ }
33
+ }
@@ -0,0 +1,77 @@
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, query } from "#src/urql.mjs";
5
+
6
+ export default class UserList extends Command {
7
+ static description =
8
+ "fetch the information about the current user (based on the token)";
9
+
10
+ static examples = ["<%= config.bin %> <%= command.id %>"];
11
+
12
+ static flags = {
13
+ ...super.globalFlags,
14
+ };
15
+
16
+ fetch = async (params) => {
17
+ const Document = gql`
18
+ query {
19
+ currentUser {
20
+ apiToken {
21
+ expiresAt
22
+ }
23
+ email
24
+ id
25
+ isAdmin
26
+ jobTitle
27
+ phone
28
+ pictureUrl
29
+ roles {
30
+ role org {name}
31
+ }
32
+ }
33
+ }
34
+ `;
35
+ const result = await query(Document);
36
+ return result.currentUser;
37
+ //return result.users.map (d => {d.config = JSON.parse(d.config); return d});
38
+ };
39
+
40
+ simplify = (d) => {
41
+ console.log(d);
42
+ const result = {
43
+ id: d.id,
44
+ email: d.email,
45
+ };
46
+ if (d.apiToken) {
47
+ result.tokenExpire = "2024-11-09T11:22:22";
48
+ }
49
+ if (d.isAdmin) {
50
+ result.admin = true;
51
+ }
52
+ const roles = d.roles.reduce((acc, item) => {
53
+ if (!acc[item.role]) {
54
+ acc[item.role] = [];
55
+ }
56
+ acc[item.role].push(item.org.name);
57
+ return acc;
58
+ }, {});
59
+ for (const role in roles) {
60
+ result[role] = roles[role].join(",");
61
+ }
62
+ return result;
63
+ };
64
+
65
+ table = (r) => {
66
+ super.table(r, null, null);
67
+ };
68
+
69
+ async run() {
70
+ const { args, flags } = await this.parse();
71
+ let data = [];
72
+
73
+ data = await this.fetch();
74
+
75
+ return this.output(data);
76
+ }
77
+ }
@@ -0,0 +1,64 @@
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
+ import { getTwitter } from "#src/util/twitter.mjs";
6
+
7
+ export default class OrgAdd extends Command {
8
+ static args = {};
9
+
10
+
11
+ static examples = [
12
+ "<%= config.bin %> <%= command.id %> --twitter <twitter of the organisation>",
13
+ ];
14
+
15
+ static flags = {
16
+ // flag with no value (-f, --force)
17
+ ...super.globalFlags,
18
+ twitter: Flags.string({
19
+ description: "twitter account",
20
+ helpValue: "<screen name>",
21
+ }),
22
+ name: Flags.string({
23
+ char: "n",
24
+ description: "name of the org",
25
+ helpValue: "<org name>",
26
+ }),
27
+ };
28
+
29
+ create = async (_org) => {
30
+ const org = { ..._org, config: JSON.stringify(_org.config) };
31
+ console.log(org);
32
+
33
+ const AddOrgDocument = gql`
34
+ mutation ($org: OrgInput!) {
35
+ addOrg(input: $org) {
36
+ config
37
+ name
38
+ title
39
+ }
40
+ }
41
+ `;
42
+ const result = await mutation(AddOrgDocument, {
43
+ org,
44
+ });
45
+ console.log(result);
46
+ return result.org;
47
+ };
48
+
49
+ async run() {
50
+ const { args, flags } = await this.parse();
51
+ if (!flags.name && !flags.twitter) {
52
+ this.error("You must provide either --name or --twitter");
53
+ }
54
+
55
+ const org = { name: flags.twitter || flags.name, config: {} };
56
+
57
+ if (flags.twitter) {
58
+ await getTwitter(org);
59
+ }
60
+
61
+ const data = await this.create(org);
62
+ return this.output(data);
63
+ }
64
+ }
@@ -5,8 +5,6 @@ import Command from "#src/procaCommand.mjs";
5
5
  import { gql, query } from "#src/urql.mjs";
6
6
 
7
7
  export default class OrgGet extends Command {
8
- actionTypes = new Set();
9
-
10
8
  static args = {};
11
9
 
12
10
  static description = "view a org";
@@ -31,7 +29,7 @@ export default class OrgGet extends Command {
31
29
  allowNo: true,
32
30
  }),
33
31
  campaigns: Flags.boolean({
34
- default: true,
32
+ default: false,
35
33
  allowNo: true,
36
34
  }),
37
35
  widgets: Flags.boolean({
@@ -44,7 +42,7 @@ export default class OrgGet extends Command {
44
42
  }),
45
43
  };
46
44
 
47
- Get = async (name) => {
45
+ fetch = async (params) => {
48
46
  const GetOrgDocument = gql`
49
47
  query GetOrg($name: String!, $withCampaigns: Boolean = true) {
50
48
  org (name: $name) {
@@ -55,8 +53,8 @@ export default class OrgGet extends Command {
55
53
  }
56
54
  `;
57
55
  const result = await query(GetOrgDocument, {
58
- name: name,
59
- // withStats: this.flags.stats,
56
+ name: params.name,
57
+ withCampaigns: params.campaigns,
60
58
  });
61
59
  return result.org;
62
60
  };
@@ -82,7 +80,7 @@ export default class OrgGet extends Command {
82
80
 
83
81
  table = (r) => {
84
82
  r.config = JSON.parse(r.config);
85
- super.table(this.simplify(r), null, null);
83
+ super.table(r, null, null);
86
84
  if (this.flags.config) {
87
85
  r.config.locales = undefined;
88
86
  this.prettyJson(r.config);
@@ -91,7 +89,7 @@ export default class OrgGet extends Command {
91
89
 
92
90
  async run() {
93
91
  const { args, flags } = await this.parse();
94
- const data = await this.Get(flags.name);
92
+ const data = await this.fetch(flags);
95
93
  return this.output(data);
96
94
  }
97
95
  }
@@ -0,0 +1,50 @@
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 UserJoinOrg extends Command {
7
+ static description = "let a user join an organisation with a role";
8
+
9
+ static examples = ["<%= config.bin %> <%= command.id %>"];
10
+
11
+ static flags = {
12
+ ...super.globalFlags,
13
+ user: Flags.string({ description: "user email" }),
14
+ role: Flags.string({
15
+ description: "permission level in that org",
16
+ options: ["owner", "campaigner", "coordinator", "translator"],
17
+ }),
18
+ org: Flags.string({
19
+ char: "o",
20
+ description: "name of the org",
21
+ helpValue: "<org name>",
22
+ }),
23
+ };
24
+
25
+ mutate = async (params) => {
26
+ const Document = gql`
27
+ mutation ($org: String!, $user: String!, $role: String = "campaigner") {
28
+ addOrgUser (orgName: $org, input : { email: $user, role: $role }) {
29
+ status
30
+ }
31
+ }
32
+ `;
33
+ const result = await mutation(Document, {
34
+ user: params.user,
35
+ org: params.org,
36
+ role: params.role,
37
+ });
38
+ console.log(result);
39
+ return result.status;
40
+ //return result.users.map (d => {d.config = JSON.parse(d.config); return d});
41
+ };
42
+
43
+ async run() {
44
+ console.log("WIP, probably not working");
45
+ const { args, flags } = await this.parse();
46
+
47
+ data = await this.mutate(flags);
48
+ console.log(data);
49
+ }
50
+ }