@amalaika/form-sdk-package 1.0.0 → 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 -233
- package/dist/cjs/client/index.d.ts +42 -3
- package/dist/cjs/client/index.d.ts.map +1 -1
- package/dist/cjs/client/index.js +274 -73
- 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 +4 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +10 -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/{types.js.map → integrations/types.js.map} +1 -1
- package/dist/cjs/state/index.d.ts +29 -0
- package/dist/cjs/state/index.d.ts.map +1 -0
- package/dist/cjs/state/index.js +97 -0
- package/dist/cjs/state/index.js.map +1 -0
- package/dist/cjs/types/index.d.ts +80 -2
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.d.ts +14 -1
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +122 -4
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/esm/client/index.d.ts +42 -3
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +274 -73
- 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 +4 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -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/{types.js.map → integrations/types.js.map} +1 -1
- package/dist/esm/state/index.d.ts +29 -0
- package/dist/esm/state/index.d.ts.map +1 -0
- package/dist/esm/state/index.js +93 -0
- package/dist/esm/state/index.js.map +1 -0
- package/dist/esm/types/index.d.ts +80 -2
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/utils/index.d.ts +14 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +117 -4
- package/dist/esm/utils/index.js.map +1 -1
- package/package.json +2 -4
- package/dist/cjs/client/__tests__/client.spec.d.ts +0 -2
- package/dist/cjs/client/__tests__/client.spec.d.ts.map +0 -1
- package/dist/cjs/client/__tests__/client.spec.js +0 -300
- package/dist/cjs/client/__tests__/client.spec.js.map +0 -1
- package/dist/cjs/client.d.ts +0 -22
- package/dist/cjs/client.d.ts.map +0 -1
- package/dist/cjs/client.js +0 -111
- package/dist/cjs/client.js.map +0 -1
- package/dist/cjs/types.d.ts +0 -78
- package/dist/cjs/types.d.ts.map +0 -1
- package/dist/cjs/utils/__tests__/utils.spec.d.ts +0 -2
- package/dist/cjs/utils/__tests__/utils.spec.d.ts.map +0 -1
- package/dist/cjs/utils/__tests__/utils.spec.js +0 -172
- package/dist/cjs/utils/__tests__/utils.spec.js.map +0 -1
- package/dist/cjs/utils.d.ts +0 -5
- package/dist/cjs/utils.d.ts.map +0 -1
- package/dist/cjs/utils.js +0 -45
- package/dist/cjs/utils.js.map +0 -1
- package/dist/esm/client/__tests__/client.spec.d.ts +0 -2
- package/dist/esm/client/__tests__/client.spec.d.ts.map +0 -1
- package/dist/esm/client/__tests__/client.spec.js +0 -355
- package/dist/esm/client/__tests__/client.spec.js.map +0 -1
- package/dist/esm/client.d.ts +0 -22
- package/dist/esm/client.d.ts.map +0 -1
- package/dist/esm/client.js +0 -107
- package/dist/esm/client.js.map +0 -1
- package/dist/esm/types.d.ts +0 -78
- package/dist/esm/types.d.ts.map +0 -1
- package/dist/esm/utils/__tests__/utils.spec.d.ts +0 -2
- package/dist/esm/utils/__tests__/utils.spec.d.ts.map +0 -1
- package/dist/esm/utils/__tests__/utils.spec.js +0 -182
- package/dist/esm/utils/__tests__/utils.spec.js.map +0 -1
- package/dist/esm/utils.d.ts +0 -5
- package/dist/esm/utils.d.ts.map +0 -1
- package/dist/esm/utils.js +0 -40
- package/dist/esm/utils.js.map +0 -1
- /package/dist/cjs/{types.js → integrations/types.js} +0 -0
- /package/dist/esm/{types.js → integrations/types.js} +0 -0
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,333 +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
|
-
|
|
60
|
-
### Locale Management
|
|
61
|
-
|
|
62
|
-
Set a default locale on the constructor so you don't have to pass it on every method call:
|
|
45
|
+
## Configuration
|
|
63
46
|
|
|
64
47
|
```ts
|
|
65
48
|
const client = new EventFormClient({
|
|
49
|
+
// Required
|
|
66
50
|
apiKey: "Am_550e8400-...",
|
|
67
|
-
resourceType: "ticketing",
|
|
68
|
-
|
|
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
|
+
},
|
|
69
80
|
});
|
|
70
|
-
|
|
71
|
-
// All calls automatically use "fr" — no need to pass locale
|
|
72
|
-
const tickets = await client.fetchTickets();
|
|
73
|
-
const form = await client.fetchForm(tickets[0].id);
|
|
74
81
|
```
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
## Client Methods
|
|
77
84
|
|
|
78
|
-
|
|
79
|
-
client.setLocale("en");
|
|
80
|
-
// All subsequent calls now use "en"
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Read the current locale:
|
|
85
|
+
### Tickets
|
|
84
86
|
|
|
85
87
|
```ts
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
// Fetch all tickets (with optional locale/name filter)
|
|
89
|
+
const tickets = await client.fetchTickets({ locale: "fr", name: "VIP" });
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
// Fetch a single ticket by ID
|
|
92
|
+
const ticket = await client.fetchTicketById(42);
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const tickets = await client.fetchTickets({ locale: "de" });
|
|
94
|
+
// Fetch a public ticket (no auth required)
|
|
95
|
+
const publicTicket = await client.fetchPublicTicket(42, "en");
|
|
94
96
|
```
|
|
95
97
|
|
|
96
|
-
###
|
|
97
|
-
|
|
98
|
-
#### `client.fetchTickets(options?)`
|
|
99
|
-
|
|
100
|
-
Fetch all published tickets for the event.
|
|
98
|
+
### Languages & Forms
|
|
101
99
|
|
|
102
100
|
```ts
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
| Option | Type | Description |
|
|
107
|
-
|--------|------|-------------|
|
|
108
|
-
| `locale` | `string` | Locale code for translations (also sent as `Accept-Language`) |
|
|
109
|
-
| `name` | `string` | Filter tickets by name |
|
|
110
|
-
|
|
111
|
-
Returns `Promise<Ticket[]>`.
|
|
112
|
-
|
|
113
|
-
---
|
|
101
|
+
// Fetch available languages
|
|
102
|
+
const languages = await client.fetchLanguages(); // ["en", "fr", "rw"]
|
|
114
103
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
Fetch a single ticket by ID.
|
|
118
|
-
|
|
119
|
-
```ts
|
|
120
|
-
const ticket = await client.fetchTicketById(42, "en");
|
|
104
|
+
// Fetch form schema for a ticket
|
|
105
|
+
const form = await client.fetchForm(ticketId, "en");
|
|
121
106
|
```
|
|
122
107
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
#### `client.fetchLanguages()`
|
|
128
|
-
|
|
129
|
-
Fetch available languages for the event. Returns codes sorted with the default language first.
|
|
108
|
+
### File Uploads
|
|
130
109
|
|
|
131
110
|
```ts
|
|
132
|
-
|
|
133
|
-
|
|
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);
|
|
134
114
|
```
|
|
135
115
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
#### `client.fetchForm(ticketId, locale?)`
|
|
141
|
-
|
|
142
|
-
Fetch the form linked to a ticket.
|
|
116
|
+
### Form Submission
|
|
143
117
|
|
|
144
118
|
```ts
|
|
145
|
-
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
|
|
146
131
|
```
|
|
147
132
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
#### `client.authorizeUpload(formId, fieldId, file, locale?)`
|
|
153
|
-
|
|
154
|
-
Step 1 of file upload — request an upload token.
|
|
133
|
+
### Locale & Cache
|
|
155
134
|
|
|
156
135
|
```ts
|
|
157
|
-
|
|
136
|
+
client.setLocale("fr");
|
|
137
|
+
client.getLocale(); // "fr"
|
|
138
|
+
client.clearCache();
|
|
158
139
|
```
|
|
159
140
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
#### `client.uploadFile(formId, token, file, locale?)`
|
|
165
|
-
|
|
166
|
-
Step 2 of file upload — upload the file using the token.
|
|
141
|
+
### Payment
|
|
167
142
|
|
|
168
143
|
```ts
|
|
169
|
-
|
|
144
|
+
// Preload the Mastercard checkout script before it's needed
|
|
145
|
+
await client.preloadCheckoutScript();
|
|
170
146
|
```
|
|
171
147
|
|
|
172
|
-
|
|
148
|
+
## FormStateManager
|
|
173
149
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
#### `client.submitForm(formId, data, context)`
|
|
177
|
-
|
|
178
|
-
Submit form data.
|
|
150
|
+
Manages form field values, dirty/touched tracking, visibility, and change subscriptions.
|
|
179
151
|
|
|
180
152
|
```ts
|
|
181
|
-
|
|
182
|
-
eventId: form.eventId,
|
|
183
|
-
ticketId: 1,
|
|
184
|
-
locale: "en",
|
|
185
|
-
});
|
|
186
|
-
```
|
|
153
|
+
import { FormStateManager, getAllFields } from "@amalaika/form-sdk-package";
|
|
187
154
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
| `eventId` | `number` | Yes | Event ID (from `form.eventId`) |
|
|
191
|
-
| `ticketId` | `number` | Yes | Ticket ID used to fetch the form |
|
|
192
|
-
| `locale` | `string` | No | Locale for `Accept-Language` header |
|
|
155
|
+
const fields = getAllFields(form.schema);
|
|
156
|
+
const state = new FormStateManager(fields);
|
|
193
157
|
|
|
194
|
-
|
|
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" }
|
|
195
163
|
|
|
196
|
-
|
|
164
|
+
// Track user interaction
|
|
165
|
+
state.touchField("email");
|
|
166
|
+
state.isTouched("email"); // true
|
|
167
|
+
state.isDirty(); // true
|
|
168
|
+
state.getDirtyFields(); // Set(["name", "email"])
|
|
197
169
|
|
|
198
|
-
|
|
170
|
+
// Visibility-aware submission data (excludes hidden fields)
|
|
171
|
+
const data = state.getSubmissionData();
|
|
199
172
|
|
|
200
|
-
|
|
173
|
+
// Get visible field IDs based on conditional logic
|
|
174
|
+
const visible = state.getVisibleFieldIds();
|
|
201
175
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
```
|
|
176
|
+
// Resolve active payment integrations
|
|
177
|
+
const integrations = state.getActiveIntegrations();
|
|
205
178
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
179
|
+
// Subscribe to changes
|
|
180
|
+
const unsubscribe = state.onChange(({ fieldId, value, values }) => {
|
|
181
|
+
console.log(`${fieldId} changed to`, value);
|
|
182
|
+
});
|
|
209
183
|
|
|
210
|
-
|
|
211
|
-
|
|
184
|
+
// Reset to initial state
|
|
185
|
+
state.reset();
|
|
212
186
|
```
|
|
213
187
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
#### `isFieldVisible(field, formValues, allFields)`
|
|
219
|
-
|
|
220
|
-
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
|
|
221
189
|
|
|
222
190
|
```ts
|
|
223
|
-
|
|
224
|
-
// render this field
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
Returns `boolean`.
|
|
191
|
+
import { validateField, validateForm, getAllFields } from "@amalaika/form-sdk-package";
|
|
229
192
|
|
|
230
|
-
|
|
193
|
+
// Validate a single field
|
|
194
|
+
const result = validateField(field, value);
|
|
195
|
+
// { valid: true } or { valid: false, error: "This field is required" }
|
|
231
196
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
| `not_equals` | `formValues[dependsOn] !== value` |
|
|
236
|
-
| `in` | Any overlap between selected values and target values |
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
#### `getVisibleFieldIds(allFields, formValues)`
|
|
241
|
-
|
|
242
|
-
Returns the set of field IDs that are currently visible. Use this to filter submission data — only submit visible fields.
|
|
243
|
-
|
|
244
|
-
```ts
|
|
245
|
-
const visibleIds = getVisibleFieldIds(allFields, formValues);
|
|
246
|
-
|
|
247
|
-
const submissionData = {};
|
|
248
|
-
for (const [key, val] of Object.entries(formValues)) {
|
|
249
|
-
if (visibleIds.has(key)) submissionData[key] = val;
|
|
250
|
-
}
|
|
197
|
+
// Validate all visible fields at once
|
|
198
|
+
const results = validateForm(fields, values);
|
|
199
|
+
// { fieldId: { valid: boolean, error?: string }, ... }
|
|
251
200
|
```
|
|
252
201
|
|
|
253
|
-
|
|
202
|
+
Supports: `required`, `minLength`, `maxLength`, `min`, `max`, `pattern`, `accept` (file types), `maxSize` (file size).
|
|
254
203
|
|
|
255
|
-
##
|
|
204
|
+
## Utility Functions
|
|
256
205
|
|
|
257
206
|
```ts
|
|
258
207
|
import {
|
|
259
|
-
EventFormClient,
|
|
260
208
|
getAllFields,
|
|
209
|
+
isFieldVisible,
|
|
261
210
|
getVisibleFieldIds,
|
|
211
|
+
hasIntegration,
|
|
212
|
+
getIntegrationMethod,
|
|
213
|
+
resolveIntegrations,
|
|
262
214
|
} from "@amalaika/form-sdk-package";
|
|
263
215
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
resourceType: "ticketing",
|
|
267
|
-
locale: "en",
|
|
268
|
-
});
|
|
216
|
+
// Flatten fields from schema (handles flat and step-based layouts)
|
|
217
|
+
const fields = getAllFields(form.schema);
|
|
269
218
|
|
|
270
|
-
//
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
// 2. Fetch the form (uses default locale "en")
|
|
275
|
-
const form = await client.fetchForm(ticket.id);
|
|
276
|
-
const allFields = getAllFields(form.schema);
|
|
277
|
-
|
|
278
|
-
// 3. Collect user input into formValues (your UI handles this)
|
|
279
|
-
const formValues: Record<string, unknown> = {
|
|
280
|
-
first_name: "Jane",
|
|
281
|
-
last_name: "Doe",
|
|
282
|
-
email: "jane@example.com",
|
|
283
|
-
role: "speaker",
|
|
284
|
-
talk_title: "Building Dynamic Forms",
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
// 4. Filter to visible fields only
|
|
288
|
-
const visibleIds = getVisibleFieldIds(allFields, formValues);
|
|
289
|
-
const submissionData: Record<string, unknown> = {};
|
|
290
|
-
for (const [key, val] of Object.entries(formValues)) {
|
|
291
|
-
if (visibleIds.has(key)) submissionData[key] = val;
|
|
292
|
-
}
|
|
219
|
+
// Conditional visibility
|
|
220
|
+
const visible = isFieldVisible(field, formValues, allFields);
|
|
221
|
+
const visibleIds = getVisibleFieldIds(fields, formValues);
|
|
293
222
|
|
|
294
|
-
//
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
-
const
|
|
298
|
-
|
|
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
|
|
299
237
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
|
304
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
|
+
}
|
|
305
255
|
```
|
|
306
256
|
|
|
307
|
-
##
|
|
257
|
+
## TypeScript
|
|
258
|
+
|
|
259
|
+
All types are exported:
|
|
308
260
|
|
|
309
261
|
```ts
|
|
310
262
|
import type {
|
|
311
|
-
ErrorMessages,
|
|
312
263
|
EventFormConfig,
|
|
313
|
-
|
|
264
|
+
FormData,
|
|
265
|
+
FormSchema,
|
|
314
266
|
FieldDefinition,
|
|
267
|
+
FieldOption,
|
|
315
268
|
StepDefinition,
|
|
316
|
-
FormSchema,
|
|
317
|
-
FormData,
|
|
318
|
-
ApiResponse,
|
|
319
|
-
TicketTranslation,
|
|
320
269
|
Ticket,
|
|
270
|
+
TicketTranslation,
|
|
271
|
+
ValidationResult,
|
|
272
|
+
SubmissionResponse,
|
|
273
|
+
PaymentInfo,
|
|
274
|
+
IntegrationResult,
|
|
275
|
+
ResolvedIntegration,
|
|
276
|
+
ApiResponse,
|
|
277
|
+
ErrorMessages,
|
|
321
278
|
} from "@amalaika/form-sdk-package";
|
|
322
279
|
```
|
|
323
280
|
|
|
324
|
-
##
|
|
281
|
+
## i18n
|
|
325
282
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
+
```
|
|
329
290
|
|
|
330
|
-
|
|
331
|
-
npm run build
|
|
291
|
+
## Build
|
|
332
292
|
|
|
333
|
-
|
|
334
|
-
npm test
|
|
293
|
+
The package ships ESM and CJS builds with TypeScript declarations:
|
|
335
294
|
|
|
336
|
-
|
|
337
|
-
npm run
|
|
295
|
+
```bash
|
|
296
|
+
npm run build # Build both ESM and CJS
|
|
297
|
+
npm test # Run tests (212 tests, 100% coverage)
|
|
338
298
|
```
|
|
339
299
|
|
|
340
300
|
## License
|
|
341
301
|
|
|
342
|
-
|
|
302
|
+
ISC
|
|
@@ -1,26 +1,65 @@
|
|
|
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;
|
|
5
5
|
private readonly resourceType;
|
|
6
6
|
private readonly messages;
|
|
7
|
+
private readonly origin;
|
|
8
|
+
private readonly timeout;
|
|
9
|
+
private readonly retryConfig;
|
|
10
|
+
private readonly cacheConfig;
|
|
11
|
+
private readonly noCache;
|
|
12
|
+
private readonly interceptors;
|
|
13
|
+
private readonly mastercardCheckoutUrl;
|
|
14
|
+
private readonly merchantName;
|
|
15
|
+
private readonly cache;
|
|
7
16
|
private locale;
|
|
8
17
|
constructor(config: EventFormConfig);
|
|
9
18
|
setLocale(locale: string): void;
|
|
10
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>;
|
|
25
|
+
clearCache(): void;
|
|
26
|
+
private getCached;
|
|
27
|
+
private setCache;
|
|
28
|
+
private applyRequestInterceptor;
|
|
29
|
+
private applyResponseInterceptor;
|
|
30
|
+
private applyErrorInterceptor;
|
|
31
|
+
private throwMapped;
|
|
32
|
+
private cachedGet;
|
|
33
|
+
private isRetryable;
|
|
34
|
+
private executeRequest;
|
|
11
35
|
fetchTickets(options?: {
|
|
12
36
|
locale?: string;
|
|
13
37
|
name?: string;
|
|
14
38
|
}): Promise<Ticket[]>;
|
|
15
39
|
fetchTicketById(id: number, locale?: string): Promise<Ticket>;
|
|
40
|
+
fetchPublicTicket(id: number, locale?: string): Promise<Ticket>;
|
|
16
41
|
fetchLanguages(): Promise<string[]>;
|
|
17
42
|
fetchForm(ticketId: number, locale?: string): Promise<FormData>;
|
|
18
43
|
authorizeUpload(formId: number, fieldId: string, file: File, locale?: string): Promise<string>;
|
|
19
44
|
uploadFile(formId: number, token: string, file: File, locale?: string): Promise<string>;
|
|
20
|
-
|
|
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: {
|
|
21
53
|
eventId: number;
|
|
22
54
|
ticketId: number;
|
|
23
55
|
locale?: string;
|
|
24
|
-
|
|
56
|
+
attendanceType?: "HYBRID" | "PHYSICAL" | "VIRTUAL" | null;
|
|
57
|
+
containerId?: string;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
submission: SubmissionResponse;
|
|
60
|
+
integrations: Array<ResolvedIntegration & {
|
|
61
|
+
result: IntegrationResult;
|
|
62
|
+
}>;
|
|
63
|
+
}>;
|
|
25
64
|
}
|
|
26
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":"AAAA,OAAO,KAAK,EAGV,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,MAAM,EACP,MAAM,mBAAmB,CAAC;AAsE3B,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,qBAAqB,CAAqB;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,MAAM,CAAqB;gBAEvB,MAAM,EAAE,eAAe;IAsBnC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B;;;OAGG;IACH,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtC,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;YAML,SAAS;IAmBvB,OAAO,CAAC,WAAW;YAOL,cAAc;IAgDtB,YAAY,CAAC,OAAO,CAAC,EAAE;QAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWf,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS7D,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS/D,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BnC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAS/D,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAwBZ,UAAU,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAoBlB;;;;;;OAMG;IACG,UAAU,CACd,IAAI,EAAE,QAAQ,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;QAChB,cAAc,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;QAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GACA,OAAO,CAAC;QACT,UAAU,EAAE,kBAAkB,CAAC;QAC/B,YAAY,EAAE,KAAK,CAAC,mBAAmB,GAAG;YAAE,MAAM,EAAE,iBAAiB,CAAA;SAAE,CAAC,CAAC;KAC1E,CAAC;CAwEH"}
|