@adriansteffan/reactive 0.0.39 → 0.0.41

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.
@@ -1,4 +1,4 @@
1
- import { W as P, b as x, E } from "./mod-B9pn3CIt.js";
1
+ import { W as P, b as x, E } from "./mod-DBgU62Mz.js";
2
2
  function m(w) {
3
3
  const e = w.split("/").filter((t) => t !== "."), r = [];
4
4
  return e.forEach((t) => {
@@ -1,4 +1,4 @@
1
- import { W as e } from "./mod-B9pn3CIt.js";
1
+ import { W as e } from "./mod-DBgU62Mz.js";
2
2
  class s extends e {
3
3
  async enable() {
4
4
  console.log("Immersive mode is only available on Android");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adriansteffan/reactive",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -108,27 +108,112 @@ function combineTrialsToCsv(
108
108
  data: any[],
109
109
  filename: string,
110
110
  names: string[],
111
- flatteningFunctions: Record<string, (item: any) => any[]>,
111
+ flatteningFunctions: Record<string, (item: any) => any[] | Record<string, any[]>>,
112
112
  fun?: (obj: any) => any,
113
- ) {
114
-
115
- const processedData = names
116
- .flatMap((name) => {
117
- const matchingItems = data.filter((d) => d.name === name);
118
-
119
- return matchingItems.flatMap((item) => {
120
- const flattener = item.type && flatteningFunctions[item.type];
121
-
122
- return flattener ? flattener(item) : transform(item);
113
+ ): FileUpload | FileUpload[] {
114
+
115
+ // Collect all flattener results first, filtering out completely empty results
116
+ const allResults: (any[] | Record<string, any[]>)[] = names.flatMap((name) => {
117
+ const matchingItems = data.filter((d) => d.name === name);
118
+
119
+ return matchingItems.map((item) => {
120
+ const flattener = item.type && flatteningFunctions[item.type];
121
+ const result = flattener ? flattener(item) : [transform(item)];
122
+
123
+ // Filter out completely empty results
124
+ if (Array.isArray(result) && result.length === 0) {
125
+ return null; // Signal this trial should be completely skipped
126
+ }
127
+
128
+ if (result && typeof result === 'object' && !Array.isArray(result)) {
129
+ // Check if all arrays in the object are empty
130
+ const hasAnyData = Object.values(result).some(val =>
131
+ Array.isArray(val) && val.length > 0
132
+ );
133
+ if (!hasAnyData) {
134
+ return null; // Signal this trial should be completely skipped
135
+ }
136
+ }
137
+
138
+ return result;
139
+ });
140
+ }).filter(result => result !== null);
141
+
142
+ // Check if any result is a multi-table object (has string keys with array values)
143
+ const hasMultiTable = allResults.some((result) =>
144
+ result &&
145
+ typeof result === 'object' &&
146
+ !Array.isArray(result) &&
147
+ Object.keys(result).some(key => Array.isArray(result[key]))
148
+ );
149
+
150
+ if (!hasMultiTable) {
151
+ // all results are arrays, combine them into one CSV
152
+ const processedData = allResults
153
+ .flatMap((result) => Array.isArray(result) ? result : [])
154
+ .map((x) => (fun ? fun(x) : x));
155
+
156
+ // Skip creating CSV if all flatteners returned empty arrays
157
+ if (processedData.length === 0) {
158
+ return [];
159
+ }
160
+
161
+ return {
162
+ filename,
163
+ encoding: 'utf8' as const,
164
+ content: convertArrayOfObjectsToCSV(processedData),
165
+ };
166
+ }
167
+
168
+ // handle multi-table results
169
+ // Collect all table keys from all results
170
+ const allTableKeys = new Set<string>();
171
+ allResults.forEach((result) => {
172
+ if (result && typeof result === 'object' && !Array.isArray(result)) {
173
+ Object.keys(result).forEach(key => {
174
+ if (Array.isArray(result[key])) {
175
+ allTableKeys.add(key);
176
+ }
123
177
  });
124
- })
125
- .map((x) => (fun ? fun(x) : x));
178
+ }
179
+ });
126
180
 
127
- return {
128
- filename,
129
- encoding: 'utf8' as const,
130
- content: convertArrayOfObjectsToCSV(processedData),
131
- };
181
+ // Create separate CSV files for each table key
182
+ const files: FileUpload[] = [];
183
+
184
+ for (const tableKey of allTableKeys) {
185
+ const tableData = allResults.flatMap((result) => {
186
+ if (Array.isArray(result)) {
187
+ // If this result is a simple array, include it in all tables for backward compatibility
188
+ return result;
189
+ } else if (result && typeof result === 'object' && result[tableKey]) {
190
+ // If this result has data for this table key, include it
191
+ return result[tableKey];
192
+ }
193
+ return [];
194
+ }).map((x) => (fun ? fun(x) : x));
195
+
196
+ // Skip creating CSV if all flatteners returned empty arrays for this table
197
+ if (tableData.length === 0) {
198
+ continue;
199
+ }
200
+
201
+ // Remove file extension from filename and add table key
202
+ const baseFilename = filename.replace(/\.csv$/, '');
203
+
204
+ files.push({
205
+ filename: `${baseFilename}_${tableKey}.csv`,
206
+ encoding: 'utf8' as const,
207
+ content: convertArrayOfObjectsToCSV(tableData),
208
+ });
209
+ }
210
+
211
+ // Return empty array if no files were created
212
+ if (files.length === 0) {
213
+ return [];
214
+ }
215
+
216
+ return files.length === 1 ? files[0] : files;
132
217
  }
133
218
 
134
219
  interface FileBackend {
@@ -281,7 +366,7 @@ export default function Upload({
281
366
  sessionID?: string | null;
282
367
  generateFiles: (sessionID: string, data: TrialData[], store?: Store) => FileUpload[];
283
368
  sessionCSVBuilder: CSVBuilder;
284
- trialCSVBuilder: {flatteners: Record<string, ((item: TrialData) => Record<string, any>[])>, builders: CSVBuilder[]};
369
+ trialCSVBuilder: {flatteners: Record<string, ((item: TrialData) => Record<string, any>[] | Record<string, Record<string, any>[]>)>, builders: CSVBuilder[]};
285
370
  uploadRaw: boolean;
286
371
  autoUpload: boolean;
287
372
  androidFolderName?: string;
@@ -415,15 +500,22 @@ export default function Upload({
415
500
 
416
501
  if (trialCSVBuilder) {
417
502
  for (const builder of trialCSVBuilder.builders) {
418
- files.push(
419
- combineTrialsToCsv(
420
- data,
421
- `${sessionIDUpload}${builder.filename}.csv`,
422
- builder.trials ?? [],
423
- {...defaultFlatteningFunctions, ...trialCSVBuilder.flatteners},
424
- builder.fun,
425
- ),
503
+ const result = combineTrialsToCsv(
504
+ data,
505
+ `${sessionIDUpload}${builder.filename}.csv`,
506
+ builder.trials ?? [],
507
+ {...defaultFlatteningFunctions, ...trialCSVBuilder.flatteners},
508
+ builder.fun,
426
509
  );
510
+
511
+ if (Array.isArray(result)) {
512
+ // Only push files if the array is not empty
513
+ if (result.length > 0) {
514
+ files.push(...result);
515
+ }
516
+ } else {
517
+ files.push(result);
518
+ }
427
519
  }
428
520
  }
429
521