react-csv-autopilot 0.0.3 → 1.0.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 +2 -2
- package/dist/index.cjs +137 -46
- package/dist/index.d.cts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +137 -46
- package/package.json +34 -34
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ function ExportButton() {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
const handleExport = async () => {
|
|
59
|
-
await handler.
|
|
59
|
+
await handler.execute({
|
|
60
60
|
fileName: 'users-export',
|
|
61
61
|
columns: [
|
|
62
62
|
{ key: 'id', label: 'ID' },
|
|
@@ -99,7 +99,7 @@ Hook that provides access to the CSV export controller.
|
|
|
99
99
|
```typescript
|
|
100
100
|
const { handler } = useExportCSV();
|
|
101
101
|
|
|
102
|
-
await handler.
|
|
102
|
+
await handler.execute({
|
|
103
103
|
fileName: 'data-export',
|
|
104
104
|
columns: [...],
|
|
105
105
|
getNextPage: async (offset) => {...}
|
package/dist/index.cjs
CHANGED
|
@@ -59,14 +59,6 @@ resolveStrategy_fn = function() {
|
|
|
59
59
|
return this.deps.blobExportStrategy;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
// src/core/strategy/BolbExportStrategy.ts
|
|
63
|
-
var BolbExportStrategy = class {
|
|
64
|
-
export(params) {
|
|
65
|
-
return Promise.resolve({});
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
var BolbExportStrategy_default = BolbExportStrategy;
|
|
69
|
-
|
|
70
62
|
// src/core/contants/index.ts
|
|
71
63
|
var WEB_WORKER_NAME = "scv-worker";
|
|
72
64
|
var BROADCAST_CHANNEL_NAME = "react-csv-exporter";
|
|
@@ -86,8 +78,8 @@ var _WorkerManager = class _WorkerManager {
|
|
|
86
78
|
workerUrl = "/worker.js";
|
|
87
79
|
}
|
|
88
80
|
__privateSet(this, _worker, new Worker(workerUrl, {
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
name: WEB_WORKER_NAME,
|
|
82
|
+
type: "module"
|
|
91
83
|
}));
|
|
92
84
|
__privateMethod(this, _WorkerManager_instances, listenerRegistry_fn).call(this);
|
|
93
85
|
}
|
|
@@ -97,9 +89,9 @@ var _WorkerManager = class _WorkerManager {
|
|
|
97
89
|
async triggerWorker(payload) {
|
|
98
90
|
const id = payload.id ?? Math.random().toString(36).substr(2);
|
|
99
91
|
const p = new Promise((resolve, reject) => {
|
|
100
|
-
pending.set(id, {
|
|
92
|
+
pending.set(id, { reject, resolve });
|
|
101
93
|
});
|
|
102
|
-
__privateGet(this, _worker)
|
|
94
|
+
__privateGet(this, _worker)?.postMessage(payload);
|
|
103
95
|
return p;
|
|
104
96
|
}
|
|
105
97
|
terminate() {
|
|
@@ -112,7 +104,7 @@ var _WorkerManager = class _WorkerManager {
|
|
|
112
104
|
_worker = new WeakMap();
|
|
113
105
|
_WorkerManager_instances = new WeakSet();
|
|
114
106
|
listenerRegistry_fn = function() {
|
|
115
|
-
__privateGet(this, _worker)
|
|
107
|
+
__privateGet(this, _worker)?.addEventListener("message", (event) => {
|
|
116
108
|
const { id, result, error } = event.data;
|
|
117
109
|
const entity = pending.get(id);
|
|
118
110
|
if (!entity) {
|
|
@@ -125,7 +117,7 @@ listenerRegistry_fn = function() {
|
|
|
125
117
|
entity.resolve(result);
|
|
126
118
|
}
|
|
127
119
|
});
|
|
128
|
-
__privateGet(this, _worker)
|
|
120
|
+
__privateGet(this, _worker)?.addEventListener("error", (event) => {
|
|
129
121
|
for (const [, { reject }] of pending) {
|
|
130
122
|
reject(event);
|
|
131
123
|
}
|
|
@@ -135,6 +127,103 @@ listenerRegistry_fn = function() {
|
|
|
135
127
|
var WorkerManager = _WorkerManager;
|
|
136
128
|
var WorkerManager_default = WorkerManager;
|
|
137
129
|
|
|
130
|
+
// src/core/strategy/BolbExportStrategy.ts
|
|
131
|
+
var BolbExportStrategy = class {
|
|
132
|
+
constructor() {
|
|
133
|
+
this.workerManager = WorkerManager_default.initialise();
|
|
134
|
+
}
|
|
135
|
+
async export(params) {
|
|
136
|
+
const suggestedName = params.fileName ?? "export";
|
|
137
|
+
const filename = suggestedName.endsWith(".csv") ? suggestedName : `${suggestedName}.csv`;
|
|
138
|
+
let iterator = 0;
|
|
139
|
+
let totalRowsLoaded = 0;
|
|
140
|
+
const messaging = new BroadcastChannel(BROADCAST_CHANNEL_NAME);
|
|
141
|
+
const csvParts = [];
|
|
142
|
+
try {
|
|
143
|
+
while (true) {
|
|
144
|
+
const response = await params.getNextPage(iterator++);
|
|
145
|
+
const safeRows = Array.isArray(response.rows) ? response.rows : [];
|
|
146
|
+
const safeTotal = response.total ?? 0;
|
|
147
|
+
const isRowsEmpty = safeRows.length === 0;
|
|
148
|
+
const nextRowsLoaded = totalRowsLoaded + safeRows.length;
|
|
149
|
+
totalRowsLoaded = isRowsEmpty ? safeTotal : nextRowsLoaded;
|
|
150
|
+
const isFinished = safeTotal > 0 ? totalRowsLoaded >= safeTotal : isRowsEmpty;
|
|
151
|
+
if (isRowsEmpty) {
|
|
152
|
+
messaging.postMessage(
|
|
153
|
+
JSON.stringify({
|
|
154
|
+
loadedItemsCount: totalRowsLoaded,
|
|
155
|
+
total: safeTotal,
|
|
156
|
+
type: "done"
|
|
157
|
+
})
|
|
158
|
+
);
|
|
159
|
+
await this.workerManager.triggerWorker({
|
|
160
|
+
id: iterator,
|
|
161
|
+
type: "completed"
|
|
162
|
+
});
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
const csvChunk = await this.workerManager.triggerWorker({
|
|
166
|
+
columns: params.columns,
|
|
167
|
+
data: safeRows,
|
|
168
|
+
id: iterator,
|
|
169
|
+
type: "to_csv_chunk"
|
|
170
|
+
});
|
|
171
|
+
csvParts.push(csvChunk);
|
|
172
|
+
messaging.postMessage(
|
|
173
|
+
JSON.stringify({
|
|
174
|
+
loadedItemsCount: totalRowsLoaded,
|
|
175
|
+
total: safeTotal,
|
|
176
|
+
type: "progress"
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
if (isFinished) {
|
|
180
|
+
messaging.postMessage(
|
|
181
|
+
JSON.stringify({
|
|
182
|
+
loadedItemsCount: totalRowsLoaded,
|
|
183
|
+
total: safeTotal,
|
|
184
|
+
type: "done"
|
|
185
|
+
})
|
|
186
|
+
);
|
|
187
|
+
await this.workerManager.triggerWorker({
|
|
188
|
+
id: iterator,
|
|
189
|
+
type: "completed"
|
|
190
|
+
});
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const blob = new Blob(["\uFEFF", ...csvParts], {
|
|
195
|
+
type: "text/csv;charset=utf-8"
|
|
196
|
+
});
|
|
197
|
+
this.downloadBlob(blob, filename);
|
|
198
|
+
return { finished: true, totalRowsLoaded };
|
|
199
|
+
} catch (error) {
|
|
200
|
+
messaging.postMessage(
|
|
201
|
+
JSON.stringify({
|
|
202
|
+
loadedItemsCount: totalRowsLoaded,
|
|
203
|
+
total: 0,
|
|
204
|
+
type: "failed"
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
throw error;
|
|
208
|
+
} finally {
|
|
209
|
+
messaging.close();
|
|
210
|
+
this.workerManager.terminate();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
downloadBlob(blob, filename) {
|
|
214
|
+
const url = URL.createObjectURL(blob);
|
|
215
|
+
const a = document.createElement("a");
|
|
216
|
+
a.href = url;
|
|
217
|
+
a.download = filename;
|
|
218
|
+
a.rel = "noopener";
|
|
219
|
+
document.body.appendChild(a);
|
|
220
|
+
a.click();
|
|
221
|
+
a.remove();
|
|
222
|
+
URL.revokeObjectURL(url);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
var BolbExportStrategy_default = BolbExportStrategy;
|
|
226
|
+
|
|
138
227
|
// src/core/strategy/FsAccessExportStrategy.ts
|
|
139
228
|
var FsAccessExportStrategy = class {
|
|
140
229
|
constructor() {
|
|
@@ -144,7 +233,7 @@ var FsAccessExportStrategy = class {
|
|
|
144
233
|
const _suggestedName = params?.fileName || "export";
|
|
145
234
|
const fileHandle = await window.showSaveFilePicker({
|
|
146
235
|
suggestedName: _suggestedName,
|
|
147
|
-
types: [{
|
|
236
|
+
types: [{ accept: { "text/csv": [".csv"] }, description: "CSV file" }]
|
|
148
237
|
});
|
|
149
238
|
const writableFileStream = await fileHandle.createWritable();
|
|
150
239
|
let iterator = 0;
|
|
@@ -158,44 +247,51 @@ var FsAccessExportStrategy = class {
|
|
|
158
247
|
const safeRows = Array.isArray(response.rows) ? response?.rows : [];
|
|
159
248
|
const safeTotal = response.total ?? 0;
|
|
160
249
|
const isRowsEmpty = !safeRows || !safeRows.length;
|
|
161
|
-
|
|
250
|
+
const nextRowsLoaded = totalRowsLoaded + safeRows.length;
|
|
251
|
+
totalRowsLoaded = isRowsEmpty ? safeTotal : nextRowsLoaded;
|
|
162
252
|
const isFinished = totalRowsLoaded >= safeTotal;
|
|
163
253
|
if (isRowsEmpty) {
|
|
164
254
|
messaging.postMessage(
|
|
165
255
|
JSON.stringify({
|
|
166
|
-
|
|
256
|
+
loadedItemsCount: totalRowsLoaded,
|
|
167
257
|
total: safeTotal,
|
|
168
|
-
|
|
258
|
+
type: "done"
|
|
169
259
|
})
|
|
170
260
|
);
|
|
171
|
-
await this.workerManager.triggerWorker({
|
|
261
|
+
await this.workerManager.triggerWorker({
|
|
262
|
+
id: iterator,
|
|
263
|
+
type: "completed"
|
|
264
|
+
});
|
|
172
265
|
messaging.close();
|
|
173
266
|
controller.close();
|
|
174
267
|
return;
|
|
175
268
|
}
|
|
176
269
|
const csvChunks = await this.workerManager.triggerWorker({
|
|
177
|
-
|
|
178
|
-
type: "to_csv_chunk",
|
|
270
|
+
columns: params.columns,
|
|
179
271
|
data: safeRows,
|
|
180
|
-
|
|
272
|
+
id: iterator,
|
|
273
|
+
type: "to_csv_chunk"
|
|
181
274
|
});
|
|
182
275
|
messaging.postMessage(
|
|
183
276
|
JSON.stringify({
|
|
184
|
-
|
|
277
|
+
loadedItemsCount: totalRowsLoaded,
|
|
185
278
|
total: safeTotal,
|
|
186
|
-
|
|
279
|
+
type: "progress"
|
|
187
280
|
})
|
|
188
281
|
);
|
|
189
282
|
controller.enqueue(encoder.encode(csvChunks));
|
|
190
283
|
if (isFinished) {
|
|
191
284
|
messaging.postMessage(
|
|
192
285
|
JSON.stringify({
|
|
193
|
-
|
|
286
|
+
loadedItemsCount: totalRowsLoaded,
|
|
194
287
|
total: safeTotal,
|
|
195
|
-
|
|
288
|
+
type: "done"
|
|
196
289
|
})
|
|
197
290
|
);
|
|
198
|
-
await this.workerManager.triggerWorker({
|
|
291
|
+
await this.workerManager.triggerWorker({
|
|
292
|
+
id: iterator,
|
|
293
|
+
type: "completed"
|
|
294
|
+
});
|
|
199
295
|
messaging.close();
|
|
200
296
|
controller.close();
|
|
201
297
|
return;
|
|
@@ -204,9 +300,9 @@ var FsAccessExportStrategy = class {
|
|
|
204
300
|
controller.error(error);
|
|
205
301
|
messaging.postMessage(
|
|
206
302
|
JSON.stringify({
|
|
207
|
-
|
|
303
|
+
loadedItemsCount: totalRowsLoaded,
|
|
208
304
|
total: 0,
|
|
209
|
-
|
|
305
|
+
type: "failed"
|
|
210
306
|
})
|
|
211
307
|
);
|
|
212
308
|
}
|
|
@@ -222,25 +318,20 @@ var FsAccessExportStrategy = class {
|
|
|
222
318
|
}
|
|
223
319
|
return {
|
|
224
320
|
finished: true,
|
|
225
|
-
totalRowsLoaded
|
|
226
|
-
logs: {
|
|
227
|
-
warnings: []
|
|
228
|
-
}
|
|
321
|
+
totalRowsLoaded
|
|
229
322
|
};
|
|
230
323
|
}
|
|
231
324
|
};
|
|
232
325
|
var FsAccessExportStrategy_default = FsAccessExportStrategy;
|
|
233
326
|
|
|
234
|
-
// src/core/
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
};
|
|
327
|
+
// src/core/createExportController.ts
|
|
328
|
+
function createExportController() {
|
|
329
|
+
return new ExportController({
|
|
330
|
+
blobExportStrategy: new BolbExportStrategy_default(),
|
|
331
|
+
fsAccessStrategy: new FsAccessExportStrategy_default()
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
var createExportController_default = createExportController;
|
|
244
335
|
|
|
245
336
|
// src/core/ExportControllerSingleton.ts
|
|
246
337
|
var _ExportControllerSingleton = class _ExportControllerSingleton {
|
|
@@ -248,7 +339,7 @@ var _ExportControllerSingleton = class _ExportControllerSingleton {
|
|
|
248
339
|
if (_ExportControllerSingleton.instance) {
|
|
249
340
|
return _ExportControllerSingleton.instance;
|
|
250
341
|
}
|
|
251
|
-
_ExportControllerSingleton.instance =
|
|
342
|
+
_ExportControllerSingleton.instance = createExportController_default();
|
|
252
343
|
_ExportControllerSingleton.initialized = true;
|
|
253
344
|
return _ExportControllerSingleton.instance;
|
|
254
345
|
}
|
|
@@ -268,7 +359,7 @@ var ExportControllerSingleton_default = ExportControllerSingleton;
|
|
|
268
359
|
function useExportCSV() {
|
|
269
360
|
const exportCallbackRef = (0, import_react.useRef)(ExportControllerSingleton_default.init());
|
|
270
361
|
return {
|
|
271
|
-
handler: exportCallbackRef
|
|
362
|
+
handler: exportCallbackRef?.current
|
|
272
363
|
};
|
|
273
364
|
}
|
|
274
365
|
var useExportCSV_default = useExportCSV;
|
|
@@ -289,6 +380,6 @@ function useMessageExportCSV(cb) {
|
|
|
289
380
|
return () => {
|
|
290
381
|
channel.close();
|
|
291
382
|
};
|
|
292
|
-
}, []);
|
|
383
|
+
}, [cb]);
|
|
293
384
|
}
|
|
294
385
|
var useMessageExportCSV_default = useMessageExportCSV;
|
package/dist/index.d.cts
CHANGED
|
@@ -5,26 +5,33 @@ type Column = {
|
|
|
5
5
|
timezone?: "UTC" | string;
|
|
6
6
|
formatType?: formatterTypes;
|
|
7
7
|
};
|
|
8
|
-
type ExportParams = {
|
|
8
|
+
type ExportParams<T> = {
|
|
9
9
|
fileName: string;
|
|
10
10
|
columns: Column[];
|
|
11
11
|
getNextPage: (offset: number) => Promise<{
|
|
12
|
-
rows:
|
|
12
|
+
rows: T[];
|
|
13
13
|
total: number;
|
|
14
14
|
}>;
|
|
15
15
|
};
|
|
16
|
+
type ExportResponse = {
|
|
17
|
+
finished: boolean;
|
|
18
|
+
totalRowsLoaded: number;
|
|
19
|
+
};
|
|
16
20
|
interface ExportStrategy {
|
|
17
|
-
export(params: ExportParams): Promise<
|
|
21
|
+
export<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
declare class BolbExportStrategy implements ExportStrategy {
|
|
21
|
-
|
|
25
|
+
private workerManager;
|
|
26
|
+
constructor();
|
|
27
|
+
export<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
28
|
+
private downloadBlob;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
declare class FsAccessExportStrategy implements ExportStrategy {
|
|
25
32
|
private workerManager;
|
|
26
33
|
constructor();
|
|
27
|
-
export(params: ExportParams): Promise<
|
|
34
|
+
export<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
type ExportControllerDeps = {
|
|
@@ -35,7 +42,7 @@ declare class ExportController {
|
|
|
35
42
|
#private;
|
|
36
43
|
private readonly deps;
|
|
37
44
|
constructor(deps: ExportControllerDeps);
|
|
38
|
-
start(params: ExportParams): Promise<
|
|
45
|
+
start<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
declare function useExportCSV(): {
|
package/dist/index.d.ts
CHANGED
|
@@ -5,26 +5,33 @@ type Column = {
|
|
|
5
5
|
timezone?: "UTC" | string;
|
|
6
6
|
formatType?: formatterTypes;
|
|
7
7
|
};
|
|
8
|
-
type ExportParams = {
|
|
8
|
+
type ExportParams<T> = {
|
|
9
9
|
fileName: string;
|
|
10
10
|
columns: Column[];
|
|
11
11
|
getNextPage: (offset: number) => Promise<{
|
|
12
|
-
rows:
|
|
12
|
+
rows: T[];
|
|
13
13
|
total: number;
|
|
14
14
|
}>;
|
|
15
15
|
};
|
|
16
|
+
type ExportResponse = {
|
|
17
|
+
finished: boolean;
|
|
18
|
+
totalRowsLoaded: number;
|
|
19
|
+
};
|
|
16
20
|
interface ExportStrategy {
|
|
17
|
-
export(params: ExportParams): Promise<
|
|
21
|
+
export<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
declare class BolbExportStrategy implements ExportStrategy {
|
|
21
|
-
|
|
25
|
+
private workerManager;
|
|
26
|
+
constructor();
|
|
27
|
+
export<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
28
|
+
private downloadBlob;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
declare class FsAccessExportStrategy implements ExportStrategy {
|
|
25
32
|
private workerManager;
|
|
26
33
|
constructor();
|
|
27
|
-
export(params: ExportParams): Promise<
|
|
34
|
+
export<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
type ExportControllerDeps = {
|
|
@@ -35,7 +42,7 @@ declare class ExportController {
|
|
|
35
42
|
#private;
|
|
36
43
|
private readonly deps;
|
|
37
44
|
constructor(deps: ExportControllerDeps);
|
|
38
|
-
start(params: ExportParams): Promise<
|
|
45
|
+
start<T>(params: ExportParams<T>): Promise<ExportResponse>;
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
declare function useExportCSV(): {
|
package/dist/index.js
CHANGED
|
@@ -33,14 +33,6 @@ resolveStrategy_fn = function() {
|
|
|
33
33
|
return this.deps.blobExportStrategy;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
// src/core/strategy/BolbExportStrategy.ts
|
|
37
|
-
var BolbExportStrategy = class {
|
|
38
|
-
export(params) {
|
|
39
|
-
return Promise.resolve({});
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
var BolbExportStrategy_default = BolbExportStrategy;
|
|
43
|
-
|
|
44
36
|
// src/core/contants/index.ts
|
|
45
37
|
var WEB_WORKER_NAME = "scv-worker";
|
|
46
38
|
var BROADCAST_CHANNEL_NAME = "react-csv-exporter";
|
|
@@ -59,8 +51,8 @@ var _WorkerManager = class _WorkerManager {
|
|
|
59
51
|
workerUrl = "/worker.js";
|
|
60
52
|
}
|
|
61
53
|
__privateSet(this, _worker, new Worker(workerUrl, {
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
name: WEB_WORKER_NAME,
|
|
55
|
+
type: "module"
|
|
64
56
|
}));
|
|
65
57
|
__privateMethod(this, _WorkerManager_instances, listenerRegistry_fn).call(this);
|
|
66
58
|
}
|
|
@@ -70,9 +62,9 @@ var _WorkerManager = class _WorkerManager {
|
|
|
70
62
|
async triggerWorker(payload) {
|
|
71
63
|
const id = payload.id ?? Math.random().toString(36).substr(2);
|
|
72
64
|
const p = new Promise((resolve, reject) => {
|
|
73
|
-
pending.set(id, {
|
|
65
|
+
pending.set(id, { reject, resolve });
|
|
74
66
|
});
|
|
75
|
-
__privateGet(this, _worker)
|
|
67
|
+
__privateGet(this, _worker)?.postMessage(payload);
|
|
76
68
|
return p;
|
|
77
69
|
}
|
|
78
70
|
terminate() {
|
|
@@ -85,7 +77,7 @@ var _WorkerManager = class _WorkerManager {
|
|
|
85
77
|
_worker = new WeakMap();
|
|
86
78
|
_WorkerManager_instances = new WeakSet();
|
|
87
79
|
listenerRegistry_fn = function() {
|
|
88
|
-
__privateGet(this, _worker)
|
|
80
|
+
__privateGet(this, _worker)?.addEventListener("message", (event) => {
|
|
89
81
|
const { id, result, error } = event.data;
|
|
90
82
|
const entity = pending.get(id);
|
|
91
83
|
if (!entity) {
|
|
@@ -98,7 +90,7 @@ listenerRegistry_fn = function() {
|
|
|
98
90
|
entity.resolve(result);
|
|
99
91
|
}
|
|
100
92
|
});
|
|
101
|
-
__privateGet(this, _worker)
|
|
93
|
+
__privateGet(this, _worker)?.addEventListener("error", (event) => {
|
|
102
94
|
for (const [, { reject }] of pending) {
|
|
103
95
|
reject(event);
|
|
104
96
|
}
|
|
@@ -108,6 +100,103 @@ listenerRegistry_fn = function() {
|
|
|
108
100
|
var WorkerManager = _WorkerManager;
|
|
109
101
|
var WorkerManager_default = WorkerManager;
|
|
110
102
|
|
|
103
|
+
// src/core/strategy/BolbExportStrategy.ts
|
|
104
|
+
var BolbExportStrategy = class {
|
|
105
|
+
constructor() {
|
|
106
|
+
this.workerManager = WorkerManager_default.initialise();
|
|
107
|
+
}
|
|
108
|
+
async export(params) {
|
|
109
|
+
const suggestedName = params.fileName ?? "export";
|
|
110
|
+
const filename = suggestedName.endsWith(".csv") ? suggestedName : `${suggestedName}.csv`;
|
|
111
|
+
let iterator = 0;
|
|
112
|
+
let totalRowsLoaded = 0;
|
|
113
|
+
const messaging = new BroadcastChannel(BROADCAST_CHANNEL_NAME);
|
|
114
|
+
const csvParts = [];
|
|
115
|
+
try {
|
|
116
|
+
while (true) {
|
|
117
|
+
const response = await params.getNextPage(iterator++);
|
|
118
|
+
const safeRows = Array.isArray(response.rows) ? response.rows : [];
|
|
119
|
+
const safeTotal = response.total ?? 0;
|
|
120
|
+
const isRowsEmpty = safeRows.length === 0;
|
|
121
|
+
const nextRowsLoaded = totalRowsLoaded + safeRows.length;
|
|
122
|
+
totalRowsLoaded = isRowsEmpty ? safeTotal : nextRowsLoaded;
|
|
123
|
+
const isFinished = safeTotal > 0 ? totalRowsLoaded >= safeTotal : isRowsEmpty;
|
|
124
|
+
if (isRowsEmpty) {
|
|
125
|
+
messaging.postMessage(
|
|
126
|
+
JSON.stringify({
|
|
127
|
+
loadedItemsCount: totalRowsLoaded,
|
|
128
|
+
total: safeTotal,
|
|
129
|
+
type: "done"
|
|
130
|
+
})
|
|
131
|
+
);
|
|
132
|
+
await this.workerManager.triggerWorker({
|
|
133
|
+
id: iterator,
|
|
134
|
+
type: "completed"
|
|
135
|
+
});
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
const csvChunk = await this.workerManager.triggerWorker({
|
|
139
|
+
columns: params.columns,
|
|
140
|
+
data: safeRows,
|
|
141
|
+
id: iterator,
|
|
142
|
+
type: "to_csv_chunk"
|
|
143
|
+
});
|
|
144
|
+
csvParts.push(csvChunk);
|
|
145
|
+
messaging.postMessage(
|
|
146
|
+
JSON.stringify({
|
|
147
|
+
loadedItemsCount: totalRowsLoaded,
|
|
148
|
+
total: safeTotal,
|
|
149
|
+
type: "progress"
|
|
150
|
+
})
|
|
151
|
+
);
|
|
152
|
+
if (isFinished) {
|
|
153
|
+
messaging.postMessage(
|
|
154
|
+
JSON.stringify({
|
|
155
|
+
loadedItemsCount: totalRowsLoaded,
|
|
156
|
+
total: safeTotal,
|
|
157
|
+
type: "done"
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
await this.workerManager.triggerWorker({
|
|
161
|
+
id: iterator,
|
|
162
|
+
type: "completed"
|
|
163
|
+
});
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const blob = new Blob(["\uFEFF", ...csvParts], {
|
|
168
|
+
type: "text/csv;charset=utf-8"
|
|
169
|
+
});
|
|
170
|
+
this.downloadBlob(blob, filename);
|
|
171
|
+
return { finished: true, totalRowsLoaded };
|
|
172
|
+
} catch (error) {
|
|
173
|
+
messaging.postMessage(
|
|
174
|
+
JSON.stringify({
|
|
175
|
+
loadedItemsCount: totalRowsLoaded,
|
|
176
|
+
total: 0,
|
|
177
|
+
type: "failed"
|
|
178
|
+
})
|
|
179
|
+
);
|
|
180
|
+
throw error;
|
|
181
|
+
} finally {
|
|
182
|
+
messaging.close();
|
|
183
|
+
this.workerManager.terminate();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
downloadBlob(blob, filename) {
|
|
187
|
+
const url = URL.createObjectURL(blob);
|
|
188
|
+
const a = document.createElement("a");
|
|
189
|
+
a.href = url;
|
|
190
|
+
a.download = filename;
|
|
191
|
+
a.rel = "noopener";
|
|
192
|
+
document.body.appendChild(a);
|
|
193
|
+
a.click();
|
|
194
|
+
a.remove();
|
|
195
|
+
URL.revokeObjectURL(url);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var BolbExportStrategy_default = BolbExportStrategy;
|
|
199
|
+
|
|
111
200
|
// src/core/strategy/FsAccessExportStrategy.ts
|
|
112
201
|
var FsAccessExportStrategy = class {
|
|
113
202
|
constructor() {
|
|
@@ -117,7 +206,7 @@ var FsAccessExportStrategy = class {
|
|
|
117
206
|
const _suggestedName = params?.fileName || "export";
|
|
118
207
|
const fileHandle = await window.showSaveFilePicker({
|
|
119
208
|
suggestedName: _suggestedName,
|
|
120
|
-
types: [{
|
|
209
|
+
types: [{ accept: { "text/csv": [".csv"] }, description: "CSV file" }]
|
|
121
210
|
});
|
|
122
211
|
const writableFileStream = await fileHandle.createWritable();
|
|
123
212
|
let iterator = 0;
|
|
@@ -131,44 +220,51 @@ var FsAccessExportStrategy = class {
|
|
|
131
220
|
const safeRows = Array.isArray(response.rows) ? response?.rows : [];
|
|
132
221
|
const safeTotal = response.total ?? 0;
|
|
133
222
|
const isRowsEmpty = !safeRows || !safeRows.length;
|
|
134
|
-
|
|
223
|
+
const nextRowsLoaded = totalRowsLoaded + safeRows.length;
|
|
224
|
+
totalRowsLoaded = isRowsEmpty ? safeTotal : nextRowsLoaded;
|
|
135
225
|
const isFinished = totalRowsLoaded >= safeTotal;
|
|
136
226
|
if (isRowsEmpty) {
|
|
137
227
|
messaging.postMessage(
|
|
138
228
|
JSON.stringify({
|
|
139
|
-
|
|
229
|
+
loadedItemsCount: totalRowsLoaded,
|
|
140
230
|
total: safeTotal,
|
|
141
|
-
|
|
231
|
+
type: "done"
|
|
142
232
|
})
|
|
143
233
|
);
|
|
144
|
-
await this.workerManager.triggerWorker({
|
|
234
|
+
await this.workerManager.triggerWorker({
|
|
235
|
+
id: iterator,
|
|
236
|
+
type: "completed"
|
|
237
|
+
});
|
|
145
238
|
messaging.close();
|
|
146
239
|
controller.close();
|
|
147
240
|
return;
|
|
148
241
|
}
|
|
149
242
|
const csvChunks = await this.workerManager.triggerWorker({
|
|
150
|
-
|
|
151
|
-
type: "to_csv_chunk",
|
|
243
|
+
columns: params.columns,
|
|
152
244
|
data: safeRows,
|
|
153
|
-
|
|
245
|
+
id: iterator,
|
|
246
|
+
type: "to_csv_chunk"
|
|
154
247
|
});
|
|
155
248
|
messaging.postMessage(
|
|
156
249
|
JSON.stringify({
|
|
157
|
-
|
|
250
|
+
loadedItemsCount: totalRowsLoaded,
|
|
158
251
|
total: safeTotal,
|
|
159
|
-
|
|
252
|
+
type: "progress"
|
|
160
253
|
})
|
|
161
254
|
);
|
|
162
255
|
controller.enqueue(encoder.encode(csvChunks));
|
|
163
256
|
if (isFinished) {
|
|
164
257
|
messaging.postMessage(
|
|
165
258
|
JSON.stringify({
|
|
166
|
-
|
|
259
|
+
loadedItemsCount: totalRowsLoaded,
|
|
167
260
|
total: safeTotal,
|
|
168
|
-
|
|
261
|
+
type: "done"
|
|
169
262
|
})
|
|
170
263
|
);
|
|
171
|
-
await this.workerManager.triggerWorker({
|
|
264
|
+
await this.workerManager.triggerWorker({
|
|
265
|
+
id: iterator,
|
|
266
|
+
type: "completed"
|
|
267
|
+
});
|
|
172
268
|
messaging.close();
|
|
173
269
|
controller.close();
|
|
174
270
|
return;
|
|
@@ -177,9 +273,9 @@ var FsAccessExportStrategy = class {
|
|
|
177
273
|
controller.error(error);
|
|
178
274
|
messaging.postMessage(
|
|
179
275
|
JSON.stringify({
|
|
180
|
-
|
|
276
|
+
loadedItemsCount: totalRowsLoaded,
|
|
181
277
|
total: 0,
|
|
182
|
-
|
|
278
|
+
type: "failed"
|
|
183
279
|
})
|
|
184
280
|
);
|
|
185
281
|
}
|
|
@@ -195,25 +291,20 @@ var FsAccessExportStrategy = class {
|
|
|
195
291
|
}
|
|
196
292
|
return {
|
|
197
293
|
finished: true,
|
|
198
|
-
totalRowsLoaded
|
|
199
|
-
logs: {
|
|
200
|
-
warnings: []
|
|
201
|
-
}
|
|
294
|
+
totalRowsLoaded
|
|
202
295
|
};
|
|
203
296
|
}
|
|
204
297
|
};
|
|
205
298
|
var FsAccessExportStrategy_default = FsAccessExportStrategy;
|
|
206
299
|
|
|
207
|
-
// src/core/
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
};
|
|
300
|
+
// src/core/createExportController.ts
|
|
301
|
+
function createExportController() {
|
|
302
|
+
return new ExportController({
|
|
303
|
+
blobExportStrategy: new BolbExportStrategy_default(),
|
|
304
|
+
fsAccessStrategy: new FsAccessExportStrategy_default()
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
var createExportController_default = createExportController;
|
|
217
308
|
|
|
218
309
|
// src/core/ExportControllerSingleton.ts
|
|
219
310
|
var _ExportControllerSingleton = class _ExportControllerSingleton {
|
|
@@ -221,7 +312,7 @@ var _ExportControllerSingleton = class _ExportControllerSingleton {
|
|
|
221
312
|
if (_ExportControllerSingleton.instance) {
|
|
222
313
|
return _ExportControllerSingleton.instance;
|
|
223
314
|
}
|
|
224
|
-
_ExportControllerSingleton.instance =
|
|
315
|
+
_ExportControllerSingleton.instance = createExportController_default();
|
|
225
316
|
_ExportControllerSingleton.initialized = true;
|
|
226
317
|
return _ExportControllerSingleton.instance;
|
|
227
318
|
}
|
|
@@ -241,7 +332,7 @@ var ExportControllerSingleton_default = ExportControllerSingleton;
|
|
|
241
332
|
function useExportCSV() {
|
|
242
333
|
const exportCallbackRef = useRef(ExportControllerSingleton_default.init());
|
|
243
334
|
return {
|
|
244
|
-
handler: exportCallbackRef
|
|
335
|
+
handler: exportCallbackRef?.current
|
|
245
336
|
};
|
|
246
337
|
}
|
|
247
338
|
var useExportCSV_default = useExportCSV;
|
|
@@ -262,7 +353,7 @@ function useMessageExportCSV(cb) {
|
|
|
262
353
|
return () => {
|
|
263
354
|
channel.close();
|
|
264
355
|
};
|
|
265
|
-
}, []);
|
|
356
|
+
}, [cb]);
|
|
266
357
|
}
|
|
267
358
|
var useMessageExportCSV_default = useMessageExportCSV;
|
|
268
359
|
export {
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "react-csv-autopilot",
|
|
3
|
-
"version": "0.0.3",
|
|
4
|
-
"description": "React hooks for CSV export with automatic pagination - drop the function, we handle the rest",
|
|
5
2
|
"author": "Pavlo Kuzina",
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/PashaSchool/utils-kit/issues"
|
|
5
|
+
},
|
|
6
|
+
"description": "React hooks for CSV export with automatic pagination - drop the function, we handle the rest",
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"@types/react": "^18",
|
|
9
|
+
"@types/wicg-file-system-access": "^2023.10.7",
|
|
10
|
+
"react": "^19.2.3",
|
|
11
|
+
"tsup": "^8.0.0",
|
|
12
|
+
"typescript": "^5.0.0"
|
|
13
|
+
},
|
|
12
14
|
"exports": {
|
|
13
15
|
".": {
|
|
14
|
-
"types": "./dist/index.d.ts",
|
|
15
16
|
"import": "./dist/index.js",
|
|
16
|
-
"require": "./dist/index.cjs"
|
|
17
|
+
"require": "./dist/index.cjs",
|
|
18
|
+
"types": "./dist/index.d.ts"
|
|
17
19
|
}
|
|
18
20
|
},
|
|
19
21
|
"files": [
|
|
@@ -21,28 +23,6 @@
|
|
|
21
23
|
"README.md",
|
|
22
24
|
"LICENSE"
|
|
23
25
|
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "tsup",
|
|
26
|
-
"dev": "tsup --watch"
|
|
27
|
-
},
|
|
28
|
-
"peerDependencies": {
|
|
29
|
-
"react": "^18 || ^19"
|
|
30
|
-
},
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@types/react": "^18",
|
|
33
|
-
"@types/wicg-file-system-access": "^2023.10.7",
|
|
34
|
-
"react": "^19.2.3",
|
|
35
|
-
"tsup": "^8.0.0",
|
|
36
|
-
"typescript": "^5.0.0"
|
|
37
|
-
},
|
|
38
|
-
"repository": {
|
|
39
|
-
"type": "git",
|
|
40
|
-
"url": "git+https://github.com/PashaSchool/utils-kit.git",
|
|
41
|
-
"directory": "packages/react-csv-autopilot"
|
|
42
|
-
},
|
|
43
|
-
"bugs": {
|
|
44
|
-
"url": "https://github.com/PashaSchool/utils-kit/issues"
|
|
45
|
-
},
|
|
46
26
|
"homepage": "https://github.com/PashaSchool/utils-kit/blob/main/packages/react-csv-autopilot/README.md",
|
|
47
27
|
"keywords": [
|
|
48
28
|
"react",
|
|
@@ -60,5 +40,25 @@
|
|
|
60
40
|
"file-system-access",
|
|
61
41
|
"large-datasets",
|
|
62
42
|
"data-export"
|
|
63
|
-
]
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"main": "dist/index.cjs",
|
|
46
|
+
"module": "dist/index.js",
|
|
47
|
+
"name": "react-csv-autopilot",
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"react": "^18 || ^19"
|
|
50
|
+
},
|
|
51
|
+
"repository": {
|
|
52
|
+
"directory": "packages/react-csv-autopilot",
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/PashaSchool/utils-kit.git"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsup",
|
|
58
|
+
"dev": "tsup --watch"
|
|
59
|
+
},
|
|
60
|
+
"sideEffects": false,
|
|
61
|
+
"type": "module",
|
|
62
|
+
"types": "dist/index.d.ts",
|
|
63
|
+
"version": "1.0.0"
|
|
64
64
|
}
|