@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.
- package/README.md +193 -239
- package/dist/cjs/client/index.d.ts +27 -3
- package/dist/cjs/client/index.d.ts.map +1 -1
- package/dist/cjs/client/index.js +148 -90
- package/dist/cjs/client/index.js.map +1 -1
- package/dist/cjs/i18n/en.json +7 -0
- package/dist/cjs/i18n/fr.json +7 -0
- package/dist/cjs/i18n/index.d.ts +2 -0
- package/dist/cjs/i18n/index.d.ts.map +1 -0
- package/dist/cjs/i18n/index.js +15 -0
- package/dist/cjs/i18n/index.js.map +1 -0
- package/dist/cjs/i18n/rw.json +7 -0
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/integrations/checkout-script.d.ts +10 -0
- package/dist/cjs/integrations/checkout-script.d.ts.map +1 -0
- package/dist/cjs/integrations/checkout-script.js +38 -0
- package/dist/cjs/integrations/checkout-script.js.map +1 -0
- package/dist/cjs/integrations/index.d.ts +5 -0
- package/dist/cjs/integrations/index.d.ts.map +1 -0
- package/dist/cjs/integrations/index.js +49 -0
- package/dist/cjs/integrations/index.js.map +1 -0
- package/dist/cjs/integrations/mastercard.d.ts +11 -0
- package/dist/cjs/integrations/mastercard.d.ts.map +1 -0
- package/dist/cjs/integrations/mastercard.js +100 -0
- package/dist/cjs/integrations/mastercard.js.map +1 -0
- package/dist/cjs/integrations/types.d.ts +31 -0
- package/dist/cjs/integrations/types.d.ts.map +1 -0
- package/dist/cjs/integrations/types.js +3 -0
- package/dist/cjs/integrations/types.js.map +1 -0
- package/dist/cjs/state/index.d.ts +6 -1
- package/dist/cjs/state/index.d.ts.map +1 -1
- package/dist/cjs/state/index.js +9 -2
- package/dist/cjs/state/index.js.map +1 -1
- package/dist/cjs/types/index.d.ts +38 -1
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.d.ts +12 -1
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +39 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/esm/client/index.d.ts +27 -3
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +148 -90
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/i18n/en.json +7 -0
- package/dist/esm/i18n/fr.json +7 -0
- package/dist/esm/i18n/index.d.ts +2 -0
- package/dist/esm/i18n/index.d.ts.map +1 -0
- package/dist/esm/i18n/index.js +9 -0
- package/dist/esm/i18n/index.js.map +1 -0
- package/dist/esm/i18n/rw.json +7 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/integrations/checkout-script.d.ts +10 -0
- package/dist/esm/integrations/checkout-script.d.ts.map +1 -0
- package/dist/esm/integrations/checkout-script.js +35 -0
- package/dist/esm/integrations/checkout-script.js.map +1 -0
- package/dist/esm/integrations/index.d.ts +5 -0
- package/dist/esm/integrations/index.d.ts.map +1 -0
- package/dist/esm/integrations/index.js +11 -0
- package/dist/esm/integrations/index.js.map +1 -0
- package/dist/esm/integrations/mastercard.d.ts +11 -0
- package/dist/esm/integrations/mastercard.d.ts.map +1 -0
- package/dist/esm/integrations/mastercard.js +97 -0
- package/dist/esm/integrations/mastercard.js.map +1 -0
- package/dist/esm/integrations/types.d.ts +31 -0
- package/dist/esm/integrations/types.d.ts.map +1 -0
- package/dist/esm/integrations/types.js +2 -0
- package/dist/esm/integrations/types.js.map +1 -0
- package/dist/esm/state/index.d.ts +6 -1
- package/dist/esm/state/index.d.ts.map +1 -1
- package/dist/esm/state/index.js +10 -3
- package/dist/esm/state/index.js.map +1 -1
- package/dist/esm/types/index.d.ts +38 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/utils/index.d.ts +12 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +36 -0
- package/dist/esm/utils/index.js.map +1 -1
- 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
|
|
3
|
+
Framework-agnostic SDK for event form integration — fetch forms, handle visibility, upload files, submit, and process payments.
|
|
4
4
|
|
|
5
|
-
Works with
|
|
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,
|
|
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
|
|
20
|
+
apiKey: "Am_550e8400-...",
|
|
30
21
|
resourceType: "ticketing",
|
|
31
|
-
locale: "en", // default locale for all requests
|
|
32
22
|
});
|
|
33
23
|
|
|
34
|
-
//
|
|
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
|
-
//
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
83
|
+
## Client Methods
|
|
83
84
|
|
|
84
|
-
|
|
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
|
-
|
|
93
|
-
|
|
88
|
+
// Fetch all tickets (with optional locale/name filter)
|
|
89
|
+
const tickets = await client.fetchTickets({ locale: "fr", name: "VIP" });
|
|
94
90
|
|
|
95
|
-
|
|
91
|
+
// Fetch a single ticket by ID
|
|
92
|
+
const ticket = await client.fetchTicketById(42);
|
|
96
93
|
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
###
|
|
103
|
-
|
|
104
|
-
#### `client.fetchTickets(options?)`
|
|
105
|
-
|
|
106
|
-
Fetch all published tickets for the event.
|
|
98
|
+
### Languages & Forms
|
|
107
99
|
|
|
108
100
|
```ts
|
|
109
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
136
|
+
client.setLocale("fr");
|
|
137
|
+
client.getLocale(); // "fr"
|
|
138
|
+
client.clearCache();
|
|
164
139
|
```
|
|
165
140
|
|
|
166
|
-
|
|
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
|
-
|
|
144
|
+
// Preload the Mastercard checkout script before it's needed
|
|
145
|
+
await client.preloadCheckoutScript();
|
|
176
146
|
```
|
|
177
147
|
|
|
178
|
-
|
|
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
|
-
|
|
188
|
-
eventId: form.eventId,
|
|
189
|
-
ticketId: 1,
|
|
190
|
-
locale: "en",
|
|
191
|
-
});
|
|
192
|
-
```
|
|
153
|
+
import { FormStateManager, getAllFields } from "@amalaika/form-sdk-package";
|
|
193
154
|
|
|
194
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
170
|
+
// Visibility-aware submission data (excludes hidden fields)
|
|
171
|
+
const data = state.getSubmissionData();
|
|
205
172
|
|
|
206
|
-
|
|
173
|
+
// Get visible field IDs based on conditional logic
|
|
174
|
+
const visible = state.getVisibleFieldIds();
|
|
207
175
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```
|
|
176
|
+
// Resolve active payment integrations
|
|
177
|
+
const integrations = state.getActiveIntegrations();
|
|
211
178
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
179
|
+
// Subscribe to changes
|
|
180
|
+
const unsubscribe = state.onChange(({ fieldId, value, values }) => {
|
|
181
|
+
console.log(`${fieldId} changed to`, value);
|
|
182
|
+
});
|
|
215
183
|
|
|
216
|
-
|
|
217
|
-
|
|
184
|
+
// Reset to initial state
|
|
185
|
+
state.reset();
|
|
218
186
|
```
|
|
219
187
|
|
|
220
|
-
|
|
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
|
-
|
|
230
|
-
// render this field
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Returns `boolean`.
|
|
191
|
+
import { validateField, validateForm, getAllFields } from "@amalaika/form-sdk-package";
|
|
235
192
|
|
|
236
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
202
|
+
Supports: `required`, `minLength`, `maxLength`, `min`, `max`, `pattern`, `accept` (file types), `maxSize` (file size).
|
|
260
203
|
|
|
261
|
-
##
|
|
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
|
-
|
|
271
|
-
|
|
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
|
-
//
|
|
277
|
-
const
|
|
278
|
-
const
|
|
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
|
-
//
|
|
301
|
-
const
|
|
302
|
-
const
|
|
303
|
-
const
|
|
304
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
##
|
|
257
|
+
## TypeScript
|
|
258
|
+
|
|
259
|
+
All types are exported:
|
|
314
260
|
|
|
315
261
|
```ts
|
|
316
262
|
import type {
|
|
317
|
-
ErrorMessages,
|
|
318
263
|
EventFormConfig,
|
|
319
|
-
|
|
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
|
-
##
|
|
281
|
+
## i18n
|
|
331
282
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
-
|
|
337
|
-
npm run build
|
|
291
|
+
## Build
|
|
338
292
|
|
|
339
|
-
|
|
340
|
-
npm test
|
|
293
|
+
The package ships ESM and CJS builds with TypeScript declarations:
|
|
341
294
|
|
|
342
|
-
|
|
343
|
-
npm run
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}
|