@open-loyalty/mcp-server 1.5.3 → 1.7.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/dist/config.d.ts +4 -0
- package/dist/config.js +11 -0
- package/dist/index.js +0 -8
- package/dist/server.js +13 -0
- package/dist/tools/achievement/handlers.js +47 -0
- package/dist/tools/achievement/index.d.ts +11 -4
- package/dist/tools/achievement/index.js +12 -1
- package/dist/tools/achievement/schemas.d.ts +4 -4
- package/dist/tools/achievement/schemas.js +13 -12
- package/dist/tools/admin/handlers.d.ts +48 -0
- package/dist/tools/admin/handlers.js +159 -0
- package/dist/tools/admin/index.d.ts +86 -0
- package/dist/tools/admin/index.js +64 -0
- package/dist/tools/admin/schemas.d.ts +40 -0
- package/dist/tools/admin/schemas.js +40 -0
- package/dist/tools/analytics/handlers.d.ts +42 -0
- package/dist/tools/analytics/handlers.js +282 -0
- package/dist/tools/analytics/index.d.ts +108 -0
- package/dist/tools/analytics/index.js +91 -0
- package/dist/tools/analytics/schemas.d.ts +42 -0
- package/dist/tools/analytics/schemas.js +47 -0
- package/dist/tools/apikey/handlers.d.ts +15 -0
- package/dist/tools/apikey/handlers.js +53 -0
- package/dist/tools/apikey/index.d.ts +41 -0
- package/dist/tools/apikey/index.js +38 -0
- package/dist/tools/apikey/schemas.d.ts +31 -0
- package/dist/tools/apikey/schemas.js +15 -0
- package/dist/tools/audit/handlers.d.ts +20 -0
- package/dist/tools/audit/handlers.js +82 -0
- package/dist/tools/audit/index.d.ts +36 -0
- package/dist/tools/audit/index.js +28 -0
- package/dist/tools/audit/schemas.d.ts +62 -0
- package/dist/tools/audit/schemas.js +18 -0
- package/dist/tools/badge/handlers.d.ts +45 -0
- package/dist/tools/badge/handlers.js +135 -0
- package/dist/tools/badge/index.d.ts +68 -0
- package/dist/tools/badge/index.js +47 -0
- package/dist/tools/badge/schemas.d.ts +37 -0
- package/dist/tools/badge/schemas.js +31 -0
- package/dist/tools/campaign/handlers.js +61 -0
- package/dist/tools/campaign/index.d.ts +12 -0
- package/dist/tools/campaign/index.js +20 -1
- package/dist/tools/campaign/member-handlers.js +37 -1
- package/dist/tools/campaign/schemas.js +16 -14
- package/dist/tools/custom-event/handlers.d.ts +98 -0
- package/dist/tools/custom-event/handlers.js +238 -0
- package/dist/tools/custom-event/index.d.ts +139 -0
- package/dist/tools/custom-event/index.js +78 -0
- package/dist/tools/custom-event/schemas.d.ts +87 -0
- package/dist/tools/custom-event/schemas.js +59 -0
- package/dist/tools/export/handlers.d.ts +29 -0
- package/dist/tools/export/handlers.js +128 -0
- package/dist/tools/export/index.d.ts +56 -0
- package/dist/tools/export/index.js +46 -0
- package/dist/tools/export/schemas.d.ts +42 -0
- package/dist/tools/export/schemas.js +41 -0
- package/dist/tools/import/handlers.d.ts +22 -0
- package/dist/tools/import/handlers.js +123 -0
- package/dist/tools/import/index.d.ts +45 -0
- package/dist/tools/import/index.js +41 -0
- package/dist/tools/import/schemas.d.ts +57 -0
- package/dist/tools/import/schemas.js +39 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +11 -11
- package/dist/tools/member/handlers.js +30 -0
- package/dist/tools/member/index.d.ts +10 -0
- package/dist/tools/member/index.js +10 -0
- package/dist/tools/member/schemas.js +13 -13
- package/dist/tools/points/handlers.js +73 -0
- package/dist/tools/points/index.d.ts +6 -0
- package/dist/tools/points/index.js +6 -0
- package/dist/tools/points/schemas.js +1 -1
- package/dist/tools/referral/index.d.ts +3 -0
- package/dist/tools/referral/index.js +3 -0
- package/dist/tools/reward/handlers.js +21 -13
- package/dist/tools/reward/index.d.ts +9 -0
- package/dist/tools/reward/index.js +12 -1
- package/dist/tools/reward/schemas.js +2 -2
- package/dist/tools/role/handlers.d.ts +35 -0
- package/dist/tools/role/handlers.js +127 -0
- package/dist/tools/role/index.d.ts +99 -0
- package/dist/tools/role/index.js +65 -0
- package/dist/tools/role/schemas.d.ts +56 -0
- package/dist/tools/role/schemas.js +35 -0
- package/dist/tools/segment/handlers.js +68 -1
- package/dist/tools/segment/index.d.ts +9 -0
- package/dist/tools/segment/index.js +13 -0
- package/dist/tools/segment/schemas.js +8 -5
- package/dist/tools/store/handlers.d.ts +25 -0
- package/dist/tools/store/handlers.js +89 -0
- package/dist/tools/store/index.d.ts +55 -0
- package/dist/tools/store/index.js +46 -0
- package/dist/tools/store/schemas.d.ts +38 -0
- package/dist/tools/store/schemas.js +23 -0
- package/dist/tools/tierset/handlers.js +92 -1
- package/dist/tools/tierset/index.d.ts +6 -0
- package/dist/tools/tierset/index.js +8 -1
- package/dist/tools/transaction/handlers.js +40 -0
- package/dist/tools/transaction/index.d.ts +4 -0
- package/dist/tools/transaction/index.js +4 -0
- package/dist/tools/transaction/schemas.js +3 -3
- package/dist/tools/wallet-type/index.d.ts +4 -0
- package/dist/tools/wallet-type/index.js +5 -1
- package/dist/tools/webhook/handlers.d.ts +34 -0
- package/dist/tools/webhook/handlers.js +147 -0
- package/dist/tools/webhook/index.d.ts +97 -0
- package/dist/tools/webhook/index.js +65 -0
- package/dist/tools/webhook/schemas.d.ts +72 -0
- package/dist/tools/{webhook.js → webhook/schemas.js} +0 -140
- package/dist/types/schemas/tierset.js +3 -1
- package/package.json +1 -1
- package/dist/tools/admin.d.ts +0 -165
- package/dist/tools/admin.js +0 -205
- package/dist/tools/analytics.d.ts +0 -180
- package/dist/tools/analytics.js +0 -255
- package/dist/tools/apikey.d.ts +0 -79
- package/dist/tools/apikey.js +0 -85
- package/dist/tools/audit.d.ts +0 -111
- package/dist/tools/audit.js +0 -94
- package/dist/tools/badge.d.ts +0 -143
- package/dist/tools/badge.js +0 -174
- package/dist/tools/custom-event.d.ts +0 -315
- package/dist/tools/custom-event.js +0 -271
- package/dist/tools/export.d.ts +0 -118
- package/dist/tools/export.js +0 -152
- package/dist/tools/import.d.ts +0 -116
- package/dist/tools/import.js +0 -143
- package/dist/tools/role.d.ts +0 -180
- package/dist/tools/role.js +0 -173
- package/dist/tools/store.d.ts +0 -109
- package/dist/tools/store.js +0 -125
- package/dist/tools/webhook.d.ts +0 -192
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { apiGet, apiPost } from "../../client/http.js";
|
|
2
|
-
import { formatApiError } from "../../utils/errors.js";
|
|
2
|
+
import { formatApiError, OpenLoyaltyError } from "../../utils/errors.js";
|
|
3
3
|
import { getStoreCode } from "../../config.js";
|
|
4
4
|
// Code management handlers
|
|
5
5
|
export async function campaignGenerateCodes(input) {
|
|
@@ -9,6 +9,15 @@ export async function campaignGenerateCodes(input) {
|
|
|
9
9
|
return { codesGenerated: input.quantity };
|
|
10
10
|
}
|
|
11
11
|
catch (error) {
|
|
12
|
+
const axiosError = error;
|
|
13
|
+
if (axiosError.response?.status === 404) {
|
|
14
|
+
throw new OpenLoyaltyError({
|
|
15
|
+
code: "NOT_FOUND",
|
|
16
|
+
message: `Campaign '${input.campaignId}' not found`,
|
|
17
|
+
hint: "Use ol_campaign_list() to find existing campaigns and their IDs. The campaignId may be incorrect or the campaign may have been deleted.",
|
|
18
|
+
relatedTool: "ol_campaign_generate_codes",
|
|
19
|
+
});
|
|
20
|
+
}
|
|
12
21
|
throw formatApiError(error, "ol_campaign_generate_codes");
|
|
13
22
|
}
|
|
14
23
|
}
|
|
@@ -83,6 +92,15 @@ export async function campaignGetAvailable(input) {
|
|
|
83
92
|
};
|
|
84
93
|
}
|
|
85
94
|
catch (error) {
|
|
95
|
+
const axiosError = error;
|
|
96
|
+
if (axiosError.response?.status === 404) {
|
|
97
|
+
throw new OpenLoyaltyError({
|
|
98
|
+
code: "NOT_FOUND",
|
|
99
|
+
message: `Member '${input.memberId}' not found`,
|
|
100
|
+
hint: "Use ol_member_list() to search for the member by email, name, or phone. The member ID may be incorrect.",
|
|
101
|
+
relatedTool: "ol_campaign_get_available",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
86
104
|
throw formatApiError(error, "ol_campaign_get_available");
|
|
87
105
|
}
|
|
88
106
|
}
|
|
@@ -117,6 +135,15 @@ export async function campaignGetVisible(input) {
|
|
|
117
135
|
};
|
|
118
136
|
}
|
|
119
137
|
catch (error) {
|
|
138
|
+
const axiosError = error;
|
|
139
|
+
if (axiosError.response?.status === 404) {
|
|
140
|
+
throw new OpenLoyaltyError({
|
|
141
|
+
code: "NOT_FOUND",
|
|
142
|
+
message: `Member '${input.memberId}' not found`,
|
|
143
|
+
hint: "Use ol_member_list() to search for the member by email, name, or phone. The member ID may be incorrect.",
|
|
144
|
+
relatedTool: "ol_campaign_get_visible",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
120
147
|
throw formatApiError(error, "ol_campaign_get_visible");
|
|
121
148
|
}
|
|
122
149
|
}
|
|
@@ -154,6 +181,15 @@ export async function campaignGetLeaderboard(input) {
|
|
|
154
181
|
};
|
|
155
182
|
}
|
|
156
183
|
catch (error) {
|
|
184
|
+
const axiosError = error;
|
|
185
|
+
if (axiosError.response?.status === 404) {
|
|
186
|
+
throw new OpenLoyaltyError({
|
|
187
|
+
code: "NOT_FOUND",
|
|
188
|
+
message: `Campaign '${input.campaignId}' not found`,
|
|
189
|
+
hint: "Use ol_campaign_list() to find existing campaigns and their IDs.",
|
|
190
|
+
relatedTool: "ol_campaign_get_leaderboard",
|
|
191
|
+
});
|
|
192
|
+
}
|
|
157
193
|
throw formatApiError(error, "ol_campaign_get_leaderboard");
|
|
158
194
|
}
|
|
159
195
|
}
|
|
@@ -18,8 +18,8 @@ const CampaignEffectInputSchema = z.object({
|
|
|
18
18
|
"Conditional: 'event.body.minutes_before >= 60 ? 25 : 0'. " +
|
|
19
19
|
"BUSINESS IMPACT: 'transaction.grossValue * 10' on $500 avg transaction = 5,000 points/purchase. " +
|
|
20
20
|
"At $0.01/point, that is a 10% return rate. Confirm the formula and earn rate with the user."),
|
|
21
|
-
walletCode: z.string().optional().describe("Wallet code for points (default wallet if not specified)."),
|
|
22
|
-
rewardId: z.string().optional().describe("Reward ID (required for give_reward effect)."),
|
|
21
|
+
walletCode: z.string().optional().describe("Wallet code for points (default wallet if not specified). Use ol_wallet_type_list to find valid codes."),
|
|
22
|
+
rewardId: z.string().optional().describe("Reward ID (required for give_reward effect). Use ol_reward_list to find valid rewardId values."),
|
|
23
23
|
customAttributeKey: z.string().optional().describe("Custom attribute key (for assign/remove member custom attribute effects)."),
|
|
24
24
|
customAttributeValueRule: z.string().optional().describe("Custom attribute value rule."),
|
|
25
25
|
});
|
|
@@ -52,8 +52,8 @@ const CampaignRuleInputSchema = z.object({
|
|
|
52
52
|
});
|
|
53
53
|
// Activity input schema
|
|
54
54
|
const CampaignActivityInputSchema = z.object({
|
|
55
|
-
startsAt: z.string().describe("Campaign start date/time (
|
|
56
|
-
endsAt: z.string().optional().describe("Campaign end date/time (
|
|
55
|
+
startsAt: z.string().describe("Campaign start date/time (format: 'YYYY-MM-DD HH:mm+TZ', e.g., '2026-01-01 00:00+00:00'). REQUIRED."),
|
|
56
|
+
endsAt: z.string().optional().describe("Campaign end date/time (format: 'YYYY-MM-DD HH:mm+TZ', e.g., '2026-12-31 23:59+00:00'). " +
|
|
57
57
|
"BUSINESS IMPACT: If not specified, campaign runs indefinitely -- this is an open-ended budget commitment. " +
|
|
58
58
|
"Confirm with user whether the campaign should have an end date."),
|
|
59
59
|
});
|
|
@@ -89,15 +89,15 @@ const CampaignLimitsInputSchema = z.object({
|
|
|
89
89
|
}).optional();
|
|
90
90
|
// Label input schema
|
|
91
91
|
const CampaignLabelInputSchema = z.object({
|
|
92
|
-
key: z.string().describe("Label key."),
|
|
93
|
-
value: z.string().describe("Label value."),
|
|
92
|
+
key: z.string().describe("Label key (e.g., 'category', 'channel', 'season')."),
|
|
93
|
+
value: z.string().describe("Label value (e.g., 'electronics', 'online', 'summer')."),
|
|
94
94
|
});
|
|
95
95
|
// Transaction item for simulation
|
|
96
96
|
const SimulateTransactionItemSchema = z.object({
|
|
97
97
|
sku: z.string().describe("Product SKU."),
|
|
98
98
|
name: z.string().describe("Product name."),
|
|
99
|
-
qty: z.union([z.string(), z.number()]).optional().describe("Item quantity."),
|
|
100
|
-
grossValue: z.union([z.string(), z.number()]).describe("Item gross value."),
|
|
99
|
+
qty: z.union([z.string(), z.number()]).optional().describe("Item quantity. Accepts string or number (API is flexible on type)."),
|
|
100
|
+
grossValue: z.union([z.string(), z.number()]).describe("Item gross value. Accepts string or number (API is flexible on type)."),
|
|
101
101
|
category: z.string().optional().describe("Product category."),
|
|
102
102
|
maker: z.string().optional().describe("Product maker/brand."),
|
|
103
103
|
labels: z.array(z.object({
|
|
@@ -120,7 +120,7 @@ const SimulateTransactionSchema = z.object({
|
|
|
120
120
|
}).optional();
|
|
121
121
|
// Custom event for simulation
|
|
122
122
|
const SimulateCustomEventSchema = z.object({
|
|
123
|
-
eventCode: z.string().describe("Custom event code (must match campaign trigger event)."),
|
|
123
|
+
eventCode: z.string().describe("Custom event code (must match campaign trigger event). Use ol_custom_event_schema_list to find valid event codes."),
|
|
124
124
|
attributes: z.record(z.unknown()).optional().describe("Custom event attributes."),
|
|
125
125
|
}).optional();
|
|
126
126
|
// Customer for simulation
|
|
@@ -156,7 +156,8 @@ export const CampaignUpdateInputSchema = {
|
|
|
156
156
|
storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
|
|
157
157
|
campaignId: z.string().describe("The campaign ID (UUID) to update."),
|
|
158
158
|
type: CampaignTypeEnum.describe("Campaign type: direct or referral."),
|
|
159
|
-
trigger: CampaignTriggerEnum.describe("What triggers the campaign: transaction, custom_event, time, achievement,
|
|
159
|
+
trigger: CampaignTriggerEnum.describe("What triggers the campaign. Valid values: transaction, custom_event, time, achievement, " +
|
|
160
|
+
"custom_event_unique_code, leaderboard, internal_event, return_transaction, challenge, fortune_wheel."),
|
|
160
161
|
translations: z.object({
|
|
161
162
|
en: z.object({
|
|
162
163
|
name: z.string().describe("Campaign name in English (REQUIRED)."),
|
|
@@ -164,8 +165,8 @@ export const CampaignUpdateInputSchema = {
|
|
|
164
165
|
}),
|
|
165
166
|
}).passthrough().describe("Translations object with at least 'en' key."),
|
|
166
167
|
activity: z.object({
|
|
167
|
-
startsAt: z.string().describe("Campaign start date/time (
|
|
168
|
-
endsAt: z.string().optional().describe("Campaign end date/time (
|
|
168
|
+
startsAt: z.string().describe("Campaign start date/time (format: 'YYYY-MM-DD HH:mm+TZ', e.g., '2026-01-01 00:00+00:00'). REQUIRED."),
|
|
169
|
+
endsAt: z.string().optional().describe("Campaign end date/time (format: 'YYYY-MM-DD HH:mm+TZ', e.g., '2026-12-31 23:59+00:00'). If not specified, campaign runs indefinitely."),
|
|
169
170
|
}).describe("Campaign active period with required startsAt."),
|
|
170
171
|
rules: z.array(z.object({
|
|
171
172
|
name: z.string().describe("Rule name (required)."),
|
|
@@ -285,7 +286,8 @@ export const CampaignGetLeaderboardInputSchema = {
|
|
|
285
286
|
export const CampaignCreateInputSchema = {
|
|
286
287
|
storeCode: z.string().optional().describe("INTERNAL: Auto-configured from server settings. NEVER ask the user for this value. Only set if the user explicitly requests a different store."),
|
|
287
288
|
type: CampaignTypeEnum.describe("Campaign type: direct (standard) or referral (for referral programs)."),
|
|
288
|
-
trigger: CampaignTriggerEnum.describe("What triggers the campaign: transaction, custom_event, time, achievement,
|
|
289
|
+
trigger: CampaignTriggerEnum.describe("What triggers the campaign. Valid values: transaction, custom_event, time, achievement, " +
|
|
290
|
+
"custom_event_unique_code, leaderboard, internal_event, return_transaction, challenge, fortune_wheel."),
|
|
289
291
|
translations: TranslationsInputSchema,
|
|
290
292
|
activity: CampaignActivityInputSchema.describe("Campaign active period with required startsAt and optional endsAt."),
|
|
291
293
|
rules: z.array(CampaignRuleInputSchema).describe("Array of rules defining when and what effects to apply. Each rule requires a name."),
|
|
@@ -300,7 +302,7 @@ export const CampaignCreateInputSchema = {
|
|
|
300
302
|
active: z.boolean().optional().describe("Whether campaign is active (default: false)."),
|
|
301
303
|
displayOrder: z.number().optional().describe("Display order for sorting campaigns."),
|
|
302
304
|
labels: z.array(CampaignLabelInputSchema).optional().describe("Custom labels/tags for the campaign."),
|
|
303
|
-
event: z.string().optional().describe("Custom event name (required for custom_event trigger). Must match an existing custom event schema."),
|
|
305
|
+
event: z.string().optional().describe("Custom event name (required for custom_event trigger). Must match an existing custom event schema. Use ol_custom_event_schema_list to find valid event codes."),
|
|
304
306
|
achievementId: z.string().optional().describe("Achievement ID (required for trigger='achievement'). " +
|
|
305
307
|
"Use achievement_create first, then pass the returned achievementId here to award points/rewards when members complete that achievement."),
|
|
306
308
|
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
interface CustomEventSchemaItem {
|
|
2
|
+
eventType: string;
|
|
3
|
+
name: string;
|
|
4
|
+
schema?: {
|
|
5
|
+
fields?: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
active: boolean;
|
|
12
|
+
createdAt?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function customEventSchemaList(input: {
|
|
15
|
+
storeCode?: string;
|
|
16
|
+
page?: number;
|
|
17
|
+
perPage?: number;
|
|
18
|
+
eventType?: string;
|
|
19
|
+
name?: string;
|
|
20
|
+
active?: boolean;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
schemas: CustomEventSchemaItem[];
|
|
23
|
+
total: {
|
|
24
|
+
all?: number;
|
|
25
|
+
filtered?: number;
|
|
26
|
+
};
|
|
27
|
+
}>;
|
|
28
|
+
export declare function customEventSchemaGet(input: {
|
|
29
|
+
storeCode?: string;
|
|
30
|
+
eventType: string;
|
|
31
|
+
}): Promise<CustomEventSchemaItem>;
|
|
32
|
+
export declare function customEventSchemaCreate(input: {
|
|
33
|
+
storeCode?: string;
|
|
34
|
+
eventType: string;
|
|
35
|
+
name: string;
|
|
36
|
+
fields: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
type: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
}>;
|
|
41
|
+
active?: boolean;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
interface CustomEventSchemaUpdateInput {
|
|
44
|
+
storeCode?: string;
|
|
45
|
+
eventType: string;
|
|
46
|
+
name: string;
|
|
47
|
+
fields: Array<{
|
|
48
|
+
name: string;
|
|
49
|
+
type: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
}>;
|
|
52
|
+
active?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export declare function customEventSchemaUpdate(input: CustomEventSchemaUpdateInput): Promise<void>;
|
|
55
|
+
export declare function customEventSchemaActivate(input: {
|
|
56
|
+
storeCode?: string;
|
|
57
|
+
eventType: string;
|
|
58
|
+
active: boolean;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
interface CustomEventSendInput {
|
|
61
|
+
storeCode?: string;
|
|
62
|
+
eventType: string;
|
|
63
|
+
customerData: {
|
|
64
|
+
customerId?: string;
|
|
65
|
+
email?: string;
|
|
66
|
+
phone?: string;
|
|
67
|
+
loyaltyCardNumber?: string;
|
|
68
|
+
};
|
|
69
|
+
eventDate: string;
|
|
70
|
+
body?: Record<string, unknown>;
|
|
71
|
+
eventId?: string;
|
|
72
|
+
}
|
|
73
|
+
export declare function customEventSend(input: CustomEventSendInput): Promise<{
|
|
74
|
+
customEventId?: string;
|
|
75
|
+
}>;
|
|
76
|
+
interface CustomEventItem {
|
|
77
|
+
customEventId: string;
|
|
78
|
+
type: string;
|
|
79
|
+
customerId?: string;
|
|
80
|
+
eventDate?: string;
|
|
81
|
+
body?: Record<string, unknown>;
|
|
82
|
+
createdAt?: string;
|
|
83
|
+
}
|
|
84
|
+
export declare function customEventList(input: {
|
|
85
|
+
storeCode?: string;
|
|
86
|
+
page?: number;
|
|
87
|
+
perPage?: number;
|
|
88
|
+
type?: string;
|
|
89
|
+
customerId?: string;
|
|
90
|
+
email?: string;
|
|
91
|
+
}): Promise<{
|
|
92
|
+
events: CustomEventItem[];
|
|
93
|
+
total: {
|
|
94
|
+
all?: number;
|
|
95
|
+
filtered?: number;
|
|
96
|
+
};
|
|
97
|
+
}>;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { apiGet, apiPost, apiPut } from "../../client/http.js";
|
|
2
|
+
import { formatApiError, OpenLoyaltyError } from "../../utils/errors.js";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
import { getStoreCode } from "../../config.js";
|
|
5
|
+
export async function customEventSchemaList(input) {
|
|
6
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
7
|
+
const params = new URLSearchParams();
|
|
8
|
+
if (input.page)
|
|
9
|
+
params.append("_page", String(input.page));
|
|
10
|
+
if (input.perPage)
|
|
11
|
+
params.append("_itemsOnPage", String(input.perPage));
|
|
12
|
+
if (input.eventType)
|
|
13
|
+
params.append("eventType", input.eventType);
|
|
14
|
+
if (input.name)
|
|
15
|
+
params.append("name", input.name);
|
|
16
|
+
if (input.active !== undefined)
|
|
17
|
+
params.append("active", String(input.active));
|
|
18
|
+
const queryString = params.toString();
|
|
19
|
+
const url = `/${storeCode}/customEvent/schema${queryString ? `?${queryString}` : ""}`;
|
|
20
|
+
try {
|
|
21
|
+
const response = await apiGet(url);
|
|
22
|
+
const total = response.total || {};
|
|
23
|
+
return {
|
|
24
|
+
schemas: response.items || [],
|
|
25
|
+
total: {
|
|
26
|
+
all: typeof total.all === "number" ? total.all : undefined,
|
|
27
|
+
filtered: typeof total.filtered === "number" ? total.filtered : undefined,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
|
33
|
+
throw new OpenLoyaltyError({
|
|
34
|
+
code: "STORE_NOT_FOUND",
|
|
35
|
+
message: "Cannot list custom event schemas - store not found",
|
|
36
|
+
hint: "Use ol_store_list() to verify the store code is correct.",
|
|
37
|
+
relatedTool: "ol_custom_event_schema_list",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (axios.isAxiosError(error) && error.response?.status === 403) {
|
|
41
|
+
throw new OpenLoyaltyError({
|
|
42
|
+
code: "CUSTOM_EVENT_PERMISSION_DENIED",
|
|
43
|
+
message: "You don't have permission to view custom event schemas",
|
|
44
|
+
hint: "Custom event management requires the EVENTS:VIEW permission. Use ol_admin_get_permissions() to check your access.",
|
|
45
|
+
relatedTool: "ol_custom_event_schema_list",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
throw formatApiError(error, "ol_custom_event_schema_list");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function customEventSchemaGet(input) {
|
|
52
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
53
|
+
try {
|
|
54
|
+
const response = await apiGet(`/${storeCode}/customEvent/schema/${input.eventType}`);
|
|
55
|
+
return response;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error.response?.status === 404) {
|
|
59
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Custom event schema '${input.eventType}' not found`,
|
|
60
|
+
hint: "Use ol_custom_event_schema_list() to find existing event schemas.", relatedTool: "ol_custom_event_schema_get" });
|
|
61
|
+
}
|
|
62
|
+
throw formatApiError(error, "ol_custom_event_schema_get");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function customEventSchemaCreate(input) {
|
|
66
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
67
|
+
const schemaPayload = {
|
|
68
|
+
customEventSchema: {
|
|
69
|
+
eventType: input.eventType,
|
|
70
|
+
name: input.name,
|
|
71
|
+
schema: {
|
|
72
|
+
fields: input.fields,
|
|
73
|
+
},
|
|
74
|
+
active: {
|
|
75
|
+
isActive: input.active ?? true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
try {
|
|
80
|
+
await apiPost(`/${storeCode}/customEvent/schema`, schemaPayload);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const axiosError = error;
|
|
84
|
+
const apiErrors = axiosError.response?.data?.errors || [];
|
|
85
|
+
const allMessages = [
|
|
86
|
+
axiosError.response?.data?.message || "",
|
|
87
|
+
...apiErrors.map(e => e.message)
|
|
88
|
+
].join(" ").toLowerCase();
|
|
89
|
+
if (allMessages.includes("already") || allMessages.includes("duplicate") || allMessages.includes("unique")) {
|
|
90
|
+
throw new OpenLoyaltyError({
|
|
91
|
+
code: "DUPLICATE_EVENT_TYPE",
|
|
92
|
+
message: `Custom event schema '${input.eventType}' already exists`,
|
|
93
|
+
hint: `Use ol_custom_event_schema_list(eventType: "${input.eventType}") to find the existing schema. Use ol_custom_event_schema_update() to modify it, or choose a different eventType code.`,
|
|
94
|
+
relatedTool: "ol_custom_event_schema_create",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
throw formatApiError(error, "ol_custom_event_schema_create");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export async function customEventSchemaUpdate(input) {
|
|
101
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
102
|
+
const schemaPayload = {
|
|
103
|
+
customEventSchema: {
|
|
104
|
+
name: input.name,
|
|
105
|
+
schema: {
|
|
106
|
+
fields: input.fields,
|
|
107
|
+
},
|
|
108
|
+
active: {
|
|
109
|
+
isActive: input.active ?? true,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
try {
|
|
114
|
+
await apiPut(`/${storeCode}/customEvent/schema/${input.eventType}`, schemaPayload);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
if (error.response?.status === 404) {
|
|
118
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Custom event schema '${input.eventType}' not found`,
|
|
119
|
+
hint: "Use ol_custom_event_schema_list() to find existing schemas, or create with ol_custom_event_schema_create().",
|
|
120
|
+
relatedTool: "ol_custom_event_schema_update" });
|
|
121
|
+
}
|
|
122
|
+
throw formatApiError(error, "ol_custom_event_schema_update");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export async function customEventSchemaActivate(input) {
|
|
126
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
127
|
+
try {
|
|
128
|
+
await apiPost(`/${storeCode}/customEvent/schema/${input.eventType}/active`, {
|
|
129
|
+
active: input.active,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (error.response?.status === 404) {
|
|
134
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Custom event schema '${input.eventType}' not found`,
|
|
135
|
+
hint: "Use ol_custom_event_schema_list() to find existing event schemas.", relatedTool: "ol_custom_event_schema_activate" });
|
|
136
|
+
}
|
|
137
|
+
throw formatApiError(error, "ol_custom_event_schema_activate");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export async function customEventSend(input) {
|
|
141
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
142
|
+
const eventPayload = {
|
|
143
|
+
event: {
|
|
144
|
+
type: input.eventType,
|
|
145
|
+
customerData: input.customerData,
|
|
146
|
+
eventDate: input.eventDate,
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
const eventObj = eventPayload.event;
|
|
150
|
+
if (input.body)
|
|
151
|
+
eventObj.body = input.body;
|
|
152
|
+
if (input.eventId)
|
|
153
|
+
eventObj.eventId = input.eventId;
|
|
154
|
+
try {
|
|
155
|
+
const response = await apiPost(`/${storeCode}/customEvent`, eventPayload);
|
|
156
|
+
return { customEventId: response.customEventId };
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
const axiosError = error;
|
|
160
|
+
const apiErrors = axiosError.response?.data?.errors || [];
|
|
161
|
+
const allMessages = [
|
|
162
|
+
error instanceof Error ? error.message : "",
|
|
163
|
+
axiosError.response?.data?.message || "",
|
|
164
|
+
...apiErrors.map(e => e.message)
|
|
165
|
+
].join(" ").toLowerCase();
|
|
166
|
+
if (allMessages.includes("schema") && (allMessages.includes("not found") || allMessages.includes("not exist") || allMessages.includes("invalid"))) {
|
|
167
|
+
throw new OpenLoyaltyError({
|
|
168
|
+
code: "SCHEMA_NOT_FOUND",
|
|
169
|
+
message: `Custom event schema '${input.eventType}' not found`,
|
|
170
|
+
hint: `Use ol_custom_event_schema_list() to find valid event type codes. The eventType must match an existing active schema. You may need to create one with ol_custom_event_schema_create().`,
|
|
171
|
+
relatedTool: "ol_custom_event_send",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (axiosError.response?.status === 404 || (allMessages.includes("event") && allMessages.includes("not found"))) {
|
|
175
|
+
throw new OpenLoyaltyError({
|
|
176
|
+
code: "SCHEMA_NOT_FOUND",
|
|
177
|
+
message: `Custom event type '${input.eventType}' not found or member not found`,
|
|
178
|
+
hint: `Verify: 1) The eventType '${input.eventType}' exists (use ol_custom_event_schema_list()). 2) The member exists (use ol_member_list() to search).`,
|
|
179
|
+
relatedTool: "ol_custom_event_send",
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (allMessages.includes("customer") && (allMessages.includes("not found") || allMessages.includes("not exist"))) {
|
|
183
|
+
throw new OpenLoyaltyError({
|
|
184
|
+
code: "MEMBER_NOT_FOUND",
|
|
185
|
+
message: "The specified member was not found",
|
|
186
|
+
hint: "Use ol_member_list() to search for the member by email, name, or phone. Verify the customerId, email, phone, or loyaltyCardNumber is correct.",
|
|
187
|
+
relatedTool: "ol_custom_event_send",
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
throw formatApiError(error, "ol_custom_event_send");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export async function customEventList(input) {
|
|
194
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
195
|
+
const params = new URLSearchParams();
|
|
196
|
+
if (input.page)
|
|
197
|
+
params.append("_page", String(input.page));
|
|
198
|
+
if (input.perPage)
|
|
199
|
+
params.append("_itemsOnPage", String(input.perPage));
|
|
200
|
+
if (input.type)
|
|
201
|
+
params.append("type", input.type);
|
|
202
|
+
if (input.customerId)
|
|
203
|
+
params.append("customerId", input.customerId);
|
|
204
|
+
if (input.email)
|
|
205
|
+
params.append("customerData:email", input.email);
|
|
206
|
+
const queryString = params.toString();
|
|
207
|
+
const url = `/${storeCode}/customEvent${queryString ? `?${queryString}` : ""}`;
|
|
208
|
+
try {
|
|
209
|
+
const response = await apiGet(url);
|
|
210
|
+
const total = response.total || {};
|
|
211
|
+
return {
|
|
212
|
+
events: response.items || [],
|
|
213
|
+
total: {
|
|
214
|
+
all: typeof total.all === "number" ? total.all : undefined,
|
|
215
|
+
filtered: typeof total.filtered === "number" ? total.filtered : undefined,
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
|
221
|
+
throw new OpenLoyaltyError({
|
|
222
|
+
code: "STORE_NOT_FOUND",
|
|
223
|
+
message: "Cannot list custom events - store not found",
|
|
224
|
+
hint: "Use ol_store_list() to verify the store code is correct.",
|
|
225
|
+
relatedTool: "ol_custom_event_list",
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
if (axios.isAxiosError(error) && error.response?.status === 403) {
|
|
229
|
+
throw new OpenLoyaltyError({
|
|
230
|
+
code: "CUSTOM_EVENT_PERMISSION_DENIED",
|
|
231
|
+
message: "You don't have permission to view custom events",
|
|
232
|
+
hint: "Custom event access requires the EVENTS:VIEW permission. Use ol_admin_get_permissions() to check your access.",
|
|
233
|
+
relatedTool: "ol_custom_event_list",
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
throw formatApiError(error, "ol_custom_event_list");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export { CustomEventSchemaListInputSchema, CustomEventSchemaGetInputSchema, CustomEventSchemaCreateInputSchema, CustomEventSchemaUpdateInputSchema, CustomEventSchemaActivateInputSchema, CustomEventSendInputSchema, CustomEventListInputSchema, } from "./schemas.js";
|
|
2
|
+
export { customEventSchemaList, customEventSchemaGet, customEventSchemaCreate, customEventSchemaUpdate, customEventSchemaActivate, customEventSend, customEventList, } from "./handlers.js";
|
|
3
|
+
import { customEventSchemaList, customEventSchemaGet, customEventSchemaCreate, customEventSchemaUpdate, customEventSchemaActivate, customEventSend, customEventList } from "./handlers.js";
|
|
4
|
+
export declare const customEventToolDefinitions: readonly [{
|
|
5
|
+
readonly name: "ol_custom_event_schema_list";
|
|
6
|
+
readonly title: "List Custom Event Schemas";
|
|
7
|
+
readonly description: string;
|
|
8
|
+
readonly readOnly: true;
|
|
9
|
+
readonly idempotent: true;
|
|
10
|
+
readonly inputSchema: {
|
|
11
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
12
|
+
page: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
13
|
+
perPage: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
14
|
+
eventType: import("zod").ZodOptional<import("zod").ZodString>;
|
|
15
|
+
name: import("zod").ZodOptional<import("zod").ZodString>;
|
|
16
|
+
active: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
17
|
+
};
|
|
18
|
+
readonly handler: typeof customEventSchemaList;
|
|
19
|
+
}, {
|
|
20
|
+
readonly name: "ol_custom_event_schema_get";
|
|
21
|
+
readonly title: "Get Custom Event Schema";
|
|
22
|
+
readonly description: "Get details of a specific custom event schema including its fields.";
|
|
23
|
+
readonly readOnly: true;
|
|
24
|
+
readonly idempotent: true;
|
|
25
|
+
readonly inputSchema: {
|
|
26
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
27
|
+
eventType: import("zod").ZodString;
|
|
28
|
+
};
|
|
29
|
+
readonly handler: typeof customEventSchemaGet;
|
|
30
|
+
}, {
|
|
31
|
+
readonly name: "ol_custom_event_schema_create";
|
|
32
|
+
readonly title: "Create Custom Event Schema";
|
|
33
|
+
readonly description: string;
|
|
34
|
+
readonly readOnly: false;
|
|
35
|
+
readonly idempotent: false;
|
|
36
|
+
readonly inputSchema: {
|
|
37
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
38
|
+
eventType: import("zod").ZodString;
|
|
39
|
+
name: import("zod").ZodString;
|
|
40
|
+
fields: import("zod").ZodArray<import("zod").ZodObject<{
|
|
41
|
+
name: import("zod").ZodString;
|
|
42
|
+
type: import("zod").ZodEnum<["text", "number", "boolean", "datetime"]>;
|
|
43
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
44
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
45
|
+
type: "number" | "boolean" | "text" | "datetime";
|
|
46
|
+
name: string;
|
|
47
|
+
description?: string | undefined;
|
|
48
|
+
}, {
|
|
49
|
+
type: "number" | "boolean" | "text" | "datetime";
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string | undefined;
|
|
52
|
+
}>, "many">;
|
|
53
|
+
active: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
54
|
+
};
|
|
55
|
+
readonly handler: typeof customEventSchemaCreate;
|
|
56
|
+
}, {
|
|
57
|
+
readonly name: "ol_custom_event_schema_update";
|
|
58
|
+
readonly title: "Update Custom Event Schema";
|
|
59
|
+
readonly description: "Update an existing custom event schema (name, fields, active status).";
|
|
60
|
+
readonly readOnly: false;
|
|
61
|
+
readonly idempotent: true;
|
|
62
|
+
readonly inputSchema: {
|
|
63
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
64
|
+
eventType: import("zod").ZodString;
|
|
65
|
+
name: import("zod").ZodString;
|
|
66
|
+
fields: import("zod").ZodArray<import("zod").ZodObject<{
|
|
67
|
+
name: import("zod").ZodString;
|
|
68
|
+
type: import("zod").ZodEnum<["text", "number", "boolean", "datetime"]>;
|
|
69
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
70
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
71
|
+
type: "number" | "boolean" | "text" | "datetime";
|
|
72
|
+
name: string;
|
|
73
|
+
description?: string | undefined;
|
|
74
|
+
}, {
|
|
75
|
+
type: "number" | "boolean" | "text" | "datetime";
|
|
76
|
+
name: string;
|
|
77
|
+
description?: string | undefined;
|
|
78
|
+
}>, "many">;
|
|
79
|
+
active: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
80
|
+
};
|
|
81
|
+
readonly handler: typeof customEventSchemaUpdate;
|
|
82
|
+
}, {
|
|
83
|
+
readonly name: "ol_custom_event_schema_activate";
|
|
84
|
+
readonly title: "Activate/Deactivate Custom Event Schema";
|
|
85
|
+
readonly description: "Activate or deactivate a custom event schema. Inactive schemas won't trigger campaigns/achievements.";
|
|
86
|
+
readonly readOnly: false;
|
|
87
|
+
readonly idempotent: true;
|
|
88
|
+
readonly inputSchema: {
|
|
89
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
90
|
+
eventType: import("zod").ZodString;
|
|
91
|
+
active: import("zod").ZodBoolean;
|
|
92
|
+
};
|
|
93
|
+
readonly handler: typeof customEventSchemaActivate;
|
|
94
|
+
}, {
|
|
95
|
+
readonly name: "ol_custom_event_send";
|
|
96
|
+
readonly title: "Send Custom Event";
|
|
97
|
+
readonly description: string;
|
|
98
|
+
readonly readOnly: false;
|
|
99
|
+
readonly idempotent: false;
|
|
100
|
+
readonly inputSchema: {
|
|
101
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
102
|
+
eventType: import("zod").ZodString;
|
|
103
|
+
customerData: import("zod").ZodObject<{
|
|
104
|
+
customerId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
105
|
+
email: import("zod").ZodOptional<import("zod").ZodString>;
|
|
106
|
+
phone: import("zod").ZodOptional<import("zod").ZodString>;
|
|
107
|
+
loyaltyCardNumber: import("zod").ZodOptional<import("zod").ZodString>;
|
|
108
|
+
}, "strip", import("zod").ZodTypeAny, {
|
|
109
|
+
email?: string | undefined;
|
|
110
|
+
phone?: string | undefined;
|
|
111
|
+
loyaltyCardNumber?: string | undefined;
|
|
112
|
+
customerId?: string | undefined;
|
|
113
|
+
}, {
|
|
114
|
+
email?: string | undefined;
|
|
115
|
+
phone?: string | undefined;
|
|
116
|
+
loyaltyCardNumber?: string | undefined;
|
|
117
|
+
customerId?: string | undefined;
|
|
118
|
+
}>;
|
|
119
|
+
eventDate: import("zod").ZodString;
|
|
120
|
+
body: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
121
|
+
eventId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
122
|
+
};
|
|
123
|
+
readonly handler: typeof customEventSend;
|
|
124
|
+
}, {
|
|
125
|
+
readonly name: "ol_custom_event_list";
|
|
126
|
+
readonly title: "List Custom Events";
|
|
127
|
+
readonly description: "List custom events that have been sent. Filter by event type or member to see event history.";
|
|
128
|
+
readonly readOnly: true;
|
|
129
|
+
readonly idempotent: true;
|
|
130
|
+
readonly inputSchema: {
|
|
131
|
+
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
132
|
+
page: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
133
|
+
perPage: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
134
|
+
type: import("zod").ZodOptional<import("zod").ZodString>;
|
|
135
|
+
customerId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
136
|
+
email: import("zod").ZodOptional<import("zod").ZodString>;
|
|
137
|
+
};
|
|
138
|
+
readonly handler: typeof customEventList;
|
|
139
|
+
}];
|