@activepieces/piece-loops 0.0.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/package.json +17 -0
- package/src/i18n/translation.json +80 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +40 -0
- package/src/index.js.map +1 -0
- package/src/lib/actions/create-contact.d.ts +11 -0
- package/src/lib/actions/create-contact.js +122 -0
- package/src/lib/actions/create-contact.js.map +1 -0
- package/src/lib/actions/delete-contact.d.ts +4 -0
- package/src/lib/actions/delete-contact.js +50 -0
- package/src/lib/actions/delete-contact.js.map +1 -0
- package/src/lib/actions/find-contact.d.ts +4 -0
- package/src/lib/actions/find-contact.js +53 -0
- package/src/lib/actions/find-contact.js.map +1 -0
- package/src/lib/actions/send-event.d.ts +8 -0
- package/src/lib/actions/send-event.js +79 -0
- package/src/lib/actions/send-event.js.map +1 -0
- package/src/lib/actions/send-transactional-email.d.ts +6 -0
- package/src/lib/actions/send-transactional-email.js +63 -0
- package/src/lib/actions/send-transactional-email.js.map +1 -0
- package/src/lib/auth.d.ts +2 -0
- package/src/lib/auth.js +37 -0
- package/src/lib/auth.js.map +1 -0
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@activepieces/piece-loops",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@activepieces/pieces-common": "0.12.0",
|
|
9
|
+
"@activepieces/pieces-framework": "0.26.0",
|
|
10
|
+
"@activepieces/shared": "0.46.0",
|
|
11
|
+
"tslib": "2.6.2"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -p tsconfig.lib.json && cp package.json dist/",
|
|
15
|
+
"lint": "eslint 'src/**/*.ts'"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Loops is an email platform for sending beautiful transactional and marketing emails. Manage contacts, trigger automations with events, and send transactional emails from your workflows.": "Loops is an email platform for sending beautiful transactional and marketing emails. Manage contacts, trigger automations with events, and send transactional emails from your workflows.",
|
|
3
|
+
"Your Loops API key. Generate one at [Settings → API](https://app.loops.so/settings?page=api) in your Loops dashboard.": "Your Loops API key. Generate one at [Settings → API](https://app.loops.so/settings?page=api) in your Loops dashboard.",
|
|
4
|
+
"Create Contact": "Create Contact",
|
|
5
|
+
"Send Event": "Send Event",
|
|
6
|
+
"Send Transactional Email": "Send Transactional Email",
|
|
7
|
+
"Find Contact": "Find Contact",
|
|
8
|
+
"Delete Contact": "Delete Contact",
|
|
9
|
+
"Custom API Call": "Custom API Call",
|
|
10
|
+
"Creates a new contact in Loops. Returns an error if a contact with the given email already exists.": "Creates a new contact in Loops. Returns an error if a contact with the given email already exists.",
|
|
11
|
+
"Sends an event to Loops for a contact. Events can trigger email automations configured in your Loops dashboard.": "Sends an event to Loops for a contact. Events can trigger email automations configured in your Loops dashboard.",
|
|
12
|
+
"Sends a transactional email to a contact using a pre-built template in Loops.": "Sends a transactional email to a contact using a pre-built template in Loops.",
|
|
13
|
+
"Finds a contact in Loops by their email address or user ID.": "Finds a contact in Loops by their email address or user ID.",
|
|
14
|
+
"Permanently deletes a contact from Loops by their email address or user ID.": "Permanently deletes a contact from Loops by their email address or user ID.",
|
|
15
|
+
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
|
|
16
|
+
"Email": "Email",
|
|
17
|
+
"First Name": "First Name",
|
|
18
|
+
"Last Name": "Last Name",
|
|
19
|
+
"User ID": "User ID",
|
|
20
|
+
"Subscribed to Marketing": "Subscribed to Marketing",
|
|
21
|
+
"User Group": "User Group",
|
|
22
|
+
"Source": "Source",
|
|
23
|
+
"Mailing Lists": "Mailing Lists",
|
|
24
|
+
"Custom Properties": "Custom Properties",
|
|
25
|
+
"Event Name": "Event Name",
|
|
26
|
+
"Event Properties": "Event Properties",
|
|
27
|
+
"Contact Properties": "Contact Properties",
|
|
28
|
+
"To Email": "To Email",
|
|
29
|
+
"Transactional Email ID": "Transactional Email ID",
|
|
30
|
+
"Add to Audience": "Add to Audience",
|
|
31
|
+
"Data Variables": "Data Variables",
|
|
32
|
+
"Search By": "Search By",
|
|
33
|
+
"Value": "Value",
|
|
34
|
+
"Method": "Method",
|
|
35
|
+
"Headers": "Headers",
|
|
36
|
+
"Query Parameters": "Query Parameters",
|
|
37
|
+
"Body Type": "Body Type",
|
|
38
|
+
"Body": "Body",
|
|
39
|
+
"Response is Binary ?": "Response is Binary ?",
|
|
40
|
+
"No Error on Failure": "No Error on Failure",
|
|
41
|
+
"Timeout (in seconds)": "Timeout (in seconds)",
|
|
42
|
+
"Follow redirects": "Follow redirects",
|
|
43
|
+
"The email address of the contact.": "The email address of the contact.",
|
|
44
|
+
"The contact's first name.": "The contact's first name.",
|
|
45
|
+
"The contact's last name.": "The contact's last name.",
|
|
46
|
+
"Your internal user ID for this contact.": "Your internal user ID for this contact.",
|
|
47
|
+
"Set subscription status. Leave as \"No Change\" to preserve existing status on update.": "Set subscription status. Leave as \"No Change\" to preserve existing status on update.",
|
|
48
|
+
"A group/segment to assign to this contact.": "A group/segment to assign to this contact.",
|
|
49
|
+
"Where this contact came from (e.g. \"signup-form\", \"import\").": "Where this contact came from (e.g. \"signup-form\", \"import\").",
|
|
50
|
+
"Subscribe or unsubscribe this contact from mailing lists. Provide list IDs as keys with `true` (subscribe) or `false` (unsubscribe) as values.": "Subscribe or unsubscribe this contact from mailing lists. Provide list IDs as keys with `true` (subscribe) or `false` (unsubscribe) as values.",
|
|
51
|
+
"Additional custom contact properties as key-value pairs. Reserved fields (email, firstName, lastName, userId, subscribed, userGroup, source) are ignored here.": "Additional custom contact properties as key-value pairs. Reserved fields (email, firstName, lastName, userId, subscribed, userGroup, source) are ignored here.",
|
|
52
|
+
"The email address of the contact to send the event for.": "The email address of the contact to send the event for.",
|
|
53
|
+
"Your internal user ID of the contact (used if email is not provided).": "Your internal user ID of the contact (used if email is not provided).",
|
|
54
|
+
"The name of the event to send (e.g. \"signup\", \"purchase\", \"password-reset\"). Must match an event set up in Loops.": "The name of the event to send (e.g. \"signup\", \"purchase\", \"password-reset\"). Must match an event set up in Loops.",
|
|
55
|
+
"Optional key-value pairs to attach to the event (used in email templates).": "Optional key-value pairs to attach to the event (used in email templates).",
|
|
56
|
+
"Optional contact property updates to apply when the event is sent.": "Optional contact property updates to apply when the event is sent.",
|
|
57
|
+
"The recipient's email address.": "The recipient's email address.",
|
|
58
|
+
"The ID of the transactional email template in Loops (find it in your Loops dashboard).": "The ID of the transactional email template in Loops (find it in your Loops dashboard).",
|
|
59
|
+
"If true, the recipient will be added to your Loops audience if they are not already a contact.": "If true, the recipient will be added to your Loops audience if they are not already a contact.",
|
|
60
|
+
"Key-value pairs to populate dynamic variables in your email template (e.g. { \"name\": \"Alice\", \"resetUrl\": \"https://...\" }).": "Key-value pairs to populate dynamic variables in your email template (e.g. { \"name\": \"Alice\", \"resetUrl\": \"https://...\" }).",
|
|
61
|
+
"The field to search by. The Loops API only allows one search parameter.": "The field to search by. The Loops API only allows one search parameter.",
|
|
62
|
+
"The email address or user ID to search for.": "The email address or user ID to search for.",
|
|
63
|
+
"The email address of the contact to delete.": "The email address of the contact to delete.",
|
|
64
|
+
"Your internal user ID of the contact to delete.": "Your internal user ID of the contact to delete.",
|
|
65
|
+
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
|
|
66
|
+
"Enable for files like PDFs, images, etc.": "Enable for files like PDFs, images, etc.",
|
|
67
|
+
"No Change": "No Change",
|
|
68
|
+
"Subscribe": "Subscribe",
|
|
69
|
+
"Unsubscribe": "Unsubscribe",
|
|
70
|
+
"GET": "GET",
|
|
71
|
+
"POST": "POST",
|
|
72
|
+
"PATCH": "PATCH",
|
|
73
|
+
"PUT": "PUT",
|
|
74
|
+
"DELETE": "DELETE",
|
|
75
|
+
"HEAD": "HEAD",
|
|
76
|
+
"None": "None",
|
|
77
|
+
"JSON": "JSON",
|
|
78
|
+
"Form Data": "Form Data",
|
|
79
|
+
"Raw": "Raw"
|
|
80
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const loops: import("@activepieces/pieces-framework").Piece<import("@activepieces/pieces-framework").SecretTextProperty<true>>;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loops = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const shared_1 = require("@activepieces/shared");
|
|
7
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
8
|
+
const auth_1 = require("./lib/auth");
|
|
9
|
+
const create_contact_1 = require("./lib/actions/create-contact");
|
|
10
|
+
const send_event_1 = require("./lib/actions/send-event");
|
|
11
|
+
const send_transactional_email_1 = require("./lib/actions/send-transactional-email");
|
|
12
|
+
const find_contact_1 = require("./lib/actions/find-contact");
|
|
13
|
+
const delete_contact_1 = require("./lib/actions/delete-contact");
|
|
14
|
+
exports.loops = (0, pieces_framework_1.createPiece)({
|
|
15
|
+
displayName: 'Loops',
|
|
16
|
+
description: 'Loops is an email platform for sending beautiful transactional and marketing emails. Manage contacts, trigger automations with events, and send transactional emails from your workflows.',
|
|
17
|
+
minimumSupportedRelease: '0.30.0',
|
|
18
|
+
logoUrl: 'https://cdn.activepieces.com/pieces/loops.png',
|
|
19
|
+
authors: ['Harmatta'],
|
|
20
|
+
categories: [shared_1.PieceCategory.COMMUNICATION, shared_1.PieceCategory.MARKETING],
|
|
21
|
+
auth: auth_1.loopsAuth,
|
|
22
|
+
actions: [
|
|
23
|
+
create_contact_1.createContact,
|
|
24
|
+
send_event_1.sendEvent,
|
|
25
|
+
send_transactional_email_1.sendTransactionalEmail,
|
|
26
|
+
find_contact_1.findContact,
|
|
27
|
+
delete_contact_1.deleteContact,
|
|
28
|
+
(0, pieces_common_1.createCustomApiCallAction)({
|
|
29
|
+
baseUrl: () => auth_1.LOOPS_BASE_URL,
|
|
30
|
+
auth: auth_1.loopsAuth,
|
|
31
|
+
authMapping: (auth) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
+
return ({
|
|
33
|
+
Authorization: `Bearer ${auth.secret_text}`,
|
|
34
|
+
});
|
|
35
|
+
}),
|
|
36
|
+
}),
|
|
37
|
+
],
|
|
38
|
+
triggers: [],
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;AAAA,qEAA6D;AAC7D,iDAAqD;AACrD,+DAAwE;AAExE,qCAAuD;AACvD,iEAA6D;AAC7D,yDAAqD;AACrD,qFAAgF;AAChF,6DAAyD;AACzD,iEAA6D;AAEhD,QAAA,KAAK,GAAG,IAAA,8BAAW,EAAC;IAC/B,WAAW,EAAE,OAAO;IACpB,WAAW,EACT,2LAA2L;IAC7L,uBAAuB,EAAE,QAAQ;IACjC,OAAO,EAAE,+CAA+C;IACxD,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,UAAU,EAAE,CAAC,sBAAa,CAAC,aAAa,EAAE,sBAAa,CAAC,SAAS,CAAC;IAClE,IAAI,EAAE,gBAAS;IACf,OAAO,EAAE;QACP,8BAAa;QACb,sBAAS;QACT,iDAAsB;QACtB,0BAAW;QACX,8BAAa;QACb,IAAA,yCAAyB,EAAC;YACxB,OAAO,EAAE,GAAG,EAAE,CAAC,qBAAc;YAC7B,IAAI,EAAE,gBAAS;YACf,WAAW,EAAE,CAAO,IAAI,EAAE,EAAE;gBAAC,OAAA,CAAC;oBAC5B,aAAa,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE;iBAC5C,CAAC,CAAA;cAAA;SACH,CAAC;KACH;IACD,QAAQ,EAAE,EAAE;CACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const createContact: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
email: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
3
|
+
firstName: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
4
|
+
lastName: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
5
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
6
|
+
subscribed: import("@activepieces/pieces-framework").StaticDropdownProperty<string, false>;
|
|
7
|
+
userGroup: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
8
|
+
source: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
9
|
+
mailingLists: import("@activepieces/pieces-framework").ObjectProperty<false>;
|
|
10
|
+
customProperties: import("@activepieces/pieces-framework").ObjectProperty<false>;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createContact = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const auth_1 = require("../auth");
|
|
8
|
+
// Reserved top-level fields that must not be overwritten by custom properties
|
|
9
|
+
const RESERVED_FIELDS = new Set([
|
|
10
|
+
'email',
|
|
11
|
+
'firstName',
|
|
12
|
+
'lastName',
|
|
13
|
+
'userId',
|
|
14
|
+
'subscribed',
|
|
15
|
+
'userGroup',
|
|
16
|
+
'source',
|
|
17
|
+
]);
|
|
18
|
+
exports.createContact = (0, pieces_framework_1.createAction)({
|
|
19
|
+
name: 'create_contact',
|
|
20
|
+
displayName: 'Create Contact',
|
|
21
|
+
description: 'Creates a new contact in Loops. Returns an error if a contact with the given email already exists.',
|
|
22
|
+
auth: auth_1.loopsAuth,
|
|
23
|
+
props: {
|
|
24
|
+
email: pieces_framework_1.Property.ShortText({
|
|
25
|
+
displayName: 'Email',
|
|
26
|
+
description: 'The email address of the contact.',
|
|
27
|
+
required: true,
|
|
28
|
+
}),
|
|
29
|
+
firstName: pieces_framework_1.Property.ShortText({
|
|
30
|
+
displayName: 'First Name',
|
|
31
|
+
description: "The contact's first name.",
|
|
32
|
+
required: false,
|
|
33
|
+
}),
|
|
34
|
+
lastName: pieces_framework_1.Property.ShortText({
|
|
35
|
+
displayName: 'Last Name',
|
|
36
|
+
description: "The contact's last name.",
|
|
37
|
+
required: false,
|
|
38
|
+
}),
|
|
39
|
+
userId: pieces_framework_1.Property.ShortText({
|
|
40
|
+
displayName: 'User ID',
|
|
41
|
+
description: 'Your internal user ID for this contact.',
|
|
42
|
+
required: false,
|
|
43
|
+
}),
|
|
44
|
+
subscribed: pieces_framework_1.Property.StaticDropdown({
|
|
45
|
+
displayName: 'Subscribed to Marketing',
|
|
46
|
+
description: 'Set subscription status. Leave as "No Change" to preserve existing status on update.',
|
|
47
|
+
required: false,
|
|
48
|
+
options: {
|
|
49
|
+
disabled: false,
|
|
50
|
+
options: [
|
|
51
|
+
{ label: 'No Change', value: 'no_change' },
|
|
52
|
+
{ label: 'Subscribe', value: 'true' },
|
|
53
|
+
{ label: 'Unsubscribe', value: 'false' },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
userGroup: pieces_framework_1.Property.ShortText({
|
|
58
|
+
displayName: 'User Group',
|
|
59
|
+
description: 'A group/segment to assign to this contact.',
|
|
60
|
+
required: false,
|
|
61
|
+
}),
|
|
62
|
+
source: pieces_framework_1.Property.ShortText({
|
|
63
|
+
displayName: 'Source',
|
|
64
|
+
description: 'Where this contact came from (e.g. "signup-form", "import").',
|
|
65
|
+
required: false,
|
|
66
|
+
}),
|
|
67
|
+
mailingLists: pieces_framework_1.Property.Object({
|
|
68
|
+
displayName: 'Mailing Lists',
|
|
69
|
+
description: 'Subscribe or unsubscribe this contact from mailing lists. Provide list IDs as keys with `true` (subscribe) or `false` (unsubscribe) as values.',
|
|
70
|
+
required: false,
|
|
71
|
+
}),
|
|
72
|
+
customProperties: pieces_framework_1.Property.Object({
|
|
73
|
+
displayName: 'Custom Properties',
|
|
74
|
+
description: 'Additional custom contact properties as key-value pairs. Reserved fields (email, firstName, lastName, userId, subscribed, userGroup, source) are ignored here.',
|
|
75
|
+
required: false,
|
|
76
|
+
}),
|
|
77
|
+
},
|
|
78
|
+
run(context) {
|
|
79
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
const { email, firstName, lastName, userId, subscribed, userGroup, source, mailingLists, customProperties, } = context.propsValue;
|
|
81
|
+
const body = { email };
|
|
82
|
+
if (firstName)
|
|
83
|
+
body['firstName'] = firstName;
|
|
84
|
+
if (lastName)
|
|
85
|
+
body['lastName'] = lastName;
|
|
86
|
+
if (userId)
|
|
87
|
+
body['userId'] = userId;
|
|
88
|
+
if (subscribed === 'true')
|
|
89
|
+
body['subscribed'] = true;
|
|
90
|
+
if (subscribed === 'false')
|
|
91
|
+
body['subscribed'] = false;
|
|
92
|
+
if (userGroup)
|
|
93
|
+
body['userGroup'] = userGroup;
|
|
94
|
+
if (source)
|
|
95
|
+
body['source'] = source;
|
|
96
|
+
if (mailingLists && typeof mailingLists === 'object') {
|
|
97
|
+
body['mailingLists'] = mailingLists;
|
|
98
|
+
}
|
|
99
|
+
// Merge custom properties at the top level (Loops expects flat properties)
|
|
100
|
+
// Skip any key that is a reserved field to prevent silent overwrites
|
|
101
|
+
if (customProperties && typeof customProperties === 'object') {
|
|
102
|
+
for (const [key, value] of Object.entries(customProperties)) {
|
|
103
|
+
if (!RESERVED_FIELDS.has(key)) {
|
|
104
|
+
body[key] = value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
109
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
110
|
+
url: `${auth_1.LOOPS_BASE_URL}/contacts/create`,
|
|
111
|
+
headers: {
|
|
112
|
+
Authorization: `Bearer ${context.auth.secret_text}`,
|
|
113
|
+
'Content-Type': 'application/json',
|
|
114
|
+
Accept: 'application/json',
|
|
115
|
+
},
|
|
116
|
+
body,
|
|
117
|
+
});
|
|
118
|
+
return response.body;
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=create-contact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-contact.js","sourceRoot":"","sources":["../../../../src/lib/actions/create-contact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const deleteContact: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
email: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
3
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
4
|
+
}>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deleteContact = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const auth_1 = require("../auth");
|
|
8
|
+
exports.deleteContact = (0, pieces_framework_1.createAction)({
|
|
9
|
+
name: 'delete_contact',
|
|
10
|
+
displayName: 'Delete Contact',
|
|
11
|
+
description: 'Permanently deletes a contact from Loops by their email address or user ID.',
|
|
12
|
+
auth: auth_1.loopsAuth,
|
|
13
|
+
props: {
|
|
14
|
+
email: pieces_framework_1.Property.ShortText({
|
|
15
|
+
displayName: 'Email',
|
|
16
|
+
description: 'The email address of the contact to delete.',
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
userId: pieces_framework_1.Property.ShortText({
|
|
20
|
+
displayName: 'User ID',
|
|
21
|
+
description: 'Your internal user ID of the contact to delete.',
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
run(context) {
|
|
26
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
const { email, userId } = context.propsValue;
|
|
28
|
+
if (!email && !userId) {
|
|
29
|
+
throw new Error('At least one of "Email" or "User ID" must be provided.');
|
|
30
|
+
}
|
|
31
|
+
const body = {};
|
|
32
|
+
if (email)
|
|
33
|
+
body['email'] = email;
|
|
34
|
+
if (userId)
|
|
35
|
+
body['userId'] = userId;
|
|
36
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
37
|
+
method: pieces_common_1.HttpMethod.DELETE,
|
|
38
|
+
url: `${auth_1.LOOPS_BASE_URL}/contacts/delete`,
|
|
39
|
+
headers: {
|
|
40
|
+
Authorization: `Bearer ${context.auth.secret_text}`,
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
Accept: 'application/json',
|
|
43
|
+
},
|
|
44
|
+
body,
|
|
45
|
+
});
|
|
46
|
+
return response.body;
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=delete-contact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-contact.js","sourceRoot":"","sources":["../../../../src/lib/actions/delete-contact.ts"],"names":[],"mappings":";;;;AAAA,qEAAwE;AACxE,+DAAqE;AACrE,kCAAoD;AAEvC,QAAA,aAAa,GAAG,IAAA,+BAAY,EAAC;IACxC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,gBAAgB;IAC7B,WAAW,EACT,6EAA6E;IAC/E,IAAI,EAAE,gBAAS;IACf,KAAK,EAAE;QACL,KAAK,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACxB,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,6CAA6C;YAC1D,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,MAAM,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACzB,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,iDAAiD;YAC9D,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YAE7C,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;YAC5E,CAAC;YAED,MAAM,IAAI,GAA2B,EAAE,CAAC;YACxC,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;YACjC,IAAI,MAAM;gBAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YAEpC,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAA0B;gBACrE,MAAM,EAAE,0BAAU,CAAC,MAAM;gBACzB,GAAG,EAAE,GAAG,qBAAc,kBAAkB;gBACxC,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;oBACnD,cAAc,EAAE,kBAAkB;oBAClC,MAAM,EAAE,kBAAkB;iBAC3B;gBACD,IAAI;aACL,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;KAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const findContact: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
searchBy: import("@activepieces/pieces-framework").StaticDropdownProperty<string, true>;
|
|
3
|
+
searchValue: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
}>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findContact = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const auth_1 = require("../auth");
|
|
8
|
+
exports.findContact = (0, pieces_framework_1.createAction)({
|
|
9
|
+
name: 'find_contact',
|
|
10
|
+
displayName: 'Find Contact',
|
|
11
|
+
description: 'Finds a contact in Loops by their email address or user ID.',
|
|
12
|
+
auth: auth_1.loopsAuth,
|
|
13
|
+
props: {
|
|
14
|
+
searchBy: pieces_framework_1.Property.StaticDropdown({
|
|
15
|
+
displayName: 'Search By',
|
|
16
|
+
description: 'The field to search by. The Loops API only allows one search parameter.',
|
|
17
|
+
required: true,
|
|
18
|
+
options: {
|
|
19
|
+
disabled: false,
|
|
20
|
+
options: [
|
|
21
|
+
{ label: 'Email', value: 'email' },
|
|
22
|
+
{ label: 'User ID', value: 'userId' },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
searchValue: pieces_framework_1.Property.ShortText({
|
|
27
|
+
displayName: 'Value',
|
|
28
|
+
description: 'The email address or user ID to search for.',
|
|
29
|
+
required: true,
|
|
30
|
+
}),
|
|
31
|
+
},
|
|
32
|
+
run(context) {
|
|
33
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const { searchBy, searchValue } = context.propsValue;
|
|
35
|
+
const params = new URLSearchParams();
|
|
36
|
+
params.set(searchBy, searchValue);
|
|
37
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
38
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
39
|
+
url: `${auth_1.LOOPS_BASE_URL}/contacts/find?${params.toString()}`,
|
|
40
|
+
headers: {
|
|
41
|
+
Authorization: `Bearer ${context.auth.secret_text}`,
|
|
42
|
+
Accept: 'application/json',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
const data = response.body;
|
|
46
|
+
return {
|
|
47
|
+
contacts: data,
|
|
48
|
+
count: Array.isArray(data) ? data.length : 0,
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=find-contact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-contact.js","sourceRoot":"","sources":["../../../../src/lib/actions/find-contact.ts"],"names":[],"mappings":";;;;AAAA,qEAAwE;AACxE,+DAAqE;AACrE,kCAAoD;AAEvC,QAAA,WAAW,GAAG,IAAA,+BAAY,EAAC;IACtC,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,6DAA6D;IAC1E,IAAI,EAAE,gBAAS;IACf,KAAK,EAAE;QACL,QAAQ,EAAE,2BAAQ,CAAC,cAAc,CAAC;YAChC,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,yEAAyE;YACtF,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE;gBACP,QAAQ,EAAE,KAAK;gBACf,OAAO,EAAE;oBACP,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;oBAClC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE;iBACtC;aACF;SACF,CAAC;QACF,WAAW,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC9B,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,6CAA6C;YAC1D,QAAQ,EAAE,IAAI;SACf,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YAErD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YAElC,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAAY;gBACvD,MAAM,EAAE,0BAAU,CAAC,GAAG;gBACtB,GAAG,EAAE,GAAG,qBAAc,kBAAkB,MAAM,CAAC,QAAQ,EAAE,EAAE;gBAC3D,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;oBACnD,MAAM,EAAE,kBAAkB;iBAC3B;aACF,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;YAE3B,OAAO;gBACL,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;aAC7C,CAAC;QACJ,CAAC;KAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const sendEvent: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
email: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
3
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
4
|
+
eventName: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
eventProperties: import("@activepieces/pieces-framework").ObjectProperty<false>;
|
|
6
|
+
mailingLists: import("@activepieces/pieces-framework").ObjectProperty<false>;
|
|
7
|
+
contactProperties: import("@activepieces/pieces-framework").ObjectProperty<false>;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendEvent = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const auth_1 = require("../auth");
|
|
8
|
+
exports.sendEvent = (0, pieces_framework_1.createAction)({
|
|
9
|
+
name: 'send_event',
|
|
10
|
+
displayName: 'Send Event',
|
|
11
|
+
description: 'Sends an event to Loops for a contact. Events can trigger email automations configured in your Loops dashboard.',
|
|
12
|
+
auth: auth_1.loopsAuth,
|
|
13
|
+
props: {
|
|
14
|
+
email: pieces_framework_1.Property.ShortText({
|
|
15
|
+
displayName: 'Email',
|
|
16
|
+
description: 'The email address of the contact to send the event for.',
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
userId: pieces_framework_1.Property.ShortText({
|
|
20
|
+
displayName: 'User ID',
|
|
21
|
+
description: 'Your internal user ID of the contact (used if email is not provided).',
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
eventName: pieces_framework_1.Property.ShortText({
|
|
25
|
+
displayName: 'Event Name',
|
|
26
|
+
description: 'The name of the event to send (e.g. "signup", "purchase", "password-reset"). Must match an event set up in Loops.',
|
|
27
|
+
required: true,
|
|
28
|
+
}),
|
|
29
|
+
eventProperties: pieces_framework_1.Property.Object({
|
|
30
|
+
displayName: 'Event Properties',
|
|
31
|
+
description: 'Optional key-value pairs to attach to the event (used in email templates).',
|
|
32
|
+
required: false,
|
|
33
|
+
}),
|
|
34
|
+
mailingLists: pieces_framework_1.Property.Object({
|
|
35
|
+
displayName: 'Mailing Lists',
|
|
36
|
+
description: 'Subscribe or unsubscribe this contact from mailing lists. Provide list IDs as keys with `true` (subscribe) or `false` (unsubscribe) as values.',
|
|
37
|
+
required: false,
|
|
38
|
+
}),
|
|
39
|
+
contactProperties: pieces_framework_1.Property.Object({
|
|
40
|
+
displayName: 'Contact Properties',
|
|
41
|
+
description: 'Optional contact property updates to apply when the event is sent.',
|
|
42
|
+
required: false,
|
|
43
|
+
}),
|
|
44
|
+
},
|
|
45
|
+
run(context) {
|
|
46
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const { email, userId, eventName, eventProperties, mailingLists, contactProperties } = context.propsValue;
|
|
48
|
+
if (!email && !userId) {
|
|
49
|
+
throw new Error('Either "Email" or "User ID" must be provided.');
|
|
50
|
+
}
|
|
51
|
+
const body = { eventName };
|
|
52
|
+
if (email)
|
|
53
|
+
body['email'] = email;
|
|
54
|
+
if (userId)
|
|
55
|
+
body['userId'] = userId;
|
|
56
|
+
if (eventProperties && typeof eventProperties === 'object') {
|
|
57
|
+
body['eventProperties'] = eventProperties;
|
|
58
|
+
}
|
|
59
|
+
if (mailingLists && typeof mailingLists === 'object') {
|
|
60
|
+
body['mailingLists'] = mailingLists;
|
|
61
|
+
}
|
|
62
|
+
if (contactProperties && typeof contactProperties === 'object') {
|
|
63
|
+
Object.assign(body, contactProperties);
|
|
64
|
+
}
|
|
65
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
66
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
67
|
+
url: `${auth_1.LOOPS_BASE_URL}/events/send`,
|
|
68
|
+
headers: {
|
|
69
|
+
Authorization: `Bearer ${context.auth.secret_text}`,
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
Accept: 'application/json',
|
|
72
|
+
},
|
|
73
|
+
body,
|
|
74
|
+
});
|
|
75
|
+
return response.body;
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=send-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-event.js","sourceRoot":"","sources":["../../../../src/lib/actions/send-event.ts"],"names":[],"mappings":";;;;AAAA,qEAAwE;AACxE,+DAAqE;AACrE,kCAAoD;AAEvC,QAAA,SAAS,GAAG,IAAA,+BAAY,EAAC;IACpC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,YAAY;IACzB,WAAW,EACT,iHAAiH;IACnH,IAAI,EAAE,gBAAS;IACf,KAAK,EAAE;QACL,KAAK,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACxB,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,MAAM,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACzB,WAAW,EAAE,SAAS;YACtB,WAAW,EACT,uEAAuE;YACzE,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,SAAS,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC5B,WAAW,EAAE,YAAY;YACzB,WAAW,EACT,mHAAmH;YACrH,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,eAAe,EAAE,2BAAQ,CAAC,MAAM,CAAC;YAC/B,WAAW,EAAE,kBAAkB;YAC/B,WAAW,EACT,4EAA4E;YAC9E,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,YAAY,EAAE,2BAAQ,CAAC,MAAM,CAAC;YAC5B,WAAW,EAAE,eAAe;YAC5B,WAAW,EACT,gJAAgJ;YAClJ,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,iBAAiB,EAAE,2BAAQ,CAAC,MAAM,CAAC;YACjC,WAAW,EAAE,oBAAoB;YACjC,WAAW,EACT,oEAAoE;YACtE,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAClF,OAAO,CAAC,UAAU,CAAC;YAErB,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;YACnE,CAAC;YAED,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,CAAC;YAEpD,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;YACjC,IAAI,MAAM;gBAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YAEpC,IAAI,eAAe,IAAI,OAAO,eAAe,KAAK,QAAQ,EAAE,CAAC;gBAC3D,IAAI,CAAC,iBAAiB,CAAC,GAAG,eAAe,CAAC;YAC5C,CAAC;YAED,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;gBACrD,IAAI,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC;YACtC,CAAC;YAED,IAAI,iBAAiB,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;gBAC/D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YACzC,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAA0B;gBACrE,MAAM,EAAE,0BAAU,CAAC,IAAI;gBACvB,GAAG,EAAE,GAAG,qBAAc,cAAc;gBACpC,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;oBACnD,cAAc,EAAE,kBAAkB;oBAClC,MAAM,EAAE,kBAAkB;iBAC3B;gBACD,IAAI;aACL,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;KAAA;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const sendTransactionalEmail: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").SecretTextProperty<true>, {
|
|
2
|
+
email: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
3
|
+
transactionalId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
addToAudience: import("@activepieces/pieces-framework").CheckboxProperty<false>;
|
|
5
|
+
dataVariables: import("@activepieces/pieces-framework").ObjectProperty<false>;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendTransactionalEmail = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const auth_1 = require("../auth");
|
|
8
|
+
exports.sendTransactionalEmail = (0, pieces_framework_1.createAction)({
|
|
9
|
+
name: 'send_transactional_email',
|
|
10
|
+
displayName: 'Send Transactional Email',
|
|
11
|
+
description: 'Sends a transactional email to a contact using a pre-built template in Loops.',
|
|
12
|
+
auth: auth_1.loopsAuth,
|
|
13
|
+
props: {
|
|
14
|
+
email: pieces_framework_1.Property.ShortText({
|
|
15
|
+
displayName: 'To Email',
|
|
16
|
+
description: "The recipient's email address.",
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
transactionalId: pieces_framework_1.Property.ShortText({
|
|
20
|
+
displayName: 'Transactional Email ID',
|
|
21
|
+
description: 'The ID of the transactional email template in Loops (find it in your Loops dashboard).',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
addToAudience: pieces_framework_1.Property.Checkbox({
|
|
25
|
+
displayName: 'Add to Audience',
|
|
26
|
+
description: 'If true, the recipient will be added to your Loops audience if they are not already a contact.',
|
|
27
|
+
required: false,
|
|
28
|
+
defaultValue: false,
|
|
29
|
+
}),
|
|
30
|
+
dataVariables: pieces_framework_1.Property.Object({
|
|
31
|
+
displayName: 'Data Variables',
|
|
32
|
+
description: 'Key-value pairs to populate dynamic variables in your email template (e.g. { "name": "Alice", "resetUrl": "https://..." }).',
|
|
33
|
+
required: false,
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
run(context) {
|
|
37
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
const { email, transactionalId, addToAudience, dataVariables } = context.propsValue;
|
|
39
|
+
const body = {
|
|
40
|
+
email,
|
|
41
|
+
transactionalId,
|
|
42
|
+
};
|
|
43
|
+
if (typeof addToAudience === 'boolean') {
|
|
44
|
+
body['addToAudience'] = addToAudience;
|
|
45
|
+
}
|
|
46
|
+
if (dataVariables && typeof dataVariables === 'object') {
|
|
47
|
+
body['dataVariables'] = dataVariables;
|
|
48
|
+
}
|
|
49
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
50
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
51
|
+
url: `${auth_1.LOOPS_BASE_URL}/transactional`,
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: `Bearer ${context.auth.secret_text}`,
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
Accept: 'application/json',
|
|
56
|
+
},
|
|
57
|
+
body,
|
|
58
|
+
});
|
|
59
|
+
return response.body;
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=send-transactional-email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-transactional-email.js","sourceRoot":"","sources":["../../../../src/lib/actions/send-transactional-email.ts"],"names":[],"mappings":";;;;AAAA,qEAAwE;AACxE,+DAAqE;AACrE,kCAAoD;AAEvC,QAAA,sBAAsB,GAAG,IAAA,+BAAY,EAAC;IACjD,IAAI,EAAE,0BAA0B;IAChC,WAAW,EAAE,0BAA0B;IACvC,WAAW,EACT,+EAA+E;IACjF,IAAI,EAAE,gBAAS;IACf,KAAK,EAAE;QACL,KAAK,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACxB,WAAW,EAAE,UAAU;YACvB,WAAW,EAAE,gCAAgC;YAC7C,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,eAAe,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAClC,WAAW,EAAE,wBAAwB;YACrC,WAAW,EACT,wFAAwF;YAC1F,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,aAAa,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YAC/B,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EACT,gGAAgG;YAClG,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,KAAK;SACpB,CAAC;QACF,aAAa,EAAE,2BAAQ,CAAC,MAAM,CAAC;YAC7B,WAAW,EAAE,gBAAgB;YAC7B,WAAW,EACT,6HAA6H;YAC/H,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH;IACK,GAAG,CAAC,OAAO;;YACf,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,GAC5D,OAAO,CAAC,UAAU,CAAC;YAErB,MAAM,IAAI,GAA4B;gBACpC,KAAK;gBACL,eAAe;aAChB,CAAC;YAEF,IAAI,OAAO,aAAa,KAAK,SAAS,EAAE,CAAC;gBACvC,IAAI,CAAC,eAAe,CAAC,GAAG,aAAa,CAAC;YACxC,CAAC;YAED,IAAI,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;gBACvD,IAAI,CAAC,eAAe,CAAC,GAAG,aAAa,CAAC;YACxC,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAA0B;gBACrE,MAAM,EAAE,0BAAU,CAAC,IAAI;gBACvB,GAAG,EAAE,GAAG,qBAAc,gBAAgB;gBACtC,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE;oBACnD,cAAc,EAAE,kBAAkB;oBAClC,MAAM,EAAE,kBAAkB;iBAC3B;gBACD,IAAI;aACL,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;KAAA;CACF,CAAC,CAAC"}
|
package/src/lib/auth.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loopsAuth = exports.LOOPS_BASE_URL = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
exports.LOOPS_BASE_URL = 'https://app.loops.so/api/v1';
|
|
8
|
+
exports.loopsAuth = pieces_framework_1.PieceAuth.SecretText({
|
|
9
|
+
displayName: 'API Key',
|
|
10
|
+
description: 'Your Loops API key. Generate one at [Settings → API](https://app.loops.so/settings?page=api) in your Loops dashboard.',
|
|
11
|
+
required: true,
|
|
12
|
+
validate: (_a) => tslib_1.__awaiter(void 0, [_a], void 0, function* ({ auth }) {
|
|
13
|
+
var _b;
|
|
14
|
+
try {
|
|
15
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
16
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
17
|
+
url: `${exports.LOOPS_BASE_URL}/api-key`,
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: `Bearer ${auth}`,
|
|
20
|
+
Accept: 'application/json',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
if (!response.body.success) {
|
|
24
|
+
return { valid: false, error: 'API key validation failed.' };
|
|
25
|
+
}
|
|
26
|
+
return { valid: true };
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
const err = e;
|
|
30
|
+
if (((_b = err === null || err === void 0 ? void 0 : err.response) === null || _b === void 0 ? void 0 : _b.status) === 401) {
|
|
31
|
+
return { valid: false, error: 'Invalid API key. Please check your Loops API key.' };
|
|
32
|
+
}
|
|
33
|
+
return { valid: false, error: 'Could not reach Loops API. Check your network.' };
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/lib/auth.ts"],"names":[],"mappings":";;;;AAAA,qEAA2D;AAC3D,+DAAqE;AAExD,QAAA,cAAc,GAAG,6BAA6B,CAAC;AAE/C,QAAA,SAAS,GAAG,4BAAS,CAAC,UAAU,CAAC;IAC5C,WAAW,EAAE,SAAS;IACtB,WAAW,EACT,uHAAuH;IACzH,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAiB,EAAE,oDAAZ,EAAE,IAAI,EAAE;;QACvB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,0BAAU,CAAC,WAAW,CAAuB;gBAClE,MAAM,EAAE,0BAAU,CAAC,GAAG;gBACtB,GAAG,EAAE,GAAG,sBAAc,UAAU;gBAChC,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,EAAE;oBAC/B,MAAM,EAAE,kBAAkB;iBAC3B;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;YAC/D,CAAC;YAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAuC,CAAC;YACpD,IAAI,CAAA,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,QAAQ,0CAAE,MAAM,MAAK,GAAG,EAAE,CAAC;gBAClC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mDAAmD,EAAE,CAAC;YACtF,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,gDAAgD,EAAE,CAAC;QACnF,CAAC;IACH,CAAC,CAAA;CACF,CAAC,CAAC"}
|