@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
package/dist/tools/export.js
CHANGED
|
@@ -5,7 +5,7 @@ import { getConfig, getStoreCode } from "../config.js";
|
|
|
5
5
|
import axios from "axios";
|
|
6
6
|
// Input Schemas
|
|
7
7
|
export const ExportCreateInputSchema = {
|
|
8
|
-
storeCode: z.string().optional().describe("Store code.
|
|
8
|
+
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."),
|
|
9
9
|
type: z.enum([
|
|
10
10
|
"campaignCode",
|
|
11
11
|
"member",
|
|
@@ -18,7 +18,7 @@ export const ExportCreateInputSchema = {
|
|
|
18
18
|
perPage: z.number().optional().describe("Items per page for export."),
|
|
19
19
|
};
|
|
20
20
|
export const ExportListInputSchema = {
|
|
21
|
-
storeCode: z.string().optional().describe("Store code.
|
|
21
|
+
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."),
|
|
22
22
|
page: z.number().optional().describe("Page number (default: 1)."),
|
|
23
23
|
perPage: z.number().optional().describe("Items per page (default: 25)."),
|
|
24
24
|
exportId: z.string().optional().describe("Filter by export ID."),
|
|
@@ -32,11 +32,11 @@ export const ExportListInputSchema = {
|
|
|
32
32
|
status: z.enum(["pending", "done", "failed", "error"]).optional().describe("Filter by export status."),
|
|
33
33
|
};
|
|
34
34
|
export const ExportGetInputSchema = {
|
|
35
|
-
storeCode: z.string().optional().describe("Store code.
|
|
35
|
+
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."),
|
|
36
36
|
exportId: z.string().describe("The export ID (UUID) to retrieve."),
|
|
37
37
|
};
|
|
38
38
|
export const ExportDownloadInputSchema = {
|
|
39
|
-
storeCode: z.string().optional().describe("Store code.
|
|
39
|
+
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."),
|
|
40
40
|
exportId: z.string().describe("The export ID (UUID) to download. Export must have status 'done'."),
|
|
41
41
|
};
|
|
42
42
|
// Handler functions
|
|
@@ -59,7 +59,7 @@ export async function exportCreate(input) {
|
|
|
59
59
|
return response;
|
|
60
60
|
}
|
|
61
61
|
catch (error) {
|
|
62
|
-
throw formatApiError(error, "
|
|
62
|
+
throw formatApiError(error, "ol_export_create");
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
export async function exportList(input) {
|
|
@@ -82,7 +82,7 @@ export async function exportList(input) {
|
|
|
82
82
|
return response;
|
|
83
83
|
}
|
|
84
84
|
catch (error) {
|
|
85
|
-
throw formatApiError(error, "
|
|
85
|
+
throw formatApiError(error, "ol_export_list");
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
export async function exportGet(input) {
|
|
@@ -92,7 +92,7 @@ export async function exportGet(input) {
|
|
|
92
92
|
return response;
|
|
93
93
|
}
|
|
94
94
|
catch (error) {
|
|
95
|
-
throw formatApiError(error, "
|
|
95
|
+
throw formatApiError(error, "ol_export_get");
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
export async function exportDownload(input) {
|
|
@@ -112,13 +112,13 @@ export async function exportDownload(input) {
|
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
catch (error) {
|
|
115
|
-
throw formatApiError(error, "
|
|
115
|
+
throw formatApiError(error, "ol_export_download");
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
// Tool definitions
|
|
119
119
|
export const exportToolDefinitions = [
|
|
120
120
|
{
|
|
121
|
-
name: "
|
|
121
|
+
name: "ol_export_create",
|
|
122
122
|
title: "Create Data Export",
|
|
123
123
|
description: "Create a new data export. Returns exportId for async tracking. Export types: campaignCode (campaign redemption codes), member (member data), memberTier (member tier assignments), memberSegment (member segment membership), rewardFulfillment (reward fulfillment records). The export runs asynchronously - use export_get to check status and export_download when status is 'done'.",
|
|
124
124
|
readOnly: false,
|
|
@@ -126,7 +126,7 @@ export const exportToolDefinitions = [
|
|
|
126
126
|
handler: exportCreate,
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
|
-
name: "
|
|
129
|
+
name: "ol_export_list",
|
|
130
130
|
title: "List Exports",
|
|
131
131
|
description: "List exports with optional filtering. Returns paginated list of exports with exportId, type, status, createdAt, and finishedAt. Status values: pending, done, failed, error.",
|
|
132
132
|
readOnly: true,
|
|
@@ -134,7 +134,7 @@ export const exportToolDefinitions = [
|
|
|
134
134
|
handler: exportList,
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
|
-
name: "
|
|
137
|
+
name: "ol_export_get",
|
|
138
138
|
title: "Get Export Details",
|
|
139
139
|
description: "Get export details and status. Returns exportId, type, status, createdAt, finishedAt, exportedRows, and message. Check status before downloading - export must have status 'done'.",
|
|
140
140
|
readOnly: true,
|
|
@@ -142,7 +142,7 @@ export const exportToolDefinitions = [
|
|
|
142
142
|
handler: exportGet,
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
|
-
name: "
|
|
145
|
+
name: "ol_export_download",
|
|
146
146
|
title: "Download Export File",
|
|
147
147
|
description: "Download export file content. Returns CSV content. IMPORTANT: Only available when export status is 'done'. Check status with export_get first.",
|
|
148
148
|
readOnly: true,
|
package/dist/tools/import.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export declare function importGet(input: {
|
|
|
77
77
|
perPage?: number;
|
|
78
78
|
}): Promise<ImportDetailsResponse>;
|
|
79
79
|
export declare const importToolDefinitions: readonly [{
|
|
80
|
-
readonly name: "
|
|
80
|
+
readonly name: "ol_import_create";
|
|
81
81
|
readonly title: "Create Bulk Import";
|
|
82
82
|
readonly description: "Create a new bulk import from CSV content. Returns importId for async tracking. Import types: member (member data), groupValue (group values), segmentMembers (segment membership), unitTransferAdding (add points), unitTransferSpending (spend points), transaction (transactions), campaignCode (campaign codes), rewardCoupon (reward coupons). CSV format required - provide plain text CSV content.";
|
|
83
83
|
readonly readOnly: false;
|
|
@@ -89,7 +89,7 @@ export declare const importToolDefinitions: readonly [{
|
|
|
89
89
|
};
|
|
90
90
|
readonly handler: typeof importCreate;
|
|
91
91
|
}, {
|
|
92
|
-
readonly name: "
|
|
92
|
+
readonly name: "ol_import_list";
|
|
93
93
|
readonly title: "List Imports";
|
|
94
94
|
readonly description: "List imports with optional filtering. Returns paginated list of imports with importId, type, uploadedDate, fileName, and status information.";
|
|
95
95
|
readonly readOnly: true;
|
|
@@ -102,7 +102,7 @@ export declare const importToolDefinitions: readonly [{
|
|
|
102
102
|
};
|
|
103
103
|
readonly handler: typeof importList;
|
|
104
104
|
}, {
|
|
105
|
-
readonly name: "
|
|
105
|
+
readonly name: "ol_import_get";
|
|
106
106
|
readonly title: "Get Import Details";
|
|
107
107
|
readonly description: "Get import details and individual item statuses. Returns paginated list of import items with their success/failure status and error messages.";
|
|
108
108
|
readonly readOnly: true;
|
package/dist/tools/import.js
CHANGED
|
@@ -3,9 +3,10 @@ import { apiGet } from "../client/http.js";
|
|
|
3
3
|
import { formatApiError } from "../utils/errors.js";
|
|
4
4
|
import { getConfig, getStoreCode } from "../config.js";
|
|
5
5
|
import axios from "axios";
|
|
6
|
+
import FormDataNode from "form-data";
|
|
6
7
|
// Input Schemas
|
|
7
8
|
export const ImportCreateInputSchema = {
|
|
8
|
-
storeCode: z.string().optional().describe("Store code.
|
|
9
|
+
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."),
|
|
9
10
|
type: z.enum([
|
|
10
11
|
"member",
|
|
11
12
|
"groupValue",
|
|
@@ -20,7 +21,7 @@ export const ImportCreateInputSchema = {
|
|
|
20
21
|
fileName: z.string().optional().describe("Optional file name for the import (default: import.csv)."),
|
|
21
22
|
};
|
|
22
23
|
export const ImportListInputSchema = {
|
|
23
|
-
storeCode: z.string().optional().describe("Store code.
|
|
24
|
+
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."),
|
|
24
25
|
page: z.number().optional().describe("Page number (default: 1)."),
|
|
25
26
|
perPage: z.number().optional().describe("Items per page (default: 25)."),
|
|
26
27
|
importId: z.string().optional().describe("Filter by import ID."),
|
|
@@ -36,7 +37,7 @@ export const ImportListInputSchema = {
|
|
|
36
37
|
]).optional().describe("Filter by import type."),
|
|
37
38
|
};
|
|
38
39
|
export const ImportGetInputSchema = {
|
|
39
|
-
storeCode: z.string().optional().describe("Store code.
|
|
40
|
+
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."),
|
|
40
41
|
importId: z.string().describe("The import ID (UUID) to retrieve."),
|
|
41
42
|
page: z.number().optional().describe("Page number for import items (default: 1)."),
|
|
42
43
|
perPage: z.number().optional().describe("Items per page for import items (default: 25)."),
|
|
@@ -45,22 +46,29 @@ export const ImportGetInputSchema = {
|
|
|
45
46
|
export async function importCreate(input) {
|
|
46
47
|
const config = getConfig();
|
|
47
48
|
const storeCode = getStoreCode(input.storeCode);
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
49
|
+
// Determine file extension and content type
|
|
50
|
+
// API accepts: application/xml, text/xml for member imports; text/csv for others
|
|
51
|
+
const fileName = input.fileName || "import.xml";
|
|
52
|
+
const isXml = fileName.endsWith('.xml') || input.fileContent.trim().startsWith('<?xml') || input.fileContent.trim().startsWith('<');
|
|
53
|
+
const contentType = isXml ? "application/xml" : "text/csv";
|
|
54
|
+
// Create form data for multipart upload using Node.js form-data package
|
|
55
|
+
// API expects field name "import[file]" per documentation
|
|
56
|
+
const formData = new FormDataNode();
|
|
57
|
+
formData.append("import[file]", Buffer.from(input.fileContent), {
|
|
58
|
+
filename: fileName,
|
|
59
|
+
contentType: contentType,
|
|
60
|
+
});
|
|
53
61
|
try {
|
|
54
62
|
const response = await axios.post(`${config.apiUrl}/${storeCode}/import/${input.type}`, formData, {
|
|
55
63
|
headers: {
|
|
56
64
|
"X-AUTH-TOKEN": config.apiToken,
|
|
57
|
-
|
|
65
|
+
...formData.getHeaders(),
|
|
58
66
|
},
|
|
59
67
|
});
|
|
60
68
|
return response.data;
|
|
61
69
|
}
|
|
62
70
|
catch (error) {
|
|
63
|
-
throw formatApiError(error, "
|
|
71
|
+
throw formatApiError(error, "ol_import_create");
|
|
64
72
|
}
|
|
65
73
|
}
|
|
66
74
|
export async function importList(input) {
|
|
@@ -81,7 +89,7 @@ export async function importList(input) {
|
|
|
81
89
|
return response;
|
|
82
90
|
}
|
|
83
91
|
catch (error) {
|
|
84
|
-
throw formatApiError(error, "
|
|
92
|
+
throw formatApiError(error, "ol_import_list");
|
|
85
93
|
}
|
|
86
94
|
}
|
|
87
95
|
export async function importGet(input) {
|
|
@@ -98,13 +106,13 @@ export async function importGet(input) {
|
|
|
98
106
|
return response;
|
|
99
107
|
}
|
|
100
108
|
catch (error) {
|
|
101
|
-
throw formatApiError(error, "
|
|
109
|
+
throw formatApiError(error, "ol_import_get");
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
112
|
// Tool definitions
|
|
105
113
|
export const importToolDefinitions = [
|
|
106
114
|
{
|
|
107
|
-
name: "
|
|
115
|
+
name: "ol_import_create",
|
|
108
116
|
title: "Create Bulk Import",
|
|
109
117
|
description: "Create a new bulk import from CSV content. Returns importId for async tracking. Import types: member (member data), groupValue (group values), segmentMembers (segment membership), unitTransferAdding (add points), unitTransferSpending (spend points), transaction (transactions), campaignCode (campaign codes), rewardCoupon (reward coupons). CSV format required - provide plain text CSV content.",
|
|
110
118
|
readOnly: false,
|
|
@@ -112,7 +120,7 @@ export const importToolDefinitions = [
|
|
|
112
120
|
handler: importCreate,
|
|
113
121
|
},
|
|
114
122
|
{
|
|
115
|
-
name: "
|
|
123
|
+
name: "ol_import_list",
|
|
116
124
|
title: "List Imports",
|
|
117
125
|
description: "List imports with optional filtering. Returns paginated list of imports with importId, type, uploadedDate, fileName, and status information.",
|
|
118
126
|
readOnly: true,
|
|
@@ -120,7 +128,7 @@ export const importToolDefinitions = [
|
|
|
120
128
|
handler: importList,
|
|
121
129
|
},
|
|
122
130
|
{
|
|
123
|
-
name: "
|
|
131
|
+
name: "ol_import_get",
|
|
124
132
|
title: "Get Import Details",
|
|
125
133
|
description: "Get import details and individual item statuses. Returns paginated list of import items with their success/failure status and error messages.",
|
|
126
134
|
readOnly: true,
|
package/dist/tools/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { walletTypeToolDefinitions } from "./wallet-type.js";
|
|
2
2
|
import { tiersetToolDefinitions } from "./tierset.js";
|
|
3
|
-
import { memberToolDefinitions } from "./member.js";
|
|
3
|
+
import { memberToolDefinitions } from "./member/index.js";
|
|
4
4
|
import { pointsToolDefinitions } from "./points.js";
|
|
5
|
-
import { rewardToolDefinitions } from "./reward.js";
|
|
5
|
+
import { rewardToolDefinitions } from "./reward/index.js";
|
|
6
6
|
import { transactionToolDefinitions } from "./transaction.js";
|
|
7
7
|
// Phase 2 tools
|
|
8
|
-
import { campaignToolDefinitions } from "./campaign.js";
|
|
9
|
-
import { segmentToolDefinitions } from "./segment.js";
|
|
10
|
-
import { achievementToolDefinitions } from "./achievement.js";
|
|
8
|
+
import { campaignToolDefinitions } from "./campaign/index.js";
|
|
9
|
+
import { segmentToolDefinitions } from "./segment/index.js";
|
|
10
|
+
import { achievementToolDefinitions } from "./achievement/index.js";
|
|
11
11
|
import { badgeToolDefinitions } from "./badge.js";
|
|
12
12
|
// Phase 3 tools
|
|
13
13
|
import { analyticsToolDefinitions } from "./analytics.js";
|
|
@@ -20,6 +20,10 @@ import { storeToolDefinitions } from "./store.js";
|
|
|
20
20
|
import { webhookToolDefinitions } from "./webhook.js";
|
|
21
21
|
import { importToolDefinitions } from "./import.js";
|
|
22
22
|
import { exportToolDefinitions } from "./export.js";
|
|
23
|
+
// Custom event tools (needed for custom_event trigger in campaigns/achievements)
|
|
24
|
+
import { customEventToolDefinitions } from "./custom-event.js";
|
|
25
|
+
// Referral tools (needed for referral tracking between members)
|
|
26
|
+
import { referralToolDefinitions } from "./referral/index.js";
|
|
23
27
|
// Collect all tool definitions
|
|
24
28
|
// Note: Single cast needed because tool handlers have specific input types
|
|
25
29
|
// (e.g., { memberId: string }) while ToolDefinition uses generic Record<string, unknown>.
|
|
@@ -48,6 +52,10 @@ const allTools = [
|
|
|
48
52
|
...webhookToolDefinitions,
|
|
49
53
|
...importToolDefinitions,
|
|
50
54
|
...exportToolDefinitions,
|
|
55
|
+
// Custom event tools
|
|
56
|
+
...customEventToolDefinitions,
|
|
57
|
+
// Referral tools
|
|
58
|
+
...referralToolDefinitions,
|
|
51
59
|
];
|
|
52
60
|
const toolHandlers = new Map();
|
|
53
61
|
for (const tool of allTools) {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Member } from "../../types/schemas/member.js";
|
|
2
|
+
export declare function memberCreate(input: {
|
|
3
|
+
storeCode?: string;
|
|
4
|
+
email: string;
|
|
5
|
+
firstName?: string;
|
|
6
|
+
lastName?: string;
|
|
7
|
+
phone?: string;
|
|
8
|
+
birthDate?: string;
|
|
9
|
+
gender?: string;
|
|
10
|
+
loyaltyCardNumber?: string;
|
|
11
|
+
agreement1?: boolean;
|
|
12
|
+
agreement2?: boolean;
|
|
13
|
+
agreement3?: boolean;
|
|
14
|
+
address?: {
|
|
15
|
+
street?: string;
|
|
16
|
+
city?: string;
|
|
17
|
+
postal?: string;
|
|
18
|
+
country?: string;
|
|
19
|
+
province?: string;
|
|
20
|
+
};
|
|
21
|
+
}): Promise<{
|
|
22
|
+
memberId: string;
|
|
23
|
+
loyaltyCardNumber: string;
|
|
24
|
+
email: string;
|
|
25
|
+
}>;
|
|
26
|
+
export declare function memberGet(input: {
|
|
27
|
+
storeCode?: string;
|
|
28
|
+
memberId: string;
|
|
29
|
+
}): Promise<Member>;
|
|
30
|
+
export declare function memberList(input: {
|
|
31
|
+
storeCode?: string;
|
|
32
|
+
cursor?: string;
|
|
33
|
+
page?: number;
|
|
34
|
+
perPage?: number;
|
|
35
|
+
email?: string;
|
|
36
|
+
firstName?: string;
|
|
37
|
+
lastName?: string;
|
|
38
|
+
phone?: string;
|
|
39
|
+
loyaltyCardNumber?: string;
|
|
40
|
+
active?: boolean;
|
|
41
|
+
}): Promise<{
|
|
42
|
+
members: Array<{
|
|
43
|
+
memberId: string;
|
|
44
|
+
email: string;
|
|
45
|
+
firstName?: string;
|
|
46
|
+
lastName?: string;
|
|
47
|
+
loyaltyCardNumber?: string;
|
|
48
|
+
active: boolean;
|
|
49
|
+
}>;
|
|
50
|
+
total: {
|
|
51
|
+
all?: number;
|
|
52
|
+
filtered?: number;
|
|
53
|
+
};
|
|
54
|
+
cursor?: string;
|
|
55
|
+
}>;
|
|
56
|
+
export declare function memberUpdate(input: {
|
|
57
|
+
storeCode?: string;
|
|
58
|
+
memberId: string;
|
|
59
|
+
firstName?: string;
|
|
60
|
+
lastName?: string;
|
|
61
|
+
phone?: string;
|
|
62
|
+
birthDate?: string;
|
|
63
|
+
gender?: string;
|
|
64
|
+
address?: {
|
|
65
|
+
street?: string;
|
|
66
|
+
city?: string;
|
|
67
|
+
postal?: string;
|
|
68
|
+
country?: string;
|
|
69
|
+
province?: string;
|
|
70
|
+
};
|
|
71
|
+
agreement1?: boolean;
|
|
72
|
+
agreement2?: boolean;
|
|
73
|
+
agreement3?: boolean;
|
|
74
|
+
}): Promise<void>;
|
|
75
|
+
export declare function memberActivate(input: {
|
|
76
|
+
storeCode?: string;
|
|
77
|
+
memberId: string;
|
|
78
|
+
}): Promise<void>;
|
|
79
|
+
export declare function memberDeactivate(input: {
|
|
80
|
+
storeCode?: string;
|
|
81
|
+
memberId: string;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
export declare function memberDelete(input: {
|
|
84
|
+
storeCode?: string;
|
|
85
|
+
memberId: string;
|
|
86
|
+
}): Promise<void>;
|
|
87
|
+
export declare function memberGetTierProgress(input: {
|
|
88
|
+
storeCode?: string;
|
|
89
|
+
memberId: string;
|
|
90
|
+
}): Promise<{
|
|
91
|
+
currentTier?: {
|
|
92
|
+
levelId: string;
|
|
93
|
+
name: string;
|
|
94
|
+
};
|
|
95
|
+
nextTier?: {
|
|
96
|
+
levelId: string;
|
|
97
|
+
name: string;
|
|
98
|
+
};
|
|
99
|
+
currentValue: number;
|
|
100
|
+
requiredValue?: number;
|
|
101
|
+
progressPercent: number;
|
|
102
|
+
}>;
|
|
103
|
+
export declare function memberAssignTier(input: {
|
|
104
|
+
storeCode?: string;
|
|
105
|
+
memberId: string;
|
|
106
|
+
levelId: string;
|
|
107
|
+
}): Promise<void>;
|
|
108
|
+
export declare function memberRemoveManualTier(input: {
|
|
109
|
+
storeCode?: string;
|
|
110
|
+
memberId: string;
|
|
111
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { apiGet, apiPost, apiPut, apiDelete } from "../../client/http.js";
|
|
2
|
+
import { MemberSchema } from "../../types/schemas/member.js";
|
|
3
|
+
import { formatApiError } from "../../utils/errors.js";
|
|
4
|
+
import { getStoreCode } from "../../config.js";
|
|
5
|
+
import { buildPaginationParams } from "../../utils/pagination.js";
|
|
6
|
+
import { omitUndefined } from "../../utils/payload.js";
|
|
7
|
+
export async function memberCreate(input) {
|
|
8
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
9
|
+
const payload = omitUndefined({
|
|
10
|
+
email: input.email,
|
|
11
|
+
firstName: input.firstName,
|
|
12
|
+
lastName: input.lastName,
|
|
13
|
+
phone: input.phone,
|
|
14
|
+
birthDate: input.birthDate,
|
|
15
|
+
gender: input.gender,
|
|
16
|
+
loyaltyCardNumber: input.loyaltyCardNumber,
|
|
17
|
+
agreement1: input.agreement1,
|
|
18
|
+
agreement2: input.agreement2,
|
|
19
|
+
agreement3: input.agreement3,
|
|
20
|
+
address: input.address,
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
const response = await apiPost(`/${storeCode}/member`, { customer: payload });
|
|
24
|
+
return {
|
|
25
|
+
memberId: response.customerId,
|
|
26
|
+
loyaltyCardNumber: response.loyaltyCardNumber || "",
|
|
27
|
+
email: response.email,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw formatApiError(error, "ol_member_create");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function memberGet(input) {
|
|
35
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
36
|
+
try {
|
|
37
|
+
const response = await apiGet(`/${storeCode}/member/${input.memberId}`);
|
|
38
|
+
// Map API response to our schema
|
|
39
|
+
const data = response;
|
|
40
|
+
const mapped = {
|
|
41
|
+
memberId: data.customerId || data.memberId,
|
|
42
|
+
email: data.email,
|
|
43
|
+
firstName: data.firstName,
|
|
44
|
+
lastName: data.lastName,
|
|
45
|
+
phone: data.phone,
|
|
46
|
+
birthDate: data.birthDate,
|
|
47
|
+
gender: data.gender,
|
|
48
|
+
loyaltyCardNumber: data.loyaltyCardNumber,
|
|
49
|
+
active: data.active ?? true,
|
|
50
|
+
createdAt: data.createdAt,
|
|
51
|
+
address: data.address,
|
|
52
|
+
agreement1: data.agreement1,
|
|
53
|
+
agreement2: data.agreement2,
|
|
54
|
+
agreement3: data.agreement3,
|
|
55
|
+
levelId: data.levelId || data.level?.levelId,
|
|
56
|
+
levelName: data.levelName || data.level?.name,
|
|
57
|
+
points: data.points,
|
|
58
|
+
};
|
|
59
|
+
return MemberSchema.parse(mapped);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw formatApiError(error, "ol_member_get");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function memberList(input) {
|
|
66
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
67
|
+
const params = new URLSearchParams();
|
|
68
|
+
// Use buildPaginationParams for cursor/page handling
|
|
69
|
+
buildPaginationParams({ cursor: input.cursor, page: input.page, perPage: input.perPage }, params);
|
|
70
|
+
if (input.email)
|
|
71
|
+
params.append("email", input.email);
|
|
72
|
+
if (input.firstName)
|
|
73
|
+
params.append("firstName", input.firstName);
|
|
74
|
+
if (input.lastName)
|
|
75
|
+
params.append("lastName", input.lastName);
|
|
76
|
+
if (input.phone)
|
|
77
|
+
params.append("phone", input.phone);
|
|
78
|
+
if (input.loyaltyCardNumber)
|
|
79
|
+
params.append("loyaltyCardNumber", input.loyaltyCardNumber);
|
|
80
|
+
if (input.active !== undefined)
|
|
81
|
+
params.append("active", String(input.active));
|
|
82
|
+
const queryString = params.toString();
|
|
83
|
+
const url = `/${storeCode}/member${queryString ? `?${queryString}` : ""}`;
|
|
84
|
+
try {
|
|
85
|
+
const response = await apiGet(url);
|
|
86
|
+
const members = (response.items || []).map((c) => {
|
|
87
|
+
const customer = c;
|
|
88
|
+
return {
|
|
89
|
+
memberId: (customer.customerId || customer.memberId),
|
|
90
|
+
email: customer.email,
|
|
91
|
+
firstName: customer.firstName,
|
|
92
|
+
lastName: customer.lastName,
|
|
93
|
+
loyaltyCardNumber: customer.loyaltyCardNumber,
|
|
94
|
+
active: (customer.active ?? true),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
const total = response.total || {};
|
|
98
|
+
return {
|
|
99
|
+
members,
|
|
100
|
+
total: {
|
|
101
|
+
all: typeof total.all === 'number' ? total.all : undefined,
|
|
102
|
+
filtered: typeof total.filtered === 'number' ? total.filtered : undefined,
|
|
103
|
+
},
|
|
104
|
+
cursor: response.scroll,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw formatApiError(error, "ol_member_list");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function memberUpdate(input) {
|
|
112
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
113
|
+
// API requires email even for partial updates - fetch existing member to get it
|
|
114
|
+
const existingResponse = await apiGet(`/${storeCode}/member/${input.memberId}`);
|
|
115
|
+
const existingEmail = existingResponse.email;
|
|
116
|
+
const payload = omitUndefined({
|
|
117
|
+
email: existingEmail, // Required by API even for partial updates
|
|
118
|
+
firstName: input.firstName,
|
|
119
|
+
lastName: input.lastName,
|
|
120
|
+
phone: input.phone,
|
|
121
|
+
birthDate: input.birthDate,
|
|
122
|
+
gender: input.gender,
|
|
123
|
+
address: input.address,
|
|
124
|
+
agreement1: input.agreement1,
|
|
125
|
+
agreement2: input.agreement2,
|
|
126
|
+
agreement3: input.agreement3,
|
|
127
|
+
});
|
|
128
|
+
try {
|
|
129
|
+
await apiPut(`/${storeCode}/member/${input.memberId}`, { customer: payload });
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw formatApiError(error, "ol_member_update");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export async function memberActivate(input) {
|
|
136
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
137
|
+
try {
|
|
138
|
+
await apiPost(`/${storeCode}/member/${input.memberId}/activate`);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
throw formatApiError(error, "ol_member_activate");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export async function memberDeactivate(input) {
|
|
145
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
146
|
+
try {
|
|
147
|
+
await apiPost(`/${storeCode}/member/${input.memberId}/deactivate`);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
throw formatApiError(error, "ol_member_deactivate");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export async function memberDelete(input) {
|
|
154
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
155
|
+
try {
|
|
156
|
+
await apiDelete(`/${storeCode}/member/${input.memberId}`);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
throw formatApiError(error, "ol_member_delete");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
export async function memberGetTierProgress(input) {
|
|
163
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
164
|
+
try {
|
|
165
|
+
// API uses /level endpoint, not /tier
|
|
166
|
+
const response = await apiGet(`/${storeCode}/member/${input.memberId}/level`);
|
|
167
|
+
// Response may have level data directly or nested
|
|
168
|
+
const currentLevel = (response.currentLevel || response.level);
|
|
169
|
+
const nextLevel = response.nextLevel;
|
|
170
|
+
return {
|
|
171
|
+
currentTier: currentLevel ? {
|
|
172
|
+
levelId: (currentLevel.levelId || currentLevel.id),
|
|
173
|
+
name: currentLevel.name,
|
|
174
|
+
} : undefined,
|
|
175
|
+
nextTier: nextLevel ? {
|
|
176
|
+
levelId: (nextLevel.levelId || nextLevel.id),
|
|
177
|
+
name: nextLevel.name,
|
|
178
|
+
} : undefined,
|
|
179
|
+
currentValue: (response.currentValue || response.value || 0),
|
|
180
|
+
requiredValue: (response.requiredValue || response.conditionValue),
|
|
181
|
+
progressPercent: (response.progressPercent || response.progress || 0),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
throw formatApiError(error, "ol_member_get_tier_progress");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export async function memberAssignTier(input) {
|
|
189
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
190
|
+
try {
|
|
191
|
+
await apiPost(`/${storeCode}/member/${input.memberId}/tier`, { levelId: input.levelId });
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
throw formatApiError(error, "ol_member_assign_tier");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
export async function memberRemoveManualTier(input) {
|
|
198
|
+
const storeCode = getStoreCode(input.storeCode);
|
|
199
|
+
try {
|
|
200
|
+
// API uses POST to /remove-manually-level, not DELETE to /tier
|
|
201
|
+
await apiPost(`/${storeCode}/member/${input.memberId}/remove-manually-level`);
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
throw formatApiError(error, "ol_member_remove_manual_tier");
|
|
205
|
+
}
|
|
206
|
+
}
|