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,91 @@
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 = "fetch the information about a user";
8
+
9
+ static examples = ["<%= config.bin %> <%= command.id %>"];
10
+
11
+ static flags = {
12
+ ...super.globalFlags,
13
+ email: Flags.string({ description: "user email" }),
14
+ org: Flags.string({
15
+ char: "o",
16
+ description: "name of the org",
17
+ exactlyOne: ["email", "id", "org"],
18
+ helpValue: "<org name>",
19
+ }),
20
+ id: Flags.string({
21
+ char: "i",
22
+ parse: (input) => {
23
+ return Number.parseInt(input, 10);
24
+ },
25
+ description: "id of the user",
26
+ }),
27
+ };
28
+
29
+ fetch = async (params) => {
30
+ const Document = gql`
31
+ query ($email: String, $org: String, $id: Int) {
32
+ users (select: {email: $email, orgName: $org, id: $id}) {
33
+ apiToken {
34
+ expiresAt
35
+ }
36
+ email
37
+ id
38
+ isAdmin
39
+ jobTitle
40
+ phone
41
+ pictureUrl
42
+ roles {
43
+ role org {name}
44
+ }
45
+ }
46
+ }
47
+ `;
48
+ const result = await query(Document, {
49
+ org: params.org,
50
+ id: params.id,
51
+ email: params.email,
52
+ });
53
+ return result.users[0];
54
+ };
55
+
56
+ simplify = (d) => {
57
+ const result = {
58
+ id: d.id,
59
+ email: d.email,
60
+ };
61
+ if (d.apiToken) {
62
+ result.tokenExpire = d.apiToken.expire;
63
+ }
64
+ if (d.isAdmin) {
65
+ result.admin = true;
66
+ }
67
+ const roles = d.roles.reduce((acc, item) => {
68
+ if (!acc[item.role]) {
69
+ acc[item.role] = [];
70
+ }
71
+ acc[item.role].push(item.org.name);
72
+ return acc;
73
+ }, {});
74
+ for (const role in roles) {
75
+ result[role] = roles[role].join(",");
76
+ }
77
+ return result;
78
+ };
79
+
80
+ table = (r) => {
81
+ super.table(r, null, null);
82
+ };
83
+
84
+ async run() {
85
+ const { args, flags } = await this.parse();
86
+ let data = [];
87
+
88
+ data = await this.fetch(flags);
89
+ return this.output(data);
90
+ }
91
+ }
@@ -0,0 +1,52 @@
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 OrgLeave extends Command {
7
+ actionTypes = new Set();
8
+
9
+ static args = {};
10
+
11
+ static description = "leave a org";
12
+
13
+ static examples = ["<%= config.bin %> <%= command.id %> -i 42"];
14
+
15
+ static flags = {
16
+ // flag with no value (-f, --force)
17
+ ...super.globalFlags,
18
+ email: Flags.string({
19
+ description: "email",
20
+ required: true,
21
+ helpValue: "<user email>",
22
+ }),
23
+ org: Flags.string({
24
+ char: "o",
25
+ description: "name of the org",
26
+ required: true,
27
+ helpValue: "<org name>",
28
+ }),
29
+ };
30
+
31
+ mutate = async ({ email, org }) => {
32
+ const Document = gql`
33
+ mutation ($email: String!, $org: String!) {
34
+ deleteOrgUser(email: $email, orgName: $org) { status }
35
+ }`;
36
+ const result = await mutation(Document, {
37
+ email: email,
38
+ org: org,
39
+ });
40
+ return result.deleteOrgUser.status;
41
+ };
42
+
43
+ table = (r) => {
44
+ super.table(r, null, null);
45
+ };
46
+
47
+ async run() {
48
+ const { args, flags } = await this.parse();
49
+ const data = await this.mutate(flags);
50
+ return data;
51
+ }
52
+ }
@@ -0,0 +1,71 @@
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
+ actionTypes = new Set();
8
+
9
+ static description = "list all the users";
10
+
11
+ static examples = ["<%= config.bin %> <%= command.id %> %pizza%"];
12
+
13
+ static flags = {
14
+ // flag with no value (-f, --force)
15
+ ...super.globalFlags,
16
+ org: Flags.string({
17
+ char: "o",
18
+ description: "organisation",
19
+ required: true,
20
+ }),
21
+ };
22
+
23
+ fetch = async (org) => {
24
+ const SearchUsersDocument = gql`
25
+ query ($org: String!) {
26
+ users(select: {orgName: $org}) {
27
+ apiToken {
28
+ expiresAt
29
+ }
30
+ email
31
+ id
32
+ isAdmin
33
+ jobTitle
34
+ phone
35
+ pictureUrl
36
+ roles {
37
+ role org {name}
38
+ }
39
+ }
40
+ }
41
+ `;
42
+ const result = await query(SearchUsersDocument, { org: org });
43
+ return result.users;
44
+ //return result.users.map (d => {d.config = JSON.parse(d.config); return d});
45
+ };
46
+
47
+ simplify = (d) => {
48
+ const result = {
49
+ id: d.id,
50
+ email: d.email,
51
+ };
52
+ result.role = d.roles.filter((d) => d.org.name === this.flags.org)[0].role;
53
+ if (d.isAdmin) {
54
+ result.superadmin = true;
55
+ }
56
+ if (d.apiToken) {
57
+ result.tokenExpire = d.apiToken.tokenExpire;
58
+ }
59
+
60
+ return result;
61
+ };
62
+
63
+ async run() {
64
+ const { args, flags } = await this.parse(UserList);
65
+ let data = [];
66
+
67
+ data = await this.fetch(flags.org);
68
+
69
+ return this.output(data);
70
+ }
71
+ }
@@ -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/widget.mjs";
5
+ import { gql, query } from "#src/urql.mjs";
6
+
7
+ export default class WidgetList extends Command {
8
+ static description = "list all the widgets of an org or campaign";
9
+
10
+ static examples = ["<%= config.bin %> <%= command.id %> -o <organisation>"];
11
+
12
+ static flags = {
13
+ // flag with no value (-f, --force)
14
+ ...super.globalFlags,
15
+ org: Flags.string({
16
+ char: "o",
17
+ exactlyOne: ["campaign", "org"],
18
+ description: "widgets of the organisation (coordinator or partner)",
19
+ helpValue: "<organisation name>",
20
+ // required: true,
21
+ }),
22
+ campaign: Flags.string({
23
+ char: "c",
24
+ description: "widgets of the campaign (coordinator or partner)",
25
+ helpValue: "<campaign name>",
26
+ // required: true,
27
+ }),
28
+ config: Flags.boolean({
29
+ description: "get the config",
30
+ default: false,
31
+ allowNo: true,
32
+ }),
33
+ };
34
+ fetchCampaign = async (name) => {
35
+ const Document = gql`
36
+ query SearchWidgets($campaign: String!, $withConfig: Boolean!) {
37
+ campaign (name:$campaign) { ...on PrivateCampaign {
38
+ actionPages {
39
+ ...Summary
40
+ config @include(if: $withConfig)
41
+ thankYouTemplate
42
+ thankYouTemplateRef
43
+ ...on PrivateActionPage {
44
+ supporterConfirmTemplate
45
+ }
46
+ }}
47
+ }
48
+ ${FragmentSummary}
49
+ }`;
50
+ const result = await query(Document, {
51
+ campaign: name,
52
+ withConfig: this.flags.config,
53
+ });
54
+ return result.campaign.actionPages;
55
+ };
56
+
57
+ fetchOrg = async (name) => {
58
+ const Document = gql`
59
+ query SearchWidgets($org: String!, $withConfig: Boolean!) {
60
+ org (name:$org) {
61
+ actionPages {
62
+ ...Summary
63
+ config @include(if: $withConfig)
64
+ thankYouTemplate
65
+ thankYouTemplateRef
66
+ ...on PrivateActionPage {
67
+ supporterConfirmTemplate
68
+ }
69
+ }
70
+ }
71
+ ${FragmentSummary}
72
+ }`;
73
+ const result = await query(Document, {
74
+ org: name,
75
+ withConfig: this.flags.config,
76
+ });
77
+ return result.org.actionPages;
78
+ };
79
+
80
+ simplify = (d) => {
81
+ const result = {
82
+ id: d.id,
83
+ name: d.name,
84
+ locale: d.locale,
85
+ status: d.status.toLowerCase(),
86
+ location: d.location?.startsWith("https://widget.proca.app")
87
+ ? undefined
88
+ : d.location || undefined,
89
+ // live: d.live,
90
+
91
+ // thankYouTemplate: d.thankYouTemplate || undefined,
92
+ // thankYouTemplateRef: d.thankYouTemplateRef || undefined,
93
+ // supporterConfirmTemplate: d.supporterConfirmTemplate || undefined,
94
+ };
95
+ if (d.extraSupporters > 0) {
96
+ result.extra = d.extraSupporters;
97
+ }
98
+ if (d.journey) result.journey = d.journey.join(" → ");
99
+
100
+ if (this.flags.config) {
101
+ }
102
+ return result;
103
+ };
104
+
105
+ table = (r) => {
106
+ super.table(r, null, (table) => table.sort(["id|des"]).toString());
107
+ };
108
+
109
+ async run() {
110
+ const { flags, args } = await this.parse(WidgetList);
111
+ let data = [];
112
+ if (flags.org) data = await this.fetchOrg(flags.org);
113
+ if (flags.campaign) data = await this.fetchCampaign(flags.campaign);
114
+ return this.output(data);
115
+ }
116
+ }
package/src/config.mjs CHANGED
@@ -19,7 +19,7 @@ export const get = (file) => {
19
19
  const userConfig = readFileSync(file, "utf8");
20
20
  return userConfig;
21
21
  } catch (e) {
22
- if (e.code === "ENOENT" && onMissing) {
22
+ if (e.code === "ENOENT") {
23
23
  return undefined;
24
24
  }
25
25
  throw e;
@@ -0,0 +1,10 @@
1
+ import { Config, Help } from "@oclif/core";
2
+
3
+ console.log("help command");
4
+
5
+ export default class CustomHelp extends Help {
6
+ async showHelp(argv) {
7
+ // Always include --all flag to show all commands
8
+ await super.showHelp([...argv, "--all"]);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import oclif from "@oclif/core";
2
+ import CustomHelp from "./help.mjs";
3
+
4
+ console.log("hook init");
5
+
6
+ const hook = async (opts) => {
7
+ opts.config.helpClass = CustomHelp;
8
+ };
9
+
10
+ export default hook;
@@ -66,8 +66,8 @@ export class ProcaCommand extends Command {
66
66
  continue;
67
67
  }
68
68
 
69
- if (typeof value === "object" && value.name) {
70
- r[key] = value.name;
69
+ if (typeof value === "object") {
70
+ if (value?.name) r[key] = value.name;
71
71
  continue;
72
72
  }
73
73
  }
@@ -118,15 +118,14 @@ export class ProcaCommand extends Command {
118
118
  });
119
119
  }
120
120
 
121
- table(
122
- data,
123
- transformRow = (d, cell) => {
124
- for (const [key, value] of Object.entries(this.simplify(d))) {
125
- cell(key, value);
126
- }
127
- },
128
- print = (table) => table.toString(),
129
- ) {
121
+ table(data, transformRow, print = (table) => table.toString()) {
122
+ if (!transformRow) {
123
+ transformRow = (d, cell) => {
124
+ for (const [key, value] of Object.entries(this.simplify(d))) {
125
+ cell(key, value);
126
+ }
127
+ };
128
+ }
130
129
  const theme = this.config.theme;
131
130
  Table.prototype.pushDelimeter = function (cols) {
132
131
  // hack to change the formatting of the header
@@ -0,0 +1,12 @@
1
+ import { gql } from "#src/urql.mjs";
2
+
3
+ export const FragmentSummary = gql`fragment Summary on PrivateActionPage {
4
+ id
5
+ locale
6
+ name
7
+ journey
8
+ extraSupporters
9
+ status,
10
+ location
11
+ }
12
+ `;
package/src/urql.mjs CHANGED
@@ -6,6 +6,8 @@ import {
6
6
  gql,
7
7
  } from "urql";
8
8
 
9
+ import { GraphQLError, formatError } from "graphql";
10
+
9
11
  export let client = {
10
12
  query: () => {
11
13
  throw new Error("urql graphql not initialised, call init first");
@@ -38,7 +40,16 @@ export const createClient = (config) => {
38
40
  export const query = async (query, payload) => {
39
41
  const result = await client.query(query, payload).toPromise();
40
42
  if (result.error) {
41
- throw new Error(result.error);
43
+ console.log(formatError(result.error));
44
+ throw result.error;
45
+ }
46
+ return result.data;
47
+ };
48
+
49
+ export const mutation = async (mutation, payload) => {
50
+ const result = await client.mutation(mutation, payload).toPromise();
51
+ if (result.error) {
52
+ throw result.error;
42
53
  }
43
54
  return result.data;
44
55
  };
@@ -0,0 +1,23 @@
1
+ export const getTwitter = async (org) => {
2
+ const orgName = org.config.twitter?.screen_name || org.name;
3
+ try {
4
+ const res = await fetch(
5
+ `https://twitter.proca.app/?screen_name=${orgName}`,
6
+ );
7
+
8
+ if (res.status >= 400) {
9
+ throw new Error("Bad response from twitter.proca.app");
10
+ }
11
+
12
+ const twitter = await res.json();
13
+ twitter.picture = twitter.profile_image_url_https;
14
+ twitter.profile_image_url_https = undefined;
15
+ if (twitter) org.config.twitter = twitter;
16
+ if (!org.config.description) org.config.description = twitter.description;
17
+ if (!org.config.location) org.config.location = twitter.location;
18
+ if (!org.config.url) org.config.url = twitter.url;
19
+ if (!org.title) org.title = twitter.name;
20
+ } catch (err) {
21
+ console.error(err);
22
+ }
23
+ };