@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.
Files changed (112) hide show
  1. package/README.md +180 -177
  2. package/dist/auth/provider.js +2 -14
  3. package/dist/auth/storage.js +22 -0
  4. package/dist/client/http.js +10 -0
  5. package/dist/config.d.ts +0 -13
  6. package/dist/config.js +0 -14
  7. package/dist/http.js +35 -3
  8. package/dist/instructions.d.ts +5 -0
  9. package/dist/instructions.js +440 -0
  10. package/dist/prompts/fan-engagement-setup.d.ts +107 -0
  11. package/dist/prompts/fan-engagement-setup.js +492 -0
  12. package/dist/server.d.ts +1 -1
  13. package/dist/server.js +60 -273
  14. package/dist/tools/achievement/handlers.d.ts +117 -0
  15. package/dist/tools/achievement/handlers.js +161 -0
  16. package/dist/tools/achievement/index.d.ts +479 -0
  17. package/dist/tools/achievement/index.js +74 -0
  18. package/dist/tools/achievement/schemas.d.ts +433 -0
  19. package/dist/tools/achievement/schemas.js +142 -0
  20. package/dist/tools/achievement.d.ts +141 -121
  21. package/dist/tools/achievement.js +60 -24
  22. package/dist/tools/admin.d.ts +6 -6
  23. package/dist/tools/admin.js +12 -12
  24. package/dist/tools/analytics.d.ts +11 -11
  25. package/dist/tools/analytics.js +30 -29
  26. package/dist/tools/apikey.d.ts +3 -3
  27. package/dist/tools/apikey.js +6 -6
  28. package/dist/tools/audit.d.ts +2 -2
  29. package/dist/tools/audit.js +4 -4
  30. package/dist/tools/badge.d.ts +6 -6
  31. package/dist/tools/badge.js +23 -18
  32. package/dist/tools/campaign/handlers.d.ts +42 -0
  33. package/dist/tools/campaign/handlers.js +223 -0
  34. package/dist/tools/campaign/index.d.ts +783 -0
  35. package/dist/tools/campaign/index.js +117 -0
  36. package/dist/tools/campaign/member-handlers.d.ts +60 -0
  37. package/dist/tools/campaign/member-handlers.js +159 -0
  38. package/dist/tools/campaign/schemas.d.ts +704 -0
  39. package/dist/tools/campaign/schemas.js +259 -0
  40. package/dist/tools/campaign/types.d.ts +161 -0
  41. package/dist/tools/campaign/types.js +2 -0
  42. package/dist/tools/custom-event.d.ts +315 -0
  43. package/dist/tools/custom-event.js +270 -0
  44. package/dist/tools/export.d.ts +4 -4
  45. package/dist/tools/export.js +12 -12
  46. package/dist/tools/import.d.ts +3 -3
  47. package/dist/tools/import.js +23 -15
  48. package/dist/tools/index.js +13 -5
  49. package/dist/tools/member/handlers.d.ts +111 -0
  50. package/dist/tools/member/handlers.js +206 -0
  51. package/dist/tools/member/index.d.ts +169 -0
  52. package/dist/tools/member/index.js +92 -0
  53. package/dist/tools/member/schemas.d.ts +89 -0
  54. package/dist/tools/member/schemas.js +65 -0
  55. package/dist/tools/points.d.ts +7 -6
  56. package/dist/tools/points.js +21 -20
  57. package/dist/tools/referral/handlers.d.ts +47 -0
  58. package/dist/tools/referral/handlers.js +115 -0
  59. package/dist/tools/referral/index.d.ts +44 -0
  60. package/dist/tools/referral/index.js +44 -0
  61. package/dist/tools/referral/schemas.d.ts +34 -0
  62. package/dist/tools/referral/schemas.js +52 -0
  63. package/dist/tools/reward/handlers.d.ts +110 -0
  64. package/dist/tools/reward/handlers.js +289 -0
  65. package/dist/tools/reward/index.d.ts +177 -0
  66. package/dist/tools/reward/index.js +93 -0
  67. package/dist/tools/reward/schemas.d.ts +116 -0
  68. package/dist/tools/reward/schemas.js +92 -0
  69. package/dist/tools/role.d.ts +6 -6
  70. package/dist/tools/role.js +12 -12
  71. package/dist/tools/segment/handlers.d.ts +87 -0
  72. package/dist/tools/segment/handlers.js +174 -0
  73. package/dist/tools/segment/index.d.ts +395 -0
  74. package/dist/tools/segment/index.js +88 -0
  75. package/dist/tools/segment/schemas.d.ts +337 -0
  76. package/dist/tools/segment/schemas.js +79 -0
  77. package/dist/tools/segment.d.ts +10 -10
  78. package/dist/tools/segment.js +55 -31
  79. package/dist/tools/store.d.ts +4 -4
  80. package/dist/tools/store.js +8 -8
  81. package/dist/tools/tierset.d.ts +10 -10
  82. package/dist/tools/tierset.js +69 -37
  83. package/dist/tools/transaction.d.ts +4 -4
  84. package/dist/tools/transaction.js +12 -12
  85. package/dist/tools/wallet-type.d.ts +221 -16
  86. package/dist/tools/wallet-type.js +248 -17
  87. package/dist/tools/webhook.d.ts +6 -6
  88. package/dist/tools/webhook.js +90 -31
  89. package/dist/types/schemas/achievement.d.ts +18 -18
  90. package/dist/types/schemas/campaign.d.ts +64 -184
  91. package/dist/types/schemas/campaign.js +2 -7
  92. package/dist/types/schemas/common.d.ts +5 -0
  93. package/dist/types/schemas/common.js +5 -0
  94. package/dist/types/schemas/member.d.ts +2 -2
  95. package/dist/types/schemas/reward.d.ts +94 -18
  96. package/dist/types/schemas/reward.js +8 -3
  97. package/dist/types/schemas/wallet-type.d.ts +306 -8
  98. package/dist/types/schemas/wallet-type.js +82 -1
  99. package/dist/utils/errors.js +32 -5
  100. package/dist/workflows/app-login-streak.d.ts +39 -0
  101. package/dist/workflows/app-login-streak.js +298 -0
  102. package/dist/workflows/early-arrival.d.ts +33 -0
  103. package/dist/workflows/early-arrival.js +148 -0
  104. package/dist/workflows/index.d.ts +101 -0
  105. package/dist/workflows/index.js +208 -0
  106. package/dist/workflows/match-attendance.d.ts +45 -0
  107. package/dist/workflows/match-attendance.js +308 -0
  108. package/dist/workflows/sportsbar-visit.d.ts +41 -0
  109. package/dist/workflows/sportsbar-visit.js +284 -0
  110. package/dist/workflows/vod-watching.d.ts +43 -0
  111. package/dist/workflows/vod-watching.js +326 -0
  112. package/package.json +8 -2
@@ -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. If not provided, uses the default store code from configuration."),
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. If not provided, uses the default store code from configuration."),
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. If not provided, uses the default store code from configuration."),
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. If not provided, uses the default store code from configuration."),
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, "openloyalty_export_create");
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, "openloyalty_export_list");
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, "openloyalty_export_get");
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, "openloyalty_export_download");
115
+ throw formatApiError(error, "ol_export_download");
116
116
  }
117
117
  }
118
118
  // Tool definitions
119
119
  export const exportToolDefinitions = [
120
120
  {
121
- name: "openloyalty_export_create",
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: "openloyalty_export_list",
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: "openloyalty_export_get",
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: "openloyalty_export_download",
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,
@@ -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: "openloyalty_import_create";
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: "openloyalty_import_list";
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: "openloyalty_import_get";
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;
@@ -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. If not provided, uses the default store code from configuration."),
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. If not provided, uses the default store code from configuration."),
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. If not provided, uses the default store code from configuration."),
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
- const fileName = input.fileName || "import.csv";
49
- // Create form data for multipart upload
50
- const formData = new FormData();
51
- const blob = new Blob([input.fileContent], { type: "text/csv" });
52
- formData.append("file", blob, fileName);
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
- "Content-Type": "multipart/form-data",
65
+ ...formData.getHeaders(),
58
66
  },
59
67
  });
60
68
  return response.data;
61
69
  }
62
70
  catch (error) {
63
- throw formatApiError(error, "openloyalty_import_create");
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, "openloyalty_import_list");
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, "openloyalty_import_get");
109
+ throw formatApiError(error, "ol_import_get");
102
110
  }
103
111
  }
104
112
  // Tool definitions
105
113
  export const importToolDefinitions = [
106
114
  {
107
- name: "openloyalty_import_create",
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: "openloyalty_import_list",
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: "openloyalty_import_get",
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,
@@ -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
+ }