Skip to content

Commit 1bffb29

Browse files
committed
Merge branch 'master' into igor/lin-28660-zapier-comments-should-support-initiative-updates-and
2 parents e4666dc + e383213 commit 1bffb29

File tree

15 files changed

+743
-157
lines changed

15 files changed

+743
-157
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "linear-zapier",
3-
"version": "4.4.6",
3+
"version": "4.6.0",
44
"description": "Linear's Zapier integration",
55
"main": "index.js",
66
"license": "MIT",
@@ -35,5 +35,6 @@
3535
},
3636
"lint-staged": {
3737
"*.{js,ts,json}": "prettier --write"
38-
}
38+
},
39+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
3940
}

src/creates/createCustomer.ts

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { Bundle, ZObject } from "zapier-platform-core";
2+
import { fetchFromLinear } from "../fetchFromLinear";
3+
import { omitBy } from "lodash";
4+
5+
interface CustomerCreateResponse {
6+
data?: {
7+
customerCreate: {
8+
customer: { id: string; name: string; domains: string[]; externalIds: string[] };
9+
success: boolean;
10+
};
11+
};
12+
errors?: {
13+
message: string;
14+
extensions?: {
15+
userPresentableMessage?: string;
16+
};
17+
}[];
18+
}
19+
20+
const createCustomerRequest = async (z: ZObject, bundle: Bundle) => {
21+
const variables = omitBy(
22+
{
23+
name: bundle.inputData.name,
24+
domains: bundle.inputData.domains || [],
25+
externalIds: bundle.inputData.externalIds || [],
26+
revenue: bundle.inputData.revenue,
27+
size: bundle.inputData.size,
28+
tierId: bundle.inputData.tierId,
29+
},
30+
(v) => v === undefined
31+
);
32+
const query = `
33+
mutation ZapierCustomerCreate(
34+
$name: String!,
35+
$domains: [String!],
36+
$externalIds: [String!],
37+
$revenue: Int,
38+
$size: Int,
39+
$tierId: String,
40+
) {
41+
customerCreate(input: {
42+
name: $name,
43+
domains: $domains,
44+
externalIds: $externalIds,
45+
revenue: $revenue,
46+
size: $size,
47+
tierId: $tierId
48+
}) {
49+
customer {
50+
id
51+
name
52+
domains
53+
externalIds
54+
}
55+
success
56+
}
57+
}`;
58+
59+
const response = await fetchFromLinear(z, bundle, query, variables);
60+
const data = response.json as CustomerCreateResponse;
61+
62+
if (data.errors && data.errors.length) {
63+
const error = data.errors[0];
64+
throw new z.errors.Error(
65+
(error.extensions && error.extensions.userPresentableMessage) || error.message,
66+
"invalid_input",
67+
400
68+
);
69+
}
70+
71+
if (data.data && data.data.customerCreate && data.data.customerCreate.success) {
72+
return data.data.customerCreate.customer;
73+
} else {
74+
const error = data.errors ? data.errors[0].message : "Something went wrong";
75+
throw new z.errors.Error("Failed to create a customer", error, 400);
76+
}
77+
};
78+
79+
export const createCustomer = {
80+
key: "createCustomer",
81+
display: {
82+
hidden: false,
83+
description: "Create a new customer in Linear",
84+
label: "Create Customer",
85+
},
86+
noun: "Customer",
87+
operation: {
88+
perform: createCustomerRequest,
89+
inputFields: [
90+
{
91+
required: true,
92+
label: "Name",
93+
helpText: "The name of the customer",
94+
key: "name",
95+
},
96+
{
97+
required: false,
98+
label: "Domains",
99+
helpText: "The domains associated with this customer",
100+
key: "domains",
101+
type: "text",
102+
list: true,
103+
},
104+
{
105+
required: false,
106+
label: "External IDs",
107+
helpText: "The ids of the customers in external systems",
108+
key: "externalIds",
109+
type: "text",
110+
list: true,
111+
},
112+
{
113+
required: false,
114+
label: "Revenue",
115+
helpText: "The annual revenue generated by the customer",
116+
key: "revenue",
117+
type: "number",
118+
},
119+
{
120+
required: false,
121+
label: "Size",
122+
helpText: "The size of the customer",
123+
key: "size",
124+
type: "number",
125+
},
126+
{
127+
required: false,
128+
label: "Tier ID",
129+
helpText: "The tier of the customer",
130+
key: "tierId",
131+
type: "text",
132+
},
133+
],
134+
sample: {
135+
data: {
136+
customerCreate: {
137+
customer: {
138+
id: "068fbd0a-c1d5-448b-af2d-432127520cbd",
139+
domains: ["https://www.example.com"],
140+
name: "Example customer",
141+
},
142+
success: true,
143+
},
144+
},
145+
},
146+
},
147+
};

src/creates/createCustomerNeed.ts

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { Bundle, ZObject } from "zapier-platform-core";
2+
import { fetchFromLinear } from "../fetchFromLinear";
3+
import { omitBy } from "lodash";
4+
5+
interface CustomerNeedCreateResponse {
6+
data?: {
7+
customerNeedCreate: {
8+
need: { id: string; customerId?: string; issueId?: string; attachmentId?: string };
9+
success: boolean;
10+
};
11+
};
12+
errors?: {
13+
message: string;
14+
extensions?: {
15+
userPresentableMessage?: string;
16+
};
17+
}[];
18+
}
19+
20+
const createCustomerNeedRequest = async (z: ZObject, bundle: Bundle) => {
21+
const variables = omitBy(
22+
{
23+
customerId: bundle.inputData.customerId,
24+
customerExternalId: bundle.inputData.customerExternalId,
25+
issueId: bundle.inputData.issueId,
26+
attachmentId: bundle.inputData.attachmentId,
27+
attachmentUrl: bundle.inputData.attachmentUrl,
28+
body: bundle.inputData.body,
29+
priority: bundle.inputData.priority,
30+
},
31+
(v) => v === undefined
32+
);
33+
34+
if (variables.attachmentId && variables.attachmentUrl) {
35+
throw new Error("Cannot specify both attachmentId and attachmentUrl");
36+
} else if (variables.customerId && variables.customerExternalId) {
37+
throw new Error("Cannot specify both customerId and customerExternalId");
38+
}
39+
40+
const query = `
41+
mutation ZapierCustomerNeedCreate(
42+
$customerId: String,
43+
$customerExternalId: String,
44+
$issueId: String,
45+
$attachmentId: String,
46+
$attachmentUrl: String,
47+
$body: String,
48+
$priority: Float,
49+
) {
50+
customerNeedCreate(input: {
51+
customerId: $customerId,
52+
customerExternalId: $customerExternalId,
53+
issueId: $issueId,
54+
attachmentId: $attachmentId,
55+
attachmentUrl: $attachmentUrl,
56+
body: $body,
57+
priority: $priority,
58+
}) {
59+
need {
60+
id
61+
customer {
62+
id
63+
}
64+
issue {
65+
id
66+
}
67+
attachment {
68+
id
69+
}
70+
}
71+
success
72+
}
73+
}`;
74+
75+
const response = await fetchFromLinear(z, bundle, query, variables);
76+
const data = response.json as CustomerNeedCreateResponse;
77+
78+
if (data.errors && data.errors.length) {
79+
const error = data.errors[0];
80+
throw new z.errors.Error(
81+
(error.extensions && error.extensions.userPresentableMessage) || error.message,
82+
"invalid_input",
83+
400
84+
);
85+
}
86+
87+
if (data.data && data.data.customerNeedCreate && data.data.customerNeedCreate.success) {
88+
return data.data.customerNeedCreate.need;
89+
} else {
90+
const error = data.errors ? data.errors[0].message : "Something went wrong";
91+
throw new z.errors.Error("Failed to create a customer need", error, 400);
92+
}
93+
};
94+
95+
export const createCustomerNeed = {
96+
key: "createCustomerNeed",
97+
display: {
98+
hidden: false,
99+
description: "Create a new customer need in Linear",
100+
label: "Create Customer Need",
101+
},
102+
noun: "Customer Need",
103+
operation: {
104+
perform: createCustomerNeedRequest,
105+
inputFields: [
106+
{
107+
required: false,
108+
label: "Customer ID",
109+
helpText: "The ID of the customer to create the need for",
110+
key: "customerId",
111+
},
112+
{
113+
required: false,
114+
label: "External Customer ID",
115+
helpText: "The external ID of the customer the need belongs to",
116+
key: "customerExternalId",
117+
},
118+
{
119+
required: false,
120+
label: "Issue ID",
121+
helpText: "The ID of the issue this need is for",
122+
key: "issueId",
123+
type: "text",
124+
},
125+
{
126+
required: false,
127+
label: "Attachment ID",
128+
helpText: "The ID of the attachment this need is associated with",
129+
key: "attachmentId",
130+
type: "text",
131+
},
132+
{
133+
required: false,
134+
label: "Attachment URL",
135+
helpText: "Optional URL for the attachment associated with the customer need",
136+
key: "attachmentUrl",
137+
type: "text",
138+
},
139+
{
140+
required: false,
141+
label: "Body",
142+
helpText: "The content of the need in markdown format.",
143+
key: "body",
144+
type: "text",
145+
},
146+
{
147+
required: false,
148+
label: "Priority",
149+
helpText: "Whether the customer need is important or not. 0 = Not important, 1 = Important.",
150+
key: "priority",
151+
type: "number",
152+
},
153+
],
154+
sample: {
155+
data: {
156+
customerNeedCreate: {
157+
need: {
158+
id: "93a02c29-da90-4d06-ab1c-96956e94bcd0",
159+
customerId: "6465f500-6626-4253-9073-144535a6c658",
160+
issueId: "a8ea3bfa-5420-492a-84e9-ffe49ca5f22a",
161+
},
162+
success: true,
163+
},
164+
},
165+
},
166+
},
167+
};

src/creates/updateIssue.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,32 +22,14 @@ interface IssueUpdateResponse {
2222
}[];
2323
}
2424

25-
interface IssueResponse {
26-
data: { issue: { labelIds: string[] } };
27-
}
28-
2925
const updateIssueRequest = async (z: ZObject, bundle: Bundle) => {
3026
if (!bundle.inputData.issueIdToUpdate) {
3127
throw new z.errors.HaltedError("You must specify the ID of the issue to update");
3228
}
3329
const priority = bundle.inputData.priority ? parseInt(bundle.inputData.priority) : undefined;
3430
const estimate = bundle.inputData.estimate ? parseInt(bundle.inputData.estimate) : undefined;
35-
let labelIds: string[] | undefined = undefined;
36-
if (bundle.inputData.labels && bundle.inputData.labels.length > 0) {
37-
// We need to append new labels to the issue's existing label set
38-
const issueQuery = `
39-
query ZapierIssue($id: String!) {
40-
issue(id: $id) {
41-
id
42-
labelIds
43-
}
44-
}
45-
`;
46-
const response = await fetchFromLinear(z, bundle, issueQuery, { id: bundle.inputData.issueIdToUpdate });
47-
const data = response.json as IssueResponse;
48-
const originalLabelIds = data.data.issue.labelIds;
49-
labelIds = uniq([...originalLabelIds, ...bundle.inputData.labels]);
50-
}
31+
const addedLabelIds: string[] | undefined =
32+
bundle.inputData.labels && bundle.inputData.labels.length > 0 ? uniq(bundle.inputData.labels) : undefined;
5133

5234
const variables = omitBy(
5335
{
@@ -63,7 +45,7 @@ const updateIssueRequest = async (z: ZObject, bundle: Bundle) => {
6345
projectId: bundle.inputData.projectId,
6446
projectMilestoneId: bundle.inputData.projectMilestoneId,
6547
dueDate: bundle.inputData.dueDate,
66-
labelIds,
48+
addedLabelIds,
6749
},
6850
(v) => v === undefined
6951
);
@@ -82,7 +64,7 @@ const updateIssueRequest = async (z: ZObject, bundle: Bundle) => {
8264
$projectId: String,
8365
$projectMilestoneId: String,
8466
$dueDate: TimelessDate,
85-
$labelIds: [String!]
67+
$addedLabelIds: [String!]
8668
) {
8769
issueUpdate(id: $issueIdToUpdate, input: {
8870
teamId: $teamId,
@@ -96,7 +78,7 @@ const updateIssueRequest = async (z: ZObject, bundle: Bundle) => {
9678
projectId: $projectId,
9779
projectMilestoneId: $projectMilestoneId,
9880
dueDate: $dueDate,
99-
labelIds: $labelIds
81+
addedLabelIds: $addedLabelIds
10082
}) {
10183
issue {
10284
id

0 commit comments

Comments
 (0)