@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
|
@@ -60,6 +60,31 @@ export async function pointsSpend(input) {
|
|
|
60
60
|
relatedTool: "ol_points_spend",
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
+
const axiosError2 = error;
|
|
64
|
+
if (axiosError2.response?.status === 404) {
|
|
65
|
+
throw new OpenLoyaltyError({
|
|
66
|
+
code: "MEMBER_NOT_FOUND",
|
|
67
|
+
message: `Member '${input.memberId}' not found`,
|
|
68
|
+
hint: `Verify the member ID exists using ol_member_get(memberId: "${input.memberId}"). If not found, use ol_member_list(email: "...") to search by email.`,
|
|
69
|
+
relatedTool: "ol_points_spend",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (axiosError2.response?.status === 403) {
|
|
73
|
+
throw new OpenLoyaltyError({
|
|
74
|
+
code: "POINTS_PERMISSION_DENIED",
|
|
75
|
+
message: "You don't have permission to spend member points",
|
|
76
|
+
hint: "Spending points requires the POINTS:MODIFY permission. Use ol_admin_get_permissions() to check your access.",
|
|
77
|
+
relatedTool: "ol_points_spend",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (allMessages.includes("points") && (allMessages.includes("positive") || allMessages.includes("greater") || allMessages.includes("zero") || allMessages.includes("negative"))) {
|
|
81
|
+
throw new OpenLoyaltyError({
|
|
82
|
+
code: "INVALID_POINTS_AMOUNT",
|
|
83
|
+
message: "Points amount must be a positive number greater than zero",
|
|
84
|
+
hint: `You requested to spend ${input.points} points. The amount must be a positive integer greater than 0.`,
|
|
85
|
+
relatedTool: "ol_points_spend",
|
|
86
|
+
});
|
|
87
|
+
}
|
|
63
88
|
throw formatApiError(error, "ol_points_spend");
|
|
64
89
|
}
|
|
65
90
|
}
|
|
@@ -102,6 +127,39 @@ export async function pointsTransfer(input) {
|
|
|
102
127
|
relatedTool: "ol_points_transfer",
|
|
103
128
|
});
|
|
104
129
|
}
|
|
130
|
+
const axiosError2 = error;
|
|
131
|
+
if (axiosError2.response?.status === 404) {
|
|
132
|
+
throw new OpenLoyaltyError({
|
|
133
|
+
code: "MEMBER_NOT_FOUND",
|
|
134
|
+
message: "Sender or receiver member not found",
|
|
135
|
+
hint: `Verify both member IDs exist: ol_member_get(memberId: "${input.senderId}") for sender and ol_member_get(memberId: "${input.receiverId}") for receiver. Use ol_member_list() to search by email if needed.`,
|
|
136
|
+
relatedTool: "ol_points_transfer",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (axiosError2.response?.status === 403) {
|
|
140
|
+
throw new OpenLoyaltyError({
|
|
141
|
+
code: "POINTS_PERMISSION_DENIED",
|
|
142
|
+
message: "You don't have permission to transfer points between members",
|
|
143
|
+
hint: "Points transfer requires the POINTS:MODIFY permission. Use ol_admin_get_permissions() to check your access.",
|
|
144
|
+
relatedTool: "ol_points_transfer",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (allMessages.includes("transfer") && (allMessages.includes("disabled") || allMessages.includes("not allowed") || allMessages.includes("not enabled"))) {
|
|
148
|
+
throw new OpenLoyaltyError({
|
|
149
|
+
code: "TRANSFER_DISABLED",
|
|
150
|
+
message: "Points transfers are not enabled for this store",
|
|
151
|
+
hint: "Point-to-point transfers must be enabled in store settings. Contact a super admin to enable the transfer feature.",
|
|
152
|
+
relatedTool: "ol_points_transfer",
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (allMessages.includes("points") && (allMessages.includes("positive") || allMessages.includes("greater") || allMessages.includes("zero"))) {
|
|
156
|
+
throw new OpenLoyaltyError({
|
|
157
|
+
code: "INVALID_POINTS_AMOUNT",
|
|
158
|
+
message: "Transfer amount must be a positive number greater than zero",
|
|
159
|
+
hint: `You requested to transfer ${input.points} points. The amount must be a positive integer greater than 0.`,
|
|
160
|
+
relatedTool: "ol_points_transfer",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
105
163
|
throw formatApiError(error, "ol_points_transfer");
|
|
106
164
|
}
|
|
107
165
|
}
|
|
@@ -151,6 +209,11 @@ export async function pointsGetBalance(input) {
|
|
|
151
209
|
};
|
|
152
210
|
}
|
|
153
211
|
catch (error) {
|
|
212
|
+
const axiosError = error;
|
|
213
|
+
if (axiosError.response?.status === 404) {
|
|
214
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Member '${input.memberId}' not found`,
|
|
215
|
+
hint: "Use ol_member_list() to search for the member by email, name, or phone.", relatedTool: "ol_points_get_balance" });
|
|
216
|
+
}
|
|
154
217
|
throw formatApiError(error, "ol_points_get_balance");
|
|
155
218
|
}
|
|
156
219
|
}
|
|
@@ -188,6 +251,11 @@ export async function pointsGetHistory(input) {
|
|
|
188
251
|
};
|
|
189
252
|
}
|
|
190
253
|
catch (error) {
|
|
254
|
+
const axiosError = error;
|
|
255
|
+
if (axiosError.response?.status === 404) {
|
|
256
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Member '${input.memberId}' not found or no history available`,
|
|
257
|
+
hint: "Use ol_member_list() to verify the member exists.", relatedTool: "ol_points_get_history" });
|
|
258
|
+
}
|
|
191
259
|
throw formatApiError(error, "ol_points_get_history");
|
|
192
260
|
}
|
|
193
261
|
}
|
|
@@ -228,6 +296,11 @@ export async function pointsGetHistogram(input) {
|
|
|
228
296
|
});
|
|
229
297
|
}
|
|
230
298
|
catch (error) {
|
|
299
|
+
const axiosError = error;
|
|
300
|
+
if (axiosError.response?.status === 404) {
|
|
301
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Member '${input.memberId}' not found`,
|
|
302
|
+
hint: "Use ol_member_list() to verify the member exists.", relatedTool: "ol_points_get_histogram" });
|
|
303
|
+
}
|
|
231
304
|
throw formatApiError(error, "ol_points_get_histogram");
|
|
232
305
|
}
|
|
233
306
|
}
|
|
@@ -6,6 +6,7 @@ export declare const pointsToolDefinitions: readonly [{
|
|
|
6
6
|
readonly title: "Add Points to Member";
|
|
7
7
|
readonly description: string;
|
|
8
8
|
readonly readOnly: false;
|
|
9
|
+
readonly idempotent: false;
|
|
9
10
|
readonly inputSchema: {
|
|
10
11
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
11
12
|
memberId: import("zod").ZodString;
|
|
@@ -21,6 +22,7 @@ export declare const pointsToolDefinitions: readonly [{
|
|
|
21
22
|
readonly title: "Spend Member Points";
|
|
22
23
|
readonly description: string;
|
|
23
24
|
readonly readOnly: false;
|
|
25
|
+
readonly idempotent: false;
|
|
24
26
|
readonly inputSchema: {
|
|
25
27
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
26
28
|
memberId: import("zod").ZodString;
|
|
@@ -34,6 +36,7 @@ export declare const pointsToolDefinitions: readonly [{
|
|
|
34
36
|
readonly title: "Transfer Points Between Members";
|
|
35
37
|
readonly description: string;
|
|
36
38
|
readonly readOnly: false;
|
|
39
|
+
readonly idempotent: false;
|
|
37
40
|
readonly inputSchema: {
|
|
38
41
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
39
42
|
senderId: import("zod").ZodString;
|
|
@@ -46,6 +49,7 @@ export declare const pointsToolDefinitions: readonly [{
|
|
|
46
49
|
readonly title: "Check Points Balance";
|
|
47
50
|
readonly description: string;
|
|
48
51
|
readonly readOnly: true;
|
|
52
|
+
readonly idempotent: true;
|
|
49
53
|
readonly inputSchema: {
|
|
50
54
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
51
55
|
memberId: import("zod").ZodString;
|
|
@@ -57,6 +61,7 @@ export declare const pointsToolDefinitions: readonly [{
|
|
|
57
61
|
readonly title: "View Points History";
|
|
58
62
|
readonly description: string;
|
|
59
63
|
readonly readOnly: true;
|
|
64
|
+
readonly idempotent: true;
|
|
60
65
|
readonly inputSchema: {
|
|
61
66
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
62
67
|
memberId: import("zod").ZodString;
|
|
@@ -71,6 +76,7 @@ export declare const pointsToolDefinitions: readonly [{
|
|
|
71
76
|
readonly title: "View Points Trends";
|
|
72
77
|
readonly description: string;
|
|
73
78
|
readonly readOnly: true;
|
|
79
|
+
readonly idempotent: true;
|
|
74
80
|
readonly inputSchema: {
|
|
75
81
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
76
82
|
memberId: import("zod").ZodString;
|
|
@@ -15,6 +15,7 @@ export const pointsToolDefinitions = [
|
|
|
15
15
|
"Confirm amount and reason with user before proceeding. " +
|
|
16
16
|
"Use for welcome bonuses, goodwill adjustments, or compensation. Returns transferId.",
|
|
17
17
|
readOnly: false,
|
|
18
|
+
idempotent: false,
|
|
18
19
|
inputSchema: PointsAddInputSchema,
|
|
19
20
|
handler: pointsAdd,
|
|
20
21
|
}, {
|
|
@@ -24,6 +25,7 @@ export const pointsToolDefinitions = [
|
|
|
24
25
|
"WORKFLOW: Use ol_points_get_balance first to verify available (activeUnits) points before spending. " +
|
|
25
26
|
"Returns transferId.",
|
|
26
27
|
readOnly: false,
|
|
28
|
+
idempotent: false,
|
|
27
29
|
inputSchema: PointsSpendInputSchema,
|
|
28
30
|
handler: pointsSpend,
|
|
29
31
|
}, {
|
|
@@ -32,6 +34,7 @@ export const pointsToolDefinitions = [
|
|
|
32
34
|
description: "Transfer points from one member to another (P2P transfer). " +
|
|
33
35
|
"Sender must have sufficient balance. Returns transferId.",
|
|
34
36
|
readOnly: false,
|
|
37
|
+
idempotent: false,
|
|
35
38
|
inputSchema: PointsTransferInputSchema,
|
|
36
39
|
handler: pointsTransfer,
|
|
37
40
|
}, {
|
|
@@ -40,6 +43,7 @@ export const pointsToolDefinitions = [
|
|
|
40
43
|
description: "Get member points balance breakdown. activeUnits is available for spending. " +
|
|
41
44
|
"earnedUnits shows lifetime earnings, lockedUnits shows pending points.",
|
|
42
45
|
readOnly: true,
|
|
46
|
+
idempotent: true,
|
|
43
47
|
inputSchema: PointsBalanceInputSchema,
|
|
44
48
|
handler: pointsGetBalance,
|
|
45
49
|
}, {
|
|
@@ -49,6 +53,7 @@ export const pointsToolDefinitions = [
|
|
|
49
53
|
"p2p_spending, p2p_adding, blocked, expired. Returns paginated list of transfers. " +
|
|
50
54
|
"Supports cursor pagination: provide 'cursor' from previous response to get next page.",
|
|
51
55
|
readOnly: true,
|
|
56
|
+
idempotent: true,
|
|
52
57
|
inputSchema: PointsHistoryInputSchema,
|
|
53
58
|
handler: pointsGetHistory,
|
|
54
59
|
}, {
|
|
@@ -57,6 +62,7 @@ export const pointsToolDefinitions = [
|
|
|
57
62
|
description: "Get points histogram data for visualization. Shows earning and spending patterns over time. " +
|
|
58
63
|
"Use interval (day/week/month) to aggregate data and dateFrom/dateTo to filter range.",
|
|
59
64
|
readOnly: true,
|
|
65
|
+
idempotent: true,
|
|
60
66
|
inputSchema: PointsHistogramInputSchema,
|
|
61
67
|
handler: pointsGetHistogram,
|
|
62
68
|
},
|
|
@@ -21,7 +21,7 @@ export const PointsTransferInputSchema = {
|
|
|
21
21
|
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."),
|
|
22
22
|
senderId: z.string().describe("The sender member ID (UUID)."),
|
|
23
23
|
receiverId: z.string().describe("The receiver member ID (UUID)."),
|
|
24
|
-
points: z.number().describe("Number of points to transfer."),
|
|
24
|
+
points: z.number().describe("Number of points to transfer (positive integer, e.g., 100). Sender must have sufficient active balance."),
|
|
25
25
|
};
|
|
26
26
|
export const PointsBalanceInputSchema = {
|
|
27
27
|
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."),
|
|
@@ -6,6 +6,7 @@ export declare const referralToolDefinitions: readonly [{
|
|
|
6
6
|
readonly title: "Create Referral Relationship";
|
|
7
7
|
readonly description: string;
|
|
8
8
|
readonly readOnly: false;
|
|
9
|
+
readonly idempotent: false;
|
|
9
10
|
readonly inputSchema: {
|
|
10
11
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
11
12
|
memberId: import("zod").ZodString;
|
|
@@ -17,6 +18,7 @@ export declare const referralToolDefinitions: readonly [{
|
|
|
17
18
|
readonly title: "List Referrals";
|
|
18
19
|
readonly description: string;
|
|
19
20
|
readonly readOnly: true;
|
|
21
|
+
readonly idempotent: true;
|
|
20
22
|
readonly inputSchema: {
|
|
21
23
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
22
24
|
referralId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
@@ -36,6 +38,7 @@ export declare const referralToolDefinitions: readonly [{
|
|
|
36
38
|
readonly description: string;
|
|
37
39
|
readonly readOnly: false;
|
|
38
40
|
readonly destructive: true;
|
|
41
|
+
readonly idempotent: true;
|
|
39
42
|
readonly inputSchema: {
|
|
40
43
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
41
44
|
memberId: import("zod").ZodString;
|
|
@@ -16,6 +16,7 @@ export const referralToolDefinitions = [
|
|
|
16
16
|
"Use this after creating a new member who was referred by an existing member. " +
|
|
17
17
|
"Both members must exist. A member can only have one referrer.",
|
|
18
18
|
readOnly: false,
|
|
19
|
+
idempotent: false,
|
|
19
20
|
inputSchema: ReferralCreateInputSchema,
|
|
20
21
|
handler: referralCreate,
|
|
21
22
|
},
|
|
@@ -27,6 +28,7 @@ export const referralToolDefinitions = [
|
|
|
27
28
|
"Filter by refereeId to find who referred a specific member. " +
|
|
28
29
|
"Returns referralId, referrerId, referrerName, refereeId, refereeName, and createdAt.",
|
|
29
30
|
readOnly: true,
|
|
31
|
+
idempotent: true,
|
|
30
32
|
inputSchema: ReferralListInputSchema,
|
|
31
33
|
handler: referralList,
|
|
32
34
|
},
|
|
@@ -38,6 +40,7 @@ export const referralToolDefinitions = [
|
|
|
38
40
|
"The memberId is the referee (the member who was referred).",
|
|
39
41
|
readOnly: false,
|
|
40
42
|
destructive: true,
|
|
43
|
+
idempotent: true,
|
|
41
44
|
inputSchema: ReferralDeleteInputSchema,
|
|
42
45
|
handler: referralDelete,
|
|
43
46
|
},
|
|
@@ -117,6 +117,10 @@ export async function rewardGet(input) {
|
|
|
117
117
|
return RewardSchema.parse(response);
|
|
118
118
|
}
|
|
119
119
|
catch (error) {
|
|
120
|
+
if (error.response?.status === 404) {
|
|
121
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Reward '${input.rewardId}' not found`,
|
|
122
|
+
hint: "Use ol_reward_list() to find existing rewards and their IDs.", relatedTool: "ol_reward_get" });
|
|
123
|
+
}
|
|
120
124
|
throw formatApiError(error, "ol_reward_get");
|
|
121
125
|
}
|
|
122
126
|
}
|
|
@@ -229,6 +233,10 @@ export async function rewardUpdate(input) {
|
|
|
229
233
|
await apiPut(`/${storeCode}/reward/${input.rewardId}`, { reward: payload });
|
|
230
234
|
}
|
|
231
235
|
catch (error) {
|
|
236
|
+
if (error.response?.status === 404) {
|
|
237
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Reward '${input.rewardId}' not found`,
|
|
238
|
+
hint: "Use ol_reward_list() to find existing rewards and their IDs.", relatedTool: "ol_reward_update" });
|
|
239
|
+
}
|
|
232
240
|
throw formatApiError(error, "ol_reward_update");
|
|
233
241
|
}
|
|
234
242
|
}
|
|
@@ -238,6 +246,10 @@ export async function rewardActivate(input) {
|
|
|
238
246
|
await apiPost(`/${storeCode}/reward/${input.rewardId}/activate`);
|
|
239
247
|
}
|
|
240
248
|
catch (error) {
|
|
249
|
+
if (error.response?.status === 404) {
|
|
250
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Reward '${input.rewardId}' not found`,
|
|
251
|
+
hint: "Use ol_reward_list() to find existing rewards and their IDs.", relatedTool: "ol_reward_activate" });
|
|
252
|
+
}
|
|
241
253
|
throw formatApiError(error, "ol_reward_activate");
|
|
242
254
|
}
|
|
243
255
|
}
|
|
@@ -247,6 +259,10 @@ export async function rewardDeactivate(input) {
|
|
|
247
259
|
await apiPost(`/${storeCode}/reward/${input.rewardId}/deactivate`);
|
|
248
260
|
}
|
|
249
261
|
catch (error) {
|
|
262
|
+
if (error.response?.status === 404) {
|
|
263
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Reward '${input.rewardId}' not found`,
|
|
264
|
+
hint: "Use ol_reward_list() to find existing rewards and their IDs.", relatedTool: "ol_reward_deactivate" });
|
|
265
|
+
}
|
|
250
266
|
throw formatApiError(error, "ol_reward_deactivate");
|
|
251
267
|
}
|
|
252
268
|
}
|
|
@@ -287,21 +303,13 @@ export async function rewardBuy(input) {
|
|
|
287
303
|
relatedTool: "ol_reward_buy",
|
|
288
304
|
});
|
|
289
305
|
}
|
|
290
|
-
if (allMessages.includes("not active") || allMessages.includes("inactive")
|
|
291
|
-
throw new OpenLoyaltyError({
|
|
292
|
-
|
|
293
|
-
message: "This reward is not active and cannot be purchased",
|
|
294
|
-
hint: `Use ol_reward_activate(rewardId: "${input.rewardId}") to activate the reward first, or use ol_reward_get(rewardId: "${input.rewardId}") to check its status.`,
|
|
295
|
-
relatedTool: "ol_reward_buy",
|
|
296
|
-
});
|
|
306
|
+
if (allMessages.includes("not active") || allMessages.includes("inactive")) {
|
|
307
|
+
throw new OpenLoyaltyError({ code: "REWARD_NOT_ACTIVE", message: "Reward is not active",
|
|
308
|
+
hint: `Use ol_reward_activate(rewardId: "${input.rewardId}") to activate it first.`, relatedTool: "ol_reward_buy" });
|
|
297
309
|
}
|
|
298
310
|
if (allMessages.includes("usage limit") || allMessages.includes("limit reached") || allMessages.includes("limit exceeded")) {
|
|
299
|
-
throw new OpenLoyaltyError({
|
|
300
|
-
|
|
301
|
-
message: "The usage limit for this reward has been reached",
|
|
302
|
-
hint: `Use ol_reward_get(rewardId: "${input.rewardId}") to check usageLimit settings. To increase limits, use ol_reward_update(rewardId: "${input.rewardId}", usageLimitPerUser: N).`,
|
|
303
|
-
relatedTool: "ol_reward_buy",
|
|
304
|
-
});
|
|
311
|
+
throw new OpenLoyaltyError({ code: "USAGE_LIMIT_REACHED", message: "Usage limit reached for this reward",
|
|
312
|
+
hint: `Use ol_reward_get(rewardId: "${input.rewardId}") to check limits. Use ol_reward_update to increase usageLimitPerUser.`, relatedTool: "ol_reward_buy" });
|
|
305
313
|
}
|
|
306
314
|
throw formatApiError(error, "ol_reward_buy");
|
|
307
315
|
}
|
|
@@ -6,6 +6,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
6
6
|
readonly title: "Browse Rewards";
|
|
7
7
|
readonly description: string;
|
|
8
8
|
readonly readOnly: true;
|
|
9
|
+
readonly idempotent: true;
|
|
9
10
|
readonly inputSchema: {
|
|
10
11
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
11
12
|
page: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
@@ -20,6 +21,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
20
21
|
readonly title: "Create New Reward";
|
|
21
22
|
readonly description: string;
|
|
22
23
|
readonly readOnly: false;
|
|
24
|
+
readonly idempotent: false;
|
|
23
25
|
readonly inputSchema: {
|
|
24
26
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
25
27
|
translations: import("zod").ZodObject<{
|
|
@@ -87,6 +89,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
87
89
|
readonly title: "Get Reward Details";
|
|
88
90
|
readonly description: "Get full reward details including configuration, targeting, and coupon settings.";
|
|
89
91
|
readonly readOnly: true;
|
|
92
|
+
readonly idempotent: true;
|
|
90
93
|
readonly inputSchema: {
|
|
91
94
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
92
95
|
rewardId: import("zod").ZodString;
|
|
@@ -95,6 +98,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
95
98
|
}, {
|
|
96
99
|
readonly name: "ol_reward_update";
|
|
97
100
|
readonly title: "Update Reward";
|
|
101
|
+
readonly idempotent: true;
|
|
98
102
|
readonly description: string;
|
|
99
103
|
readonly readOnly: false;
|
|
100
104
|
readonly inputSchema: {
|
|
@@ -115,6 +119,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
115
119
|
readonly title: "Activate Reward";
|
|
116
120
|
readonly description: "Activate a reward, making it available for members to redeem.";
|
|
117
121
|
readonly readOnly: false;
|
|
122
|
+
readonly idempotent: true;
|
|
118
123
|
readonly inputSchema: {
|
|
119
124
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
120
125
|
rewardId: import("zod").ZodString;
|
|
@@ -125,6 +130,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
125
130
|
readonly title: "Deactivate Reward";
|
|
126
131
|
readonly description: "Deactivate a reward, hiding it from members. Already purchased rewards remain valid.";
|
|
127
132
|
readonly readOnly: false;
|
|
133
|
+
readonly idempotent: true;
|
|
128
134
|
readonly inputSchema: {
|
|
129
135
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
130
136
|
rewardId: import("zod").ZodString;
|
|
@@ -135,6 +141,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
135
141
|
readonly title: "Redeem Reward for Member";
|
|
136
142
|
readonly description: string;
|
|
137
143
|
readonly readOnly: false;
|
|
144
|
+
readonly idempotent: false;
|
|
138
145
|
readonly inputSchema: {
|
|
139
146
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
140
147
|
rewardId: import("zod").ZodString;
|
|
@@ -149,6 +156,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
149
156
|
readonly title: "Use Coupon Code";
|
|
150
157
|
readonly description: string;
|
|
151
158
|
readonly readOnly: false;
|
|
159
|
+
readonly idempotent: false;
|
|
152
160
|
readonly inputSchema: {
|
|
153
161
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
154
162
|
memberId: import("zod").ZodString;
|
|
@@ -160,6 +168,7 @@ export declare const rewardToolDefinitions: readonly [{
|
|
|
160
168
|
readonly title: "List Reward Categories";
|
|
161
169
|
readonly description: "List reward categories. Use categoryId when creating or filtering rewards.";
|
|
162
170
|
readonly readOnly: true;
|
|
171
|
+
readonly idempotent: true;
|
|
163
172
|
readonly inputSchema: {
|
|
164
173
|
storeCode: import("zod").ZodOptional<import("zod").ZodString>;
|
|
165
174
|
page: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
@@ -13,6 +13,7 @@ export const rewardToolDefinitions = [
|
|
|
13
13
|
description: "List available rewards. Use reward_get for full details or reward_buy to redeem. " +
|
|
14
14
|
"Filter by type, active status, or category.",
|
|
15
15
|
readOnly: true,
|
|
16
|
+
idempotent: true,
|
|
16
17
|
inputSchema: RewardListInputSchema,
|
|
17
18
|
handler: rewardList,
|
|
18
19
|
},
|
|
@@ -26,8 +27,11 @@ export const rewardToolDefinitions = [
|
|
|
26
27
|
"3. Usage limits -- how many redemptions per member? How many total? (0 = unlimited, creates uncapped liability) " +
|
|
27
28
|
"4. Targeting -- all members, or restricted to specific tiers/segments? " +
|
|
28
29
|
"REQUIRED: translations.en.name, reward type, activity period, visibility period. " +
|
|
29
|
-
"For static_coupon: couponValue is also required."
|
|
30
|
+
"For static_coupon: couponValue is also required. " +
|
|
31
|
+
"TARGET: Use target='level' (NOT 'tier') for tier targeting, target='segment' for segment targeting, or omit for all members. " +
|
|
32
|
+
"DATETIME: Use 'from'/'to' (NOT 'startsAt'/'endsAt' like campaigns). Format: 'YYYY-MM-DD HH:mm' e.g., '2026-01-01 00:00'.",
|
|
30
33
|
readOnly: false,
|
|
34
|
+
idempotent: false,
|
|
31
35
|
inputSchema: RewardCreateInputSchema,
|
|
32
36
|
handler: rewardCreate,
|
|
33
37
|
},
|
|
@@ -36,12 +40,14 @@ export const rewardToolDefinitions = [
|
|
|
36
40
|
title: "Get Reward Details",
|
|
37
41
|
description: "Get full reward details including configuration, targeting, and coupon settings.",
|
|
38
42
|
readOnly: true,
|
|
43
|
+
idempotent: true,
|
|
39
44
|
inputSchema: RewardGetInputSchema,
|
|
40
45
|
handler: rewardGet,
|
|
41
46
|
},
|
|
42
47
|
{
|
|
43
48
|
name: "ol_reward_update",
|
|
44
49
|
title: "Update Reward",
|
|
50
|
+
idempotent: true,
|
|
45
51
|
description: "Update reward configuration. Cannot change reward type after creation. " +
|
|
46
52
|
"Uses GET-then-PUT pattern (fetches existing reward, merges changes, sends full object). " +
|
|
47
53
|
"usageLimitPerUser can be set here or at creation time. " +
|
|
@@ -55,6 +61,7 @@ export const rewardToolDefinitions = [
|
|
|
55
61
|
title: "Activate Reward",
|
|
56
62
|
description: "Activate a reward, making it available for members to redeem.",
|
|
57
63
|
readOnly: false,
|
|
64
|
+
idempotent: true,
|
|
58
65
|
inputSchema: RewardIdInputSchema,
|
|
59
66
|
handler: rewardActivate,
|
|
60
67
|
},
|
|
@@ -63,6 +70,7 @@ export const rewardToolDefinitions = [
|
|
|
63
70
|
title: "Deactivate Reward",
|
|
64
71
|
description: "Deactivate a reward, hiding it from members. Already purchased rewards remain valid.",
|
|
65
72
|
readOnly: false,
|
|
73
|
+
idempotent: true,
|
|
66
74
|
inputSchema: RewardIdInputSchema,
|
|
67
75
|
handler: rewardDeactivate,
|
|
68
76
|
},
|
|
@@ -72,6 +80,7 @@ export const rewardToolDefinitions = [
|
|
|
72
80
|
description: "Purchase reward for member, deducting points. Returns issuedRewardId and couponCode if applicable. " +
|
|
73
81
|
"Use reward_redeem to mark the coupon as used.",
|
|
74
82
|
readOnly: false,
|
|
83
|
+
idempotent: false,
|
|
75
84
|
inputSchema: RewardBuyInputSchema,
|
|
76
85
|
handler: rewardBuy,
|
|
77
86
|
},
|
|
@@ -81,6 +90,7 @@ export const rewardToolDefinitions = [
|
|
|
81
90
|
description: "Mark coupon as used. Validates coupon exists, belongs to member, and is active. " +
|
|
82
91
|
"Fails if coupon is expired, already used, or doesn't exist.",
|
|
83
92
|
readOnly: false,
|
|
93
|
+
idempotent: false,
|
|
84
94
|
inputSchema: RewardRedeemInputSchema,
|
|
85
95
|
handler: rewardRedeem,
|
|
86
96
|
},
|
|
@@ -89,6 +99,7 @@ export const rewardToolDefinitions = [
|
|
|
89
99
|
title: "List Reward Categories",
|
|
90
100
|
description: "List reward categories. Use categoryId when creating or filtering rewards.",
|
|
91
101
|
readOnly: true,
|
|
102
|
+
idempotent: true,
|
|
92
103
|
inputSchema: RewardCategoryListInputSchema,
|
|
93
104
|
handler: rewardCategoryList,
|
|
94
105
|
},
|
|
@@ -73,9 +73,9 @@ export const RewardGetInputSchema = {
|
|
|
73
73
|
export const RewardUpdateInputSchema = {
|
|
74
74
|
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."),
|
|
75
75
|
rewardId: z.string().describe("The reward ID (UUID) to update."),
|
|
76
|
-
name: z.string().optional().describe("Reward name."),
|
|
76
|
+
name: z.string().optional().describe("Reward name (updates translations.en.name internally)."),
|
|
77
77
|
costInPoints: z.number().optional().describe("Points required to redeem."),
|
|
78
|
-
description: z.string().optional().describe("Reward description."),
|
|
78
|
+
description: z.string().optional().describe("Reward description (updates translations.en.description internally)."),
|
|
79
79
|
active: z.boolean().optional().describe("Whether reward is active."),
|
|
80
80
|
categories: z.array(z.string()).optional().describe("Array of category UUIDs. Use ol_reward_category_list() to find valid categoryId values."),
|
|
81
81
|
levels: z.array(z.string()).optional().describe("Array of tier level UUIDs. Use ol_tierset_get_tiers(tierSetId) to find valid levelId values."),
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Role, RoleListItem, ACLResource } from "../../types/schemas/role.js";
|
|
2
|
+
import type { RolePermissionInput } from "./schemas.js";
|
|
3
|
+
export declare function roleList(input: {
|
|
4
|
+
page?: number;
|
|
5
|
+
perPage?: number;
|
|
6
|
+
name?: string;
|
|
7
|
+
master?: boolean;
|
|
8
|
+
default?: boolean;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
items: RoleListItem[];
|
|
11
|
+
total?: Record<string, unknown>;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function roleCreate(input: {
|
|
14
|
+
name: string;
|
|
15
|
+
permissions?: RolePermissionInput[];
|
|
16
|
+
stores?: string[];
|
|
17
|
+
default?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
export declare function roleGet(input: {
|
|
20
|
+
roleId: string | number;
|
|
21
|
+
}): Promise<Role>;
|
|
22
|
+
export declare function roleUpdate(input: {
|
|
23
|
+
roleId: string | number;
|
|
24
|
+
name?: string;
|
|
25
|
+
permissions?: RolePermissionInput[];
|
|
26
|
+
stores?: string[];
|
|
27
|
+
default?: boolean;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
export declare function roleDelete(input: {
|
|
30
|
+
roleId: string | number;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
export declare function aclGetResources(): Promise<{
|
|
33
|
+
items: ACLResource[];
|
|
34
|
+
total?: Record<string, unknown>;
|
|
35
|
+
}>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { apiGet, apiPost, apiPut, apiDelete } from "../../client/http.js";
|
|
2
|
+
import { formatApiError, OpenLoyaltyError } from "../../utils/errors.js";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
export async function roleList(input) {
|
|
5
|
+
const params = new URLSearchParams();
|
|
6
|
+
if (input.page)
|
|
7
|
+
params.append("_page", String(input.page));
|
|
8
|
+
if (input.perPage)
|
|
9
|
+
params.append("_itemsOnPage", String(input.perPage));
|
|
10
|
+
if (input.name)
|
|
11
|
+
params.append("name", input.name);
|
|
12
|
+
if (input.master !== undefined)
|
|
13
|
+
params.append("master", String(input.master));
|
|
14
|
+
if (input.default !== undefined)
|
|
15
|
+
params.append("default", String(input.default));
|
|
16
|
+
const queryString = params.toString();
|
|
17
|
+
const url = `/acl/role${queryString ? `?${queryString}` : ""}`;
|
|
18
|
+
try {
|
|
19
|
+
const response = await apiGet(url);
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (axios.isAxiosError(error) && error.response?.status === 403) {
|
|
24
|
+
throw new OpenLoyaltyError({
|
|
25
|
+
code: "ROLE_PERMISSION_DENIED",
|
|
26
|
+
message: "You don't have permission to view roles",
|
|
27
|
+
hint: "Role management requires super admin access or the ROLE:VIEW permission. Use ol_admin_get_permissions() to check your access.",
|
|
28
|
+
relatedTool: "ol_role_list",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
throw formatApiError(error, "ol_role_list");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function roleCreate(input) {
|
|
35
|
+
const payload = {
|
|
36
|
+
name: input.name,
|
|
37
|
+
};
|
|
38
|
+
if (input.permissions)
|
|
39
|
+
payload.permissions = input.permissions;
|
|
40
|
+
if (input.stores)
|
|
41
|
+
payload.stores = input.stores;
|
|
42
|
+
if (input.default !== undefined)
|
|
43
|
+
payload.default = input.default;
|
|
44
|
+
try {
|
|
45
|
+
await apiPost("/acl/role", { role: payload });
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (axios.isAxiosError(error)) {
|
|
49
|
+
const allMessages = [error.response?.data?.message || "", ...(error.response?.data?.errors || []).map((e) => e.message)].join(" ").toLowerCase();
|
|
50
|
+
if (allMessages.includes("name") && (allMessages.includes("already") || allMessages.includes("unique") || allMessages.includes("exists"))) {
|
|
51
|
+
throw new OpenLoyaltyError({ code: "DUPLICATE_NAME", message: `Role with name '${input.name}' already exists`,
|
|
52
|
+
hint: "Use ol_role_list() to find existing roles, or choose a different name.", relatedTool: "ol_role_create" });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
throw formatApiError(error, "ol_role_create");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function roleGet(input) {
|
|
59
|
+
try {
|
|
60
|
+
const response = await apiGet(`/acl/role/${input.roleId}`);
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
|
65
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Role '${input.roleId}' not found`,
|
|
66
|
+
hint: "Use ol_role_list() to find existing roles and their IDs.", relatedTool: "ol_role_get" });
|
|
67
|
+
}
|
|
68
|
+
throw formatApiError(error, "ol_role_get");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export async function roleUpdate(input) {
|
|
72
|
+
const payload = {};
|
|
73
|
+
if (input.name)
|
|
74
|
+
payload.name = input.name;
|
|
75
|
+
if (input.permissions)
|
|
76
|
+
payload.permissions = input.permissions;
|
|
77
|
+
if (input.stores)
|
|
78
|
+
payload.stores = input.stores;
|
|
79
|
+
if (input.default !== undefined)
|
|
80
|
+
payload.default = input.default;
|
|
81
|
+
try {
|
|
82
|
+
await apiPut(`/acl/role/${input.roleId}`, { role: payload });
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (axios.isAxiosError(error) && error.response?.status === 404) {
|
|
86
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Role '${input.roleId}' not found`,
|
|
87
|
+
hint: "Use ol_role_list() to find existing roles and their IDs.", relatedTool: "ol_role_update" });
|
|
88
|
+
}
|
|
89
|
+
throw formatApiError(error, "ol_role_update");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export async function roleDelete(input) {
|
|
93
|
+
try {
|
|
94
|
+
await apiDelete(`/acl/role/${input.roleId}`);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (axios.isAxiosError(error)) {
|
|
98
|
+
if (error.response?.status === 404) {
|
|
99
|
+
throw new OpenLoyaltyError({ code: "NOT_FOUND", message: `Role '${input.roleId}' not found`,
|
|
100
|
+
hint: "Use ol_role_list() to find existing roles and their IDs.", relatedTool: "ol_role_delete" });
|
|
101
|
+
}
|
|
102
|
+
const allMessages = [error.response?.data?.message || "", ...(error.response?.data?.errors || []).map((e) => e.message)].join(" ").toLowerCase();
|
|
103
|
+
if (allMessages.includes("in use") || allMessages.includes("assigned") || allMessages.includes("cannot delete")) {
|
|
104
|
+
throw new OpenLoyaltyError({ code: "ROLE_IN_USE", message: `Role '${input.roleId}' is assigned to admin users and cannot be deleted`,
|
|
105
|
+
hint: "Remove this role from all admin users first using ol_admin_update(), then retry deletion.", relatedTool: "ol_role_delete" });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
throw formatApiError(error, "ol_role_delete");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function aclGetResources() {
|
|
112
|
+
try {
|
|
113
|
+
const response = await apiGet("/acl/resources");
|
|
114
|
+
return response;
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
if (axios.isAxiosError(error) && error.response?.status === 403) {
|
|
118
|
+
throw new OpenLoyaltyError({
|
|
119
|
+
code: "ACL_PERMISSION_DENIED",
|
|
120
|
+
message: "You don't have permission to view ACL resources",
|
|
121
|
+
hint: "ACL resource listing requires super admin access or the ROLE:VIEW permission. Use ol_admin_get_permissions() to check your access.",
|
|
122
|
+
relatedTool: "ol_acl_get_resources",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
throw formatApiError(error, "ol_acl_get_resources");
|
|
126
|
+
}
|
|
127
|
+
}
|