@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
@@ -44,7 +44,7 @@ export declare function apiKeyDelete(input: {
44
44
  apiKeyId: string;
45
45
  }): Promise<void>;
46
46
  export declare const apiKeyToolDefinitions: readonly [{
47
- readonly name: "openloyalty_apikey_create";
47
+ readonly name: "ol_apikey_create";
48
48
  readonly title: "Create API Key";
49
49
  readonly description: "Create a new API key for an admin user. CRITICAL: The API token is ONLY returned at creation time. Store it securely immediately - it cannot be retrieved later. Returns apiKeyId, token, adminId, name, and expirationDate.";
50
50
  readonly readOnly: false;
@@ -55,7 +55,7 @@ export declare const apiKeyToolDefinitions: readonly [{
55
55
  };
56
56
  readonly handler: typeof apiKeyCreate;
57
57
  }, {
58
- readonly name: "openloyalty_apikey_list";
58
+ readonly name: "ol_apikey_list";
59
59
  readonly title: "List API Keys";
60
60
  readonly description: "List API keys for an admin user. Returns list of API keys with apiKeyId, adminId, name, and expirationDate. Note: tokens are not returned in list responses for security.";
61
61
  readonly readOnly: true;
@@ -66,7 +66,7 @@ export declare const apiKeyToolDefinitions: readonly [{
66
66
  };
67
67
  readonly handler: typeof apiKeyList;
68
68
  }, {
69
- readonly name: "openloyalty_apikey_delete";
69
+ readonly name: "ol_apikey_delete";
70
70
  readonly title: "Delete API Key (Permanent)";
71
71
  readonly description: "Delete an API key. Returns void on success (204 No Content). The API key will be immediately invalidated.";
72
72
  readonly readOnly: false;
@@ -28,7 +28,7 @@ export async function apiKeyCreate(input) {
28
28
  return response;
29
29
  }
30
30
  catch (error) {
31
- throw formatApiError(error, "openloyalty_apikey_create");
31
+ throw formatApiError(error, "ol_apikey_create");
32
32
  }
33
33
  }
34
34
  export async function apiKeyList(input) {
@@ -44,7 +44,7 @@ export async function apiKeyList(input) {
44
44
  return response;
45
45
  }
46
46
  catch (error) {
47
- throw formatApiError(error, "openloyalty_apikey_list");
47
+ throw formatApiError(error, "ol_apikey_list");
48
48
  }
49
49
  }
50
50
  export async function apiKeyDelete(input) {
@@ -52,13 +52,13 @@ export async function apiKeyDelete(input) {
52
52
  await apiDelete(`/admin/${input.adminId}/api-key/${input.apiKeyId}`);
53
53
  }
54
54
  catch (error) {
55
- throw formatApiError(error, "openloyalty_apikey_delete");
55
+ throw formatApiError(error, "ol_apikey_delete");
56
56
  }
57
57
  }
58
58
  // Tool definitions
59
59
  export const apiKeyToolDefinitions = [
60
60
  {
61
- name: "openloyalty_apikey_create",
61
+ name: "ol_apikey_create",
62
62
  title: "Create API Key",
63
63
  description: "Create a new API key for an admin user. CRITICAL: The API token is ONLY returned at creation time. Store it securely immediately - it cannot be retrieved later. Returns apiKeyId, token, adminId, name, and expirationDate.",
64
64
  readOnly: false,
@@ -66,7 +66,7 @@ export const apiKeyToolDefinitions = [
66
66
  handler: apiKeyCreate,
67
67
  },
68
68
  {
69
- name: "openloyalty_apikey_list",
69
+ name: "ol_apikey_list",
70
70
  title: "List API Keys",
71
71
  description: "List API keys for an admin user. Returns list of API keys with apiKeyId, adminId, name, and expirationDate. Note: tokens are not returned in list responses for security.",
72
72
  readOnly: true,
@@ -74,7 +74,7 @@ export const apiKeyToolDefinitions = [
74
74
  handler: apiKeyList,
75
75
  },
76
76
  {
77
- name: "openloyalty_apikey_delete",
77
+ name: "ol_apikey_delete",
78
78
  title: "Delete API Key (Permanent)",
79
79
  description: "Delete an API key. Returns void on success (204 No Content). The API key will be immediately invalidated.",
80
80
  readOnly: false,
@@ -80,7 +80,7 @@ export declare function auditExport(input: {
80
80
  exportId: string;
81
81
  }>;
82
82
  export declare const auditToolDefinitions: readonly [{
83
- readonly name: "openloyalty_audit_list";
83
+ readonly name: "ol_audit_list";
84
84
  readonly title: "List Audit Logs";
85
85
  readonly description: "List audit log entries with optional filtering. Returns paginated list of audit entries with auditLogId, eventType, entityType, entityId, username, timestamp, and details. Audit logs track all administrative actions. Use for compliance and troubleshooting.";
86
86
  readonly readOnly: true;
@@ -97,7 +97,7 @@ export declare const auditToolDefinitions: readonly [{
97
97
  };
98
98
  readonly handler: typeof auditList;
99
99
  }, {
100
- readonly name: "openloyalty_audit_export";
100
+ readonly name: "ol_audit_export";
101
101
  readonly title: "Export Audit Logs";
102
102
  readonly description: "Create an export of system logs. Returns exportId that can be used to track export status. The export will be processed asynchronously. Use date filters to scope the export range.";
103
103
  readonly readOnly: false;
@@ -47,7 +47,7 @@ export async function auditList(input) {
47
47
  return response;
48
48
  }
49
49
  catch (error) {
50
- throw formatApiError(error, "openloyalty_audit_list");
50
+ throw formatApiError(error, "ol_audit_list");
51
51
  }
52
52
  }
53
53
  export async function auditExport(input) {
@@ -70,13 +70,13 @@ export async function auditExport(input) {
70
70
  return response;
71
71
  }
72
72
  catch (error) {
73
- throw formatApiError(error, "openloyalty_audit_export");
73
+ throw formatApiError(error, "ol_audit_export");
74
74
  }
75
75
  }
76
76
  // Tool definitions
77
77
  export const auditToolDefinitions = [
78
78
  {
79
- name: "openloyalty_audit_list",
79
+ name: "ol_audit_list",
80
80
  title: "List Audit Logs",
81
81
  description: "List audit log entries with optional filtering. Returns paginated list of audit entries with auditLogId, eventType, entityType, entityId, username, timestamp, and details. Audit logs track all administrative actions. Use for compliance and troubleshooting.",
82
82
  readOnly: true,
@@ -84,7 +84,7 @@ export const auditToolDefinitions = [
84
84
  handler: auditList,
85
85
  },
86
86
  {
87
- name: "openloyalty_audit_export",
87
+ name: "ol_audit_export",
88
88
  title: "Export Audit Logs",
89
89
  description: "Create an export of system logs. Returns exportId that can be used to track export status. The export will be processed asynchronously. Use date filters to scope the export range.",
90
90
  readOnly: false,
@@ -14,7 +14,7 @@ export declare const BadgeGetInputSchema: {
14
14
  export declare const BadgeUpdateInputSchema: {
15
15
  storeCode: z.ZodOptional<z.ZodString>;
16
16
  badgeTypeId: z.ZodString;
17
- name: z.ZodOptional<z.ZodString>;
17
+ name: z.ZodString;
18
18
  translations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
19
19
  name: z.ZodString;
20
20
  description: z.ZodOptional<z.ZodString>;
@@ -80,7 +80,7 @@ export declare function badgeGetMemberBadges(input: {
80
80
  };
81
81
  }>;
82
82
  export declare const badgeToolDefinitions: readonly [{
83
- readonly name: "openloyalty_badge_list";
83
+ readonly name: "ol_badge_list";
84
84
  readonly title: "List Badges";
85
85
  readonly description: "List badge types. Badges are visual rewards linked to achievements. When a member completes an achievement with a badgeTypeId, they earn that badge. Use for displaying available badges.";
86
86
  readonly readOnly: true;
@@ -93,7 +93,7 @@ export declare const badgeToolDefinitions: readonly [{
93
93
  };
94
94
  readonly handler: typeof badgeList;
95
95
  }, {
96
- readonly name: "openloyalty_badge_get";
96
+ readonly name: "ol_badge_get";
97
97
  readonly title: "Get Badge Details";
98
98
  readonly description: "Get badge type details including name, image URL, and linked achievements count.";
99
99
  readonly readOnly: true;
@@ -103,14 +103,14 @@ export declare const badgeToolDefinitions: readonly [{
103
103
  };
104
104
  readonly handler: typeof badgeGet;
105
105
  }, {
106
- readonly name: "openloyalty_badge_update";
106
+ readonly name: "ol_badge_update";
107
107
  readonly title: "Update Badge";
108
108
  readonly description: "Update badge type configuration. Badge types are created automatically when referenced by achievements. Use this to update name, image, or translations.";
109
109
  readonly readOnly: false;
110
110
  readonly inputSchema: {
111
111
  storeCode: z.ZodOptional<z.ZodString>;
112
112
  badgeTypeId: z.ZodString;
113
- name: z.ZodOptional<z.ZodString>;
113
+ name: z.ZodString;
114
114
  translations: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
115
115
  name: z.ZodString;
116
116
  description: z.ZodOptional<z.ZodString>;
@@ -126,7 +126,7 @@ export declare const badgeToolDefinitions: readonly [{
126
126
  };
127
127
  readonly handler: typeof badgeUpdate;
128
128
  }, {
129
- readonly name: "openloyalty_badge_get_member_badges";
129
+ readonly name: "ol_badge_get_member_badges";
130
130
  readonly title: "Get Member Badges";
131
131
  readonly description: "Get badges earned by a member. Returns each badge with completedCount showing how many times it was earned. Use for displaying member's badge collection.";
132
132
  readonly readOnly: true;
@@ -4,29 +4,29 @@ import { formatApiError } from "../utils/errors.js";
4
4
  import { getStoreCode } from "../config.js";
5
5
  // Input Schemas
6
6
  export const BadgeListInputSchema = {
7
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
7
+ 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."),
8
8
  page: z.number().optional().describe("Page number (default: 1)."),
9
9
  perPage: z.number().optional().describe("Items per page (default: 10)."),
10
10
  name: z.string().optional().describe("Filter by badge name."),
11
11
  badgeTypeId: z.string().optional().describe("Filter by specific badge type ID."),
12
12
  };
13
13
  export const BadgeGetInputSchema = {
14
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
14
+ 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."),
15
15
  badgeTypeId: z.string().describe("The badge type ID (UUID) to retrieve."),
16
16
  };
17
17
  export const BadgeUpdateInputSchema = {
18
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
18
+ 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."),
19
19
  badgeTypeId: z.string().describe("The badge type ID (UUID) to update."),
20
- name: z.string().optional().describe("Badge name."),
20
+ name: z.string().describe("Badge name (REQUIRED). API requires name as a direct field."),
21
21
  translations: z.record(z.string(), z.object({
22
22
  name: z.string(),
23
23
  description: z.string().optional(),
24
- })).optional().describe("Badge translations."),
24
+ })).optional().describe("Badge translations (for convenience - will extract name from translations.en.name if name not provided directly)."),
25
25
  imageUrl: z.string().optional().describe("URL to badge image."),
26
26
  active: z.boolean().optional().describe("Whether badge type is active."),
27
27
  };
28
28
  export const BadgeGetMemberBadgesInputSchema = {
29
- storeCode: z.string().optional().describe("Store code. If not provided, uses the default store code from configuration."),
29
+ 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."),
30
30
  memberId: z.string().describe("The member ID (UUID)."),
31
31
  page: z.number().optional().describe("Page number (default: 1)."),
32
32
  perPage: z.number().optional().describe("Items per page (default: 10)."),
@@ -65,7 +65,7 @@ export async function badgeList(input) {
65
65
  };
66
66
  }
67
67
  catch (error) {
68
- throw formatApiError(error, "openloyalty_badge_list");
68
+ throw formatApiError(error, "ol_badge_list");
69
69
  }
70
70
  }
71
71
  export async function badgeGet(input) {
@@ -75,16 +75,21 @@ export async function badgeGet(input) {
75
75
  return response;
76
76
  }
77
77
  catch (error) {
78
- throw formatApiError(error, "openloyalty_badge_get");
78
+ throw formatApiError(error, "ol_badge_get");
79
79
  }
80
80
  }
81
81
  export async function badgeUpdate(input) {
82
82
  const storeCode = getStoreCode(input.storeCode);
83
83
  const badgePayload = {};
84
- if (input.name !== undefined)
85
- badgePayload.name = input.name;
86
- if (input.translations)
87
- badgePayload.translations = input.translations;
84
+ // API requires name as direct field, not nested in translations
85
+ // Extract from translations.en.name if name not provided directly
86
+ let badgeName = input.name;
87
+ if (!badgeName && input.translations?.en?.name) {
88
+ badgeName = input.translations.en.name;
89
+ }
90
+ if (badgeName !== undefined)
91
+ badgePayload.name = badgeName;
92
+ // Note: API does not accept nested translations - only direct fields
88
93
  if (input.imageUrl !== undefined)
89
94
  badgePayload.imageUrl = input.imageUrl;
90
95
  if (input.active !== undefined)
@@ -94,7 +99,7 @@ export async function badgeUpdate(input) {
94
99
  await apiPut(`/${storeCode}/badge-type/${input.badgeTypeId}`, { badgeType: badgePayload });
95
100
  }
96
101
  catch (error) {
97
- throw formatApiError(error, "openloyalty_badge_update");
102
+ throw formatApiError(error, "ol_badge_update");
98
103
  }
99
104
  }
100
105
  export async function badgeGetMemberBadges(input) {
@@ -129,13 +134,13 @@ export async function badgeGetMemberBadges(input) {
129
134
  };
130
135
  }
131
136
  catch (error) {
132
- throw formatApiError(error, "openloyalty_badge_get_member_badges");
137
+ throw formatApiError(error, "ol_badge_get_member_badges");
133
138
  }
134
139
  }
135
140
  // Tool definitions
136
141
  export const badgeToolDefinitions = [
137
142
  {
138
- name: "openloyalty_badge_list",
143
+ name: "ol_badge_list",
139
144
  title: "List Badges",
140
145
  description: "List badge types. Badges are visual rewards linked to achievements. When a member completes an achievement with a badgeTypeId, they earn that badge. Use for displaying available badges.",
141
146
  readOnly: true,
@@ -143,7 +148,7 @@ export const badgeToolDefinitions = [
143
148
  handler: badgeList,
144
149
  },
145
150
  {
146
- name: "openloyalty_badge_get",
151
+ name: "ol_badge_get",
147
152
  title: "Get Badge Details",
148
153
  description: "Get badge type details including name, image URL, and linked achievements count.",
149
154
  readOnly: true,
@@ -151,7 +156,7 @@ export const badgeToolDefinitions = [
151
156
  handler: badgeGet,
152
157
  },
153
158
  {
154
- name: "openloyalty_badge_update",
159
+ name: "ol_badge_update",
155
160
  title: "Update Badge",
156
161
  description: "Update badge type configuration. Badge types are created automatically when referenced by achievements. Use this to update name, image, or translations.",
157
162
  readOnly: false,
@@ -159,7 +164,7 @@ export const badgeToolDefinitions = [
159
164
  handler: badgeUpdate,
160
165
  },
161
166
  {
162
- name: "openloyalty_badge_get_member_badges",
167
+ name: "ol_badge_get_member_badges",
163
168
  title: "Get Member Badges",
164
169
  description: "Get badges earned by a member. Returns each badge with completedCount showing how many times it was earned. Use for displaying member's badge collection.",
165
170
  readOnly: true,
@@ -0,0 +1,42 @@
1
+ import { CampaignListItem } from "../../types/schemas/campaign.js";
2
+ import { SimulatedEffect, CampaignSimulateInput, CampaignCreateInput } from "./types.js";
3
+ export declare function campaignList(input: {
4
+ storeCode?: string;
5
+ page?: number;
6
+ perPage?: number;
7
+ active?: boolean;
8
+ type?: string;
9
+ trigger?: string;
10
+ }): Promise<{
11
+ campaigns: CampaignListItem[];
12
+ total: {
13
+ all?: number;
14
+ filtered?: number;
15
+ };
16
+ }>;
17
+ export declare function campaignGet(input: {
18
+ storeCode?: string;
19
+ campaignId: string;
20
+ }): Promise<Record<string, unknown>>;
21
+ export declare function campaignCreate(input: CampaignCreateInput): Promise<{
22
+ campaignId: string;
23
+ }>;
24
+ export declare function campaignUpdate(input: Record<string, unknown>): Promise<void>;
25
+ export declare function campaignPatch(input: {
26
+ storeCode?: string;
27
+ campaignId: string;
28
+ active?: boolean;
29
+ displayOrder?: number;
30
+ }): Promise<void>;
31
+ export declare function campaignDelete(input: {
32
+ storeCode?: string;
33
+ campaignId: string;
34
+ }): Promise<void>;
35
+ export declare function campaignSimulate(input: CampaignSimulateInput): Promise<{
36
+ simulatedEffects: SimulatedEffect[];
37
+ evaluationWarnings?: Array<{
38
+ campaignId: string;
39
+ message: string;
40
+ }>;
41
+ simulatedMember?: Record<string, unknown>;
42
+ }>;
@@ -0,0 +1,223 @@
1
+ import { apiGet, apiPost, apiPut, apiPatch, apiDelete } from "../../client/http.js";
2
+ import { formatApiError } from "../../utils/errors.js";
3
+ import { getStoreCode } from "../../config.js";
4
+ // Core CRUD handlers
5
+ export async function campaignList(input) {
6
+ const storeCode = getStoreCode(input.storeCode);
7
+ const params = new URLSearchParams();
8
+ if (input.page)
9
+ params.append("_page", String(input.page));
10
+ if (input.perPage)
11
+ params.append("_itemsOnPage", String(input.perPage));
12
+ if (input.active !== undefined)
13
+ params.append("active", String(input.active));
14
+ if (input.type)
15
+ params.append("type", input.type);
16
+ if (input.trigger)
17
+ params.append("trigger", input.trigger);
18
+ const queryString = params.toString();
19
+ const url = `/${storeCode}/campaign${queryString ? `?${queryString}` : ""}`;
20
+ try {
21
+ const response = await apiGet(url);
22
+ const campaigns = (response.items || []).map((item) => {
23
+ const campaign = item;
24
+ const translations = campaign.translations;
25
+ let name = "";
26
+ if (Array.isArray(translations)) {
27
+ const enTranslation = translations.find((t) => t.locale === "en" || t.locale?.startsWith("en"));
28
+ name = enTranslation?.name || translations[0]?.name || campaign.name || "";
29
+ }
30
+ else if (translations && typeof translations === "object") {
31
+ name = translations.en?.name || campaign.name || "";
32
+ }
33
+ else {
34
+ name = campaign.name || "";
35
+ }
36
+ return {
37
+ campaignId: campaign.campaignId,
38
+ name,
39
+ type: campaign.type,
40
+ trigger: campaign.trigger,
41
+ active: (campaign.active ?? false),
42
+ displayOrder: campaign.displayOrder,
43
+ };
44
+ });
45
+ const total = response.total || {};
46
+ return {
47
+ campaigns,
48
+ total: {
49
+ all: typeof total.all === "number" ? total.all : undefined,
50
+ filtered: typeof total.filtered === "number" ? total.filtered : undefined,
51
+ },
52
+ };
53
+ }
54
+ catch (error) {
55
+ throw formatApiError(error, "ol_campaign_list");
56
+ }
57
+ }
58
+ export async function campaignGet(input) {
59
+ const storeCode = getStoreCode(input.storeCode);
60
+ try {
61
+ const response = await apiGet(`/${storeCode}/campaign/${input.campaignId}`);
62
+ return response;
63
+ }
64
+ catch (error) {
65
+ throw formatApiError(error, "ol_campaign_get");
66
+ }
67
+ }
68
+ export async function campaignCreate(input) {
69
+ const storeCode = getStoreCode(input.storeCode);
70
+ const campaignPayload = {
71
+ type: input.type,
72
+ trigger: input.trigger,
73
+ translations: input.translations,
74
+ activity: input.activity,
75
+ rules: input.rules,
76
+ };
77
+ if (input.visibility)
78
+ campaignPayload.visibility = input.visibility;
79
+ if (input.audience)
80
+ campaignPayload.audience = input.audience;
81
+ if (input.limits)
82
+ campaignPayload.limits = input.limits;
83
+ if (input.active !== undefined)
84
+ campaignPayload.active = input.active;
85
+ if (input.displayOrder !== undefined)
86
+ campaignPayload.displayOrder = input.displayOrder;
87
+ if (input.labels)
88
+ campaignPayload.labels = input.labels;
89
+ if (input.event)
90
+ campaignPayload.event = input.event;
91
+ if (input.achievementId)
92
+ campaignPayload.achievementId = input.achievementId;
93
+ try {
94
+ const response = await apiPost(`/${storeCode}/campaign`, { campaign: campaignPayload });
95
+ return { campaignId: response.campaignId };
96
+ }
97
+ catch (error) {
98
+ throw formatApiError(error, "ol_campaign_create");
99
+ }
100
+ }
101
+ export async function campaignUpdate(input) {
102
+ const storeCode = getStoreCode(input.storeCode);
103
+ const campaignId = input.campaignId;
104
+ const { storeCode: _sc, campaignId: _cid, ...campaignPayload } = input;
105
+ try {
106
+ await apiPut(`/${storeCode}/campaign/${campaignId}`, { campaign: campaignPayload });
107
+ }
108
+ catch (error) {
109
+ throw formatApiError(error, "ol_campaign_update");
110
+ }
111
+ }
112
+ export async function campaignPatch(input) {
113
+ const storeCode = getStoreCode(input.storeCode);
114
+ const patchPayload = {};
115
+ if (input.active !== undefined)
116
+ patchPayload.active = input.active;
117
+ if (input.displayOrder !== undefined)
118
+ patchPayload.displayOrder = input.displayOrder;
119
+ try {
120
+ await apiPatch(`/${storeCode}/campaign/${input.campaignId}`, { campaign: patchPayload });
121
+ }
122
+ catch (error) {
123
+ throw formatApiError(error, "ol_campaign_patch");
124
+ }
125
+ }
126
+ export async function campaignDelete(input) {
127
+ const storeCode = getStoreCode(input.storeCode);
128
+ try {
129
+ await apiDelete(`/${storeCode}/campaign/${input.campaignId}`);
130
+ }
131
+ catch (error) {
132
+ throw formatApiError(error, "ol_campaign_delete");
133
+ }
134
+ }
135
+ // Simulation handler
136
+ export async function campaignSimulate(input) {
137
+ const storeCode = getStoreCode(input.storeCode);
138
+ const simulatePayload = {
139
+ trigger: input.trigger,
140
+ customer: {},
141
+ };
142
+ const customer = {};
143
+ if (input.customer.customerId)
144
+ customer.id = input.customer.customerId;
145
+ if (input.customer.id)
146
+ customer.id = input.customer.id;
147
+ if (input.customer.email)
148
+ customer.email = input.customer.email;
149
+ if (input.customer.loyaltyCardNumber)
150
+ customer.loyaltyCardNumber = input.customer.loyaltyCardNumber;
151
+ if (input.customer.phone)
152
+ customer.phone = input.customer.phone;
153
+ if (input.customer.firstName)
154
+ customer.firstName = input.customer.firstName;
155
+ if (input.customer.lastName)
156
+ customer.lastName = input.customer.lastName;
157
+ simulatePayload.customer = customer;
158
+ if (input.transaction) {
159
+ const transaction = {};
160
+ if (input.transaction.grossValue !== undefined)
161
+ transaction.grossValue = input.transaction.grossValue;
162
+ if (input.transaction.documentNumber)
163
+ transaction.documentNumber = input.transaction.documentNumber;
164
+ if (input.transaction.purchasedAt)
165
+ transaction.purchasedAt = input.transaction.purchasedAt;
166
+ if (input.transaction.documentType)
167
+ transaction.documentType = input.transaction.documentType;
168
+ if (input.transaction.purchasePlace)
169
+ transaction.purchasePlace = input.transaction.purchasePlace;
170
+ if (input.transaction.items)
171
+ transaction.items = input.transaction.items;
172
+ if (input.transaction.labels)
173
+ transaction.labels = input.transaction.labels;
174
+ simulatePayload.transaction = transaction;
175
+ }
176
+ if (input.customEvent) {
177
+ simulatePayload.event = input.customEvent.eventCode;
178
+ if (input.customEvent.attributes) {
179
+ simulatePayload.eventAttributes = input.customEvent.attributes;
180
+ }
181
+ }
182
+ if (input.referrer) {
183
+ const referrer = {};
184
+ if (input.referrer.id)
185
+ referrer.id = input.referrer.id;
186
+ if (input.referrer.email)
187
+ referrer.email = input.referrer.email;
188
+ if (input.referrer.loyaltyCardNumber)
189
+ referrer.loyaltyCardNumber = input.referrer.loyaltyCardNumber;
190
+ simulatePayload.referrer = referrer;
191
+ }
192
+ try {
193
+ const response = await apiPost(`/${storeCode}/campaign/simulate`, { simulate: simulatePayload });
194
+ const effectsByCampaign = new Map();
195
+ for (const effect of response.effects || []) {
196
+ const campaignId = effect.campaign?.campaignId || "unknown";
197
+ const campaignName = effect.campaign?.name || undefined;
198
+ if (!effectsByCampaign.has(campaignId)) {
199
+ effectsByCampaign.set(campaignId, {
200
+ campaignId,
201
+ campaignName,
202
+ effects: [],
203
+ });
204
+ }
205
+ const campaignEffect = effectsByCampaign.get(campaignId);
206
+ campaignEffect.effects.push({
207
+ type: effect.type,
208
+ target: effect.target,
209
+ points: effect.points,
210
+ wallet: effect.wallet,
211
+ rewardId: effect.rewardId,
212
+ });
213
+ }
214
+ return {
215
+ simulatedEffects: Array.from(effectsByCampaign.values()),
216
+ evaluationWarnings: response.evaluationWarnings,
217
+ simulatedMember: response.simulatedMember,
218
+ };
219
+ }
220
+ catch (error) {
221
+ throw formatApiError(error, "ol_campaign_simulate");
222
+ }
223
+ }