@open-loyalty/mcp-server 1.0.3 → 1.3.1

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 (142) 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.d.ts +5 -0
  5. package/dist/client/http.js +62 -3
  6. package/dist/config.d.ts +6 -5
  7. package/dist/config.js +15 -11
  8. package/dist/http.js +170 -65
  9. package/dist/instructions.d.ts +5 -0
  10. package/dist/instructions.js +420 -0
  11. package/dist/prompts/fan-engagement-setup.d.ts +107 -0
  12. package/dist/prompts/fan-engagement-setup.js +492 -0
  13. package/dist/server.d.ts +1 -1
  14. package/dist/server.js +68 -278
  15. package/dist/tools/achievement/handlers.d.ts +117 -0
  16. package/dist/tools/achievement/handlers.js +161 -0
  17. package/dist/tools/achievement/index.d.ts +479 -0
  18. package/dist/tools/achievement/index.js +74 -0
  19. package/dist/tools/achievement/schemas.d.ts +433 -0
  20. package/dist/tools/achievement/schemas.js +142 -0
  21. package/dist/tools/achievement.d.ts +155 -121
  22. package/dist/tools/achievement.js +82 -39
  23. package/dist/tools/admin.d.ts +18 -6
  24. package/dist/tools/admin.js +24 -12
  25. package/dist/tools/analytics.d.ts +29 -11
  26. package/dist/tools/analytics.js +58 -48
  27. package/dist/tools/apikey.d.ts +10 -3
  28. package/dist/tools/apikey.js +13 -6
  29. package/dist/tools/audit.d.ts +6 -2
  30. package/dist/tools/audit.js +8 -4
  31. package/dist/tools/badge.d.ts +14 -6
  32. package/dist/tools/badge.js +36 -27
  33. package/dist/tools/campaign/handlers.d.ts +42 -0
  34. package/dist/tools/campaign/handlers.js +223 -0
  35. package/dist/tools/campaign/index.d.ts +783 -0
  36. package/dist/tools/campaign/index.js +112 -0
  37. package/dist/tools/campaign/member-handlers.d.ts +60 -0
  38. package/dist/tools/campaign/member-handlers.js +159 -0
  39. package/dist/tools/campaign/schemas.d.ts +704 -0
  40. package/dist/tools/campaign/schemas.js +259 -0
  41. package/dist/tools/campaign/types.d.ts +161 -0
  42. package/dist/tools/campaign/types.js +2 -0
  43. package/dist/tools/campaign.d.ts +41 -16
  44. package/dist/tools/campaign.js +38 -25
  45. package/dist/tools/custom-event.d.ts +315 -0
  46. package/dist/tools/custom-event.js +270 -0
  47. package/dist/tools/export.d.ts +12 -4
  48. package/dist/tools/export.js +25 -20
  49. package/dist/tools/import.d.ts +9 -3
  50. package/dist/tools/import.js +33 -21
  51. package/dist/tools/index.d.ts +3 -11
  52. package/dist/tools/index.js +17 -475
  53. package/dist/tools/member/handlers.d.ts +111 -0
  54. package/dist/tools/member/handlers.js +206 -0
  55. package/dist/tools/member/index.d.ts +169 -0
  56. package/dist/tools/member/index.js +92 -0
  57. package/dist/tools/member/schemas.d.ts +89 -0
  58. package/dist/tools/member/schemas.js +65 -0
  59. package/dist/tools/member.d.ts +21 -0
  60. package/dist/tools/member.js +56 -62
  61. package/dist/tools/points.d.ts +19 -6
  62. package/dist/tools/points.js +51 -49
  63. package/dist/tools/referral/handlers.d.ts +47 -0
  64. package/dist/tools/referral/handlers.js +115 -0
  65. package/dist/tools/referral/index.d.ts +44 -0
  66. package/dist/tools/referral/index.js +44 -0
  67. package/dist/tools/referral/schemas.d.ts +34 -0
  68. package/dist/tools/referral/schemas.js +52 -0
  69. package/dist/tools/reward/handlers.d.ts +110 -0
  70. package/dist/tools/reward/handlers.js +289 -0
  71. package/dist/tools/reward/index.d.ts +177 -0
  72. package/dist/tools/reward/index.js +90 -0
  73. package/dist/tools/reward/schemas.d.ts +116 -0
  74. package/dist/tools/reward/schemas.js +91 -0
  75. package/dist/tools/reward.d.ts +18 -0
  76. package/dist/tools/reward.js +56 -66
  77. package/dist/tools/role.d.ts +26 -7
  78. package/dist/tools/role.js +25 -12
  79. package/dist/tools/segment/handlers.d.ts +87 -0
  80. package/dist/tools/segment/handlers.js +174 -0
  81. package/dist/tools/segment/index.d.ts +395 -0
  82. package/dist/tools/segment/index.js +87 -0
  83. package/dist/tools/segment/schemas.d.ts +337 -0
  84. package/dist/tools/segment/schemas.js +79 -0
  85. package/dist/tools/segment.d.ts +29 -10
  86. package/dist/tools/segment.js +84 -50
  87. package/dist/tools/store.d.ts +12 -4
  88. package/dist/tools/store.js +16 -8
  89. package/dist/tools/tierset.d.ts +19 -7
  90. package/dist/tools/tierset.js +44 -35
  91. package/dist/tools/transaction.d.ts +16 -8
  92. package/dist/tools/transaction.js +25 -21
  93. package/dist/tools/wallet-type.d.ts +7 -3
  94. package/dist/tools/wallet-type.js +14 -12
  95. package/dist/tools/webhook.d.ts +23 -10
  96. package/dist/tools/webhook.js +135 -33
  97. package/dist/types/schemas/achievement.d.ts +12 -309
  98. package/dist/types/schemas/achievement.js +0 -13
  99. package/dist/types/schemas/admin.d.ts +10 -97
  100. package/dist/types/schemas/admin.js +0 -38
  101. package/dist/types/schemas/badge.d.ts +0 -37
  102. package/dist/types/schemas/badge.js +0 -11
  103. package/dist/types/schemas/campaign.d.ts +64 -832
  104. package/dist/types/schemas/campaign.js +2 -25
  105. package/dist/types/schemas/common.d.ts +5 -0
  106. package/dist/types/schemas/common.js +5 -0
  107. package/dist/types/schemas/export.d.ts +0 -17
  108. package/dist/types/schemas/export.js +0 -7
  109. package/dist/types/schemas/member.d.ts +37 -176
  110. package/dist/types/schemas/member.js +0 -27
  111. package/dist/types/schemas/points.d.ts +0 -63
  112. package/dist/types/schemas/points.js +0 -22
  113. package/dist/types/schemas/reward.d.ts +71 -68
  114. package/dist/types/schemas/reward.js +8 -28
  115. package/dist/types/schemas/role.d.ts +0 -100
  116. package/dist/types/schemas/role.js +0 -29
  117. package/dist/types/schemas/segment.d.ts +0 -58
  118. package/dist/types/schemas/segment.js +0 -17
  119. package/dist/types/schemas/tierset.d.ts +0 -176
  120. package/dist/types/schemas/tierset.js +0 -27
  121. package/dist/types/schemas/transaction.d.ts +23 -254
  122. package/dist/types/schemas/transaction.js +0 -7
  123. package/dist/types/schemas/wallet-type.d.ts +8 -8
  124. package/dist/types/schemas/wallet-type.js +1 -1
  125. package/dist/types/schemas/webhook.d.ts +0 -58
  126. package/dist/types/schemas/webhook.js +0 -12
  127. package/dist/utils/errors.js +30 -3
  128. package/dist/utils/payload.d.ts +12 -0
  129. package/dist/utils/payload.js +14 -0
  130. package/dist/workflows/app-login-streak.d.ts +39 -0
  131. package/dist/workflows/app-login-streak.js +298 -0
  132. package/dist/workflows/early-arrival.d.ts +33 -0
  133. package/dist/workflows/early-arrival.js +148 -0
  134. package/dist/workflows/index.d.ts +101 -0
  135. package/dist/workflows/index.js +208 -0
  136. package/dist/workflows/match-attendance.d.ts +45 -0
  137. package/dist/workflows/match-attendance.js +308 -0
  138. package/dist/workflows/sportsbar-visit.d.ts +41 -0
  139. package/dist/workflows/sportsbar-visit.js +284 -0
  140. package/dist/workflows/vod-watching.d.ts +43 -0
  141. package/dist/workflows/vod-watching.js +326 -0
  142. package/package.json +10 -2
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Early Arrival Workflow
3
+ *
4
+ * Creates a campaign to reward fans who arrive early to matches.
5
+ * Uses a custom event with minutes_before attribute for conditional rewards.
6
+ */
7
+ import { campaignCreate } from "../tools/campaign/handlers.js";
8
+ import { formatOLDate, DEFAULTS } from "../prompts/fan-engagement-setup.js";
9
+ // ============================================================================
10
+ // Workflow Implementation
11
+ // ============================================================================
12
+ /**
13
+ * Execute the early arrival workflow
14
+ */
15
+ export async function executeEarlyArrivalWorkflow(config = {}) {
16
+ const result = {
17
+ success: false,
18
+ errors: [],
19
+ summary: "",
20
+ };
21
+ // Merge with defaults
22
+ const cfg = {
23
+ minutesBefore: config.minutesBefore ?? DEFAULTS.earlyArrival.minutesBefore,
24
+ coinsPerArrival: config.coinsPerArrival ?? DEFAULTS.earlyArrival.coinsPerArrival,
25
+ limitPerMatch: config.limitPerMatch ?? DEFAULTS.earlyArrival.limitPerMatch,
26
+ seasonStart: config.seasonStart ?? DEFAULTS.seasonDates.start,
27
+ seasonEnd: config.seasonEnd ?? DEFAULTS.seasonDates.end,
28
+ };
29
+ try {
30
+ // Create the early arrival campaign with condition
31
+ const campaignResult = await createEarlyArrivalCampaign(cfg);
32
+ if (campaignResult.error) {
33
+ result.errors.push(campaignResult.error);
34
+ }
35
+ else {
36
+ result.campaignId = campaignResult.campaignId;
37
+ result.success = true;
38
+ }
39
+ // Build summary
40
+ result.summary = buildSummary(cfg, result);
41
+ }
42
+ catch (error) {
43
+ result.errors.push(`Workflow error: ${error instanceof Error ? error.message : String(error)}`);
44
+ }
45
+ return result;
46
+ }
47
+ // ============================================================================
48
+ // Helper Functions
49
+ // ============================================================================
50
+ async function createEarlyArrivalCampaign(cfg) {
51
+ try {
52
+ /**
53
+ * The early_arrival custom event expects:
54
+ * {
55
+ * "event": "early_arrival",
56
+ * "attributes": {
57
+ * "minutes_before": 75 // how many minutes before kickoff they arrived
58
+ * }
59
+ * }
60
+ *
61
+ * The campaign condition checks if minutes_before >= threshold
62
+ */
63
+ const response = await campaignCreate({
64
+ type: "direct",
65
+ trigger: "custom_event",
66
+ event: "early_arrival",
67
+ translations: {
68
+ en: {
69
+ name: "Early Arrival Bonus",
70
+ description: `Earn ${cfg.coinsPerArrival} bonus coins for arriving at least ${cfg.minutesBefore} minutes before kickoff`,
71
+ },
72
+ },
73
+ activity: {
74
+ startsAt: formatOLDate(cfg.seasonStart),
75
+ endsAt: formatOLDate(cfg.seasonEnd),
76
+ },
77
+ rules: [
78
+ {
79
+ name: "Award coins for early arrival",
80
+ effects: [
81
+ {
82
+ effect: "give_points",
83
+ pointsRule: { fixedValue: cfg.coinsPerArrival },
84
+ },
85
+ ],
86
+ conditions: [
87
+ {
88
+ operator: "gte",
89
+ attribute: "event.minutes_before",
90
+ data: { value: cfg.minutesBefore },
91
+ },
92
+ ],
93
+ },
94
+ ],
95
+ limits: {
96
+ executionsPerMember: {
97
+ value: cfg.limitPerMatch,
98
+ interval: { type: "days", value: 1 },
99
+ },
100
+ },
101
+ active: true,
102
+ });
103
+ return { campaignId: response.campaignId };
104
+ }
105
+ catch (error) {
106
+ return {
107
+ error: `Failed to create early arrival campaign: ${error instanceof Error ? error.message : String(error)}`,
108
+ };
109
+ }
110
+ }
111
+ function buildSummary(cfg, result) {
112
+ const lines = [];
113
+ if (result.success && result.campaignId) {
114
+ lines.push(`Early arrival campaign created successfully!`);
115
+ lines.push(`\nReward: ${cfg.coinsPerArrival} coins`);
116
+ lines.push(`Requirement: Arrive at least ${cfg.minutesBefore} minutes before kickoff`);
117
+ lines.push(`Limit: ${cfg.limitPerMatch} bonus per match day`);
118
+ lines.push(`\nSeason: ${cfg.seasonStart} to ${cfg.seasonEnd}`);
119
+ lines.push(`\nCustom event to trigger reward:`);
120
+ lines.push(` Event: early_arrival`);
121
+ lines.push(` Required attribute: minutes_before (number)`);
122
+ lines.push(`\nExample event payload:`);
123
+ lines.push(`{`);
124
+ lines.push(` "event": "early_arrival",`);
125
+ lines.push(` "attributes": {`);
126
+ lines.push(` "minutes_before": 75`);
127
+ lines.push(` }`);
128
+ lines.push(`}`);
129
+ }
130
+ else {
131
+ lines.push(`Early arrival campaign setup failed.`);
132
+ }
133
+ if (result.errors.length > 0) {
134
+ lines.push(`\nErrors:`);
135
+ for (const error of result.errors) {
136
+ lines.push(`- ${error}`);
137
+ }
138
+ }
139
+ return lines.join("\n");
140
+ }
141
+ // ============================================================================
142
+ // Exports
143
+ // ============================================================================
144
+ export const earlyArrivalWorkflow = {
145
+ id: "early-arrival",
146
+ name: "Early Arrival Campaign",
147
+ execute: executeEarlyArrivalWorkflow,
148
+ };
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Fan Engagement Workflows
3
+ *
4
+ * Orchestrated workflows for setting up complete fan engagement campaigns.
5
+ * These combine multiple Open Loyalty tools into guided, step-by-step flows.
6
+ */
7
+ import { matchAttendanceWorkflow, executeMatchAttendanceWorkflow, type MatchAttendanceConfig, type MatchAttendanceResult } from "./match-attendance.js";
8
+ import { earlyArrivalWorkflow, executeEarlyArrivalWorkflow, type EarlyArrivalConfig, type EarlyArrivalResult } from "./early-arrival.js";
9
+ import { sportsbarVisitWorkflow, executeSportsbarVisitWorkflow, type SportsbarVisitConfig, type SportsbarVisitResult } from "./sportsbar-visit.js";
10
+ import { vodWatchingWorkflow, executeVodWatchingWorkflow, type VodWatchingConfig, type VodWatchingResult } from "./vod-watching.js";
11
+ import { appLoginStreakWorkflow, executeAppLoginStreakWorkflow, type AppLoginStreakConfig, type AppLoginStreakResult } from "./app-login-streak.js";
12
+ export { matchAttendanceWorkflow, executeMatchAttendanceWorkflow, type MatchAttendanceConfig, type MatchAttendanceResult, };
13
+ export { earlyArrivalWorkflow, executeEarlyArrivalWorkflow, type EarlyArrivalConfig, type EarlyArrivalResult, };
14
+ export { sportsbarVisitWorkflow, executeSportsbarVisitWorkflow, type SportsbarVisitConfig, type SportsbarVisitResult, };
15
+ export { vodWatchingWorkflow, executeVodWatchingWorkflow, type VodWatchingConfig, type VodWatchingResult, };
16
+ export { appLoginStreakWorkflow, executeAppLoginStreakWorkflow, type AppLoginStreakConfig, type AppLoginStreakResult, };
17
+ export { DEFAULTS, ALL_WORKFLOWS, findMatchingWorkflow, getWorkflowById, parseCommaSeparated, parseMilestones, formatOLDate, AGENT_PROMPTS, type WorkflowDefinition, type WorkflowQuestion, type WorkflowStep, } from "../prompts/fan-engagement-setup.js";
18
+ export interface FanEngagementConfig {
19
+ /** Match attendance configuration */
20
+ matchAttendance?: Partial<MatchAttendanceConfig>;
21
+ /** Early arrival configuration */
22
+ earlyArrival?: Partial<EarlyArrivalConfig>;
23
+ /** Sports bar visit configuration */
24
+ sportsbarVisit?: Partial<SportsbarVisitConfig>;
25
+ /** VOD watching configuration */
26
+ vodWatching?: Partial<VodWatchingConfig>;
27
+ /** App login streak configuration */
28
+ appLoginStreak?: Partial<AppLoginStreakConfig>;
29
+ /** Which workflows to execute (default: all) */
30
+ enabledWorkflows?: ("match-attendance" | "early-arrival" | "sportsbar-visit" | "vod-watching" | "app-login-streak")[];
31
+ }
32
+ export interface FanEngagementResult {
33
+ success: boolean;
34
+ results: {
35
+ matchAttendance?: MatchAttendanceResult;
36
+ earlyArrival?: EarlyArrivalResult;
37
+ sportsbarVisit?: SportsbarVisitResult;
38
+ vodWatching?: VodWatchingResult;
39
+ appLoginStreak?: AppLoginStreakResult;
40
+ };
41
+ summary: string;
42
+ totalCampaigns: number;
43
+ totalAchievements: number;
44
+ errors: string[];
45
+ }
46
+ /**
47
+ * Execute all fan engagement workflows
48
+ *
49
+ * This is the master workflow that orchestrates all individual workflows
50
+ * based on the provided configuration.
51
+ */
52
+ export declare function executeAllFanEngagementWorkflows(config?: FanEngagementConfig): Promise<FanEngagementResult>;
53
+ export declare const allWorkflows: readonly [{
54
+ id: string;
55
+ name: string;
56
+ execute: typeof executeMatchAttendanceWorkflow;
57
+ }, {
58
+ id: string;
59
+ name: string;
60
+ execute: typeof executeEarlyArrivalWorkflow;
61
+ }, {
62
+ id: string;
63
+ name: string;
64
+ execute: typeof executeSportsbarVisitWorkflow;
65
+ }, {
66
+ id: string;
67
+ name: string;
68
+ execute: typeof executeVodWatchingWorkflow;
69
+ }, {
70
+ id: string;
71
+ name: string;
72
+ execute: typeof executeAppLoginStreakWorkflow;
73
+ }];
74
+ /**
75
+ * Get workflow by ID
76
+ */
77
+ export declare function getWorkflow(id: string): {
78
+ id: string;
79
+ name: string;
80
+ execute: typeof executeAppLoginStreakWorkflow;
81
+ } | {
82
+ id: string;
83
+ name: string;
84
+ execute: typeof executeEarlyArrivalWorkflow;
85
+ } | {
86
+ id: string;
87
+ name: string;
88
+ execute: typeof executeMatchAttendanceWorkflow;
89
+ } | {
90
+ id: string;
91
+ name: string;
92
+ execute: typeof executeSportsbarVisitWorkflow;
93
+ } | {
94
+ id: string;
95
+ name: string;
96
+ execute: typeof executeVodWatchingWorkflow;
97
+ } | undefined;
98
+ /**
99
+ * Execute a workflow by ID with given config
100
+ */
101
+ export declare function executeWorkflowById(id: string, config?: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Fan Engagement Workflows
3
+ *
4
+ * Orchestrated workflows for setting up complete fan engagement campaigns.
5
+ * These combine multiple Open Loyalty tools into guided, step-by-step flows.
6
+ */
7
+ // Import execute functions for internal use
8
+ import { matchAttendanceWorkflow, executeMatchAttendanceWorkflow, } from "./match-attendance.js";
9
+ import { earlyArrivalWorkflow, executeEarlyArrivalWorkflow, } from "./early-arrival.js";
10
+ import { sportsbarVisitWorkflow, executeSportsbarVisitWorkflow, } from "./sportsbar-visit.js";
11
+ import { vodWatchingWorkflow, executeVodWatchingWorkflow, } from "./vod-watching.js";
12
+ import { appLoginStreakWorkflow, executeAppLoginStreakWorkflow, } from "./app-login-streak.js";
13
+ // Re-export all workflow components
14
+ export { matchAttendanceWorkflow, executeMatchAttendanceWorkflow, };
15
+ export { earlyArrivalWorkflow, executeEarlyArrivalWorkflow, };
16
+ export { sportsbarVisitWorkflow, executeSportsbarVisitWorkflow, };
17
+ export { vodWatchingWorkflow, executeVodWatchingWorkflow, };
18
+ export { appLoginStreakWorkflow, executeAppLoginStreakWorkflow, };
19
+ // Re-export prompt utilities
20
+ export { DEFAULTS, ALL_WORKFLOWS, findMatchingWorkflow, getWorkflowById, parseCommaSeparated, parseMilestones, formatOLDate, AGENT_PROMPTS, } from "../prompts/fan-engagement-setup.js";
21
+ // ============================================================================
22
+ // Master Workflow
23
+ // ============================================================================
24
+ /**
25
+ * Execute all fan engagement workflows
26
+ *
27
+ * This is the master workflow that orchestrates all individual workflows
28
+ * based on the provided configuration.
29
+ */
30
+ export async function executeAllFanEngagementWorkflows(config = {}) {
31
+ const enabledWorkflows = config.enabledWorkflows || [
32
+ "match-attendance",
33
+ "early-arrival",
34
+ "sportsbar-visit",
35
+ "vod-watching",
36
+ "app-login-streak",
37
+ ];
38
+ const result = {
39
+ success: false,
40
+ results: {},
41
+ summary: "",
42
+ totalCampaigns: 0,
43
+ totalAchievements: 0,
44
+ errors: [],
45
+ };
46
+ try {
47
+ // Execute each enabled workflow
48
+ for (const workflowId of enabledWorkflows) {
49
+ switch (workflowId) {
50
+ case "match-attendance": {
51
+ const maResult = await executeMatchAttendanceWorkflow(config.matchAttendance);
52
+ result.results.matchAttendance = maResult;
53
+ if (maResult.baseCampaignId)
54
+ result.totalCampaigns++;
55
+ result.totalCampaigns += maResult.achievements.filter((a) => a.bonusCampaignId).length;
56
+ result.totalAchievements += maResult.achievements.length;
57
+ result.errors.push(...maResult.errors);
58
+ break;
59
+ }
60
+ case "early-arrival": {
61
+ const eaResult = await executeEarlyArrivalWorkflow(config.earlyArrival);
62
+ result.results.earlyArrival = eaResult;
63
+ if (eaResult.campaignId)
64
+ result.totalCampaigns++;
65
+ result.errors.push(...eaResult.errors);
66
+ break;
67
+ }
68
+ case "sportsbar-visit": {
69
+ const sbResult = await executeSportsbarVisitWorkflow(config.sportsbarVisit);
70
+ result.results.sportsbarVisit = sbResult;
71
+ if (sbResult.visitCampaignId)
72
+ result.totalCampaigns++;
73
+ if (sbResult.bonusCampaignId)
74
+ result.totalCampaigns++;
75
+ if (sbResult.achievementId)
76
+ result.totalAchievements++;
77
+ result.errors.push(...sbResult.errors);
78
+ break;
79
+ }
80
+ case "vod-watching": {
81
+ const vodResult = await executeVodWatchingWorkflow(config.vodWatching);
82
+ result.results.vodWatching = vodResult;
83
+ if (vodResult.watchCampaignId)
84
+ result.totalCampaigns++;
85
+ if (vodResult.bonusCampaignId)
86
+ result.totalCampaigns++;
87
+ if (vodResult.achievementId)
88
+ result.totalAchievements++;
89
+ result.errors.push(...vodResult.errors);
90
+ break;
91
+ }
92
+ case "app-login-streak": {
93
+ const loginResult = await executeAppLoginStreakWorkflow(config.appLoginStreak);
94
+ result.results.appLoginStreak = loginResult;
95
+ if (loginResult.loginCampaignId)
96
+ result.totalCampaigns++;
97
+ if (loginResult.streakBonusCampaignId)
98
+ result.totalCampaigns++;
99
+ if (loginResult.streakAchievementId)
100
+ result.totalAchievements++;
101
+ result.errors.push(...loginResult.errors);
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ // Determine overall success
107
+ result.success = result.errors.length === 0 && result.totalCampaigns > 0;
108
+ // Build summary
109
+ result.summary = buildMasterSummary(result);
110
+ }
111
+ catch (error) {
112
+ result.errors.push(`Master workflow error: ${error instanceof Error ? error.message : String(error)}`);
113
+ }
114
+ return result;
115
+ }
116
+ // ============================================================================
117
+ // Helper Functions
118
+ // ============================================================================
119
+ function buildMasterSummary(result) {
120
+ const lines = [];
121
+ lines.push(`Fan Engagement Program Setup Complete!`);
122
+ lines.push(`========================================`);
123
+ lines.push(`\nCreated: ${result.totalCampaigns} campaigns, ${result.totalAchievements} achievements`);
124
+ // Match Attendance
125
+ if (result.results.matchAttendance) {
126
+ const ma = result.results.matchAttendance;
127
+ if (ma.baseCampaignId) {
128
+ lines.push(`\nMatch Attendance:`);
129
+ lines.push(` - Base campaign: ${ma.baseCampaignId}`);
130
+ if (ma.achievements.length > 0) {
131
+ lines.push(` - Achievements: ${ma.achievements.map((a) => a.milestone).join(", ")} matches`);
132
+ }
133
+ }
134
+ }
135
+ // Early Arrival
136
+ if (result.results.earlyArrival?.campaignId) {
137
+ lines.push(`\nEarly Arrival:`);
138
+ lines.push(` - Campaign: ${result.results.earlyArrival.campaignId}`);
139
+ }
140
+ // Sports Bar
141
+ if (result.results.sportsbarVisit?.visitCampaignId) {
142
+ lines.push(`\nSports Bar Visits:`);
143
+ lines.push(` - Visit campaign: ${result.results.sportsbarVisit.visitCampaignId}`);
144
+ if (result.results.sportsbarVisit.achievementId) {
145
+ lines.push(` - Achievement: ${result.results.sportsbarVisit.achievementId}`);
146
+ }
147
+ }
148
+ // VOD Watching
149
+ if (result.results.vodWatching?.watchCampaignId) {
150
+ lines.push(`\nVOD Watching:`);
151
+ lines.push(` - Watch campaign: ${result.results.vodWatching.watchCampaignId}`);
152
+ if (result.results.vodWatching.achievementId) {
153
+ lines.push(` - Achievement: ${result.results.vodWatching.achievementId}`);
154
+ }
155
+ }
156
+ // App Login
157
+ if (result.results.appLoginStreak?.loginCampaignId) {
158
+ lines.push(`\nApp Login Streak:`);
159
+ lines.push(` - Login campaign: ${result.results.appLoginStreak.loginCampaignId}`);
160
+ if (result.results.appLoginStreak.streakAchievementId) {
161
+ lines.push(` - Streak achievement: ${result.results.appLoginStreak.streakAchievementId}`);
162
+ }
163
+ }
164
+ // Custom events reference
165
+ lines.push(`\nCustom Events Reference:`);
166
+ lines.push(` - match_attendance: Triggered when fan scans at stadium entry`);
167
+ lines.push(` - early_arrival: Triggered when fan arrives early (needs minutes_before attribute)`);
168
+ lines.push(` - sportsbar_visit: Triggered when fan visits the sports bar`);
169
+ lines.push(` - vod_watch: Triggered when fan watches video (needs minutes_watched attribute)`);
170
+ lines.push(` - app_login: Triggered on daily app login`);
171
+ // Errors
172
+ if (result.errors.length > 0) {
173
+ lines.push(`\nWarnings/Errors (${result.errors.length}):`);
174
+ for (const error of result.errors.slice(0, 5)) {
175
+ lines.push(` - ${error}`);
176
+ }
177
+ if (result.errors.length > 5) {
178
+ lines.push(` ... and ${result.errors.length - 5} more`);
179
+ }
180
+ }
181
+ return lines.join("\n");
182
+ }
183
+ // ============================================================================
184
+ // All Workflows Registry
185
+ // ============================================================================
186
+ export const allWorkflows = [
187
+ matchAttendanceWorkflow,
188
+ earlyArrivalWorkflow,
189
+ sportsbarVisitWorkflow,
190
+ vodWatchingWorkflow,
191
+ appLoginStreakWorkflow,
192
+ ];
193
+ /**
194
+ * Get workflow by ID
195
+ */
196
+ export function getWorkflow(id) {
197
+ return allWorkflows.find((w) => w.id === id);
198
+ }
199
+ /**
200
+ * Execute a workflow by ID with given config
201
+ */
202
+ export async function executeWorkflowById(id, config) {
203
+ const workflow = getWorkflow(id);
204
+ if (!workflow) {
205
+ throw new Error(`Workflow not found: ${id}`);
206
+ }
207
+ return workflow.execute(config);
208
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Match Attendance Workflow
3
+ *
4
+ * Creates a complete match attendance reward program including:
5
+ * - Base campaign for per-match coin rewards
6
+ * - Achievements for attendance milestones (6, 12 matches, etc.)
7
+ * - Bonus campaigns triggered by achievement completion
8
+ */
9
+ export interface MatchAttendanceConfig {
10
+ /** Coins awarded per match attendance */
11
+ coinsPerMatch: number;
12
+ /** Attendance milestones for achievements (e.g., [6, 12] or [6, 12, "80%"]) */
13
+ milestones: (number | string)[];
14
+ /** Badge names for each milestone */
15
+ badgeNames: string[];
16
+ /** Bonus coins for each milestone */
17
+ milestoneBonuses: number[];
18
+ /** Maximum attendances counted per day (anti-fraud) */
19
+ limitPerDay: number;
20
+ /** Season start date (ISO format) */
21
+ seasonStart: string;
22
+ /** Season end date (ISO format) */
23
+ seasonEnd: string;
24
+ }
25
+ export interface MatchAttendanceResult {
26
+ success: boolean;
27
+ baseCampaignId?: string;
28
+ achievements: Array<{
29
+ achievementId: string;
30
+ milestone: number | string;
31
+ badgeName: string;
32
+ bonusCampaignId?: string;
33
+ }>;
34
+ errors: string[];
35
+ summary: string;
36
+ }
37
+ /**
38
+ * Execute the match attendance workflow
39
+ */
40
+ export declare function executeMatchAttendanceWorkflow(config?: Partial<MatchAttendanceConfig>): Promise<MatchAttendanceResult>;
41
+ export declare const matchAttendanceWorkflow: {
42
+ id: string;
43
+ name: string;
44
+ execute: typeof executeMatchAttendanceWorkflow;
45
+ };