@thebookingkit/server 0.1.1 → 0.1.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 (68) hide show
  1. package/README.md +50 -0
  2. package/dist/adapters/email-adapter.js +2 -2
  3. package/dist/adapters/email-adapter.js.map +1 -1
  4. package/dist/adapters/job-adapter.d.ts +10 -10
  5. package/dist/adapters/job-adapter.d.ts.map +1 -1
  6. package/dist/adapters/job-adapter.js +10 -10
  7. package/dist/adapters/job-adapter.js.map +1 -1
  8. package/dist/api.d.ts +3 -3
  9. package/dist/api.js +5 -5
  10. package/dist/api.js.map +1 -1
  11. package/package.json +21 -2
  12. package/.turbo/turbo-build.log +0 -6
  13. package/.turbo/turbo-test.log +0 -20
  14. package/CHANGELOG.md +0 -9
  15. package/dist/__tests__/api.test.d.ts +0 -2
  16. package/dist/__tests__/api.test.d.ts.map +0 -1
  17. package/dist/__tests__/api.test.js +0 -280
  18. package/dist/__tests__/api.test.js.map +0 -1
  19. package/dist/__tests__/auth.test.d.ts +0 -2
  20. package/dist/__tests__/auth.test.d.ts.map +0 -1
  21. package/dist/__tests__/auth.test.js +0 -78
  22. package/dist/__tests__/auth.test.js.map +0 -1
  23. package/dist/__tests__/concurrent-booking.test.d.ts +0 -2
  24. package/dist/__tests__/concurrent-booking.test.d.ts.map +0 -1
  25. package/dist/__tests__/concurrent-booking.test.js +0 -111
  26. package/dist/__tests__/concurrent-booking.test.js.map +0 -1
  27. package/dist/__tests__/multi-tenancy.test.d.ts +0 -2
  28. package/dist/__tests__/multi-tenancy.test.d.ts.map +0 -1
  29. package/dist/__tests__/multi-tenancy.test.js +0 -196
  30. package/dist/__tests__/multi-tenancy.test.js.map +0 -1
  31. package/dist/__tests__/serialization-retry.test.d.ts +0 -2
  32. package/dist/__tests__/serialization-retry.test.d.ts.map +0 -1
  33. package/dist/__tests__/serialization-retry.test.js +0 -53
  34. package/dist/__tests__/serialization-retry.test.js.map +0 -1
  35. package/dist/__tests__/webhooks.test.d.ts +0 -2
  36. package/dist/__tests__/webhooks.test.d.ts.map +0 -1
  37. package/dist/__tests__/webhooks.test.js +0 -286
  38. package/dist/__tests__/webhooks.test.js.map +0 -1
  39. package/dist/__tests__/workflows.test.d.ts +0 -2
  40. package/dist/__tests__/workflows.test.d.ts.map +0 -1
  41. package/dist/__tests__/workflows.test.js +0 -299
  42. package/dist/__tests__/workflows.test.js.map +0 -1
  43. package/src/__tests__/api.test.ts +0 -354
  44. package/src/__tests__/auth.test.ts +0 -111
  45. package/src/__tests__/concurrent-booking.test.ts +0 -170
  46. package/src/__tests__/multi-tenancy.test.ts +0 -267
  47. package/src/__tests__/serialization-retry.test.ts +0 -76
  48. package/src/__tests__/webhooks.test.ts +0 -412
  49. package/src/__tests__/workflows.test.ts +0 -422
  50. package/src/adapters/calendar-adapter.ts +0 -49
  51. package/src/adapters/email-adapter.ts +0 -108
  52. package/src/adapters/index.ts +0 -36
  53. package/src/adapters/job-adapter.ts +0 -26
  54. package/src/adapters/payment-adapter.ts +0 -118
  55. package/src/adapters/sms-adapter.ts +0 -35
  56. package/src/adapters/storage-adapter.ts +0 -11
  57. package/src/api.ts +0 -446
  58. package/src/auth.ts +0 -146
  59. package/src/booking-tokens.ts +0 -61
  60. package/src/email-templates.ts +0 -140
  61. package/src/index.ts +0 -192
  62. package/src/multi-tenancy.ts +0 -301
  63. package/src/notification-jobs.ts +0 -428
  64. package/src/serialization-retry.ts +0 -94
  65. package/src/webhooks.ts +0 -378
  66. package/src/workflows.ts +0 -441
  67. package/tsconfig.json +0 -9
  68. package/vitest.config.ts +0 -7
@@ -1,286 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
- import { signWebhookPayload, verifyWebhookSignature, createWebhookEnvelope, resolvePayloadTemplate, matchWebhookSubscriptions, getRetryDelay, isSuccessResponse, validateWebhookSubscription, WEBHOOK_TRIGGERS, } from "../webhooks.js";
3
- // ---------------------------------------------------------------------------
4
- // Fixtures
5
- // ---------------------------------------------------------------------------
6
- const testSecret = "whsec_test_secret_key_123";
7
- const testPayload = '{"triggerEvent":"BOOKING_CREATED","payload":{}}';
8
- const samplePayload = {
9
- bookingId: "bk-1",
10
- eventType: "consultation",
11
- startTime: "2026-03-15T14:00:00.000Z",
12
- endTime: "2026-03-15T14:30:00.000Z",
13
- organizer: { name: "Dr. Smith", email: "smith@example.com" },
14
- attendees: [{ email: "jane@example.com", name: "Jane Doe" }],
15
- status: "confirmed",
16
- };
17
- function makeSub(overrides) {
18
- return {
19
- id: "wh-1",
20
- subscriberUrl: "https://api.example.com/webhooks",
21
- triggers: ["BOOKING_CREATED"],
22
- isActive: true,
23
- ...overrides,
24
- };
25
- }
26
- // ---------------------------------------------------------------------------
27
- // signWebhookPayload
28
- // ---------------------------------------------------------------------------
29
- describe("signWebhookPayload", () => {
30
- it("produces a hex-encoded HMAC-SHA256 signature", () => {
31
- const sig = signWebhookPayload(testPayload, testSecret, 1710000000);
32
- expect(sig).toMatch(/^[0-9a-f]{64}$/);
33
- });
34
- it("produces different signatures for different payloads", () => {
35
- const sig1 = signWebhookPayload("body1", testSecret, 1710000000);
36
- const sig2 = signWebhookPayload("body2", testSecret, 1710000000);
37
- expect(sig1).not.toBe(sig2);
38
- });
39
- it("produces different signatures for different timestamps", () => {
40
- const sig1 = signWebhookPayload(testPayload, testSecret, 1710000000);
41
- const sig2 = signWebhookPayload(testPayload, testSecret, 1710000001);
42
- expect(sig1).not.toBe(sig2);
43
- });
44
- it("produces different signatures for different secrets", () => {
45
- const sig1 = signWebhookPayload(testPayload, "secret1", 1710000000);
46
- const sig2 = signWebhookPayload(testPayload, "secret2", 1710000000);
47
- expect(sig1).not.toBe(sig2);
48
- });
49
- });
50
- // ---------------------------------------------------------------------------
51
- // verifyWebhookSignature
52
- // ---------------------------------------------------------------------------
53
- describe("verifyWebhookSignature", () => {
54
- beforeEach(() => {
55
- vi.useFakeTimers();
56
- });
57
- afterEach(() => {
58
- vi.useRealTimers();
59
- });
60
- it("returns valid for a correct signature within tolerance", () => {
61
- const now = 1710000000;
62
- vi.setSystemTime(now * 1000);
63
- const sig = signWebhookPayload(testPayload, testSecret, now);
64
- const result = verifyWebhookSignature(testPayload, sig, now, testSecret);
65
- expect(result).toEqual({ valid: true });
66
- });
67
- it("returns signature_mismatch for tampered payload", () => {
68
- const now = 1710000000;
69
- vi.setSystemTime(now * 1000);
70
- const sig = signWebhookPayload(testPayload, testSecret, now);
71
- const result = verifyWebhookSignature("tampered_body", sig, now, testSecret);
72
- expect(result).toEqual({ valid: false, reason: "signature_mismatch" });
73
- });
74
- it("returns signature_mismatch for wrong secret", () => {
75
- const now = 1710000000;
76
- vi.setSystemTime(now * 1000);
77
- const sig = signWebhookPayload(testPayload, testSecret, now);
78
- const result = verifyWebhookSignature(testPayload, sig, now, "wrong_secret");
79
- expect(result).toEqual({ valid: false, reason: "signature_mismatch" });
80
- });
81
- it("returns timestamp_expired for old timestamp (>5 min)", () => {
82
- const now = 1710000600; // 10 min later
83
- vi.setSystemTime(now * 1000);
84
- const oldTimestamp = now - 301; // 5 min 1 sec ago
85
- const sig = signWebhookPayload(testPayload, testSecret, oldTimestamp);
86
- const result = verifyWebhookSignature(testPayload, sig, oldTimestamp, testSecret);
87
- expect(result).toEqual({ valid: false, reason: "timestamp_expired" });
88
- });
89
- it("accepts timestamp within tolerance", () => {
90
- const now = 1710000000;
91
- vi.setSystemTime(now * 1000);
92
- const recentTimestamp = now - 299; // 4 min 59 sec ago
93
- const sig = signWebhookPayload(testPayload, testSecret, recentTimestamp);
94
- const result = verifyWebhookSignature(testPayload, sig, recentTimestamp, testSecret);
95
- expect(result).toEqual({ valid: true });
96
- });
97
- it("supports custom tolerance", () => {
98
- const now = 1710000000;
99
- vi.setSystemTime(now * 1000);
100
- const oldTimestamp = now - 61;
101
- const sig = signWebhookPayload(testPayload, testSecret, oldTimestamp);
102
- const result = verifyWebhookSignature(testPayload, sig, oldTimestamp, testSecret, { toleranceSeconds: 60 });
103
- expect(result).toEqual({ valid: false, reason: "timestamp_expired" });
104
- });
105
- it("rejects future timestamps beyond tolerance", () => {
106
- const now = 1710000000;
107
- vi.setSystemTime(now * 1000);
108
- const futureTimestamp = now + 400;
109
- const sig = signWebhookPayload(testPayload, testSecret, futureTimestamp);
110
- const result = verifyWebhookSignature(testPayload, sig, futureTimestamp, testSecret);
111
- expect(result).toEqual({ valid: false, reason: "timestamp_expired" });
112
- });
113
- });
114
- // ---------------------------------------------------------------------------
115
- // createWebhookEnvelope
116
- // ---------------------------------------------------------------------------
117
- describe("createWebhookEnvelope", () => {
118
- it("creates a valid envelope with ISO 8601 timestamp", () => {
119
- const envelope = createWebhookEnvelope("BOOKING_CREATED", samplePayload);
120
- expect(envelope.triggerEvent).toBe("BOOKING_CREATED");
121
- expect(envelope.payload).toBe(samplePayload);
122
- expect(new Date(envelope.createdAt).toISOString()).toBe(envelope.createdAt);
123
- });
124
- });
125
- // ---------------------------------------------------------------------------
126
- // resolvePayloadTemplate
127
- // ---------------------------------------------------------------------------
128
- describe("resolvePayloadTemplate", () => {
129
- const envelope = createWebhookEnvelope("BOOKING_CREATED", samplePayload);
130
- it("resolves all standard template variables", () => {
131
- const template = '{"event":"{{triggerEvent}}","booking":"{{bookingId}}","type":"{{eventType}}","start":"{{startTime}}","end":"{{endTime}}","status":"{{status}}","org":"{{organizerName}}","email":"{{organizerEmail}}"}';
132
- const result = resolvePayloadTemplate(template, envelope);
133
- const parsed = JSON.parse(result);
134
- expect(parsed.event).toBe("BOOKING_CREATED");
135
- expect(parsed.booking).toBe("bk-1");
136
- expect(parsed.type).toBe("consultation");
137
- expect(parsed.start).toBe("2026-03-15T14:00:00.000Z");
138
- expect(parsed.status).toBe("confirmed");
139
- expect(parsed.org).toBe("Dr. Smith");
140
- expect(parsed.email).toBe("smith@example.com");
141
- });
142
- it("handles template with no variables", () => {
143
- const result = resolvePayloadTemplate('{"static":"value"}', envelope);
144
- expect(result).toBe('{"static":"value"}');
145
- });
146
- });
147
- // ---------------------------------------------------------------------------
148
- // matchWebhookSubscriptions
149
- // ---------------------------------------------------------------------------
150
- describe("matchWebhookSubscriptions", () => {
151
- const subs = [
152
- makeSub({ id: "wh-1", triggers: ["BOOKING_CREATED", "BOOKING_CANCELLED"] }),
153
- makeSub({ id: "wh-2", triggers: ["BOOKING_CREATED"], isActive: false }),
154
- makeSub({
155
- id: "wh-3",
156
- triggers: ["BOOKING_CREATED"],
157
- eventTypeId: "evt-1",
158
- }),
159
- makeSub({
160
- id: "wh-4",
161
- triggers: ["BOOKING_CREATED"],
162
- teamId: "team-1",
163
- }),
164
- ];
165
- it("matches active webhooks with matching trigger", () => {
166
- const matched = matchWebhookSubscriptions(subs, "BOOKING_CREATED");
167
- expect(matched.map((s) => s.id)).toContain("wh-1");
168
- });
169
- it("excludes inactive webhooks", () => {
170
- const matched = matchWebhookSubscriptions(subs, "BOOKING_CREATED");
171
- expect(matched.find((s) => s.id === "wh-2")).toBeUndefined();
172
- });
173
- it("matches scoped webhooks when scope matches", () => {
174
- const matched = matchWebhookSubscriptions(subs, "BOOKING_CREATED", {
175
- eventTypeId: "evt-1",
176
- });
177
- expect(matched.find((s) => s.id === "wh-3")).toBeDefined();
178
- });
179
- it("excludes scoped webhooks when scope doesn't match", () => {
180
- const matched = matchWebhookSubscriptions(subs, "BOOKING_CREATED", {
181
- eventTypeId: "evt-99",
182
- });
183
- expect(matched.find((s) => s.id === "wh-3")).toBeUndefined();
184
- });
185
- it("matches team-scoped webhooks", () => {
186
- const matched = matchWebhookSubscriptions(subs, "BOOKING_CREATED", {
187
- teamId: "team-1",
188
- });
189
- expect(matched.find((s) => s.id === "wh-4")).toBeDefined();
190
- });
191
- it("returns empty for unsubscribed trigger", () => {
192
- const matched = matchWebhookSubscriptions(subs, "OOO_CREATED");
193
- expect(matched).toHaveLength(0);
194
- });
195
- });
196
- // ---------------------------------------------------------------------------
197
- // getRetryDelay
198
- // ---------------------------------------------------------------------------
199
- describe("getRetryDelay", () => {
200
- it("returns correct delays for default config", () => {
201
- expect(getRetryDelay(0)).toBe(10);
202
- expect(getRetryDelay(1)).toBe(60);
203
- expect(getRetryDelay(2)).toBe(300);
204
- });
205
- it("returns null when max retries exceeded", () => {
206
- expect(getRetryDelay(3)).toBeNull();
207
- expect(getRetryDelay(10)).toBeNull();
208
- });
209
- it("uses custom config", () => {
210
- const config = { maxRetries: 2, backoffSeconds: [5, 30] };
211
- expect(getRetryDelay(0, config)).toBe(5);
212
- expect(getRetryDelay(1, config)).toBe(30);
213
- expect(getRetryDelay(2, config)).toBeNull();
214
- });
215
- });
216
- // ---------------------------------------------------------------------------
217
- // isSuccessResponse
218
- // ---------------------------------------------------------------------------
219
- describe("isSuccessResponse", () => {
220
- it("returns true for 200", () => {
221
- expect(isSuccessResponse(200)).toBe(true);
222
- });
223
- it("returns true for 201", () => {
224
- expect(isSuccessResponse(201)).toBe(true);
225
- });
226
- it("returns true for 204", () => {
227
- expect(isSuccessResponse(204)).toBe(true);
228
- });
229
- it("returns false for 400", () => {
230
- expect(isSuccessResponse(400)).toBe(false);
231
- });
232
- it("returns false for 500", () => {
233
- expect(isSuccessResponse(500)).toBe(false);
234
- });
235
- it("returns false for 301 redirect", () => {
236
- expect(isSuccessResponse(301)).toBe(false);
237
- });
238
- });
239
- // ---------------------------------------------------------------------------
240
- // validateWebhookSubscription
241
- // ---------------------------------------------------------------------------
242
- describe("validateWebhookSubscription", () => {
243
- it("accepts valid subscription", () => {
244
- expect(() => validateWebhookSubscription({
245
- subscriberUrl: "https://example.com/webhook",
246
- triggers: ["BOOKING_CREATED"],
247
- isActive: true,
248
- })).not.toThrow();
249
- });
250
- it("rejects missing URL", () => {
251
- expect(() => validateWebhookSubscription({
252
- subscriberUrl: "",
253
- triggers: ["BOOKING_CREATED"],
254
- isActive: true,
255
- })).toThrow("Subscriber URL is required");
256
- });
257
- it("rejects invalid URL", () => {
258
- expect(() => validateWebhookSubscription({
259
- subscriberUrl: "not-a-url",
260
- triggers: ["BOOKING_CREATED"],
261
- isActive: true,
262
- })).toThrow("Invalid subscriber URL");
263
- });
264
- it("rejects empty triggers array", () => {
265
- expect(() => validateWebhookSubscription({
266
- subscriberUrl: "https://example.com/webhook",
267
- triggers: [],
268
- isActive: true,
269
- })).toThrow("At least one trigger");
270
- });
271
- it("rejects invalid trigger", () => {
272
- expect(() => validateWebhookSubscription({
273
- subscriberUrl: "https://example.com/webhook",
274
- triggers: ["INVALID_TRIGGER"],
275
- isActive: true,
276
- })).toThrow('Invalid trigger: "INVALID_TRIGGER"');
277
- });
278
- it("accepts all valid triggers", () => {
279
- expect(() => validateWebhookSubscription({
280
- subscriberUrl: "https://example.com/webhook",
281
- triggers: [...WEBHOOK_TRIGGERS],
282
- isActive: true,
283
- })).not.toThrow();
284
- });
285
- });
286
- //# sourceMappingURL=webhooks.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webhooks.test.js","sourceRoot":"","sources":["../../src/__tests__/webhooks.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=workflows.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workflows.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/workflows.test.ts"],"names":[],"mappings":""}
@@ -1,299 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { resolveTemplateVariables, evaluateConditions, validateWorkflow, matchWorkflows, DEFAULT_TEMPLATES, WorkflowValidationError, } from "../workflows.js";
3
- // ---------------------------------------------------------------------------
4
- // Fixtures
5
- // ---------------------------------------------------------------------------
6
- function makeWorkflow(overrides) {
7
- return {
8
- id: "wf-1",
9
- name: "Confirmation Email",
10
- trigger: "booking_created",
11
- conditions: [],
12
- actions: [
13
- {
14
- type: "send_email",
15
- to: "customer",
16
- subject: "Booking Confirmed: {booking.title}",
17
- body: "Hi {attendee.name}, your booking is confirmed.",
18
- },
19
- ],
20
- isActive: true,
21
- ...overrides,
22
- };
23
- }
24
- const sampleContext = {
25
- bookingId: "bk-1",
26
- eventTypeId: "evt-1",
27
- providerId: "prov-1",
28
- customerEmail: "jane@example.com",
29
- customerName: "Jane Doe",
30
- hostName: "Dr. Smith",
31
- eventTitle: "Consultation",
32
- eventDuration: 30,
33
- eventLocation: "123 Main St",
34
- startsAt: new Date("2026-03-15T14:00:00Z"),
35
- endsAt: new Date("2026-03-15T14:30:00Z"),
36
- managementUrl: "https://example.com/manage/bk-1",
37
- status: "confirmed",
38
- };
39
- // ---------------------------------------------------------------------------
40
- // resolveTemplateVariables
41
- // ---------------------------------------------------------------------------
42
- describe("resolveTemplateVariables", () => {
43
- it("resolves all standard variables", () => {
44
- const template = "Hi {attendee.name}, your {booking.title} with {host.name} is on {booking.date} at {booking.startTime}–{booking.endTime}. Duration: {event.duration}. Location: {event.location}. Manage: {booking.managementUrl}";
45
- const result = resolveTemplateVariables(template, sampleContext);
46
- expect(result).toContain("Jane Doe");
47
- expect(result).toContain("Consultation");
48
- expect(result).toContain("Dr. Smith");
49
- expect(result).toContain("30 minutes");
50
- expect(result).toContain("123 Main St");
51
- expect(result).toContain("https://example.com/manage/bk-1");
52
- expect(result).not.toContain("{");
53
- });
54
- it("replaces missing variables with empty strings", () => {
55
- const template = "Hi {attendee.name}, location: {event.location}";
56
- const result = resolveTemplateVariables(template, {
57
- customerName: "Jane",
58
- });
59
- expect(result).toBe("Hi Jane, location: ");
60
- });
61
- it("handles template with no variables", () => {
62
- const result = resolveTemplateVariables("Hello world", sampleContext);
63
- expect(result).toBe("Hello world");
64
- });
65
- it("handles empty template", () => {
66
- const result = resolveTemplateVariables("", sampleContext);
67
- expect(result).toBe("");
68
- });
69
- it("resolves default confirmation template", () => {
70
- const result = resolveTemplateVariables(DEFAULT_TEMPLATES.confirmation.body, sampleContext);
71
- expect(result).toContain("Jane Doe");
72
- expect(result).toContain("Consultation");
73
- expect(result).toContain("Dr. Smith");
74
- expect(result).not.toContain("{attendee.name}");
75
- });
76
- it("resolves default reminder template", () => {
77
- const result = resolveTemplateVariables(DEFAULT_TEMPLATES.reminder_24h.body, sampleContext);
78
- expect(result).toContain("Jane Doe");
79
- expect(result).toContain("Consultation");
80
- });
81
- it("resolves default cancellation template", () => {
82
- const result = resolveTemplateVariables(DEFAULT_TEMPLATES.cancellation.body, sampleContext);
83
- expect(result).toContain("Jane Doe");
84
- expect(result).toContain("Consultation");
85
- });
86
- });
87
- // ---------------------------------------------------------------------------
88
- // evaluateConditions
89
- // ---------------------------------------------------------------------------
90
- describe("evaluateConditions", () => {
91
- it("returns true for empty conditions (unconditional)", () => {
92
- expect(evaluateConditions([], sampleContext)).toBe(true);
93
- });
94
- it("equals operator matches", () => {
95
- const conditions = [
96
- { field: "eventTypeId", operator: "equals", value: "evt-1" },
97
- ];
98
- expect(evaluateConditions(conditions, sampleContext)).toBe(true);
99
- });
100
- it("equals operator rejects non-match", () => {
101
- const conditions = [
102
- { field: "eventTypeId", operator: "equals", value: "evt-2" },
103
- ];
104
- expect(evaluateConditions(conditions, sampleContext)).toBe(false);
105
- });
106
- it("not_equals operator works", () => {
107
- const conditions = [
108
- { field: "status", operator: "not_equals", value: "cancelled" },
109
- ];
110
- expect(evaluateConditions(conditions, sampleContext)).toBe(true);
111
- });
112
- it("contains operator works (case-insensitive)", () => {
113
- const conditions = [
114
- { field: "customerEmail", operator: "contains", value: "EXAMPLE" },
115
- ];
116
- expect(evaluateConditions(conditions, sampleContext)).toBe(true);
117
- });
118
- it("in operator works with array", () => {
119
- const conditions = [
120
- { field: "status", operator: "in", value: ["confirmed", "pending"] },
121
- ];
122
- expect(evaluateConditions(conditions, sampleContext)).toBe(true);
123
- });
124
- it("in operator rejects when not in array", () => {
125
- const conditions = [
126
- { field: "status", operator: "in", value: ["cancelled", "pending"] },
127
- ];
128
- expect(evaluateConditions(conditions, sampleContext)).toBe(false);
129
- });
130
- it("requires ALL conditions to match (AND logic)", () => {
131
- const conditions = [
132
- { field: "eventTypeId", operator: "equals", value: "evt-1" },
133
- { field: "status", operator: "equals", value: "cancelled" }, // doesn't match
134
- ];
135
- expect(evaluateConditions(conditions, sampleContext)).toBe(false);
136
- });
137
- it("handles missing context fields gracefully", () => {
138
- const conditions = [
139
- { field: "nonexistentField", operator: "equals", value: "" },
140
- ];
141
- expect(evaluateConditions(conditions, sampleContext)).toBe(true); // "" === ""
142
- });
143
- });
144
- // ---------------------------------------------------------------------------
145
- // validateWorkflow
146
- // ---------------------------------------------------------------------------
147
- describe("validateWorkflow", () => {
148
- it("accepts valid workflow", () => {
149
- expect(() => validateWorkflow(makeWorkflow())).not.toThrow();
150
- });
151
- it("rejects empty name", () => {
152
- expect(() => validateWorkflow(makeWorkflow({ name: "" }))).toThrow(WorkflowValidationError);
153
- expect(() => validateWorkflow(makeWorkflow({ name: "" }))).toThrow("name is required");
154
- });
155
- it("rejects invalid trigger", () => {
156
- expect(() => validateWorkflow(makeWorkflow({ trigger: "invalid" }))).toThrow("Invalid trigger");
157
- });
158
- it("rejects empty actions", () => {
159
- expect(() => validateWorkflow(makeWorkflow({ actions: [] }))).toThrow("at least one action");
160
- });
161
- it("rejects email action without to", () => {
162
- expect(() => validateWorkflow(makeWorkflow({
163
- actions: [
164
- { type: "send_email", to: "", subject: "Hi", body: "Hello" },
165
- ],
166
- }))).toThrow("'to' field");
167
- });
168
- it("rejects email action without subject", () => {
169
- expect(() => validateWorkflow(makeWorkflow({
170
- actions: [
171
- { type: "send_email", to: "customer", subject: "", body: "Hello" },
172
- ],
173
- }))).toThrow("'subject' field");
174
- });
175
- it("rejects email action without body", () => {
176
- expect(() => validateWorkflow(makeWorkflow({
177
- actions: [
178
- { type: "send_email", to: "customer", subject: "Hi", body: "" },
179
- ],
180
- }))).toThrow("'body' field");
181
- });
182
- it("rejects SMS action without to", () => {
183
- expect(() => validateWorkflow(makeWorkflow({
184
- actions: [{ type: "send_sms", to: "", body: "Hello" }],
185
- }))).toThrow("'to' field");
186
- });
187
- it("rejects webhook action without url", () => {
188
- expect(() => validateWorkflow(makeWorkflow({
189
- actions: [{ type: "fire_webhook", url: "" }],
190
- }))).toThrow("'url' field");
191
- });
192
- it("rejects status update action without status", () => {
193
- expect(() => validateWorkflow(makeWorkflow({
194
- actions: [{ type: "update_status", status: "" }],
195
- }))).toThrow("'status' field");
196
- });
197
- it("accepts calendar event action with no extra fields", () => {
198
- expect(() => validateWorkflow(makeWorkflow({
199
- actions: [{ type: "create_calendar_event" }],
200
- }))).not.toThrow();
201
- });
202
- it("rejects condition with empty field", () => {
203
- expect(() => validateWorkflow(makeWorkflow({
204
- conditions: [{ field: "", operator: "equals", value: "x" }],
205
- }))).toThrow("Condition field is required");
206
- });
207
- it("rejects invalid condition operator", () => {
208
- expect(() => validateWorkflow(makeWorkflow({
209
- conditions: [
210
- { field: "status", operator: "invalid", value: "x" },
211
- ],
212
- }))).toThrow("Invalid condition operator");
213
- });
214
- it("validates all supported triggers", () => {
215
- const triggers = [
216
- "booking_created",
217
- "booking_confirmed",
218
- "booking_cancelled",
219
- "booking_rescheduled",
220
- "before_event",
221
- "after_event",
222
- "payment_received",
223
- "payment_failed",
224
- "no_show_confirmed",
225
- "form_submitted",
226
- ];
227
- for (const trigger of triggers) {
228
- expect(() => validateWorkflow(makeWorkflow({ trigger }))).not.toThrow();
229
- }
230
- });
231
- });
232
- // ---------------------------------------------------------------------------
233
- // matchWorkflows
234
- // ---------------------------------------------------------------------------
235
- describe("matchWorkflows", () => {
236
- const workflows = [
237
- makeWorkflow({ id: "wf-1", trigger: "booking_created" }),
238
- makeWorkflow({
239
- id: "wf-2",
240
- trigger: "booking_cancelled",
241
- conditions: [
242
- { field: "eventTypeId", operator: "equals", value: "evt-1" },
243
- ],
244
- }),
245
- makeWorkflow({
246
- id: "wf-3",
247
- trigger: "booking_created",
248
- isActive: false,
249
- }),
250
- makeWorkflow({
251
- id: "wf-4",
252
- trigger: "booking_created",
253
- conditions: [
254
- { field: "eventTypeId", operator: "equals", value: "evt-99" },
255
- ],
256
- }),
257
- ];
258
- it("matches active workflows with matching trigger", () => {
259
- const matched = matchWorkflows(workflows, "booking_created", sampleContext);
260
- expect(matched).toHaveLength(1);
261
- expect(matched[0].id).toBe("wf-1");
262
- });
263
- it("excludes inactive workflows", () => {
264
- const matched = matchWorkflows(workflows, "booking_created", sampleContext);
265
- expect(matched.find((w) => w.id === "wf-3")).toBeUndefined();
266
- });
267
- it("excludes workflows with unmet conditions", () => {
268
- const matched = matchWorkflows(workflows, "booking_created", sampleContext);
269
- expect(matched.find((w) => w.id === "wf-4")).toBeUndefined();
270
- });
271
- it("matches workflows with met conditions", () => {
272
- const matched = matchWorkflows(workflows, "booking_cancelled", sampleContext);
273
- expect(matched).toHaveLength(1);
274
- expect(matched[0].id).toBe("wf-2");
275
- });
276
- it("returns empty array when no workflows match", () => {
277
- const matched = matchWorkflows(workflows, "payment_received", sampleContext);
278
- expect(matched).toHaveLength(0);
279
- });
280
- });
281
- // ---------------------------------------------------------------------------
282
- // DEFAULT_TEMPLATES
283
- // ---------------------------------------------------------------------------
284
- describe("DEFAULT_TEMPLATES", () => {
285
- it("has all expected templates", () => {
286
- expect(DEFAULT_TEMPLATES).toHaveProperty("confirmation");
287
- expect(DEFAULT_TEMPLATES).toHaveProperty("reminder_24h");
288
- expect(DEFAULT_TEMPLATES).toHaveProperty("reminder_1h");
289
- expect(DEFAULT_TEMPLATES).toHaveProperty("cancellation");
290
- expect(DEFAULT_TEMPLATES).toHaveProperty("followup");
291
- });
292
- it("each template has subject and body", () => {
293
- for (const [, template] of Object.entries(DEFAULT_TEMPLATES)) {
294
- expect(template.subject).toBeTruthy();
295
- expect(template.body).toBeTruthy();
296
- }
297
- });
298
- });
299
- //# sourceMappingURL=workflows.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workflows.test.js","sourceRoot":"","sources":["../../src/__tests__/workflows.test.ts"],"names":[],"mappings":"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"}