piece-flexprice 0.1.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.
- package/index.js +256 -0
- package/package.json +10 -0
- package/src/index.ts +39 -0
- package/src/lib/actions/create-customer.ts +57 -0
- package/src/lib/actions/get-customer.ts +38 -0
- package/src/lib/actions/get-invoices.ts +38 -0
- package/src/lib/actions/get-subscriptions.ts +38 -0
- package/src/lib/actions/ingest-event.ts +85 -0
- package/src/lib/types.ts +9 -0
- package/tsconfig.json +15 -0
package/index.js
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
const { createPiece, createAction, Property } = require("@activepieces/pieces-framework");
|
|
2
|
+
|
|
3
|
+
const ingestEventAction = createAction({
|
|
4
|
+
name: "ingest_event",
|
|
5
|
+
displayName: "Ingest Usage Event",
|
|
6
|
+
description: "Report a billable usage event to Flexprice (e.g. lead_received, whatsapp_message_sent)",
|
|
7
|
+
props: {
|
|
8
|
+
eventName: Property.ShortText({
|
|
9
|
+
displayName: "Event Name",
|
|
10
|
+
description: "Name of the usage event (e.g. lead_received, whatsapp_message_sent)",
|
|
11
|
+
required: true,
|
|
12
|
+
defaultValue: "lead_received"
|
|
13
|
+
}),
|
|
14
|
+
customerId: Property.ShortText({
|
|
15
|
+
displayName: "Flexprice Customer ID",
|
|
16
|
+
description: "Internal Flexprice Customer UUID (or leave empty if passing External Customer ID)",
|
|
17
|
+
required: false
|
|
18
|
+
}),
|
|
19
|
+
externalCustomerId: Property.ShortText({
|
|
20
|
+
displayName: "External Customer ID",
|
|
21
|
+
description: "External Tenant/Client ID (e.g. Supabase client_id)",
|
|
22
|
+
required: false
|
|
23
|
+
}),
|
|
24
|
+
quantity: Property.Number({
|
|
25
|
+
displayName: "Quantity",
|
|
26
|
+
description: "Usage quantity / units (default: 1)",
|
|
27
|
+
required: false,
|
|
28
|
+
defaultValue: 1
|
|
29
|
+
}),
|
|
30
|
+
propertiesJson: Property.LongText({
|
|
31
|
+
displayName: "Custom Event Properties (JSON)",
|
|
32
|
+
description: "Optional JSON metadata object for the event",
|
|
33
|
+
required: false
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
async run(context) {
|
|
37
|
+
const apiKey = context.auth?.apiKey || "";
|
|
38
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
39
|
+
|
|
40
|
+
let propertiesObj = {};
|
|
41
|
+
if (context.propsValue.propertiesJson) {
|
|
42
|
+
try {
|
|
43
|
+
propertiesObj = JSON.parse(context.propsValue.propertiesJson);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
propertiesObj = { raw: context.propsValue.propertiesJson };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const payload = {
|
|
50
|
+
event_name: context.propsValue.eventName,
|
|
51
|
+
customer_id: context.propsValue.customerId || undefined,
|
|
52
|
+
external_customer_id: context.propsValue.externalCustomerId || undefined,
|
|
53
|
+
timestamp: new Date().toISOString(),
|
|
54
|
+
properties: {
|
|
55
|
+
quantity: context.propsValue.quantity ?? 1,
|
|
56
|
+
...propertiesObj
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const res = await fetch(`${baseUrl}/events`, {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: {
|
|
63
|
+
"Content-Type": "application/json",
|
|
64
|
+
"x-api-key": apiKey
|
|
65
|
+
},
|
|
66
|
+
body: JSON.stringify(payload)
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const data = await res.json();
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
throw new Error(`Flexprice Event Ingestion Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return data;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const createCustomerAction = createAction({
|
|
79
|
+
name: "create_customer",
|
|
80
|
+
displayName: "Create Customer",
|
|
81
|
+
description: "Provision a new billing customer profile in Flexprice",
|
|
82
|
+
props: {
|
|
83
|
+
externalId: Property.ShortText({
|
|
84
|
+
displayName: "External Customer ID",
|
|
85
|
+
description: "Unique identifier for client in your system (e.g. Supabase client_id)",
|
|
86
|
+
required: true
|
|
87
|
+
}),
|
|
88
|
+
name: Property.ShortText({
|
|
89
|
+
displayName: "Customer Name",
|
|
90
|
+
description: "Client business or individual name",
|
|
91
|
+
required: true
|
|
92
|
+
}),
|
|
93
|
+
email: Property.ShortText({
|
|
94
|
+
displayName: "Customer Email",
|
|
95
|
+
description: "Billing contact email address",
|
|
96
|
+
required: false
|
|
97
|
+
})
|
|
98
|
+
},
|
|
99
|
+
async run(context) {
|
|
100
|
+
const apiKey = context.auth?.apiKey || "";
|
|
101
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
102
|
+
|
|
103
|
+
const payload = {
|
|
104
|
+
external_id: context.propsValue.externalId,
|
|
105
|
+
name: context.propsValue.name,
|
|
106
|
+
email: context.propsValue.email || undefined
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const res = await fetch(`${baseUrl}/customers`, {
|
|
110
|
+
method: "POST",
|
|
111
|
+
headers: {
|
|
112
|
+
"Content-Type": "application/json",
|
|
113
|
+
"x-api-key": apiKey
|
|
114
|
+
},
|
|
115
|
+
body: JSON.stringify(payload)
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const data = await res.json();
|
|
119
|
+
if (!res.ok) {
|
|
120
|
+
throw new Error(`Flexprice Customer Creation Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return data;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const getCustomerAction = createAction({
|
|
128
|
+
name: "get_customer",
|
|
129
|
+
displayName: "Get Customer Details",
|
|
130
|
+
description: "Fetch customer details from Flexprice by external ID or customer ID",
|
|
131
|
+
props: {
|
|
132
|
+
externalId: Property.ShortText({
|
|
133
|
+
displayName: "External Customer ID",
|
|
134
|
+
description: "External tenant ID",
|
|
135
|
+
required: true
|
|
136
|
+
})
|
|
137
|
+
},
|
|
138
|
+
async run(context) {
|
|
139
|
+
const apiKey = context.auth?.apiKey || "";
|
|
140
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
141
|
+
|
|
142
|
+
const url = `${baseUrl}/customers?external_id=${encodeURIComponent(context.propsValue.externalId)}`;
|
|
143
|
+
const res = await fetch(url, {
|
|
144
|
+
method: "GET",
|
|
145
|
+
headers: {
|
|
146
|
+
"x-api-key": apiKey
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const data = await res.json();
|
|
151
|
+
if (!res.ok) {
|
|
152
|
+
throw new Error(`Flexprice Fetch Customer Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return data;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const getSubscriptionsAction = createAction({
|
|
160
|
+
name: "get_subscriptions",
|
|
161
|
+
displayName: "Get Subscriptions",
|
|
162
|
+
description: "Fetch customer subscription plan and status from Flexprice",
|
|
163
|
+
props: {
|
|
164
|
+
customerId: Property.ShortText({
|
|
165
|
+
displayName: "Flexprice Customer ID",
|
|
166
|
+
description: "Customer ID in Flexprice",
|
|
167
|
+
required: true
|
|
168
|
+
})
|
|
169
|
+
},
|
|
170
|
+
async run(context) {
|
|
171
|
+
const apiKey = context.auth?.apiKey || "";
|
|
172
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
173
|
+
|
|
174
|
+
const url = `${baseUrl}/subscriptions?customer_id=${encodeURIComponent(context.propsValue.customerId)}`;
|
|
175
|
+
const res = await fetch(url, {
|
|
176
|
+
method: "GET",
|
|
177
|
+
headers: {
|
|
178
|
+
"x-api-key": apiKey
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const data = await res.json();
|
|
183
|
+
if (!res.ok) {
|
|
184
|
+
throw new Error(`Flexprice Fetch Subscriptions Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return data;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const getInvoicesAction = createAction({
|
|
192
|
+
name: "get_invoices",
|
|
193
|
+
displayName: "Get Invoices",
|
|
194
|
+
description: "Fetch invoices and billing statements from Flexprice",
|
|
195
|
+
props: {
|
|
196
|
+
customerId: Property.ShortText({
|
|
197
|
+
displayName: "Flexprice Customer ID",
|
|
198
|
+
description: "Customer ID in Flexprice",
|
|
199
|
+
required: true
|
|
200
|
+
})
|
|
201
|
+
},
|
|
202
|
+
async run(context) {
|
|
203
|
+
const apiKey = context.auth?.apiKey || "";
|
|
204
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
205
|
+
|
|
206
|
+
const url = `${baseUrl}/invoices?customer_id=${encodeURIComponent(context.propsValue.customerId)}`;
|
|
207
|
+
const res = await fetch(url, {
|
|
208
|
+
method: "GET",
|
|
209
|
+
headers: {
|
|
210
|
+
"x-api-key": apiKey
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const data = await res.json();
|
|
215
|
+
if (!res.ok) {
|
|
216
|
+
throw new Error(`Flexprice Fetch Invoices Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return data;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const flexpricePiece = createPiece({
|
|
224
|
+
displayName: "Flexprice Billing & Metering",
|
|
225
|
+
logoUrl: "https://raw.githubusercontent.com/flexprice/flexprice-front/main/assets/flexprice_logo.png",
|
|
226
|
+
minimumSupportedRelease: "0.5.0",
|
|
227
|
+
authors: ["Whatomation Team"],
|
|
228
|
+
auth: Property.CustomAuth({
|
|
229
|
+
displayName: "Flexprice Authentication",
|
|
230
|
+
description: "Provide your Flexprice API key and server URL",
|
|
231
|
+
required: true,
|
|
232
|
+
props: {
|
|
233
|
+
apiKey: Property.SecretText({
|
|
234
|
+
displayName: "API Key",
|
|
235
|
+
description: "Your master Flexprice API key (x-api-key)",
|
|
236
|
+
required: true
|
|
237
|
+
}),
|
|
238
|
+
baseUrl: Property.ShortText({
|
|
239
|
+
displayName: "API Base URL",
|
|
240
|
+
description: "Flexprice API Base URL (default: http://localhost:8080/v1)",
|
|
241
|
+
required: true,
|
|
242
|
+
defaultValue: "http://localhost:8080/v1"
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
}),
|
|
246
|
+
actions: [
|
|
247
|
+
ingestEventAction,
|
|
248
|
+
createCustomerAction,
|
|
249
|
+
getCustomerAction,
|
|
250
|
+
getSubscriptionsAction,
|
|
251
|
+
getInvoicesAction
|
|
252
|
+
],
|
|
253
|
+
triggers: []
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
module.exports = { flexpricePiece };
|
package/package.json
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createPiece, Property } from "@activepieces/pieces-framework";
|
|
2
|
+
import { ingestEventAction } from "./lib/actions/ingest-event";
|
|
3
|
+
import { createCustomerAction } from "./lib/actions/create-customer";
|
|
4
|
+
import { getCustomerAction } from "./lib/actions/get-customer";
|
|
5
|
+
import { getSubscriptionsAction } from "./lib/actions/get-subscriptions";
|
|
6
|
+
import { getInvoicesAction } from "./lib/actions/get-invoices";
|
|
7
|
+
|
|
8
|
+
export const flexpricePiece = createPiece({
|
|
9
|
+
displayName: "Flexprice Billing & Metering",
|
|
10
|
+
logoUrl: "https://raw.githubusercontent.com/flexprice/flexprice-front/main/assets/flexprice_logo.png",
|
|
11
|
+
minimumSupportedRelease: "0.5.0",
|
|
12
|
+
authors: ["Whatomation Team"],
|
|
13
|
+
auth: Property.CustomAuth({
|
|
14
|
+
displayName: "Flexprice Authentication",
|
|
15
|
+
description: "Provide your Flexprice API key and server URL",
|
|
16
|
+
required: true,
|
|
17
|
+
props: {
|
|
18
|
+
apiKey: Property.SecretText({
|
|
19
|
+
displayName: "API Key",
|
|
20
|
+
description: "Your master Flexprice API key (x-api-key)",
|
|
21
|
+
required: true
|
|
22
|
+
}),
|
|
23
|
+
baseUrl: Property.ShortText({
|
|
24
|
+
displayName: "API Base URL",
|
|
25
|
+
description: "Flexprice API Base URL (default: http://localhost:8080/v1)",
|
|
26
|
+
required: true,
|
|
27
|
+
defaultValue: "http://localhost:8080/v1"
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
actions: [
|
|
32
|
+
ingestEventAction,
|
|
33
|
+
createCustomerAction,
|
|
34
|
+
getCustomerAction,
|
|
35
|
+
getSubscriptionsAction,
|
|
36
|
+
getInvoicesAction
|
|
37
|
+
],
|
|
38
|
+
triggers: []
|
|
39
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createAction, Property } from "@activepieces/pieces-framework";
|
|
2
|
+
import { ActionContext, FlexpriceAuth } from "../types";
|
|
3
|
+
|
|
4
|
+
interface CreateCustomerProps {
|
|
5
|
+
externalId: string;
|
|
6
|
+
name: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const createCustomerAction = createAction({
|
|
11
|
+
name: "create_customer",
|
|
12
|
+
displayName: "Create Customer",
|
|
13
|
+
description: "Provision a new billing customer profile in Flexprice",
|
|
14
|
+
props: {
|
|
15
|
+
externalId: Property.ShortText({
|
|
16
|
+
displayName: "External Customer ID",
|
|
17
|
+
description: "Unique identifier for client in your system (e.g. Supabase client_id)",
|
|
18
|
+
required: true
|
|
19
|
+
}),
|
|
20
|
+
name: Property.ShortText({
|
|
21
|
+
displayName: "Customer Name",
|
|
22
|
+
description: "Client business or individual name",
|
|
23
|
+
required: true
|
|
24
|
+
}),
|
|
25
|
+
email: Property.ShortText({
|
|
26
|
+
displayName: "Customer Email",
|
|
27
|
+
description: "Billing contact email address",
|
|
28
|
+
required: false
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
async run(context: ActionContext<CreateCustomerProps, FlexpriceAuth>) {
|
|
32
|
+
const apiKey = context.auth?.apiKey || "";
|
|
33
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
34
|
+
|
|
35
|
+
const payload = {
|
|
36
|
+
external_id: context.propsValue.externalId,
|
|
37
|
+
name: context.propsValue.name,
|
|
38
|
+
email: context.propsValue.email || undefined
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const res = await fetch(`${baseUrl}/customers`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
"Content-Type": "application/json",
|
|
45
|
+
"x-api-key": apiKey
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify(payload)
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const data = await res.json();
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
throw new Error(`Flexprice Customer Creation Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return data;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createAction, Property } from "@activepieces/pieces-framework";
|
|
2
|
+
import { ActionContext, FlexpriceAuth } from "../types";
|
|
3
|
+
|
|
4
|
+
interface GetCustomerProps {
|
|
5
|
+
externalId: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getCustomerAction = createAction({
|
|
9
|
+
name: "get_customer",
|
|
10
|
+
displayName: "Get Customer Details",
|
|
11
|
+
description: "Fetch customer details from Flexprice by external ID or customer ID",
|
|
12
|
+
props: {
|
|
13
|
+
externalId: Property.ShortText({
|
|
14
|
+
displayName: "External Customer ID",
|
|
15
|
+
description: "External tenant ID",
|
|
16
|
+
required: true
|
|
17
|
+
})
|
|
18
|
+
},
|
|
19
|
+
async run(context: ActionContext<GetCustomerProps, FlexpriceAuth>) {
|
|
20
|
+
const apiKey = context.auth?.apiKey || "";
|
|
21
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
22
|
+
|
|
23
|
+
const url = `${baseUrl}/customers?external_id=${encodeURIComponent(context.propsValue.externalId)}`;
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
method: "GET",
|
|
26
|
+
headers: {
|
|
27
|
+
"x-api-key": apiKey
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const data = await res.json();
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
throw new Error(`Flexprice Fetch Customer Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createAction, Property } from "@activepieces/pieces-framework";
|
|
2
|
+
import { ActionContext, FlexpriceAuth } from "../types";
|
|
3
|
+
|
|
4
|
+
interface GetInvoicesProps {
|
|
5
|
+
customerId: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getInvoicesAction = createAction({
|
|
9
|
+
name: "get_invoices",
|
|
10
|
+
displayName: "Get Invoices",
|
|
11
|
+
description: "Fetch invoices and billing statements from Flexprice",
|
|
12
|
+
props: {
|
|
13
|
+
customerId: Property.ShortText({
|
|
14
|
+
displayName: "Flexprice Customer ID",
|
|
15
|
+
description: "Customer ID in Flexprice",
|
|
16
|
+
required: true
|
|
17
|
+
})
|
|
18
|
+
},
|
|
19
|
+
async run(context: ActionContext<GetInvoicesProps, FlexpriceAuth>) {
|
|
20
|
+
const apiKey = context.auth?.apiKey || "";
|
|
21
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
22
|
+
|
|
23
|
+
const url = `${baseUrl}/invoices?customer_id=${encodeURIComponent(context.propsValue.customerId)}`;
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
method: "GET",
|
|
26
|
+
headers: {
|
|
27
|
+
"x-api-key": apiKey
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const data = await res.json();
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
throw new Error(`Flexprice Fetch Invoices Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createAction, Property } from "@activepieces/pieces-framework";
|
|
2
|
+
import { ActionContext, FlexpriceAuth } from "../types";
|
|
3
|
+
|
|
4
|
+
interface GetSubscriptionsProps {
|
|
5
|
+
customerId: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getSubscriptionsAction = createAction({
|
|
9
|
+
name: "get_subscriptions",
|
|
10
|
+
displayName: "Get Subscriptions",
|
|
11
|
+
description: "Fetch customer subscription plan and status from Flexprice",
|
|
12
|
+
props: {
|
|
13
|
+
customerId: Property.ShortText({
|
|
14
|
+
displayName: "Flexprice Customer ID",
|
|
15
|
+
description: "Customer ID in Flexprice",
|
|
16
|
+
required: true
|
|
17
|
+
})
|
|
18
|
+
},
|
|
19
|
+
async run(context: ActionContext<GetSubscriptionsProps, FlexpriceAuth>) {
|
|
20
|
+
const apiKey = context.auth?.apiKey || "";
|
|
21
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
22
|
+
|
|
23
|
+
const url = `${baseUrl}/subscriptions?customer_id=${encodeURIComponent(context.propsValue.customerId)}`;
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
method: "GET",
|
|
26
|
+
headers: {
|
|
27
|
+
"x-api-key": apiKey
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const data = await res.json();
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
throw new Error(`Flexprice Fetch Subscriptions Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createAction, Property } from "@activepieces/pieces-framework";
|
|
2
|
+
import { ActionContext, FlexpriceAuth } from "../types";
|
|
3
|
+
|
|
4
|
+
interface IngestEventProps {
|
|
5
|
+
eventName: string;
|
|
6
|
+
customerId?: string;
|
|
7
|
+
externalCustomerId?: string;
|
|
8
|
+
quantity?: number;
|
|
9
|
+
propertiesJson?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ingestEventAction = createAction({
|
|
13
|
+
name: "ingest_event",
|
|
14
|
+
displayName: "Ingest Usage Event",
|
|
15
|
+
description: "Report a billable usage event to Flexprice (e.g. lead_received, whatsapp_message_sent)",
|
|
16
|
+
props: {
|
|
17
|
+
eventName: Property.ShortText({
|
|
18
|
+
displayName: "Event Name",
|
|
19
|
+
description: "Name of the usage event (e.g. lead_received, whatsapp_message_sent)",
|
|
20
|
+
required: true,
|
|
21
|
+
defaultValue: "lead_received"
|
|
22
|
+
}),
|
|
23
|
+
customerId: Property.ShortText({
|
|
24
|
+
displayName: "Flexprice Customer ID",
|
|
25
|
+
description: "Internal Flexprice Customer UUID (or leave empty if passing External Customer ID)",
|
|
26
|
+
required: false
|
|
27
|
+
}),
|
|
28
|
+
externalCustomerId: Property.ShortText({
|
|
29
|
+
displayName: "External Customer ID",
|
|
30
|
+
description: "External Tenant/Client ID (e.g. Supabase client_id)",
|
|
31
|
+
required: false
|
|
32
|
+
}),
|
|
33
|
+
quantity: Property.Number({
|
|
34
|
+
displayName: "Quantity",
|
|
35
|
+
description: "Usage quantity / units (default: 1)",
|
|
36
|
+
required: false,
|
|
37
|
+
defaultValue: 1
|
|
38
|
+
}),
|
|
39
|
+
propertiesJson: Property.LongText({
|
|
40
|
+
displayName: "Custom Event Properties (JSON)",
|
|
41
|
+
description: "Optional JSON metadata object for the event",
|
|
42
|
+
required: false
|
|
43
|
+
})
|
|
44
|
+
},
|
|
45
|
+
async run(context: ActionContext<IngestEventProps, FlexpriceAuth>) {
|
|
46
|
+
const apiKey = context.auth?.apiKey || "";
|
|
47
|
+
const baseUrl = (context.auth?.baseUrl || "http://localhost:8080/v1").replace(/\/+$/, "");
|
|
48
|
+
|
|
49
|
+
let propertiesObj = {};
|
|
50
|
+
if (context.propsValue.propertiesJson) {
|
|
51
|
+
try {
|
|
52
|
+
propertiesObj = JSON.parse(context.propsValue.propertiesJson);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
propertiesObj = { raw: context.propsValue.propertiesJson };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const payload = {
|
|
59
|
+
event_name: context.propsValue.eventName,
|
|
60
|
+
customer_id: context.propsValue.customerId || undefined,
|
|
61
|
+
external_customer_id: context.propsValue.externalCustomerId || undefined,
|
|
62
|
+
timestamp: new Date().toISOString(),
|
|
63
|
+
properties: {
|
|
64
|
+
quantity: context.propsValue.quantity ?? 1,
|
|
65
|
+
...propertiesObj
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const res = await fetch(`${baseUrl}/events`, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"x-api-key": apiKey
|
|
74
|
+
},
|
|
75
|
+
body: JSON.stringify(payload)
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const data = await res.json();
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
throw new Error(`Flexprice Event Ingestion Failed (${res.status}): ${JSON.stringify(data)}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
});
|
package/src/lib/types.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"baseUrl": ".",
|
|
10
|
+
"paths": {
|
|
11
|
+
"@activepieces/pieces-framework": ["./node_modules/@activepieces/pieces-framework"]
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|