Skip to content

Commit 24de042

Browse files
authored
Added support for initiative updates
chore: added support for initiative updates
2 parents e383213 + fc68659 commit 24de042

File tree

11 files changed

+432
-210
lines changed

11 files changed

+432
-210
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "linear-zapier",
3-
"version": "4.6.0",
3+
"version": "4.7.0",
44
"description": "Linear's Zapier integration",
55
"main": "index.js",
66
"license": "MIT",

src/creates/createCustomer.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import { fetchFromLinear } from "../fetchFromLinear";
33
import { omitBy } from "lodash";
44

55
interface CustomerCreateResponse {
6-
data?: { customerCreate: { customer: { id: string; name: string, domains: string[], externalIds: string[] }; success: boolean } };
6+
data?: {
7+
customerCreate: {
8+
customer: { id: string; name: string; domains: string[]; externalIds: string[] };
9+
success: boolean;
10+
};
11+
};
712
errors?: {
813
message: string;
914
extensions?: {
@@ -129,7 +134,11 @@ export const createCustomer = {
129134
sample: {
130135
data: {
131136
customerCreate: {
132-
customer: { id: "068fbd0a-c1d5-448b-af2d-432127520cbd", domains: ["https://www.example.com"], name: "Example customer" },
137+
customer: {
138+
id: "068fbd0a-c1d5-448b-af2d-432127520cbd",
139+
domains: ["https://www.example.com"],
140+
name: "Example customer",
141+
},
133142
success: true,
134143
},
135144
},

src/creates/createCustomerNeed.ts

Lines changed: 115 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,41 @@ import { fetchFromLinear } from "../fetchFromLinear";
33
import { omitBy } from "lodash";
44

55
interface CustomerNeedCreateResponse {
6-
data?: { customerNeedCreate: { need: { id: string; customerId?: string, issueId?: string, attachmentId?: string }; success: boolean } };
7-
errors?: {
8-
message: string;
9-
extensions?: {
10-
userPresentableMessage?: string;
11-
};
12-
}[];
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+
}[];
1318
}
1419

1520
const createCustomerNeedRequest = async (z: ZObject, bundle: Bundle) => {
16-
const variables = omitBy(
17-
{
18-
customerId: bundle.inputData.customerId,
19-
customerExternalId: bundle.inputData.customerExternalId,
20-
issueId: bundle.inputData.issueId,
21-
attachmentId: bundle.inputData.attachmentId,
22-
attachmentUrl: bundle.inputData.attachmentUrl,
23-
body: bundle.inputData.body,
24-
priority: bundle.inputData.priority,
25-
},
26-
(v) => v === undefined
27-
);
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+
);
2833

29-
if(variables.attachmentId && variables.attachmentUrl) {
30-
throw new Error ("Cannot specify both attachmentId and attachmentUrl");
31-
} else if (variables.customerId && variables.customerExternalId) {
32-
throw new Error ("Cannot specify both customerId and customerExternalId");
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+
}
3439

35-
const query = `
40+
const query = `
3641
mutation ZapierCustomerNeedCreate(
3742
$customerId: String,
3843
$customerExternalId: String,
@@ -67,92 +72,96 @@ const createCustomerNeedRequest = async (z: ZObject, bundle: Bundle) => {
6772
}
6873
}`;
6974

70-
const response = await fetchFromLinear(z, bundle, query, variables);
71-
const data = response.json as CustomerNeedCreateResponse;
75+
const response = await fetchFromLinear(z, bundle, query, variables);
76+
const data = response.json as CustomerNeedCreateResponse;
7277

73-
if (data.errors && data.errors.length) {
74-
const error = data.errors[0];
75-
throw new z.errors.Error(
76-
(error.extensions && error.extensions.userPresentableMessage) || error.message,
77-
"invalid_input",
78-
400
79-
);
80-
}
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+
}
8186

82-
if (data.data && data.data.customerNeedCreate && data.data.customerNeedCreate.success) {
83-
return data.data.customerNeedCreate.need;
84-
} else {
85-
const error = data.errors ? data.errors[0].message : "Something went wrong";
86-
throw new z.errors.Error("Failed to create a customer need", error, 400);
87-
}
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+
}
8893
};
8994

9095
export const createCustomerNeed = {
91-
key: "createCustomerNeed",
92-
display: {
93-
hidden: false,
94-
description: "Create a new customer need in Linear",
95-
label: "Create Customer Need",
96-
},
97-
noun: "Customer Need",
98-
operation: {
99-
perform: createCustomerNeedRequest,
100-
inputFields: [
101-
{
102-
required: false,
103-
label: "Customer ID",
104-
helpText: "The ID of the customer to create the need for",
105-
key: "customerId",
106-
},
107-
{
108-
required: false,
109-
label: "External Customer ID",
110-
helpText: "The external ID of the customer the need belongs to",
111-
key: "customerExternalId",
112-
},
113-
{
114-
required: false,
115-
label: "Issue ID",
116-
helpText: "The ID of the issue this need is for",
117-
key: "issueId",
118-
type: "text",
119-
},
120-
{
121-
required: false,
122-
label: "Attachment ID",
123-
helpText: "The ID of the attachment this need is associated with",
124-
key: "attachmentId",
125-
type: "text",
126-
},
127-
{
128-
required: false,
129-
label: "Attachment URL",
130-
helpText: "Optional URL for the attachment associated with the customer need",
131-
key: "attachmentUrl",
132-
type: "text",
133-
},
134-
{
135-
required: false,
136-
label: "Body",
137-
helpText: "The content of the need in markdown format.",
138-
key: "body",
139-
type: "text",
140-
},
141-
{
142-
required: false,
143-
label: "Priority",
144-
helpText: "Whether the customer need is important or not. 0 = Not important, 1 = Important.",
145-
key: "priority",
146-
type: "number",
147-
},
148-
],
149-
sample: {
150-
data: {
151-
customerNeedCreate: {
152-
need: { id: "93a02c29-da90-4d06-ab1c-96956e94bcd0", customerId: "6465f500-6626-4253-9073-144535a6c658", issueId: "a8ea3bfa-5420-492a-84e9-ffe49ca5f22a" },
153-
success: true,
154-
},
155-
},
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,
156163
},
164+
},
157165
},
166+
},
158167
};

src/index.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ import { updateIssue } from "./creates/updateIssue";
2929
import { issueTemplates } from "./triggers/issueTemplates";
3030
import { findIssueByID } from "./searches/issue";
3131
import { findProjectByID } from "./searches/project";
32-
import {createCustomer} from "./creates/createCustomer";
33-
import {findCustomerByID} from "./searches/customer";
34-
import {newCustomerInstant, updatedCustomerInstant} from "./triggers/customer";
35-
import {createCustomerNeed} from "./creates/createCustomerNeed";
36-
import {newCustomerNeedInstant, updatedCustomerNeedInstant} from "./triggers/customerNeed";
32+
import { newInitiativeUpdateInstant, updatedInitiativeUpdateInstant } from "./triggers/initiativeUpdate";
33+
import { createCustomer } from "./creates/createCustomer";
34+
import { findCustomerByID } from "./searches/customer";
35+
import { newCustomerInstant, updatedCustomerInstant } from "./triggers/customer";
36+
import { createCustomerNeed } from "./creates/createCustomerNeed";
37+
import { newCustomerNeedInstant, updatedCustomerNeedInstant } from "./triggers/customerNeed";
3738

3839
const handleErrors = (response: HttpResponse, z: ZObject) => {
3940
if (response.request.url !== "https://api.linear.app/graphql") {
@@ -80,6 +81,8 @@ const App = {
8081
[newDocumentCommentInstant.key]: newDocumentCommentInstant,
8182
[updatedProjectUpdate.key]: updatedProjectUpdate,
8283
[updatedProjectUpdateInstant.key]: updatedProjectUpdateInstant,
84+
[newInitiativeUpdateInstant.key]: newInitiativeUpdateInstant,
85+
[updatedInitiativeUpdateInstant.key]: updatedInitiativeUpdateInstant,
8386
[team.key]: team,
8487
[issueTemplates.key]: issueTemplates,
8588
[status.key]: status,
@@ -97,7 +100,6 @@ const App = {
97100
[updatedCustomerInstant.key]: updatedCustomerInstant,
98101
[newCustomerNeedInstant.key]: newCustomerNeedInstant,
99102
[updatedCustomerNeedInstant.key]: updatedCustomerNeedInstant,
100-
101103
},
102104
searches: {
103105
[findIssueByID.key]: findIssueByID,

src/samples/customer.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
"name": "Example",
44
"createdAt": "2024-10-04T22:38:43.396Z",
55
"updatedAt": "2024-10-04T22:39:43.396Z",
6-
"domains": [
7-
"example.com"
8-
],
6+
"domains": ["example.com"],
97
"externalIds": ["123456789"],
108
"revenue": 10000,
119
"size": 100,

src/samples/initiativeUpdate.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"id": "722c8d97-f01e-4d2a-85da-271592463f8d",
3+
"body": "This is an initiative update body in Markdown format!",
4+
"health": "onTrack",
5+
"url": "https://local.linear.dev/linear/updateA",
6+
"editedAt": "2022-10-27T21:20:59.199Z",
7+
"createdAt": "2022-10-27T21:20:59.199Z",
8+
"updatedAt": "2022-10-27T21:20:59.199Z",
9+
"initiative": {
10+
"id": "e632a843-19da-4199-9489-3a962a96b549",
11+
"name": "My Initiative"
12+
},
13+
"user": {
14+
"id": "e632a843-19da-4199-9489-3a962a96b549",
15+
"name": "Zapier User",
16+
"email": "creator@example.com"
17+
}
18+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"id": "e632a843-19da-4199-9489-3a962a96b549",
3+
"body": "A great update! I'm looking forward to trying it out.",
4+
"createdAt": "2024-01-05T23:36:40.311Z",
5+
"resolvedAt": null,
6+
"initiativeUpdate": {
7+
"id": "799e7b95-2902-4c0a-86d8-d817a60f7f9f",
8+
"body": "This week I focused on getting email attachments working and an initial implementation is now in review on GitHub.",
9+
"user": {
10+
"id": "a3188fa9-f757-4046-a847-b5174a39b978",
11+
"name": "John Smith",
12+
"email": "user@example.com",
13+
"avatarUrl": null
14+
},
15+
"url": "https://linear.app/example/initiative/the-bext-initiative-4437c60bc5ec#initiativeUpdate-bb1cfa33",
16+
"initiative": {
17+
"id": "a3188fa9-f757-4046-a847-b5174a39b978",
18+
"name": "The Best Initiative",
19+
"url": "https://linear.app/example/initiative/the-bext-initiative-4437c60bc5ec"
20+
}
21+
},
22+
"user": {
23+
"id": "fda6d8ba-2d19-4776-affa-0cdd7ab158de",
24+
"email": "another-user@example.com",
25+
"name": "Tom Lee",
26+
"avatarUrl": null
27+
},
28+
"parent": null
29+
}

src/searches/customer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ZObject, Bundle } from "zapier-platform-core";
22
import sample from "../samples/customer.json";
3-
import {CustomerCommon} from "../triggers/customer";
3+
import { CustomerCommon } from "../triggers/customer";
44

55
interface CustomerResponse {
66
data: {

src/triggers/customer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import {Bundle, ZObject} from "zapier-platform-core";
1+
import { Bundle, ZObject } from "zapier-platform-core";
22
import sample from "../samples/customer.json";
3-
import {getWebhookData, unsubscribeHook} from "../handleWebhook";
4-
import {jsonToGraphQLQuery} from "json-to-graphql-query";
5-
import {fetchFromLinear} from "../fetchFromLinear";
3+
import { getWebhookData, unsubscribeHook } from "../handleWebhook";
4+
import { jsonToGraphQLQuery } from "json-to-graphql-query";
5+
import { fetchFromLinear } from "../fetchFromLinear";
66

77
export interface CustomerCommon {
88
id: string;

0 commit comments

Comments
 (0)