@open-loyalty/mcp-server 1.1.0 → 1.3.3
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/README.md +180 -177
- package/dist/auth/provider.js +2 -14
- package/dist/auth/storage.js +22 -0
- package/dist/client/http.js +10 -0
- package/dist/config.d.ts +0 -13
- package/dist/config.js +0 -14
- package/dist/http.js +35 -3
- package/dist/instructions.d.ts +5 -0
- package/dist/instructions.js +440 -0
- package/dist/prompts/fan-engagement-setup.d.ts +107 -0
- package/dist/prompts/fan-engagement-setup.js +492 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +60 -273
- package/dist/tools/achievement/handlers.d.ts +117 -0
- package/dist/tools/achievement/handlers.js +161 -0
- package/dist/tools/achievement/index.d.ts +479 -0
- package/dist/tools/achievement/index.js +74 -0
- package/dist/tools/achievement/schemas.d.ts +433 -0
- package/dist/tools/achievement/schemas.js +142 -0
- package/dist/tools/achievement.d.ts +141 -121
- package/dist/tools/achievement.js +60 -24
- package/dist/tools/admin.d.ts +6 -6
- package/dist/tools/admin.js +12 -12
- package/dist/tools/analytics.d.ts +11 -11
- package/dist/tools/analytics.js +30 -29
- package/dist/tools/apikey.d.ts +3 -3
- package/dist/tools/apikey.js +6 -6
- package/dist/tools/audit.d.ts +2 -2
- package/dist/tools/audit.js +4 -4
- package/dist/tools/badge.d.ts +6 -6
- package/dist/tools/badge.js +23 -18
- package/dist/tools/campaign/handlers.d.ts +42 -0
- package/dist/tools/campaign/handlers.js +223 -0
- package/dist/tools/campaign/index.d.ts +783 -0
- package/dist/tools/campaign/index.js +117 -0
- package/dist/tools/campaign/member-handlers.d.ts +60 -0
- package/dist/tools/campaign/member-handlers.js +159 -0
- package/dist/tools/campaign/schemas.d.ts +704 -0
- package/dist/tools/campaign/schemas.js +259 -0
- package/dist/tools/campaign/types.d.ts +161 -0
- package/dist/tools/campaign/types.js +2 -0
- package/dist/tools/custom-event.d.ts +315 -0
- package/dist/tools/custom-event.js +270 -0
- package/dist/tools/export.d.ts +4 -4
- package/dist/tools/export.js +12 -12
- package/dist/tools/import.d.ts +3 -3
- package/dist/tools/import.js +23 -15
- package/dist/tools/index.js +13 -5
- package/dist/tools/member/handlers.d.ts +111 -0
- package/dist/tools/member/handlers.js +206 -0
- package/dist/tools/member/index.d.ts +169 -0
- package/dist/tools/member/index.js +92 -0
- package/dist/tools/member/schemas.d.ts +89 -0
- package/dist/tools/member/schemas.js +65 -0
- package/dist/tools/points.d.ts +7 -6
- package/dist/tools/points.js +21 -20
- package/dist/tools/referral/handlers.d.ts +47 -0
- package/dist/tools/referral/handlers.js +115 -0
- package/dist/tools/referral/index.d.ts +44 -0
- package/dist/tools/referral/index.js +44 -0
- package/dist/tools/referral/schemas.d.ts +34 -0
- package/dist/tools/referral/schemas.js +52 -0
- package/dist/tools/reward/handlers.d.ts +110 -0
- package/dist/tools/reward/handlers.js +289 -0
- package/dist/tools/reward/index.d.ts +177 -0
- package/dist/tools/reward/index.js +93 -0
- package/dist/tools/reward/schemas.d.ts +116 -0
- package/dist/tools/reward/schemas.js +92 -0
- package/dist/tools/role.d.ts +6 -6
- package/dist/tools/role.js +12 -12
- package/dist/tools/segment/handlers.d.ts +87 -0
- package/dist/tools/segment/handlers.js +174 -0
- package/dist/tools/segment/index.d.ts +395 -0
- package/dist/tools/segment/index.js +88 -0
- package/dist/tools/segment/schemas.d.ts +337 -0
- package/dist/tools/segment/schemas.js +79 -0
- package/dist/tools/segment.d.ts +10 -10
- package/dist/tools/segment.js +55 -31
- package/dist/tools/store.d.ts +4 -4
- package/dist/tools/store.js +8 -8
- package/dist/tools/tierset.d.ts +10 -10
- package/dist/tools/tierset.js +69 -37
- package/dist/tools/transaction.d.ts +4 -4
- package/dist/tools/transaction.js +12 -12
- package/dist/tools/wallet-type.d.ts +221 -16
- package/dist/tools/wallet-type.js +248 -17
- package/dist/tools/webhook.d.ts +6 -6
- package/dist/tools/webhook.js +90 -31
- package/dist/types/schemas/achievement.d.ts +18 -18
- package/dist/types/schemas/campaign.d.ts +64 -184
- package/dist/types/schemas/campaign.js +2 -7
- package/dist/types/schemas/common.d.ts +5 -0
- package/dist/types/schemas/common.js +5 -0
- package/dist/types/schemas/member.d.ts +2 -2
- package/dist/types/schemas/reward.d.ts +94 -18
- package/dist/types/schemas/reward.js +8 -3
- package/dist/types/schemas/wallet-type.d.ts +306 -8
- package/dist/types/schemas/wallet-type.js +82 -1
- package/dist/utils/errors.js +32 -5
- package/dist/workflows/app-login-streak.d.ts +39 -0
- package/dist/workflows/app-login-streak.js +298 -0
- package/dist/workflows/early-arrival.d.ts +33 -0
- package/dist/workflows/early-arrival.js +148 -0
- package/dist/workflows/index.d.ts +101 -0
- package/dist/workflows/index.js +208 -0
- package/dist/workflows/match-attendance.d.ts +45 -0
- package/dist/workflows/match-attendance.js +308 -0
- package/dist/workflows/sportsbar-visit.d.ts +41 -0
- package/dist/workflows/sportsbar-visit.js +284 -0
- package/dist/workflows/vod-watching.d.ts +43 -0
- package/dist/workflows/vod-watching.js +326 -0
- package/package.json +8 -2
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const RewardListInputSchema = {
|
|
3
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
4
|
+
page: z.number().optional().describe("Page number (default: 1)."),
|
|
5
|
+
perPage: z.number().optional().describe("Items per page (default: 10)."),
|
|
6
|
+
active: z.boolean().optional().describe("Filter by active status."),
|
|
7
|
+
type: z.enum(["static_coupon", "dynamic_coupon", "conversion_coupon", "material", "fortune_wheel"]).optional().describe("Filter by reward type."),
|
|
8
|
+
categoryId: z.string().optional().describe("Filter by category ID."),
|
|
9
|
+
};
|
|
10
|
+
// Translations schema for rewards (API requires translations.en at minimum)
|
|
11
|
+
// Note: translations.en must ONLY contain name, description is a separate field at top level
|
|
12
|
+
const RewardTranslationsInputSchema = z.object({
|
|
13
|
+
en: z.object({
|
|
14
|
+
name: z.string().describe("Reward name in English (required)."),
|
|
15
|
+
}),
|
|
16
|
+
}).passthrough().describe("Translations object with at least 'en' key containing { name }. Description goes at top level.");
|
|
17
|
+
// Activity period schema (REQUIRED by API)
|
|
18
|
+
// API requires datetime format: YYYY-MM-DD HH:mm (NOT just YYYY-MM-DD)
|
|
19
|
+
const RewardActivityInputSchema = z.object({
|
|
20
|
+
from: z.string().describe("Start datetime (format: 'YYYY-MM-DD HH:mm', e.g., '2026-01-01 00:00'). REQUIRED."),
|
|
21
|
+
to: z.string().describe("End datetime (format: 'YYYY-MM-DD HH:mm', e.g., '2026-12-31 23:59'). REQUIRED."),
|
|
22
|
+
});
|
|
23
|
+
// Visibility period schema (REQUIRED by API)
|
|
24
|
+
// API requires datetime format: YYYY-MM-DD HH:mm (NOT just YYYY-MM-DD)
|
|
25
|
+
const RewardVisibilityInputSchema = z.object({
|
|
26
|
+
from: z.string().describe("Visibility start datetime (format: 'YYYY-MM-DD HH:mm'). REQUIRED."),
|
|
27
|
+
to: z.string().describe("Visibility end datetime (format: 'YYYY-MM-DD HH:mm'). REQUIRED."),
|
|
28
|
+
});
|
|
29
|
+
// Usage limit schema (REQUIRED by API)
|
|
30
|
+
// NOTE: API uses 'general' (not 'total') for total redemptions limit
|
|
31
|
+
// BOTH perUser and general are REQUIRED by the API
|
|
32
|
+
const RewardUsageLimitInputSchema = z.object({
|
|
33
|
+
perUser: z.number().describe("Maximum redemptions per member. REQUIRED."),
|
|
34
|
+
general: z.number().describe("Total redemptions across all members. REQUIRED. Use a large number (e.g., 10000) if unlimited."),
|
|
35
|
+
});
|
|
36
|
+
export const RewardCreateInputSchema = {
|
|
37
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
38
|
+
translations: RewardTranslationsInputSchema.describe("Reward name translations. At least 'en' key with { name } is REQUIRED."),
|
|
39
|
+
reward: z.enum(["static_coupon", "dynamic_coupon", "conversion_coupon", "material", "fortune_wheel"]).describe("Reward type: static_coupon (fixed discount), dynamic_coupon (variable value), " +
|
|
40
|
+
"conversion_coupon (converts points to coupon), material (physical goods), fortune_wheel (gamified)."),
|
|
41
|
+
activity: RewardActivityInputSchema.describe("Activity period when reward can be purchased. Use datetime format 'YYYY-MM-DD HH:mm'. REQUIRED."),
|
|
42
|
+
visibility: RewardVisibilityInputSchema.describe("Visibility period when reward is shown. Use datetime format 'YYYY-MM-DD HH:mm'. REQUIRED."),
|
|
43
|
+
usageLimit: RewardUsageLimitInputSchema.describe("Usage limits. ⚠️ BOTH perUser AND general are REQUIRED by the API."),
|
|
44
|
+
costInPoints: z.number().optional().describe("Points required to redeem this reward."),
|
|
45
|
+
usageInstruction: z.string().optional().describe("Instructions for using the reward."),
|
|
46
|
+
active: z.boolean().optional().describe("Whether reward is active (default: false)."),
|
|
47
|
+
categories: z.array(z.string()).optional().describe("Array of category UUIDs."),
|
|
48
|
+
levels: z.array(z.string()).optional().describe("Array of tier level UUIDs that can see/redeem."),
|
|
49
|
+
segments: z.array(z.string()).optional().describe("Array of segment UUIDs that can see/redeem."),
|
|
50
|
+
target: z.enum(["level", "segment"]).nullable().optional().describe("Target type for visibility: level (tier-based), segment (segment-based), or null (all)."),
|
|
51
|
+
couponValue: z.number().optional().describe("Coupon value (required for static_coupon)."),
|
|
52
|
+
couponValueType: z.enum(["money", "percentage"]).optional().describe("Coupon value type: 'money' or 'percentage' (lowercase)."),
|
|
53
|
+
daysValid: z.number().optional().describe("Days the coupon remains valid after purchase."),
|
|
54
|
+
};
|
|
55
|
+
export const RewardGetInputSchema = {
|
|
56
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
57
|
+
rewardId: z.string().describe("The reward ID (UUID) to retrieve."),
|
|
58
|
+
};
|
|
59
|
+
export const RewardUpdateInputSchema = {
|
|
60
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
61
|
+
rewardId: z.string().describe("The reward ID (UUID) to update."),
|
|
62
|
+
name: z.string().optional().describe("Reward name."),
|
|
63
|
+
costInPoints: z.number().optional().describe("Points required to redeem."),
|
|
64
|
+
description: z.string().optional().describe("Reward description."),
|
|
65
|
+
active: z.boolean().optional().describe("Whether reward is active."),
|
|
66
|
+
categories: z.array(z.string()).optional().describe("Array of category UUIDs."),
|
|
67
|
+
levels: z.array(z.string()).optional().describe("Array of tier level UUIDs."),
|
|
68
|
+
segments: z.array(z.string()).optional().describe("Array of segment UUIDs."),
|
|
69
|
+
};
|
|
70
|
+
export const RewardIdInputSchema = {
|
|
71
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
72
|
+
rewardId: z.string().describe("The reward ID (UUID)."),
|
|
73
|
+
};
|
|
74
|
+
export const RewardBuyInputSchema = {
|
|
75
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
76
|
+
rewardId: z.string().describe("The reward ID (UUID) to purchase."),
|
|
77
|
+
memberId: z.string().describe("The member ID (UUID) purchasing the reward."),
|
|
78
|
+
quantity: z.number().optional().describe("Number of rewards to purchase (1-32, default: 1)."),
|
|
79
|
+
couponValue: z.number().optional().describe("Coupon value (for dynamic coupons)."),
|
|
80
|
+
withoutPoints: z.boolean().optional().describe("Admin only: skip points deduction."),
|
|
81
|
+
};
|
|
82
|
+
export const RewardRedeemInputSchema = {
|
|
83
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
84
|
+
memberId: z.string().describe("The member ID (UUID) redeeming the coupon."),
|
|
85
|
+
couponCode: z.string().describe("The coupon code to redeem."),
|
|
86
|
+
};
|
|
87
|
+
export const RewardCategoryListInputSchema = {
|
|
88
|
+
storeCode: z.string().optional().describe("Store code for multi-tenant routing. DO NOT pass this parameter - the configured default will be used automatically. Only provide a value if the user explicitly asks to work with a different store."),
|
|
89
|
+
page: z.number().optional().describe("Page number (default: 1)."),
|
|
90
|
+
perPage: z.number().optional().describe("Items per page (default: 10)."),
|
|
91
|
+
active: z.boolean().optional().describe("Filter by active status."),
|
|
92
|
+
};
|
package/dist/tools/role.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ export declare function aclGetResources(): Promise<{
|
|
|
89
89
|
total?: Record<string, unknown>;
|
|
90
90
|
}>;
|
|
91
91
|
export declare const roleToolDefinitions: readonly [{
|
|
92
|
-
readonly name: "
|
|
92
|
+
readonly name: "ol_role_list";
|
|
93
93
|
readonly title: "List Roles";
|
|
94
94
|
readonly description: "List all roles with optional filtering. Returns paginated list of roles with id, name, permissions, master status, and default status.";
|
|
95
95
|
readonly readOnly: true;
|
|
@@ -102,7 +102,7 @@ export declare const roleToolDefinitions: readonly [{
|
|
|
102
102
|
};
|
|
103
103
|
readonly handler: typeof roleList;
|
|
104
104
|
}, {
|
|
105
|
-
readonly name: "
|
|
105
|
+
readonly name: "ol_role_create";
|
|
106
106
|
readonly title: "Create Role";
|
|
107
107
|
readonly description: "Create a new role with permissions. Requires name. Optionally specify permissions (array of {resource, access, filterQuery}) and stores. Returns void on success (201 Created).";
|
|
108
108
|
readonly readOnly: false;
|
|
@@ -126,7 +126,7 @@ export declare const roleToolDefinitions: readonly [{
|
|
|
126
126
|
};
|
|
127
127
|
readonly handler: typeof roleCreate;
|
|
128
128
|
}, {
|
|
129
|
-
readonly name: "
|
|
129
|
+
readonly name: "ol_role_get";
|
|
130
130
|
readonly title: "Get Role Details";
|
|
131
131
|
readonly description: "Get full role details by ID. Returns role with name, permissions array, master status, default status, and stores.";
|
|
132
132
|
readonly readOnly: true;
|
|
@@ -135,7 +135,7 @@ export declare const roleToolDefinitions: readonly [{
|
|
|
135
135
|
};
|
|
136
136
|
readonly handler: typeof roleGet;
|
|
137
137
|
}, {
|
|
138
|
-
readonly name: "
|
|
138
|
+
readonly name: "ol_role_update";
|
|
139
139
|
readonly title: "Update Role";
|
|
140
140
|
readonly description: "Update a role's name, permissions, or stores. Returns void on success (204 No Content).";
|
|
141
141
|
readonly readOnly: false;
|
|
@@ -160,7 +160,7 @@ export declare const roleToolDefinitions: readonly [{
|
|
|
160
160
|
};
|
|
161
161
|
readonly handler: typeof roleUpdate;
|
|
162
162
|
}, {
|
|
163
|
-
readonly name: "
|
|
163
|
+
readonly name: "ol_role_delete";
|
|
164
164
|
readonly title: "Delete Role (Permanent)";
|
|
165
165
|
readonly description: "Delete a role by ID. Returns void on success (204 No Content). Cannot delete roles that are assigned to admin users.";
|
|
166
166
|
readonly readOnly: false;
|
|
@@ -170,7 +170,7 @@ export declare const roleToolDefinitions: readonly [{
|
|
|
170
170
|
};
|
|
171
171
|
readonly handler: typeof roleDelete;
|
|
172
172
|
}, {
|
|
173
|
-
readonly name: "
|
|
173
|
+
readonly name: "ol_acl_get_resources";
|
|
174
174
|
readonly title: "Get ACL Resources";
|
|
175
175
|
readonly description: "Get list of available ACL resources. Returns items with code and name for each resource type. Use this to discover available permissions before creating roles.";
|
|
176
176
|
readonly readOnly: true;
|
package/dist/tools/role.js
CHANGED
|
@@ -56,7 +56,7 @@ export async function roleList(input) {
|
|
|
56
56
|
return response;
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
|
-
throw formatApiError(error, "
|
|
59
|
+
throw formatApiError(error, "ol_role_list");
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
export async function roleCreate(input) {
|
|
@@ -73,7 +73,7 @@ export async function roleCreate(input) {
|
|
|
73
73
|
await apiPost("/acl/role", { role: payload });
|
|
74
74
|
}
|
|
75
75
|
catch (error) {
|
|
76
|
-
throw formatApiError(error, "
|
|
76
|
+
throw formatApiError(error, "ol_role_create");
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
export async function roleGet(input) {
|
|
@@ -82,7 +82,7 @@ export async function roleGet(input) {
|
|
|
82
82
|
return response;
|
|
83
83
|
}
|
|
84
84
|
catch (error) {
|
|
85
|
-
throw formatApiError(error, "
|
|
85
|
+
throw formatApiError(error, "ol_role_get");
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
export async function roleUpdate(input) {
|
|
@@ -99,7 +99,7 @@ export async function roleUpdate(input) {
|
|
|
99
99
|
await apiPut(`/acl/role/${input.roleId}`, { role: payload });
|
|
100
100
|
}
|
|
101
101
|
catch (error) {
|
|
102
|
-
throw formatApiError(error, "
|
|
102
|
+
throw formatApiError(error, "ol_role_update");
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
export async function roleDelete(input) {
|
|
@@ -107,7 +107,7 @@ export async function roleDelete(input) {
|
|
|
107
107
|
await apiDelete(`/acl/role/${input.roleId}`);
|
|
108
108
|
}
|
|
109
109
|
catch (error) {
|
|
110
|
-
throw formatApiError(error, "
|
|
110
|
+
throw formatApiError(error, "ol_role_delete");
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
export async function aclGetResources() {
|
|
@@ -116,13 +116,13 @@ export async function aclGetResources() {
|
|
|
116
116
|
return response;
|
|
117
117
|
}
|
|
118
118
|
catch (error) {
|
|
119
|
-
throw formatApiError(error, "
|
|
119
|
+
throw formatApiError(error, "ol_acl_get_resources");
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
// Tool definitions
|
|
123
123
|
export const roleToolDefinitions = [
|
|
124
124
|
{
|
|
125
|
-
name: "
|
|
125
|
+
name: "ol_role_list",
|
|
126
126
|
title: "List Roles",
|
|
127
127
|
description: "List all roles with optional filtering. Returns paginated list of roles with id, name, permissions, master status, and default status.",
|
|
128
128
|
readOnly: true,
|
|
@@ -130,7 +130,7 @@ export const roleToolDefinitions = [
|
|
|
130
130
|
handler: roleList,
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
|
-
name: "
|
|
133
|
+
name: "ol_role_create",
|
|
134
134
|
title: "Create Role",
|
|
135
135
|
description: "Create a new role with permissions. Requires name. Optionally specify permissions (array of {resource, access, filterQuery}) and stores. Returns void on success (201 Created).",
|
|
136
136
|
readOnly: false,
|
|
@@ -138,7 +138,7 @@ export const roleToolDefinitions = [
|
|
|
138
138
|
handler: roleCreate,
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
|
-
name: "
|
|
141
|
+
name: "ol_role_get",
|
|
142
142
|
title: "Get Role Details",
|
|
143
143
|
description: "Get full role details by ID. Returns role with name, permissions array, master status, default status, and stores.",
|
|
144
144
|
readOnly: true,
|
|
@@ -146,7 +146,7 @@ export const roleToolDefinitions = [
|
|
|
146
146
|
handler: roleGet,
|
|
147
147
|
},
|
|
148
148
|
{
|
|
149
|
-
name: "
|
|
149
|
+
name: "ol_role_update",
|
|
150
150
|
title: "Update Role",
|
|
151
151
|
description: "Update a role's name, permissions, or stores. Returns void on success (204 No Content).",
|
|
152
152
|
readOnly: false,
|
|
@@ -154,7 +154,7 @@ export const roleToolDefinitions = [
|
|
|
154
154
|
handler: roleUpdate,
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
|
-
name: "
|
|
157
|
+
name: "ol_role_delete",
|
|
158
158
|
title: "Delete Role (Permanent)",
|
|
159
159
|
description: "Delete a role by ID. Returns void on success (204 No Content). Cannot delete roles that are assigned to admin users.",
|
|
160
160
|
readOnly: false,
|
|
@@ -163,7 +163,7 @@ export const roleToolDefinitions = [
|
|
|
163
163
|
handler: roleDelete,
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
|
-
name: "
|
|
166
|
+
name: "ol_acl_get_resources",
|
|
167
167
|
title: "Get ACL Resources",
|
|
168
168
|
description: "Get list of available ACL resources. Returns items with code and name for each resource type. Use this to discover available permissions before creating roles.",
|
|
169
169
|
readOnly: true,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { SegmentListItem } from "../../types/schemas/segment.js";
|
|
2
|
+
export declare function segmentList(input: {
|
|
3
|
+
storeCode?: string;
|
|
4
|
+
page?: number;
|
|
5
|
+
perPage?: number;
|
|
6
|
+
active?: boolean;
|
|
7
|
+
name?: string;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
segments: SegmentListItem[];
|
|
10
|
+
total: {
|
|
11
|
+
all?: number;
|
|
12
|
+
filtered?: number;
|
|
13
|
+
};
|
|
14
|
+
}>;
|
|
15
|
+
interface SegmentCreateInput {
|
|
16
|
+
storeCode?: string;
|
|
17
|
+
name: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
active?: boolean;
|
|
20
|
+
parts: Array<{
|
|
21
|
+
segmentPartId?: string;
|
|
22
|
+
criteria: Array<Record<string, unknown>>;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export declare function segmentCreate(input: SegmentCreateInput): Promise<{
|
|
26
|
+
segmentId: string;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function segmentGet(input: {
|
|
29
|
+
storeCode?: string;
|
|
30
|
+
segmentId: string;
|
|
31
|
+
}): Promise<Record<string, unknown>>;
|
|
32
|
+
interface SegmentUpdateInput {
|
|
33
|
+
storeCode?: string;
|
|
34
|
+
segmentId: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
active?: boolean;
|
|
38
|
+
parts: Array<{
|
|
39
|
+
segmentPartId?: string;
|
|
40
|
+
criteria: Array<Record<string, unknown>>;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
export declare function segmentUpdate(input: SegmentUpdateInput): Promise<void>;
|
|
44
|
+
export declare function segmentDelete(input: {
|
|
45
|
+
storeCode?: string;
|
|
46
|
+
segmentId: string;
|
|
47
|
+
}): Promise<void>;
|
|
48
|
+
interface SegmentMember {
|
|
49
|
+
customerId: string;
|
|
50
|
+
firstName?: string;
|
|
51
|
+
lastName?: string;
|
|
52
|
+
email?: string;
|
|
53
|
+
loyaltyCardNumber?: string;
|
|
54
|
+
active?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare function segmentGetMembers(input: {
|
|
57
|
+
storeCode?: string;
|
|
58
|
+
segmentId: string;
|
|
59
|
+
page?: number;
|
|
60
|
+
perPage?: number;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
members: SegmentMember[];
|
|
63
|
+
total: {
|
|
64
|
+
all?: number;
|
|
65
|
+
filtered?: number;
|
|
66
|
+
};
|
|
67
|
+
}>;
|
|
68
|
+
export declare function segmentActivate(input: {
|
|
69
|
+
storeCode?: string;
|
|
70
|
+
segmentId: string;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
export declare function segmentDeactivate(input: {
|
|
73
|
+
storeCode?: string;
|
|
74
|
+
segmentId: string;
|
|
75
|
+
}): Promise<void>;
|
|
76
|
+
interface SegmentResource {
|
|
77
|
+
resourceId: string;
|
|
78
|
+
resourceType: string;
|
|
79
|
+
name?: string;
|
|
80
|
+
}
|
|
81
|
+
export declare function segmentGetResources(input: {
|
|
82
|
+
storeCode?: string;
|
|
83
|
+
segmentId: string;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
resources: SegmentResource[];
|
|
86
|
+
}>;
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { apiGet, apiPost, apiPut, apiDelete } from "../../client/http.js";
|
|
2
|
+
import { formatApiError } from "../../utils/errors.js";
|
|
3
|
+
import { getStoreCode } from "../../config.js";
|
|
4
|
+
const DEFAULT_TRANSACTION_COUNT_MAX = 999999;
|
|
5
|
+
function normalizeSegmentParts(parts) {
|
|
6
|
+
return parts.map((part) => ({
|
|
7
|
+
...part,
|
|
8
|
+
criteria: part.criteria.map((criterion) => {
|
|
9
|
+
if (!criterion || typeof criterion !== "object") {
|
|
10
|
+
return criterion;
|
|
11
|
+
}
|
|
12
|
+
const normalized = { ...criterion };
|
|
13
|
+
if (normalized.type === "transaction_count" &&
|
|
14
|
+
normalized.min !== undefined &&
|
|
15
|
+
normalized.max === undefined) {
|
|
16
|
+
normalized.max = DEFAULT_TRANSACTION_COUNT_MAX;
|
|
17
|
+
}
|
|
18
|
+
return normalized;
|
|
19
|
+
}),
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
export async function segmentList(input) {
|
|
23
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
24
|
+
const params = new URLSearchParams();
|
|
25
|
+
if (input.page)
|
|
26
|
+
params.append("_page", String(input.page));
|
|
27
|
+
if (input.perPage)
|
|
28
|
+
params.append("_itemsOnPage", String(input.perPage));
|
|
29
|
+
if (input.active !== undefined)
|
|
30
|
+
params.append("active", String(input.active));
|
|
31
|
+
if (input.name)
|
|
32
|
+
params.append("name", input.name);
|
|
33
|
+
const queryString = params.toString();
|
|
34
|
+
const url = `/${storeCode}/segment${queryString ? `?${queryString}` : ""}`;
|
|
35
|
+
try {
|
|
36
|
+
const response = await apiGet(url);
|
|
37
|
+
const segments = (response.items || []).map((item) => ({
|
|
38
|
+
segmentId: item.segmentId,
|
|
39
|
+
name: item.name,
|
|
40
|
+
description: item.description,
|
|
41
|
+
active: item.active,
|
|
42
|
+
customersCount: item.customersCount,
|
|
43
|
+
createdAt: item.createdAt,
|
|
44
|
+
}));
|
|
45
|
+
const total = response.total || {};
|
|
46
|
+
return {
|
|
47
|
+
segments,
|
|
48
|
+
total: {
|
|
49
|
+
all: typeof total.all === "number" ? total.all : undefined,
|
|
50
|
+
filtered: typeof total.filtered === "number" ? total.filtered : undefined,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw formatApiError(error, "ol_segment_list");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function segmentCreate(input) {
|
|
59
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
60
|
+
const segmentPayload = {
|
|
61
|
+
name: input.name,
|
|
62
|
+
parts: normalizeSegmentParts(input.parts),
|
|
63
|
+
};
|
|
64
|
+
if (input.description)
|
|
65
|
+
segmentPayload.description = input.description;
|
|
66
|
+
if (input.active !== undefined)
|
|
67
|
+
segmentPayload.active = input.active;
|
|
68
|
+
try {
|
|
69
|
+
// CRITICAL: Wrap body as { segment: {...} }
|
|
70
|
+
const response = await apiPost(`/${storeCode}/segment`, { segment: segmentPayload });
|
|
71
|
+
return { segmentId: response.segmentId };
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
throw formatApiError(error, "ol_segment_create");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function segmentGet(input) {
|
|
78
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
79
|
+
try {
|
|
80
|
+
const response = await apiGet(`/${storeCode}/segment/${input.segmentId}`);
|
|
81
|
+
return response;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw formatApiError(error, "ol_segment_get");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function segmentUpdate(input) {
|
|
88
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
89
|
+
const segmentPayload = {
|
|
90
|
+
name: input.name,
|
|
91
|
+
parts: normalizeSegmentParts(input.parts),
|
|
92
|
+
};
|
|
93
|
+
if (input.description !== undefined)
|
|
94
|
+
segmentPayload.description = input.description;
|
|
95
|
+
if (input.active !== undefined)
|
|
96
|
+
segmentPayload.active = input.active;
|
|
97
|
+
try {
|
|
98
|
+
// CRITICAL: Wrap body as { segment: {...} }
|
|
99
|
+
await apiPut(`/${storeCode}/segment/${input.segmentId}`, { segment: segmentPayload });
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
throw formatApiError(error, "ol_segment_update");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export async function segmentDelete(input) {
|
|
106
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
107
|
+
try {
|
|
108
|
+
await apiDelete(`/${storeCode}/segment/${input.segmentId}`);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
throw formatApiError(error, "ol_segment_delete");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function segmentGetMembers(input) {
|
|
115
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
116
|
+
const params = new URLSearchParams();
|
|
117
|
+
if (input.page)
|
|
118
|
+
params.append("_page", String(input.page));
|
|
119
|
+
if (input.perPage)
|
|
120
|
+
params.append("_itemsOnPage", String(input.perPage));
|
|
121
|
+
const queryString = params.toString();
|
|
122
|
+
const url = `/${storeCode}/segment/${input.segmentId}/members${queryString ? `?${queryString}` : ""}`;
|
|
123
|
+
try {
|
|
124
|
+
const response = await apiGet(url);
|
|
125
|
+
const members = (response.items || []).map((item) => ({
|
|
126
|
+
customerId: item.customerId,
|
|
127
|
+
firstName: item.firstName,
|
|
128
|
+
lastName: item.lastName,
|
|
129
|
+
email: item.email,
|
|
130
|
+
loyaltyCardNumber: item.loyaltyCardNumber,
|
|
131
|
+
active: item.active,
|
|
132
|
+
}));
|
|
133
|
+
const total = response.total || {};
|
|
134
|
+
return {
|
|
135
|
+
members,
|
|
136
|
+
total: {
|
|
137
|
+
all: typeof total.all === "number" ? total.all : undefined,
|
|
138
|
+
filtered: typeof total.filtered === "number" ? total.filtered : undefined,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
throw formatApiError(error, "ol_segment_get_members");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export async function segmentActivate(input) {
|
|
147
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
148
|
+
try {
|
|
149
|
+
await apiPost(`/${storeCode}/segment/${input.segmentId}/activate`, {});
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
throw formatApiError(error, "ol_segment_activate");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export async function segmentDeactivate(input) {
|
|
156
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
157
|
+
try {
|
|
158
|
+
await apiPost(`/${storeCode}/segment/${input.segmentId}/deactivate`, {});
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
throw formatApiError(error, "ol_segment_deactivate");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export async function segmentGetResources(input) {
|
|
165
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
166
|
+
try {
|
|
167
|
+
const response = await apiGet(`/${storeCode}/segment/${input.segmentId}/resources`);
|
|
168
|
+
const resources = response.items || response.resources || [];
|
|
169
|
+
return { resources };
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
throw formatApiError(error, "ol_segment_get_resources");
|
|
173
|
+
}
|
|
174
|
+
}
|