@expresscsv/sdk 0.1.22 → 0.1.23
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 +53 -193
- package/dist/index.d.cts +62 -62
- package/dist/index.d.mts +62 -62
- package/dist/index.d.ts +62 -62
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,15 +44,17 @@ const importer = new CSVImporter({
|
|
|
44
44
|
importer.open({
|
|
45
45
|
onData: (chunk, next) => {
|
|
46
46
|
console.log(`Chunk ${chunk.currentChunkIndex + 1}/${chunk.totalChunks}`);
|
|
47
|
+
console.log("Session:", chunk.sessionId);
|
|
48
|
+
console.log("Idempotency key:", chunk.chunkIdempotencyKey);
|
|
47
49
|
console.log("Records:", chunk.records);
|
|
48
50
|
// Process your validated, typed records here
|
|
49
51
|
next();
|
|
50
52
|
},
|
|
51
|
-
onComplete: () => {
|
|
52
|
-
console.log("All chunks processed successfully");
|
|
53
|
+
onComplete: ({ sessionId }) => {
|
|
54
|
+
console.log("All chunks processed successfully for", sessionId);
|
|
53
55
|
},
|
|
54
|
-
onError: (error) => {
|
|
55
|
-
console.error("Import failed
|
|
56
|
+
onError: (error, { sessionId }) => {
|
|
57
|
+
console.error("Import failed for", sessionId, error);
|
|
56
58
|
},
|
|
57
59
|
});
|
|
58
60
|
```
|
|
@@ -61,182 +63,52 @@ If your schema is assembled dynamically at runtime, still use `x.row(...)`. Just
|
|
|
61
63
|
|
|
62
64
|
Have your backend keep the ExpressCSV secret key, call the ExpressCSV session-creation endpoint, and return a short-lived importer session token to the browser via `getSessionToken`. The SDK opens the importer immediately, then completes the initial session bootstrap in the background.
|
|
63
65
|
|
|
64
|
-
##
|
|
66
|
+
## Delivery
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
importer.open({
|
|
70
|
-
webhook: {
|
|
71
|
-
url: "https://api.example.com/webhooks/csv-import",
|
|
72
|
-
method: "POST",
|
|
73
|
-
headers: {
|
|
74
|
-
Authorization: "Bearer your-api-token",
|
|
75
|
-
},
|
|
76
|
-
metadata: {
|
|
77
|
-
source: "web-app",
|
|
78
|
-
userId: "user-123",
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
onComplete: () => {
|
|
82
|
-
console.log("Webhook delivery initiated");
|
|
83
|
-
},
|
|
84
|
-
onError: (error) => {
|
|
85
|
-
console.error("Delivery error:", error);
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Webhook Payload Structure
|
|
91
|
-
|
|
92
|
-
Each chunk is delivered as a JSON `POST` (or whichever method you configured) to your endpoint. The request body has this shape:
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
interface WebhookPayload {
|
|
96
|
-
/** Imported records for this chunk, matching your schema */
|
|
97
|
-
records: Record<string, unknown>[];
|
|
98
|
-
/** 0-based index of the current chunk */
|
|
99
|
-
chunkIndex: number;
|
|
100
|
-
/** Total number of chunks in this delivery */
|
|
101
|
-
totalChunks: number;
|
|
102
|
-
/** Total number of records across all chunks */
|
|
103
|
-
totalRecords: number;
|
|
104
|
-
/** Present only if you passed `metadata` in `WebhookConfig` */
|
|
105
|
-
metadata?: Record<string, unknown>;
|
|
106
|
-
/** Delivery context added by ExpressCSV */
|
|
107
|
-
delivery: {
|
|
108
|
-
environmentName: string;
|
|
109
|
-
environmentType: string;
|
|
110
|
-
teamSlug: string;
|
|
111
|
-
importIdentifier: string;
|
|
112
|
-
deliveryId: string;
|
|
113
|
-
timestamp: string; // ISO 8601
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
When you already have a schema, prefer `InferWebhookPayload<typeof schema>` from `@expresscsv/schemas` instead of rewriting this object shape by hand.
|
|
119
|
-
|
|
120
|
-
Example payload:
|
|
121
|
-
|
|
122
|
-
```json
|
|
123
|
-
{
|
|
124
|
-
"records": [
|
|
125
|
-
{ "name": "Alice Johnson", "email": "alice@example.com", "age": 32 },
|
|
126
|
-
{ "name": "Bob Smith", "email": "bob@example.com", "age": 45 }
|
|
127
|
-
],
|
|
128
|
-
"chunkIndex": 0,
|
|
129
|
-
"totalChunks": 3,
|
|
130
|
-
"totalRecords": 2500,
|
|
131
|
-
"metadata": {
|
|
132
|
-
"source": "web-app",
|
|
133
|
-
"userId": "user-123"
|
|
134
|
-
},
|
|
135
|
-
"delivery": {
|
|
136
|
-
"environmentName": "Production",
|
|
137
|
-
"environmentType": "production",
|
|
138
|
-
"teamSlug": "my-team",
|
|
139
|
-
"importIdentifier": "user-import",
|
|
140
|
-
"deliveryId": "del_abc123",
|
|
141
|
-
"timestamp": "2026-03-02T14:30:00.000Z"
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
The request includes a `Content-Type: application/json` header plus any custom `headers` you specified in `WebhookConfig`.
|
|
147
|
-
|
|
148
|
-
### Handling Webhooks on Your Server
|
|
149
|
-
|
|
150
|
-
Your endpoint should return a **2xx** status code to acknowledge each chunk. Non-2xx responses trigger the following retry behaviour:
|
|
151
|
-
|
|
152
|
-
- **5xx** and **429** responses are retried automatically (up to 5 attempts per chunk).
|
|
153
|
-
- **4xx** responses (except 429) are treated as permanent failures and are **not** retried.
|
|
154
|
-
|
|
155
|
-
Chunks are delivered **serially** — the next chunk is only sent after the previous one succeeds.
|
|
156
|
-
|
|
157
|
-
If your schema is defined in shared or backend code with `@expresscsv/schemas`, you can reuse the built-in webhook payload helper when handling deliveries:
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
import express from "express";
|
|
161
|
-
import type { InferWebhookPayload } from "@expresscsv/schemas";
|
|
162
|
-
import { employeeSchema } from "../shared/employee-schema";
|
|
163
|
-
|
|
164
|
-
const app = express();
|
|
165
|
-
app.use(express.json());
|
|
166
|
-
|
|
167
|
-
app.post("/webhooks/csv-import", async (req, res) => {
|
|
168
|
-
const payload = req.body as InferWebhookPayload<typeof employeeSchema>;
|
|
169
|
-
|
|
170
|
-
await db.insertMany("users", payload.records);
|
|
171
|
-
|
|
172
|
-
res.status(200).json({ ok: true });
|
|
173
|
-
});
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Below is a minimal Express.js example:
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
import express from "express";
|
|
180
|
-
|
|
181
|
-
const app = express();
|
|
182
|
-
app.use(express.json());
|
|
183
|
-
|
|
184
|
-
app.post("/webhooks/csv-import", async (req, res) => {
|
|
185
|
-
const token = req.headers.authorization;
|
|
186
|
-
if (token !== "Bearer your-api-token") {
|
|
187
|
-
return res.status(401).json({ error: "Unauthorized" });
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const { records, chunkIndex, totalChunks, totalRecords, metadata, delivery } =
|
|
191
|
-
req.body;
|
|
192
|
-
|
|
193
|
-
try {
|
|
194
|
-
// Process the records — e.g. insert into your database
|
|
195
|
-
await db.insertMany("users", records);
|
|
196
|
-
|
|
197
|
-
console.log(
|
|
198
|
-
`Chunk ${chunkIndex + 1}/${totalChunks} processed ` +
|
|
199
|
-
`(${records.length} records, delivery ${delivery.deliveryId})`
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
res.status(200).json({ success: true });
|
|
203
|
-
} catch (error) {
|
|
204
|
-
// Return 500 so ExpressCSV retries this chunk
|
|
205
|
-
console.error("Failed to process chunk:", error);
|
|
206
|
-
res.status(500).json({ error: "Internal server error" });
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
app.listen(3000);
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
**Tips:**
|
|
214
|
-
|
|
215
|
-
- Use `delivery.deliveryId` and `chunkIndex` to **deduplicate** retried chunks (the same chunk may be delivered more than once on retry).
|
|
216
|
-
- Use `chunkIndex` and `totalChunks` to track progress and know when the full import is complete (`chunkIndex === totalChunks - 1` for the last chunk).
|
|
217
|
-
- Store `metadata` alongside imported records if you need to correlate the import with a specific user or action in your app.
|
|
218
|
-
|
|
219
|
-
### Combined Local Callback and Webhook
|
|
220
|
-
|
|
221
|
-
You can use both `onData` and `webhook` simultaneously:
|
|
68
|
+
ExpressCSV delivers imported data through `onData`. Your app receives validated chunks in the browser and can forward them to your backend using whatever request shape fits your stack.
|
|
222
69
|
|
|
223
70
|
```typescript
|
|
224
71
|
importer.open({
|
|
225
72
|
chunkSize: 500,
|
|
226
73
|
onData: async (chunk, next) => {
|
|
227
|
-
await
|
|
74
|
+
const response = await fetch("/api/import-users/chunks", {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: {
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
sessionId: chunk.sessionId,
|
|
81
|
+
chunkIdempotencyKey: chunk.chunkIdempotencyKey,
|
|
82
|
+
records: chunk.records,
|
|
83
|
+
currentChunkIndex: chunk.currentChunkIndex,
|
|
84
|
+
totalChunks: chunk.totalChunks,
|
|
85
|
+
totalRecords: chunk.totalRecords,
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw new Error("Backend rejected this import chunk");
|
|
91
|
+
}
|
|
92
|
+
|
|
228
93
|
next();
|
|
229
94
|
},
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
headers: { Authorization: "Bearer your-api-token" },
|
|
233
|
-
},
|
|
234
|
-
onComplete: () => {
|
|
235
|
-
console.log("Local processing and webhook delivery complete");
|
|
95
|
+
onComplete: ({ sessionId }) => {
|
|
96
|
+
console.log("Import complete for", sessionId);
|
|
236
97
|
},
|
|
237
98
|
});
|
|
238
99
|
```
|
|
239
100
|
|
|
101
|
+
Each delivered chunk includes:
|
|
102
|
+
|
|
103
|
+
- `records`
|
|
104
|
+
- `sessionId`
|
|
105
|
+
- `chunkIdempotencyKey`
|
|
106
|
+
- `currentChunkIndex`
|
|
107
|
+
- `totalChunks`
|
|
108
|
+
- `totalRecords`
|
|
109
|
+
|
|
110
|
+
Use `sessionId` and `chunkIdempotencyKey` to stage writes safely and deduplicate retries from your own app logic.
|
|
111
|
+
|
|
240
112
|
## Preloading
|
|
241
113
|
|
|
242
114
|
By default, the SDK preloads the importer in a hidden iframe for instant display when `open()` is called. This provides the best user experience while the initial session bootstrap continues in the background.
|
|
@@ -432,7 +304,7 @@ const importer = new CSVImporter({
|
|
|
432
304
|
|
|
433
305
|
The `x` schema builder provides a type-safe, fluent API for defining your CSV structure.
|
|
434
306
|
|
|
435
|
-
For apps that share schema definitions with backend code
|
|
307
|
+
For apps that share schema definitions with backend code, prefer defining the schema in `@expresscsv/schemas` and importing it into your frontend. That keeps schema authoring free of importer/runtime dependencies.
|
|
436
308
|
|
|
437
309
|
### Field Types
|
|
438
310
|
|
|
@@ -689,13 +561,16 @@ new CSVImporter(options: SDKOptions)
|
|
|
689
561
|
| `fonts` | `Record<string, ECSVFontSource>` | No | - | Custom font sources |
|
|
690
562
|
| `stepDisplay` | `'progressBar' \| 'segmented' \| 'numbered'` | No | `'progressBar'` | Step indicator style |
|
|
691
563
|
| `previewSchemaBeforeUpload` | `boolean` | No | `true` | Show schema preview before upload |
|
|
564
|
+
| `aiColumnMatching` | `boolean` | No | `true` | Enable AI-assisted column matching |
|
|
565
|
+
| `aiTransform` | `boolean` | No | `true` | Enable AI-assisted transform generation |
|
|
692
566
|
| `templateDownload` | `TemplateDownloadOptions<TSchema>` | No | - | Template download configuration with optional schema-typed example rows |
|
|
693
|
-
| `
|
|
567
|
+
| `storage` | `{ type: "local" } \| { type: "custom", ... }` | No | - | Enable Recovered Sessions with the built-in local backend or a custom adapter implementing `get`, `set`, and `remove` |
|
|
694
568
|
| `locale` | `DeepPartial<ExpressCSVLocaleInput>` | No | - | Localization overrides |
|
|
569
|
+
| `disableStatusStep` | `boolean` | No | - | Skip the success/error status screen |
|
|
695
570
|
|
|
696
571
|
#### `open(options)`
|
|
697
572
|
|
|
698
|
-
Opens the importer and begins the import flow.
|
|
573
|
+
Opens the importer and begins the import flow.
|
|
699
574
|
|
|
700
575
|
```typescript
|
|
701
576
|
importer.open(options: OpenOptions): void
|
|
@@ -703,18 +578,15 @@ importer.open(options: OpenOptions): void
|
|
|
703
578
|
|
|
704
579
|
| Option | Type | Required | Description |
|
|
705
580
|
|---|---|---|---|
|
|
706
|
-
| `onData` | `(chunk: RecordsChunk<T>, next: () => void) => void` |
|
|
707
|
-
| `webhook` | `WebhookConfig` | * | Webhook endpoint for server-side delivery |
|
|
581
|
+
| `onData` | `(chunk: RecordsChunk<T>, next: () => void) => void` | Yes | Callback for each delivered chunk of records. Call `next()` to continue. |
|
|
708
582
|
| `chunkSize` | `number` | No | Records per chunk (default: 1000) |
|
|
709
|
-
| `onComplete` | `() => void` | No | Called when all chunks have been processed |
|
|
710
|
-
| `onCancel` | `() => void` | No | Called when the user cancels the import |
|
|
711
|
-
| `onError` | `(error: Error) => void` | No | Called when an error occurs |
|
|
583
|
+
| `onComplete` | `(context: { sessionId: string }) => void` | No | Called when all chunks have been processed |
|
|
584
|
+
| `onCancel` | `(context: { sessionId: string }) => void` | No | Called when the user cancels the import |
|
|
585
|
+
| `onError` | `(error: Error, context: { sessionId: string }) => void` | No | Called when an error occurs |
|
|
712
586
|
| `onImporterOpen` | `() => void` | No | Called when the importer opens |
|
|
713
|
-
| `onImporterClose` | `(reason:
|
|
587
|
+
| `onImporterClose` | `(reason: 'user_close' \| 'cancel' \| 'complete' \| 'error') => void` | No | Called when the importer closes |
|
|
714
588
|
| `onStepChange` | `(stepId, previousStepId?) => void` | No | Called when the wizard step changes |
|
|
715
589
|
|
|
716
|
-
\* At least one of `onData` or `webhook` is required.
|
|
717
|
-
|
|
718
590
|
#### `close(reason?)`
|
|
719
591
|
|
|
720
592
|
Closes the importer and cleans up resources.
|
|
@@ -736,7 +608,6 @@ await importer.close(reason?: 'user_close' | 'cancel' | 'complete' | 'error'): P
|
|
|
736
608
|
| `getCanRestart()` | `boolean` | Whether the importer can be restarted |
|
|
737
609
|
| `getLastError()` | `Error \| null` | Last error, if any |
|
|
738
610
|
| `getStatus()` | `object` | Comprehensive status snapshot |
|
|
739
|
-
| `getVersion()` | `string` | SDK version |
|
|
740
611
|
|
|
741
612
|
#### `restart(newOptions?)`
|
|
742
613
|
|
|
@@ -752,19 +623,8 @@ interface RecordsChunk<T> {
|
|
|
752
623
|
totalChunks: number;
|
|
753
624
|
currentChunkIndex: number;
|
|
754
625
|
totalRecords: number;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
### `WebhookConfig`
|
|
759
|
-
|
|
760
|
-
```typescript
|
|
761
|
-
interface WebhookConfig {
|
|
762
|
-
url: string;
|
|
763
|
-
headers?: Record<string, string>;
|
|
764
|
-
method?: "POST" | "PUT" | "PATCH";
|
|
765
|
-
timeout?: number;
|
|
766
|
-
retries?: number;
|
|
767
|
-
metadata?: Record<string, unknown>;
|
|
626
|
+
sessionId: string;
|
|
627
|
+
chunkIdempotencyKey: string;
|
|
768
628
|
}
|
|
769
629
|
```
|
|
770
630
|
|
package/dist/index.d.cts
CHANGED
|
@@ -1256,6 +1256,8 @@ export declare class CSVImporter<TSchema extends ExType<unknown, ExBaseDef, unkn
|
|
|
1256
1256
|
private importerMode;
|
|
1257
1257
|
private canRestart;
|
|
1258
1258
|
private lastError;
|
|
1259
|
+
private stateChangeListeners;
|
|
1260
|
+
private lastTerminalSessionState;
|
|
1259
1261
|
private openOptions;
|
|
1260
1262
|
private cachedSchemaJson;
|
|
1261
1263
|
private initCompletePromise;
|
|
@@ -1263,11 +1265,17 @@ export declare class CSVImporter<TSchema extends ExType<unknown, ExBaseDef, unkn
|
|
|
1263
1265
|
private resolvedTemplateDownload;
|
|
1264
1266
|
private importerStartupGeneration;
|
|
1265
1267
|
constructor(options: SDKOptions<TSchema>);
|
|
1268
|
+
private getCustomStorageRpcHandler;
|
|
1266
1269
|
/**
|
|
1267
1270
|
* Enhanced state management
|
|
1268
1271
|
*/
|
|
1269
1272
|
private setState;
|
|
1270
1273
|
private updateDerivedState;
|
|
1274
|
+
private createSessionId;
|
|
1275
|
+
private getOrCreateSessionId;
|
|
1276
|
+
private getImportSessionContext;
|
|
1277
|
+
private getChunkIdempotencyKey;
|
|
1278
|
+
private createRecordsChunk;
|
|
1271
1279
|
private handleError;
|
|
1272
1280
|
private sendImportProgress;
|
|
1273
1281
|
private waitForEvent;
|
|
@@ -1297,16 +1305,7 @@ export declare class CSVImporter<TSchema extends ExType<unknown, ExBaseDef, unkn
|
|
|
1297
1305
|
*/
|
|
1298
1306
|
private createImportSession;
|
|
1299
1307
|
/**
|
|
1300
|
-
*
|
|
1301
|
-
* Chunks data using SDK-determined chunk size (independent of customer's chunkSize)
|
|
1302
|
-
*/
|
|
1303
|
-
private deliverToWebhook;
|
|
1304
|
-
/**
|
|
1305
|
-
* Send a single chunk to backend webhook API with retry logic
|
|
1306
|
-
*/
|
|
1307
|
-
private sendChunkToBackend;
|
|
1308
|
-
/**
|
|
1309
|
-
* Process results in chunks, calling onData and/or webhook for each chunk with backpressure control
|
|
1308
|
+
* Process results in chunks, calling onData with backpressure control
|
|
1310
1309
|
*/
|
|
1311
1310
|
private processResultsInChunks;
|
|
1312
1311
|
/**
|
|
@@ -1342,6 +1341,7 @@ export declare class CSVImporter<TSchema extends ExType<unknown, ExBaseDef, unkn
|
|
|
1342
1341
|
private handleImporterClosed;
|
|
1343
1342
|
private hideContainer;
|
|
1344
1343
|
getConnectionStatus(): boolean;
|
|
1344
|
+
subscribeToStateChanges(listener: StateChangeListener): () => void;
|
|
1345
1345
|
getState(): ImporterState;
|
|
1346
1346
|
getMode(): ImporterMode;
|
|
1347
1347
|
getIsReady(): boolean;
|
|
@@ -1358,7 +1358,6 @@ export declare class CSVImporter<TSchema extends ExType<unknown, ExBaseDef, unkn
|
|
|
1358
1358
|
lastError: Error | null;
|
|
1359
1359
|
connectionStatus: boolean;
|
|
1360
1360
|
};
|
|
1361
|
-
getVersion(): string;
|
|
1362
1361
|
}
|
|
1363
1362
|
|
|
1364
1363
|
/**
|
|
@@ -2004,6 +2003,13 @@ declare const CurrencyCodes: readonly [{
|
|
|
2004
2003
|
readonly numeric: "932";
|
|
2005
2004
|
}];
|
|
2006
2005
|
|
|
2006
|
+
export declare type CustomStorageOptions = {
|
|
2007
|
+
type: 'custom';
|
|
2008
|
+
get: (key: StorageKey) => Promise<StoredSession | null>;
|
|
2009
|
+
set: (key: StorageKey, value: StoredSession) => Promise<void>;
|
|
2010
|
+
remove: (key: StorageKey) => Promise<void>;
|
|
2011
|
+
};
|
|
2012
|
+
|
|
2007
2013
|
declare interface DatetimeOptions {
|
|
2008
2014
|
message?: string;
|
|
2009
2015
|
}
|
|
@@ -2012,19 +2018,9 @@ export declare type DeepPartial<T> = {
|
|
|
2012
2018
|
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
2013
2019
|
};
|
|
2014
2020
|
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
export declare type DeliveryOptions<T> = RequireAtLeastOne<DeliveryOptionsBase<T>, 'onData' | 'webhook'>;
|
|
2019
|
-
|
|
2020
|
-
/**
|
|
2021
|
-
* Base delivery options - at least one must be provided
|
|
2022
|
-
*/
|
|
2023
|
-
declare interface DeliveryOptionsBase<T> {
|
|
2024
|
-
/** Local callback for processing chunks */
|
|
2025
|
-
onData?: (chunk: RecordsChunk<T>, next: () => void) => void | Promise<void>;
|
|
2026
|
-
/** Webhook configuration for remote delivery */
|
|
2027
|
-
webhook?: WebhookConfig;
|
|
2021
|
+
export declare interface DeliveryOptions<T> {
|
|
2022
|
+
/** Callback for processing delivered chunks */
|
|
2023
|
+
onData: (chunk: RecordsChunk<T>, next: () => void) => void | Promise<void>;
|
|
2028
2024
|
}
|
|
2029
2025
|
|
|
2030
2026
|
/**
|
|
@@ -3624,12 +3620,21 @@ export declare enum ImporterState {
|
|
|
3624
3620
|
DESTROYED = "destroyed"
|
|
3625
3621
|
}
|
|
3626
3622
|
|
|
3623
|
+
export declare interface ImportSessionContext {
|
|
3624
|
+
/** Generated session ID for the current import run */
|
|
3625
|
+
sessionId: string;
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3627
3628
|
export declare type Infer<T extends ExType<unknown, ExBaseDef, unknown>> = T extends ExType<infer Output, ExBaseDef, unknown> ? Output : never;
|
|
3628
3629
|
|
|
3629
3630
|
export declare type InferCSVImporter<TSchema extends ExType<unknown, ExBaseDef, unknown>> = CSVImporter<TSchema>;
|
|
3630
3631
|
|
|
3631
3632
|
declare type IPAddressVersion = 'v4' | 'v6' | 'all';
|
|
3632
3633
|
|
|
3634
|
+
export declare type LocalStorageOptions = {
|
|
3635
|
+
type: 'local';
|
|
3636
|
+
};
|
|
3637
|
+
|
|
3633
3638
|
declare interface MultiselectOptions {
|
|
3634
3639
|
enforceCaseSensitiveMatch?: boolean;
|
|
3635
3640
|
message?: string;
|
|
@@ -3637,17 +3642,17 @@ declare interface MultiselectOptions {
|
|
|
3637
3642
|
|
|
3638
3643
|
/**
|
|
3639
3644
|
* Options for the open() method
|
|
3640
|
-
* Requires
|
|
3645
|
+
* Requires an onData callback for delivery
|
|
3641
3646
|
*/
|
|
3642
|
-
export declare type OpenOptions<T> =
|
|
3647
|
+
export declare type OpenOptions<T> = DeliveryOptions<T> & {
|
|
3643
3648
|
/** Number of records per chunk (default: 1000) */
|
|
3644
3649
|
chunkSize?: number;
|
|
3645
3650
|
/** Called when all chunks have been processed */
|
|
3646
|
-
onComplete?: () => void;
|
|
3651
|
+
onComplete?: (context: ImportSessionContext) => void;
|
|
3647
3652
|
/** Called when the user cancels the import */
|
|
3648
|
-
onCancel?: () => void;
|
|
3653
|
+
onCancel?: (context: ImportSessionContext) => void;
|
|
3649
3654
|
/** Called when an error occurs */
|
|
3650
|
-
onError?: (error: Error) => void;
|
|
3655
|
+
onError?: (error: Error, context: ImportSessionContext) => void;
|
|
3651
3656
|
/** Called when the importer opens */
|
|
3652
3657
|
onImporterOpen?: () => void;
|
|
3653
3658
|
/** Called when the importer closes */
|
|
@@ -3656,6 +3661,17 @@ export declare type OpenOptions<T> = RequireAtLeastOne<DeliveryOptionsBase<T>, '
|
|
|
3656
3661
|
onStepChange?: (stepId: ExpressCSVStep, previousStepId?: ExpressCSVStep) => void;
|
|
3657
3662
|
};
|
|
3658
3663
|
|
|
3664
|
+
declare interface PersistedImportSessionData {
|
|
3665
|
+
data: PersistedImportSessionPayload;
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3668
|
+
declare type PersistedImportSessionKey = string;
|
|
3669
|
+
|
|
3670
|
+
declare type PersistedImportSessionPayload = {
|
|
3671
|
+
rowData: Record<string, unknown>[];
|
|
3672
|
+
columnKeys: string[];
|
|
3673
|
+
};
|
|
3674
|
+
|
|
3659
3675
|
declare type PhoneNumberFormat = 'international' | 'national' | 'both';
|
|
3660
3676
|
|
|
3661
3677
|
declare type PhoneNumberOutput = 'e164' | 'formatted' | 'digits';
|
|
@@ -3762,6 +3778,10 @@ export declare interface RecordsChunk<T> {
|
|
|
3762
3778
|
currentChunkIndex: number;
|
|
3763
3779
|
/** Total number of records across all chunks */
|
|
3764
3780
|
totalRecords: number;
|
|
3781
|
+
/** Generated session ID for the current import run */
|
|
3782
|
+
sessionId: string;
|
|
3783
|
+
/** Stable per-chunk idempotency key */
|
|
3784
|
+
chunkIdempotencyKey: string;
|
|
3765
3785
|
}
|
|
3766
3786
|
|
|
3767
3787
|
declare type RefineBatchResultItem = {
|
|
@@ -3793,13 +3813,6 @@ declare type RefineResultItem = {
|
|
|
3793
3813
|
};
|
|
3794
3814
|
};
|
|
3795
3815
|
|
|
3796
|
-
/**
|
|
3797
|
-
* Type helper that requires at least one of the specified keys to be present
|
|
3798
|
-
*/
|
|
3799
|
-
declare type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & {
|
|
3800
|
-
[K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>;
|
|
3801
|
-
}[Keys];
|
|
3802
|
-
|
|
3803
3816
|
export declare interface SDKOptions<TSchema extends ExType<unknown, ExBaseDef, unknown>> {
|
|
3804
3817
|
schema: TSchema;
|
|
3805
3818
|
getSessionToken: () => Promise<string>;
|
|
@@ -3813,8 +3826,10 @@ export declare interface SDKOptions<TSchema extends ExType<unknown, ExBaseDef, u
|
|
|
3813
3826
|
fonts?: Record<string, ECSVFontSource>;
|
|
3814
3827
|
stepDisplay?: 'progressBar' | 'segmented' | 'numbered';
|
|
3815
3828
|
previewSchemaBeforeUpload?: boolean;
|
|
3829
|
+
aiColumnMatching?: boolean;
|
|
3830
|
+
aiTransform?: boolean;
|
|
3816
3831
|
templateDownload?: TemplateDownloadOptions<TSchema>;
|
|
3817
|
-
|
|
3832
|
+
storage?: StorageOptions;
|
|
3818
3833
|
locale?: DeepPartial<ExpressCSVLocaleInput>;
|
|
3819
3834
|
disableStatusStep?: boolean;
|
|
3820
3835
|
}
|
|
@@ -3831,6 +3846,16 @@ declare interface SelectOptions {
|
|
|
3831
3846
|
message?: string;
|
|
3832
3847
|
}
|
|
3833
3848
|
|
|
3849
|
+
declare type StateChangeListener = (state: ImporterState) => void;
|
|
3850
|
+
|
|
3851
|
+
export declare type StorageKey = PersistedImportSessionKey;
|
|
3852
|
+
|
|
3853
|
+
export declare type StorageOptions = LocalStorageOptions | CustomStorageOptions;
|
|
3854
|
+
|
|
3855
|
+
export declare type StoredSession = PersistedImportSessionData;
|
|
3856
|
+
|
|
3857
|
+
export declare type StoredSessionData = PersistedImportSessionPayload;
|
|
3858
|
+
|
|
3834
3859
|
declare type StripBrand<T> = {
|
|
3835
3860
|
[K in keyof T]: T[K] extends TemplateString<string> ? string : T[K] extends object ? StripBrand<T[K]> : T[K];
|
|
3836
3861
|
};
|
|
@@ -3927,31 +3952,6 @@ declare interface ValidatorCheck {
|
|
|
3927
3952
|
message?: string;
|
|
3928
3953
|
}
|
|
3929
3954
|
|
|
3930
|
-
/**
|
|
3931
|
-
* Webhook configuration for remote delivery of results
|
|
3932
|
-
*/
|
|
3933
|
-
export declare interface WebhookConfig {
|
|
3934
|
-
/** The URL to send webhook requests to */
|
|
3935
|
-
url: string;
|
|
3936
|
-
/** Optional HTTP headers to include in the request */
|
|
3937
|
-
headers?: Record<string, string>;
|
|
3938
|
-
/** HTTP method to use (default: 'POST') */
|
|
3939
|
-
method?: 'POST' | 'PUT' | 'PATCH';
|
|
3940
|
-
/** Request timeout in milliseconds (default: 30000) */
|
|
3941
|
-
timeout?: number;
|
|
3942
|
-
/** Number of retry attempts on failure (default: 0) */
|
|
3943
|
-
retries?: number;
|
|
3944
|
-
/** Arbitrary developer-provided metadata */
|
|
3945
|
-
metadata?: Record<string, unknown>;
|
|
3946
|
-
/**
|
|
3947
|
-
* Whether to wait for the delivery service to confirm the webhook was
|
|
3948
|
-
* successfully received before considering the import complete.
|
|
3949
|
-
* When false, the import completes as soon as all chunks are queued.
|
|
3950
|
-
* Default: false
|
|
3951
|
-
*/
|
|
3952
|
-
awaitWebhookArrival?: boolean;
|
|
3953
|
-
}
|
|
3954
|
-
|
|
3955
3955
|
export declare const x: {
|
|
3956
3956
|
string: typeof ExString.create;
|
|
3957
3957
|
number: typeof ExNumber.create;
|