n8n-nodes-lemonsqueezy 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.
- package/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/credentials/LemonSqueezyApi.credentials.d.ts +10 -0
- package/dist/credentials/LemonSqueezyApi.credentials.js +41 -0
- package/dist/nodes/LemonSqueezy/LemonSqueezy.node.d.ts +5 -0
- package/dist/nodes/LemonSqueezy/LemonSqueezy.node.js +358 -0
- package/dist/nodes/LemonSqueezy/LemonSqueezyTrigger.node.d.ts +12 -0
- package/dist/nodes/LemonSqueezy/LemonSqueezyTrigger.node.js +230 -0
- package/dist/nodes/LemonSqueezy/constants.d.ts +89 -0
- package/dist/nodes/LemonSqueezy/constants.js +207 -0
- package/dist/nodes/LemonSqueezy/helpers.d.ts +28 -0
- package/dist/nodes/LemonSqueezy/helpers.js +241 -0
- package/dist/nodes/LemonSqueezy/lemonSqueezy.svg +20 -0
- package/dist/nodes/LemonSqueezy/resources/checkout.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/checkout.js +272 -0
- package/dist/nodes/LemonSqueezy/resources/customer.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/customer.js +242 -0
- package/dist/nodes/LemonSqueezy/resources/discount.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/discount.js +210 -0
- package/dist/nodes/LemonSqueezy/resources/index.d.ts +15 -0
- package/dist/nodes/LemonSqueezy/resources/index.js +76 -0
- package/dist/nodes/LemonSqueezy/resources/licenseKey.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/licenseKey.js +209 -0
- package/dist/nodes/LemonSqueezy/resources/order.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/order.js +113 -0
- package/dist/nodes/LemonSqueezy/resources/product.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/product.js +93 -0
- package/dist/nodes/LemonSqueezy/resources/store.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/store.js +64 -0
- package/dist/nodes/LemonSqueezy/resources/subscription.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/subscription.js +196 -0
- package/dist/nodes/LemonSqueezy/resources/variant.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/variant.js +96 -0
- package/dist/nodes/LemonSqueezy/resources/webhook.d.ts +3 -0
- package/dist/nodes/LemonSqueezy/resources/webhook.js +206 -0
- package/dist/nodes/LemonSqueezy/types.d.ts +364 -0
- package/dist/nodes/LemonSqueezy/types.js +2 -0
- package/package.json +71 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.lemonSqueezyApiRequest = lemonSqueezyApiRequest;
|
|
37
|
+
exports.lemonSqueezyApiRequestAllItems = lemonSqueezyApiRequestAllItems;
|
|
38
|
+
exports.validateRequiredFields = validateRequiredFields;
|
|
39
|
+
exports.buildFilterParams = buildFilterParams;
|
|
40
|
+
exports.buildJsonApiBody = buildJsonApiBody;
|
|
41
|
+
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
42
|
+
const crypto = __importStar(require("crypto"));
|
|
43
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
44
|
+
const constants_1 = require("./constants");
|
|
45
|
+
/**
|
|
46
|
+
* Sleep for a specified number of milliseconds
|
|
47
|
+
*/
|
|
48
|
+
function sleep(ms) {
|
|
49
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if error is a rate limit error
|
|
53
|
+
*/
|
|
54
|
+
function isRateLimitError(error) {
|
|
55
|
+
var _a;
|
|
56
|
+
if (error && typeof error === 'object') {
|
|
57
|
+
const err = error;
|
|
58
|
+
return err.statusCode === 429 || ((_a = err.response) === null || _a === void 0 ? void 0 : _a.statusCode) === 429;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if error is retryable (5xx errors or network errors)
|
|
64
|
+
*/
|
|
65
|
+
function isRetryableError(error) {
|
|
66
|
+
var _a;
|
|
67
|
+
if (error && typeof error === 'object') {
|
|
68
|
+
const err = error;
|
|
69
|
+
const statusCode = err.statusCode || ((_a = err.response) === null || _a === void 0 ? void 0 : _a.statusCode);
|
|
70
|
+
if (statusCode && statusCode >= 500 && statusCode < 600) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
if (err.code === 'ECONNRESET' || err.code === 'ETIMEDOUT' || err.code === 'ECONNREFUSED') {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Make an authenticated request to the Lemon Squeezy API with retry logic
|
|
81
|
+
*/
|
|
82
|
+
async function lemonSqueezyApiRequest(method, endpoint, body, qs = {}) {
|
|
83
|
+
const options = {
|
|
84
|
+
method,
|
|
85
|
+
url: `${constants_1.API_BASE_URL}${endpoint}`,
|
|
86
|
+
qs,
|
|
87
|
+
json: true,
|
|
88
|
+
};
|
|
89
|
+
if (body) {
|
|
90
|
+
options.body = body;
|
|
91
|
+
}
|
|
92
|
+
let lastError;
|
|
93
|
+
for (let attempt = 0; attempt < constants_1.MAX_RETRIES; attempt++) {
|
|
94
|
+
try {
|
|
95
|
+
return (await this.helpers.requestWithAuthentication.call(this, 'lemonSqueezyApi', options));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
lastError = error;
|
|
99
|
+
if (isRateLimitError(error)) {
|
|
100
|
+
// Wait for rate limit to reset (usually 60 seconds)
|
|
101
|
+
await sleep(constants_1.RATE_LIMIT_DELAY_MS);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (isRetryableError(error) && attempt < constants_1.MAX_RETRIES - 1) {
|
|
105
|
+
// Exponential backoff for retryable errors
|
|
106
|
+
await sleep(constants_1.RETRY_DELAY_MS * Math.pow(2, attempt));
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
// Non-retryable error, throw immediately
|
|
110
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error, {
|
|
111
|
+
message: getErrorMessage(error),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// All retries exhausted
|
|
116
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), lastError, {
|
|
117
|
+
message: getErrorMessage(lastError),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Make paginated requests to fetch all items
|
|
122
|
+
*/
|
|
123
|
+
async function lemonSqueezyApiRequestAllItems(method, endpoint, qs = {}) {
|
|
124
|
+
var _a;
|
|
125
|
+
const returnData = [];
|
|
126
|
+
let nextPageUrl = `${constants_1.API_BASE_URL}${endpoint}`;
|
|
127
|
+
qs['page[size]'] = constants_1.DEFAULT_PAGE_SIZE;
|
|
128
|
+
do {
|
|
129
|
+
const options = {
|
|
130
|
+
method,
|
|
131
|
+
url: nextPageUrl,
|
|
132
|
+
qs: nextPageUrl.includes('?') ? {} : qs,
|
|
133
|
+
json: true,
|
|
134
|
+
};
|
|
135
|
+
let responseData;
|
|
136
|
+
try {
|
|
137
|
+
responseData = (await this.helpers.requestWithAuthentication.call(this, 'lemonSqueezyApi', options));
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (isRateLimitError(error)) {
|
|
141
|
+
await sleep(constants_1.RATE_LIMIT_DELAY_MS);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error, {
|
|
145
|
+
message: getErrorMessage(error),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
returnData.push(...responseData.data);
|
|
149
|
+
nextPageUrl = ((_a = responseData.links) === null || _a === void 0 ? void 0 : _a.next) || null;
|
|
150
|
+
} while (nextPageUrl);
|
|
151
|
+
return returnData;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Extract error message from error object
|
|
155
|
+
*/
|
|
156
|
+
function getErrorMessage(error) {
|
|
157
|
+
var _a, _b, _c, _d, _e;
|
|
158
|
+
if (error && typeof error === 'object') {
|
|
159
|
+
const err = error;
|
|
160
|
+
// Check for JSON:API error format
|
|
161
|
+
if ((_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.errors) === null || _c === void 0 ? void 0 : _c[0]) {
|
|
162
|
+
const apiError = err.response.body.errors[0];
|
|
163
|
+
return apiError.detail || apiError.title || 'Unknown API error';
|
|
164
|
+
}
|
|
165
|
+
if ((_e = (_d = err.response) === null || _d === void 0 ? void 0 : _d.body) === null || _e === void 0 ? void 0 : _e.message) {
|
|
166
|
+
return err.response.body.message;
|
|
167
|
+
}
|
|
168
|
+
if (err.message) {
|
|
169
|
+
return err.message;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return 'An unknown error occurred';
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Validate required fields before making API request
|
|
176
|
+
*/
|
|
177
|
+
function validateRequiredFields(fields, requiredFields) {
|
|
178
|
+
const missingFields = [];
|
|
179
|
+
for (const field of requiredFields) {
|
|
180
|
+
if (fields[field] === undefined || fields[field] === null || fields[field] === '') {
|
|
181
|
+
missingFields.push(field);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (missingFields.length > 0) {
|
|
185
|
+
throw new Error(`Missing required fields: ${missingFields.join(', ')}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Build filter query string parameters
|
|
190
|
+
*/
|
|
191
|
+
function buildFilterParams(filters) {
|
|
192
|
+
const qs = {};
|
|
193
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
194
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
195
|
+
// Convert camelCase to snake_case for API
|
|
196
|
+
const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
197
|
+
qs[`filter[${snakeKey}]`] = value;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return qs;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Build JSON:API request body
|
|
204
|
+
*/
|
|
205
|
+
function buildJsonApiBody(type, attributes, relationships, id) {
|
|
206
|
+
const body = {
|
|
207
|
+
data: {
|
|
208
|
+
type,
|
|
209
|
+
attributes,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
if (id) {
|
|
213
|
+
body.data.id = id;
|
|
214
|
+
}
|
|
215
|
+
if (relationships) {
|
|
216
|
+
const relationshipsObj = {};
|
|
217
|
+
for (const [key, value] of Object.entries(relationships)) {
|
|
218
|
+
relationshipsObj[key] = {
|
|
219
|
+
data: {
|
|
220
|
+
type: value.type,
|
|
221
|
+
id: value.id,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
body.data.relationships = relationshipsObj;
|
|
226
|
+
}
|
|
227
|
+
return body;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Parse webhook signature for validation
|
|
231
|
+
*/
|
|
232
|
+
function verifyWebhookSignature(payload, signature, secret) {
|
|
233
|
+
const hmac = crypto.createHmac('sha256', secret);
|
|
234
|
+
const digest = hmac.update(payload).digest('hex');
|
|
235
|
+
try {
|
|
236
|
+
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="lemonGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#FFC233"/>
|
|
5
|
+
<stop offset="100%" style="stop-color:#F5A623"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<!-- Lemon body -->
|
|
9
|
+
<ellipse cx="32" cy="34" rx="22" ry="18" fill="url(#lemonGradient)"/>
|
|
10
|
+
<!-- Lemon tip -->
|
|
11
|
+
<path d="M54 34 Q62 34 58 28 Q56 32 54 34" fill="#F5A623"/>
|
|
12
|
+
<path d="M10 34 Q2 34 6 28 Q8 32 10 34" fill="#FFC233"/>
|
|
13
|
+
<!-- Leaf -->
|
|
14
|
+
<path d="M32 16 Q38 8 44 12 Q38 14 36 18 Q34 14 32 16" fill="#7CB342"/>
|
|
15
|
+
<path d="M32 16 Q26 8 20 12 Q26 14 28 18 Q30 14 32 16" fill="#8BC34A"/>
|
|
16
|
+
<!-- Stem -->
|
|
17
|
+
<rect x="30" y="14" width="4" height="6" rx="2" fill="#5D4037"/>
|
|
18
|
+
<!-- Highlight -->
|
|
19
|
+
<ellipse cx="24" cy="30" rx="6" ry="4" fill="rgba(255,255,255,0.3)" transform="rotate(-20 24 30)"/>
|
|
20
|
+
</svg>
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkoutFields = exports.checkoutOperations = void 0;
|
|
4
|
+
exports.checkoutOperations = {
|
|
5
|
+
displayName: 'Operation',
|
|
6
|
+
name: 'operation',
|
|
7
|
+
type: 'options',
|
|
8
|
+
noDataExpression: true,
|
|
9
|
+
displayOptions: {
|
|
10
|
+
show: { resource: ['checkout'] },
|
|
11
|
+
},
|
|
12
|
+
options: [
|
|
13
|
+
{
|
|
14
|
+
name: 'Create',
|
|
15
|
+
value: 'create',
|
|
16
|
+
action: 'Create a checkout',
|
|
17
|
+
description: 'Create a new checkout link',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Get',
|
|
21
|
+
value: 'get',
|
|
22
|
+
action: 'Get a checkout',
|
|
23
|
+
description: 'Retrieve a single checkout by ID',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'Get Many',
|
|
27
|
+
value: 'getAll',
|
|
28
|
+
action: 'Get many checkouts',
|
|
29
|
+
description: 'Retrieve multiple checkouts',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
default: 'create',
|
|
33
|
+
};
|
|
34
|
+
exports.checkoutFields = [
|
|
35
|
+
// Checkout ID for Get operation
|
|
36
|
+
{
|
|
37
|
+
displayName: 'Checkout ID',
|
|
38
|
+
name: 'checkoutId',
|
|
39
|
+
type: 'string',
|
|
40
|
+
required: true,
|
|
41
|
+
default: '',
|
|
42
|
+
description: 'The ID of the checkout to retrieve',
|
|
43
|
+
displayOptions: {
|
|
44
|
+
show: { resource: ['checkout'], operation: ['get'] },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
// Create Fields
|
|
48
|
+
{
|
|
49
|
+
displayName: 'Store ID',
|
|
50
|
+
name: 'checkoutStoreId',
|
|
51
|
+
type: 'string',
|
|
52
|
+
required: true,
|
|
53
|
+
default: '',
|
|
54
|
+
description: 'The ID of the store',
|
|
55
|
+
displayOptions: {
|
|
56
|
+
show: { resource: ['checkout'], operation: ['create'] },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
displayName: 'Variant ID',
|
|
61
|
+
name: 'checkoutVariantId',
|
|
62
|
+
type: 'string',
|
|
63
|
+
required: true,
|
|
64
|
+
default: '',
|
|
65
|
+
description: 'The ID of the variant to checkout',
|
|
66
|
+
displayOptions: {
|
|
67
|
+
show: { resource: ['checkout'], operation: ['create'] },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
displayName: 'Additional Options',
|
|
72
|
+
name: 'additionalOptions',
|
|
73
|
+
type: 'collection',
|
|
74
|
+
placeholder: 'Add Option',
|
|
75
|
+
default: {},
|
|
76
|
+
displayOptions: {
|
|
77
|
+
show: { resource: ['checkout'], operation: ['create'] },
|
|
78
|
+
},
|
|
79
|
+
options: [
|
|
80
|
+
{
|
|
81
|
+
displayName: 'Custom Price',
|
|
82
|
+
name: 'customPrice',
|
|
83
|
+
type: 'number',
|
|
84
|
+
default: 0,
|
|
85
|
+
description: 'Custom price in cents (for pay-what-you-want products)',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
displayName: 'Discount Code',
|
|
89
|
+
name: 'discountCode',
|
|
90
|
+
type: 'string',
|
|
91
|
+
default: '',
|
|
92
|
+
description: 'Discount code to apply to the checkout',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
displayName: 'Customer Email',
|
|
96
|
+
name: 'email',
|
|
97
|
+
type: 'string',
|
|
98
|
+
default: '',
|
|
99
|
+
description: 'Pre-fill customer email',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
displayName: 'Customer Name',
|
|
103
|
+
name: 'name',
|
|
104
|
+
type: 'string',
|
|
105
|
+
default: '',
|
|
106
|
+
description: 'Pre-fill customer name',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: 'Redirect URL',
|
|
110
|
+
name: 'redirectUrl',
|
|
111
|
+
type: 'string',
|
|
112
|
+
default: '',
|
|
113
|
+
description: 'URL to redirect after successful purchase',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
displayName: 'Receipt Button Text',
|
|
117
|
+
name: 'receiptButtonText',
|
|
118
|
+
type: 'string',
|
|
119
|
+
default: '',
|
|
120
|
+
description: 'Custom text for receipt button',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
displayName: 'Receipt Link URL',
|
|
124
|
+
name: 'receiptLinkUrl',
|
|
125
|
+
type: 'string',
|
|
126
|
+
default: '',
|
|
127
|
+
description: 'Custom URL for receipt button',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
displayName: 'Receipt Thank You Note',
|
|
131
|
+
name: 'receiptThankYouNote',
|
|
132
|
+
type: 'string',
|
|
133
|
+
default: '',
|
|
134
|
+
description: 'Custom thank you note on receipt',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
displayName: 'Custom Data',
|
|
138
|
+
name: 'customData',
|
|
139
|
+
type: 'json',
|
|
140
|
+
default: '{}',
|
|
141
|
+
description: 'Custom data to attach to the checkout (will be passed to webhooks)',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
displayName: 'Expires At',
|
|
145
|
+
name: 'expiresAt',
|
|
146
|
+
type: 'dateTime',
|
|
147
|
+
default: '',
|
|
148
|
+
description: 'When the checkout link expires (ISO 8601 format)',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
displayName: 'Test Mode',
|
|
152
|
+
name: 'testMode',
|
|
153
|
+
type: 'boolean',
|
|
154
|
+
default: false,
|
|
155
|
+
description: 'Whether this is a test checkout',
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
// Checkout Options
|
|
160
|
+
{
|
|
161
|
+
displayName: 'Checkout Display Options',
|
|
162
|
+
name: 'checkoutOptions',
|
|
163
|
+
type: 'collection',
|
|
164
|
+
placeholder: 'Add Display Option',
|
|
165
|
+
default: {},
|
|
166
|
+
displayOptions: {
|
|
167
|
+
show: { resource: ['checkout'], operation: ['create'] },
|
|
168
|
+
},
|
|
169
|
+
options: [
|
|
170
|
+
{
|
|
171
|
+
displayName: 'Dark Mode',
|
|
172
|
+
name: 'dark',
|
|
173
|
+
type: 'boolean',
|
|
174
|
+
default: false,
|
|
175
|
+
description: 'Whether to use dark mode',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
displayName: 'Embed Mode',
|
|
179
|
+
name: 'embed',
|
|
180
|
+
type: 'boolean',
|
|
181
|
+
default: false,
|
|
182
|
+
description: 'Whether checkout is embedded',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
displayName: 'Show Logo',
|
|
186
|
+
name: 'logo',
|
|
187
|
+
type: 'boolean',
|
|
188
|
+
default: true,
|
|
189
|
+
description: 'Whether to show the store logo',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
displayName: 'Show Description',
|
|
193
|
+
name: 'desc',
|
|
194
|
+
type: 'boolean',
|
|
195
|
+
default: true,
|
|
196
|
+
description: 'Whether to show the product description',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
displayName: 'Show Media',
|
|
200
|
+
name: 'media',
|
|
201
|
+
type: 'boolean',
|
|
202
|
+
default: true,
|
|
203
|
+
description: 'Whether to show product media',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
displayName: 'Show Discount Field',
|
|
207
|
+
name: 'discount',
|
|
208
|
+
type: 'boolean',
|
|
209
|
+
default: true,
|
|
210
|
+
description: 'Whether to show the discount code field',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
displayName: 'Button Color',
|
|
214
|
+
name: 'buttonColor',
|
|
215
|
+
type: 'string',
|
|
216
|
+
default: '',
|
|
217
|
+
description: 'Custom button color (hex code)',
|
|
218
|
+
placeholder: '#7c3aed',
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
// Return All
|
|
223
|
+
{
|
|
224
|
+
displayName: 'Return All',
|
|
225
|
+
name: 'returnAll',
|
|
226
|
+
type: 'boolean',
|
|
227
|
+
default: false,
|
|
228
|
+
description: 'Whether to return all results or only up to a given limit',
|
|
229
|
+
displayOptions: {
|
|
230
|
+
show: { resource: ['checkout'], operation: ['getAll'] },
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
// Limit
|
|
234
|
+
{
|
|
235
|
+
displayName: 'Limit',
|
|
236
|
+
name: 'limit',
|
|
237
|
+
type: 'number',
|
|
238
|
+
default: 50,
|
|
239
|
+
description: 'Max number of results to return',
|
|
240
|
+
typeOptions: { minValue: 1 },
|
|
241
|
+
displayOptions: {
|
|
242
|
+
show: { resource: ['checkout'], operation: ['getAll'], returnAll: [false] },
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
// Filters
|
|
246
|
+
{
|
|
247
|
+
displayName: 'Filters',
|
|
248
|
+
name: 'filters',
|
|
249
|
+
type: 'collection',
|
|
250
|
+
placeholder: 'Add Filter',
|
|
251
|
+
default: {},
|
|
252
|
+
displayOptions: {
|
|
253
|
+
show: { resource: ['checkout'], operation: ['getAll'] },
|
|
254
|
+
},
|
|
255
|
+
options: [
|
|
256
|
+
{
|
|
257
|
+
displayName: 'Store ID',
|
|
258
|
+
name: 'storeId',
|
|
259
|
+
type: 'string',
|
|
260
|
+
default: '',
|
|
261
|
+
description: 'Filter by store ID',
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
displayName: 'Variant ID',
|
|
265
|
+
name: 'variantId',
|
|
266
|
+
type: 'string',
|
|
267
|
+
default: '',
|
|
268
|
+
description: 'Filter by variant ID',
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
},
|
|
272
|
+
];
|