@amalaika/form-sdk-package 1.0.1 → 1.1.0

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 (84) hide show
  1. package/README.md +193 -239
  2. package/dist/cjs/client/index.d.ts +27 -3
  3. package/dist/cjs/client/index.d.ts.map +1 -1
  4. package/dist/cjs/client/index.js +148 -90
  5. package/dist/cjs/client/index.js.map +1 -1
  6. package/dist/cjs/i18n/en.json +7 -0
  7. package/dist/cjs/i18n/fr.json +7 -0
  8. package/dist/cjs/i18n/index.d.ts +2 -0
  9. package/dist/cjs/i18n/index.d.ts.map +1 -0
  10. package/dist/cjs/i18n/index.js +15 -0
  11. package/dist/cjs/i18n/index.js.map +1 -0
  12. package/dist/cjs/i18n/rw.json +7 -0
  13. package/dist/cjs/index.d.ts +3 -2
  14. package/dist/cjs/index.d.ts.map +1 -1
  15. package/dist/cjs/index.js +6 -1
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/integrations/checkout-script.d.ts +10 -0
  18. package/dist/cjs/integrations/checkout-script.d.ts.map +1 -0
  19. package/dist/cjs/integrations/checkout-script.js +38 -0
  20. package/dist/cjs/integrations/checkout-script.js.map +1 -0
  21. package/dist/cjs/integrations/index.d.ts +5 -0
  22. package/dist/cjs/integrations/index.d.ts.map +1 -0
  23. package/dist/cjs/integrations/index.js +49 -0
  24. package/dist/cjs/integrations/index.js.map +1 -0
  25. package/dist/cjs/integrations/mastercard.d.ts +11 -0
  26. package/dist/cjs/integrations/mastercard.d.ts.map +1 -0
  27. package/dist/cjs/integrations/mastercard.js +100 -0
  28. package/dist/cjs/integrations/mastercard.js.map +1 -0
  29. package/dist/cjs/integrations/types.d.ts +31 -0
  30. package/dist/cjs/integrations/types.d.ts.map +1 -0
  31. package/dist/cjs/integrations/types.js +3 -0
  32. package/dist/cjs/integrations/types.js.map +1 -0
  33. package/dist/cjs/state/index.d.ts +6 -1
  34. package/dist/cjs/state/index.d.ts.map +1 -1
  35. package/dist/cjs/state/index.js +9 -2
  36. package/dist/cjs/state/index.js.map +1 -1
  37. package/dist/cjs/types/index.d.ts +38 -1
  38. package/dist/cjs/types/index.d.ts.map +1 -1
  39. package/dist/cjs/utils/index.d.ts +12 -1
  40. package/dist/cjs/utils/index.d.ts.map +1 -1
  41. package/dist/cjs/utils/index.js +39 -0
  42. package/dist/cjs/utils/index.js.map +1 -1
  43. package/dist/esm/client/index.d.ts +27 -3
  44. package/dist/esm/client/index.d.ts.map +1 -1
  45. package/dist/esm/client/index.js +148 -90
  46. package/dist/esm/client/index.js.map +1 -1
  47. package/dist/esm/i18n/en.json +7 -0
  48. package/dist/esm/i18n/fr.json +7 -0
  49. package/dist/esm/i18n/index.d.ts +2 -0
  50. package/dist/esm/i18n/index.d.ts.map +1 -0
  51. package/dist/esm/i18n/index.js +9 -0
  52. package/dist/esm/i18n/index.js.map +1 -0
  53. package/dist/esm/i18n/rw.json +7 -0
  54. package/dist/esm/index.d.ts +3 -2
  55. package/dist/esm/index.d.ts.map +1 -1
  56. package/dist/esm/index.js +2 -1
  57. package/dist/esm/index.js.map +1 -1
  58. package/dist/esm/integrations/checkout-script.d.ts +10 -0
  59. package/dist/esm/integrations/checkout-script.d.ts.map +1 -0
  60. package/dist/esm/integrations/checkout-script.js +35 -0
  61. package/dist/esm/integrations/checkout-script.js.map +1 -0
  62. package/dist/esm/integrations/index.d.ts +5 -0
  63. package/dist/esm/integrations/index.d.ts.map +1 -0
  64. package/dist/esm/integrations/index.js +11 -0
  65. package/dist/esm/integrations/index.js.map +1 -0
  66. package/dist/esm/integrations/mastercard.d.ts +11 -0
  67. package/dist/esm/integrations/mastercard.d.ts.map +1 -0
  68. package/dist/esm/integrations/mastercard.js +97 -0
  69. package/dist/esm/integrations/mastercard.js.map +1 -0
  70. package/dist/esm/integrations/types.d.ts +31 -0
  71. package/dist/esm/integrations/types.d.ts.map +1 -0
  72. package/dist/esm/integrations/types.js +2 -0
  73. package/dist/esm/integrations/types.js.map +1 -0
  74. package/dist/esm/state/index.d.ts +6 -1
  75. package/dist/esm/state/index.d.ts.map +1 -1
  76. package/dist/esm/state/index.js +10 -3
  77. package/dist/esm/state/index.js.map +1 -1
  78. package/dist/esm/types/index.d.ts +38 -1
  79. package/dist/esm/types/index.d.ts.map +1 -1
  80. package/dist/esm/utils/index.d.ts +12 -1
  81. package/dist/esm/utils/index.d.ts.map +1 -1
  82. package/dist/esm/utils/index.js +36 -0
  83. package/dist/esm/utils/index.js.map +1 -1
  84. package/package.json +2 -4
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @amalaika/form-sdk-package
2
2
 
3
- Framework-agnostic SDK for integrating the event registration form system. Handles data fetching, conditional visibility, file uploads, and form submission — no UI rendering included.
3
+ Framework-agnostic SDK for event form integration fetch forms, handle visibility, upload files, submit, and process payments.
4
4
 
5
- Works with React, Vue, Angular, Svelte, vanilla JS, or any environment with the Fetch API.
5
+ **Zero runtime dependencies.** Works with any JavaScript framework or vanilla JS.
6
6
 
7
7
  ## Installation
8
8
 
@@ -10,339 +10,293 @@ Works with React, Vue, Angular, Svelte, vanilla JS, or any environment with the
10
10
  npm install @amalaika/form-sdk-package
11
11
  ```
12
12
 
13
- For local development (monorepo):
14
-
15
- ```json
16
- {
17
- "dependencies": {
18
- "@amalaika/form-sdk-package": "file:../form-sdk-package"
19
- }
20
- }
21
- ```
22
-
23
13
  ## Quick Start
24
14
 
25
15
  ```ts
26
- import { EventFormClient, getAllFields, isFieldVisible } from "@amalaika/form-sdk-package";
16
+ import { EventFormClient, FormStateManager, validateForm, getAllFields } from "@amalaika/form-sdk-package";
27
17
 
18
+ // 1. Create a client
28
19
  const client = new EventFormClient({
29
- apiKey: "Am_550e8400-e29b-41d4-a716-446655440000",
20
+ apiKey: "Am_550e8400-...",
30
21
  resourceType: "ticketing",
31
- locale: "en", // default locale for all requests
32
22
  });
33
23
 
34
- // All calls automatically use "en" — no locale param needed
24
+ // 2. Fetch tickets and forms
35
25
  const tickets = await client.fetchTickets();
36
26
  const form = await client.fetchForm(tickets[0].id);
37
- const fields = getAllFields(form.schema);
38
27
 
39
- // Switch language without reinstantiating
40
- client.setLocale("fr");
41
- const ticketsFr = await client.fetchTickets(); // now uses "fr"
42
- ```
43
-
44
- ## API Reference
45
-
46
- ### Constructor
47
-
48
- ```ts
49
- const client = new EventFormClient(config: EventFormConfig);
28
+ // 3. Manage form state
29
+ const fields = getAllFields(form.schema);
30
+ const state = new FormStateManager(fields);
31
+ state.setValue("email", "user@example.com");
32
+
33
+ // 4. Validate and submit
34
+ const errors = validateForm(fields, state.getValues());
35
+ const allValid = Object.values(errors).every((r) => r.valid);
36
+
37
+ if (allValid) {
38
+ const { submission, integrations } = await client.submitForm(form, state.getSubmissionData(), {
39
+ resourceId: tickets[0].id,
40
+ attendanceType: "PHYSICAL",
41
+ });
42
+ }
50
43
  ```
51
44
 
52
- | Parameter | Type | Required | Description |
53
- |-----------|------|----------|-------------|
54
- | `apiKey` | `string` | Yes | Event API key (e.g. `"Am_550e8400-..."`) |
55
- | `resourceType` | `"ticketing" \| "accommodation" \| "exhibition"` | Yes | Resource type for submissions |
56
- | `apiBaseUrl` | `string` | No | API base URL. Defaults to `"https://api.eventsfactory.rw/api"` |
57
- | `locale` | `string` | No | Default locale for all requests. Can be changed later via `setLocale()` |
58
- | `errorMessages` | `Partial<ErrorMessages>` | No | Custom error messages — override any or all defaults |
59
- | `origin` | `string` | No | Origin header sent with every request. Defaults to `"https://smartevent.rw"` |
60
- | `timeout` | `number` | No | Request timeout in milliseconds. Defaults to `30000` |
61
- | `retry` | `{ maxRetries?: number; delay?: number }` | No | Retry configuration. Defaults to 3 retries with 1s delay and exponential backoff. Only retries on 5xx and network errors |
62
- | `cache` | `{ enabled?: boolean; ttl?: number }` | No | Response caching for GET requests. Disabled by default. Use `clearCache()` to invalidate |
63
- | `noCache` | `boolean` | No | Send `Cache-Control: no-cache` header with every request. Defaults to `false` |
64
- | `interceptors` | `{ request?, response?, error? }` | No | Request/response interceptors for modifying headers, transforming data, or handling errors |
65
-
66
- ### Locale Management
67
-
68
- Set a default locale on the constructor so you don't have to pass it on every method call:
45
+ ## Configuration
69
46
 
70
47
  ```ts
71
48
  const client = new EventFormClient({
49
+ // Required
72
50
  apiKey: "Am_550e8400-...",
73
- resourceType: "ticketing",
74
- locale: "fr",
51
+ resourceType: "ticketing", // "ticketing" | "accommodation" | "exhibition"
52
+
53
+ // Optional
54
+ apiBaseUrl: "https://api.example.com", // defaults to production
55
+ locale: "en", // default locale for requests
56
+ origin: "https://myapp.com", // Origin header
57
+ timeout: 30000, // request timeout (ms)
58
+ noCache: false, // send Cache-Control: no-cache
59
+ mastercardCheckoutUrl: "https://...", // checkout script URL override
60
+ merchantName: "My Event", // shown in payment UI
61
+
62
+ // Retry failed requests
63
+ retry: { maxRetries: 3, delay: 1000 },
64
+
65
+ // Cache GET responses
66
+ cache: { enabled: true, ttl: 60000 },
67
+
68
+ // Custom error messages
69
+ errorMessages: {
70
+ fetchTickets: "Could not load tickets",
71
+ submitForm: "Submission failed",
72
+ },
73
+
74
+ // Interceptors
75
+ interceptors: {
76
+ request: (config) => { /* modify request */ return config; },
77
+ response: (data) => { /* transform response */ return data; },
78
+ error: (err) => { /* handle error */ return err; },
79
+ },
75
80
  });
76
-
77
- // All calls automatically use "fr" — no need to pass locale
78
- const tickets = await client.fetchTickets();
79
- const form = await client.fetchForm(tickets[0].id);
80
81
  ```
81
82
 
82
- Switch locale at any time without reinstantiating:
83
+ ## Client Methods
83
84
 
84
- ```ts
85
- client.setLocale("en");
86
- // All subsequent calls now use "en"
87
- ```
88
-
89
- Read the current locale:
85
+ ### Tickets
90
86
 
91
87
  ```ts
92
- client.getLocale(); // "en"
93
- ```
88
+ // Fetch all tickets (with optional locale/name filter)
89
+ const tickets = await client.fetchTickets({ locale: "fr", name: "VIP" });
94
90
 
95
- Per-call locale still overrides the default when needed:
91
+ // Fetch a single ticket by ID
92
+ const ticket = await client.fetchTicketById(42);
96
93
 
97
- ```ts
98
- // Uses "de" for this call only, default remains "en"
99
- const tickets = await client.fetchTickets({ locale: "de" });
94
+ // Fetch a public ticket (no auth required)
95
+ const publicTicket = await client.fetchPublicTicket(42, "en");
100
96
  ```
101
97
 
102
- ### Methods
103
-
104
- #### `client.fetchTickets(options?)`
105
-
106
- Fetch all published tickets for the event.
98
+ ### Languages & Forms
107
99
 
108
100
  ```ts
109
- const tickets = await client.fetchTickets({ locale: "fr", name: "VIP" });
110
- ```
111
-
112
- | Option | Type | Description |
113
- |--------|------|-------------|
114
- | `locale` | `string` | Locale code for translations (also sent as `Accept-Language`) |
115
- | `name` | `string` | Filter tickets by name |
116
-
117
- Returns `Promise<Ticket[]>`.
118
-
119
- ---
101
+ // Fetch available languages
102
+ const languages = await client.fetchLanguages(); // ["en", "fr", "rw"]
120
103
 
121
- #### `client.fetchTicketById(id, locale?)`
122
-
123
- Fetch a single ticket by ID.
124
-
125
- ```ts
126
- const ticket = await client.fetchTicketById(42, "en");
104
+ // Fetch form schema for a ticket
105
+ const form = await client.fetchForm(ticketId, "en");
127
106
  ```
128
107
 
129
- Returns `Promise<Ticket>`.
130
-
131
- ---
132
-
133
- #### `client.fetchLanguages()`
134
-
135
- Fetch available languages for the event. Returns codes sorted with the default language first.
108
+ ### File Uploads
136
109
 
137
110
  ```ts
138
- const languages = await client.fetchLanguages();
139
- // ["en", "fr", "ar"]
111
+ // Two-step upload: authorize, then upload
112
+ const token = await client.authorizeUpload(formId, fieldId, file);
113
+ const fileUrl = await client.uploadFile(formId, token, file);
140
114
  ```
141
115
 
142
- Returns `Promise<string[]>`.
143
-
144
- ---
145
-
146
- #### `client.fetchForm(ticketId, locale?)`
147
-
148
- Fetch the form linked to a ticket.
116
+ ### Form Submission
149
117
 
150
118
  ```ts
151
- const form = await client.fetchForm(1, "fr");
119
+ const { submission, integrations } = await client.submitForm(
120
+ form,
121
+ formValues,
122
+ {
123
+ resourceId: ticketId,
124
+ attendanceType: "PHYSICAL", // "VIRTUAL" | "PHYSICAL" | "HYBRID"
125
+ containerId: "#payment-container", // CSS selector for payment UI
126
+ },
127
+ );
128
+
129
+ // submission: SubmissionResponse with id, formId, payment info, etc.
130
+ // integrations: IntegrationResult[] from any payment handlers
152
131
  ```
153
132
 
154
- Returns `Promise<FormData>`. The `form.schema` contains the field definitions used to render the form.
155
-
156
- ---
157
-
158
- #### `client.authorizeUpload(formId, fieldId, file, locale?)`
159
-
160
- Step 1 of file upload — request an upload token.
133
+ ### Locale & Cache
161
134
 
162
135
  ```ts
163
- const token = await client.authorizeUpload(form.id, "resume", file);
136
+ client.setLocale("fr");
137
+ client.getLocale(); // "fr"
138
+ client.clearCache();
164
139
  ```
165
140
 
166
- Returns `Promise<string>` (the upload token).
167
-
168
- ---
169
-
170
- #### `client.uploadFile(formId, token, file, locale?)`
171
-
172
- Step 2 of file upload — upload the file using the token.
141
+ ### Payment
173
142
 
174
143
  ```ts
175
- const fileUrl = await client.uploadFile(form.id, token, file);
144
+ // Preload the Mastercard checkout script before it's needed
145
+ await client.preloadCheckoutScript();
176
146
  ```
177
147
 
178
- Returns `Promise<string>` (the uploaded file URL to include in submission data).
148
+ ## FormStateManager
179
149
 
180
- ---
181
-
182
- #### `client.submitForm(formId, data, context)`
183
-
184
- Submit form data.
150
+ Manages form field values, dirty/touched tracking, visibility, and change subscriptions.
185
151
 
186
152
  ```ts
187
- await client.submitForm(form.id, submissionData, {
188
- eventId: form.eventId,
189
- ticketId: 1,
190
- locale: "en",
191
- });
192
- ```
153
+ import { FormStateManager, getAllFields } from "@amalaika/form-sdk-package";
193
154
 
194
- | Context Field | Type | Required | Description |
195
- |---------------|------|----------|-------------|
196
- | `eventId` | `number` | Yes | Event ID (from `form.eventId`) |
197
- | `ticketId` | `number` | Yes | Ticket ID used to fetch the form |
198
- | `locale` | `string` | No | Locale for `Accept-Language` header |
155
+ const fields = getAllFields(form.schema);
156
+ const state = new FormStateManager(fields);
199
157
 
200
- The `resourceType` is automatically sent from the constructor config.
158
+ // Get/set values
159
+ state.setValue("name", "Alice");
160
+ state.getValue("name"); // "Alice"
161
+ state.setValues({ name: "Alice", email: "alice@example.com" });
162
+ state.getValues(); // { name: "Alice", email: "alice@example.com" }
201
163
 
202
- Returns `Promise<void>`.
164
+ // Track user interaction
165
+ state.touchField("email");
166
+ state.isTouched("email"); // true
167
+ state.isDirty(); // true
168
+ state.getDirtyFields(); // Set(["name", "email"])
203
169
 
204
- ### Utility Functions
170
+ // Visibility-aware submission data (excludes hidden fields)
171
+ const data = state.getSubmissionData();
205
172
 
206
- Pure functions for working with form schemas and conditional visibility. Import directly:
173
+ // Get visible field IDs based on conditional logic
174
+ const visible = state.getVisibleFieldIds();
207
175
 
208
- ```ts
209
- import { getAllFields, isFieldVisible, getVisibleFieldIds } from "@amalaika/form-sdk-package";
210
- ```
176
+ // Resolve active payment integrations
177
+ const integrations = state.getActiveIntegrations();
211
178
 
212
- #### `getAllFields(schema)`
213
-
214
- Extracts all fields from a `FormSchema`, whether flat or stepped.
179
+ // Subscribe to changes
180
+ const unsubscribe = state.onChange(({ fieldId, value, values }) => {
181
+ console.log(`${fieldId} changed to`, value);
182
+ });
215
183
 
216
- ```ts
217
- const fields = getAllFields(form.schema);
184
+ // Reset to initial state
185
+ state.reset();
218
186
  ```
219
187
 
220
- Returns `FieldDefinition[]`.
221
-
222
- ---
223
-
224
- #### `isFieldVisible(field, formValues, allFields)`
225
-
226
- Checks whether a field should be visible based on the current form values. Supports cascading visibility (if a parent field is hidden, its dependents are too).
188
+ ## Validation
227
189
 
228
190
  ```ts
229
- if (isFieldVisible(field, currentValues, allFields)) {
230
- // render this field
231
- }
232
- ```
233
-
234
- Returns `boolean`.
191
+ import { validateField, validateForm, getAllFields } from "@amalaika/form-sdk-package";
235
192
 
236
- **Supported operators:**
193
+ // Validate a single field
194
+ const result = validateField(field, value);
195
+ // { valid: true } or { valid: false, error: "This field is required" }
237
196
 
238
- | Operator | Visible when |
239
- |----------|-------------|
240
- | `equals` | `formValues[dependsOn] === value` |
241
- | `not_equals` | `formValues[dependsOn] !== value` |
242
- | `in` | Any overlap between selected values and target values |
243
-
244
- ---
245
-
246
- #### `getVisibleFieldIds(allFields, formValues)`
247
-
248
- Returns the set of field IDs that are currently visible. Use this to filter submission data — only submit visible fields.
249
-
250
- ```ts
251
- const visibleIds = getVisibleFieldIds(allFields, formValues);
252
-
253
- const submissionData = {};
254
- for (const [key, val] of Object.entries(formValues)) {
255
- if (visibleIds.has(key)) submissionData[key] = val;
256
- }
197
+ // Validate all visible fields at once
198
+ const results = validateForm(fields, values);
199
+ // { fieldId: { valid: boolean, error?: string }, ... }
257
200
  ```
258
201
 
259
- Returns `Set<string>`.
202
+ Supports: `required`, `minLength`, `maxLength`, `min`, `max`, `pattern`, `accept` (file types), `maxSize` (file size).
260
203
 
261
- ## Full Example
204
+ ## Utility Functions
262
205
 
263
206
  ```ts
264
207
  import {
265
- EventFormClient,
266
208
  getAllFields,
209
+ isFieldVisible,
267
210
  getVisibleFieldIds,
211
+ hasIntegration,
212
+ getIntegrationMethod,
213
+ resolveIntegrations,
268
214
  } from "@amalaika/form-sdk-package";
269
215
 
270
- const client = new EventFormClient({
271
- apiKey: "Am_550e8400-e29b-41d4-a716-446655440000",
272
- resourceType: "ticketing",
273
- locale: "en",
274
- });
216
+ // Flatten fields from schema (handles flat and step-based layouts)
217
+ const fields = getAllFields(form.schema);
275
218
 
276
- // 1. Fetch tickets and pick one (uses default locale "en")
277
- const tickets = await client.fetchTickets();
278
- const ticket = tickets[0];
279
-
280
- // 2. Fetch the form (uses default locale "en")
281
- const form = await client.fetchForm(ticket.id);
282
- const allFields = getAllFields(form.schema);
283
-
284
- // 3. Collect user input into formValues (your UI handles this)
285
- const formValues: Record<string, unknown> = {
286
- first_name: "Jane",
287
- last_name: "Doe",
288
- email: "jane@example.com",
289
- role: "speaker",
290
- talk_title: "Building Dynamic Forms",
291
- };
292
-
293
- // 4. Filter to visible fields only
294
- const visibleIds = getVisibleFieldIds(allFields, formValues);
295
- const submissionData: Record<string, unknown> = {};
296
- for (const [key, val] of Object.entries(formValues)) {
297
- if (visibleIds.has(key)) submissionData[key] = val;
298
- }
219
+ // Conditional visibility
220
+ const visible = isFieldVisible(field, formValues, allFields);
221
+ const visibleIds = getVisibleFieldIds(fields, formValues);
299
222
 
300
- // 5. Handle file uploads (if any)
301
- const resumeFile = new File(["..."], "resume.pdf", { type: "application/pdf" });
302
- const token = await client.authorizeUpload(form.id, "resume", resumeFile);
303
- const fileUrl = await client.uploadFile(form.id, token, resumeFile);
304
- submissionData["resume"] = fileUrl;
223
+ // Payment integrations
224
+ const hasPay = hasIntegration(field);
225
+ const method = getIntegrationMethod(field, "CARD"); // "mastercard_payment_gateway"
226
+ const active = resolveIntegrations(fields, formValues);
227
+ ```
228
+
229
+ ## Mastercard Payment Integration
230
+
231
+ The SDK handles Mastercard Hosted Checkout via an embedded page flow:
232
+
233
+ 1. Submit the form — the API returns a `payment` object with `session_id` and `order_id`
234
+ 2. The SDK loads the Mastercard checkout script and renders the embedded payment UI in a container element
235
+ 3. On successful payment, the SDK confirms the payment with the backend
236
+ 4. The result is returned as part of the `integrations` array
305
237
 
306
- // 6. Submit (locale comes from constructor default)
307
- await client.submitForm(form.id, submissionData, {
308
- eventId: form.eventId!,
309
- ticketId: ticket.id,
238
+ ```ts
239
+ // Provide a container element for the payment UI
240
+ const { submission, integrations } = await client.submitForm(form, values, {
241
+ resourceId: ticketId,
242
+ attendanceType: "PHYSICAL",
243
+ containerId: "#payment-container", // must exist in the DOM
310
244
  });
245
+
246
+ // Check payment result
247
+ for (const result of integrations) {
248
+ if (result.success) {
249
+ // Payment completed
250
+ } else {
251
+ // result.error contains the error message
252
+ // result.data may contain additional details
253
+ }
254
+ }
311
255
  ```
312
256
 
313
- ## Exported Types
257
+ ## TypeScript
258
+
259
+ All types are exported:
314
260
 
315
261
  ```ts
316
262
  import type {
317
- ErrorMessages,
318
263
  EventFormConfig,
319
- FieldOption,
264
+ FormData,
265
+ FormSchema,
320
266
  FieldDefinition,
267
+ FieldOption,
321
268
  StepDefinition,
322
- FormSchema,
323
- FormData,
324
- ApiResponse,
325
- TicketTranslation,
326
269
  Ticket,
270
+ TicketTranslation,
271
+ ValidationResult,
272
+ SubmissionResponse,
273
+ PaymentInfo,
274
+ IntegrationResult,
275
+ ResolvedIntegration,
276
+ ApiResponse,
277
+ ErrorMessages,
327
278
  } from "@amalaika/form-sdk-package";
328
279
  ```
329
280
 
330
- ## Development
281
+ ## i18n
331
282
 
332
- ```bash
333
- # Install dependencies
334
- npm install
283
+ The SDK supports `en`, `fr`, and `rw` locales for error messages. Pass a locale to the client constructor or to individual methods:
284
+
285
+ ```ts
286
+ const client = new EventFormClient({ apiKey: "...", resourceType: "ticketing", locale: "fr" });
287
+ // or per-request:
288
+ const tickets = await client.fetchTickets({ locale: "rw" });
289
+ ```
335
290
 
336
- # Build (ESM + CJS)
337
- npm run build
291
+ ## Build
338
292
 
339
- # Run tests
340
- npm test
293
+ The package ships ESM and CJS builds with TypeScript declarations:
341
294
 
342
- # Lint
343
- npm run lint
295
+ ```bash
296
+ npm run build # Build both ESM and CJS
297
+ npm test # Run tests (212 tests, 100% coverage)
344
298
  ```
345
299
 
346
300
  ## License
347
301
 
348
- MIT
302
+ ISC
@@ -1,4 +1,4 @@
1
- import type { EventFormConfig, FormData, Ticket } from "../types/index.js";
1
+ import type { EventFormConfig, FormData, IntegrationResult, ResolvedIntegration, SubmissionResponse, Ticket } from "../types/index.js";
2
2
  export declare class EventFormClient {
3
3
  private readonly apiBase;
4
4
  private readonly apiKey;
@@ -10,17 +10,26 @@ export declare class EventFormClient {
10
10
  private readonly cacheConfig;
11
11
  private readonly noCache;
12
12
  private readonly interceptors;
13
+ private readonly mastercardCheckoutUrl;
14
+ private readonly merchantName;
13
15
  private readonly cache;
14
16
  private locale;
15
17
  constructor(config: EventFormConfig);
16
18
  setLocale(locale: string): void;
17
19
  getLocale(): string | undefined;
20
+ /**
21
+ * Preload the Mastercard Checkout.js script so it's ready when payment starts.
22
+ * Call this early (e.g. on page load) to avoid skeleton delay.
23
+ */
24
+ preloadCheckoutScript(): Promise<void>;
18
25
  clearCache(): void;
19
26
  private getCached;
20
27
  private setCache;
21
28
  private applyRequestInterceptor;
22
29
  private applyResponseInterceptor;
23
30
  private applyErrorInterceptor;
31
+ private throwMapped;
32
+ private cachedGet;
24
33
  private isRetryable;
25
34
  private executeRequest;
26
35
  fetchTickets(options?: {
@@ -28,14 +37,29 @@ export declare class EventFormClient {
28
37
  name?: string;
29
38
  }): Promise<Ticket[]>;
30
39
  fetchTicketById(id: number, locale?: string): Promise<Ticket>;
40
+ fetchPublicTicket(id: number, locale?: string): Promise<Ticket>;
31
41
  fetchLanguages(): Promise<string[]>;
32
42
  fetchForm(ticketId: number, locale?: string): Promise<FormData>;
33
43
  authorizeUpload(formId: number, fieldId: string, file: File, locale?: string): Promise<string>;
34
44
  uploadFile(formId: number, token: string, file: File, locale?: string): Promise<string>;
35
- submitForm(formId: number, data: Record<string, unknown>, context: {
45
+ /**
46
+ * Submits the form to the backend first, then conditionally runs payment
47
+ * integrations if the response indicates payment is required.
48
+ *
49
+ * If an integration fails after submission, the failure is returned in the
50
+ * result (not thrown), since the submission is already saved on the backend.
51
+ */
52
+ submitForm(form: FormData, data: Record<string, unknown>, context: {
36
53
  eventId: number;
37
54
  ticketId: number;
38
55
  locale?: string;
39
- }): Promise<void>;
56
+ attendanceType?: "HYBRID" | "PHYSICAL" | "VIRTUAL" | null;
57
+ containerId?: string;
58
+ }): Promise<{
59
+ submission: SubmissionResponse;
60
+ integrations: Array<ResolvedIntegration & {
61
+ result: IntegrationResult;
62
+ }>;
63
+ }>;
40
64
  }
41
65
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,eAAe,EACf,QAAQ,EACR,MAAM,EACP,MAAM,mBAAmB,CAAC;AAuD3B,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwC;IACpE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoC;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAC/D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,EAAE,eAAe;IAoBnC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B,UAAU,IAAI,IAAI;IAIlB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,wBAAwB;IAOhC,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,WAAW;YAOL,cAAc;IAsBtB,YAAY,CAAC,OAAO,CAAC,EAAE;QAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA6Bf,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB7D,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA4BnC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAwB/D,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IA0BZ,UAAU,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAsBZ,UAAU,CACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,IAAI,CAAC;CAyBjB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}