bxo 0.0.5-dev.80 → 0.0.5-dev.81
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 +26 -0
- package/example/multipart-example.ts +119 -0
- package/package.json +1 -1
- package/src/index.ts +29 -0
package/README.md
CHANGED
|
@@ -320,9 +320,35 @@ app.post("/items", async (ctx) => {
|
|
|
320
320
|
});
|
|
321
321
|
```
|
|
322
322
|
|
|
323
|
+
### Deep Nested Array Objects
|
|
324
|
+
Form fields like `workspace_items[0][id]`, `workspace_items[0][type]` are automatically converted to arrays of objects:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const WorkspaceSchema = z.object({
|
|
328
|
+
id: z.string(),
|
|
329
|
+
workspace_items: z.array(z.object({
|
|
330
|
+
id: z.string(),
|
|
331
|
+
type: z.string(),
|
|
332
|
+
value: z.string(),
|
|
333
|
+
options: z.string(),
|
|
334
|
+
label: z.string()
|
|
335
|
+
}))
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
app.post("/workspace", async (ctx) => {
|
|
339
|
+
// Form data: workspace_items[0][id]="item1", workspace_items[0][type]="Link"
|
|
340
|
+
// becomes { workspace_items: [{ id: "item1", type: "Link", ... }] }
|
|
341
|
+
console.log(ctx.body); // { id: "...", workspace_items: [{ id: "item1", type: "Link", ... }] }
|
|
342
|
+
return ctx.json({ success: true, data: ctx.body });
|
|
343
|
+
}, {
|
|
344
|
+
body: WorkspaceSchema
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
323
348
|
### Supported Patterns
|
|
324
349
|
- **Nested objects**: `profile[name]`, `settings[theme]` → `{ profile: { name: "..." }, settings: { theme: "..." } }`
|
|
325
350
|
- **Arrays**: `items[0]`, `items[1]` → `{ items: ["...", "..."] }`
|
|
351
|
+
- **Deep nested array objects**: `workspace_items[0][id]`, `workspace_items[0][type]` → `{ workspace_items: [{ id: "...", type: "..." }] }`
|
|
326
352
|
- **Duplicate keys**: Multiple values with same key → `{ tags: ["tag1", "tag2"] }`
|
|
327
353
|
|
|
328
354
|
## Running
|
|
@@ -63,6 +63,46 @@ app.post("/items", async (ctx) => {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
// Example with deep nested array objects (like workspace_items[0][id])
|
|
67
|
+
const WorkspaceFormSchema = z.object({
|
|
68
|
+
id: z.string(),
|
|
69
|
+
created_at: z.string(),
|
|
70
|
+
updated_at: z.string(),
|
|
71
|
+
updated_by: z.string(),
|
|
72
|
+
doc_status: z.string().transform(val => parseInt(val, 10)),
|
|
73
|
+
idx: z.string().transform(val => parseInt(val, 10)),
|
|
74
|
+
workspace_items: z.array(z.object({
|
|
75
|
+
id: z.string(),
|
|
76
|
+
type: z.string(),
|
|
77
|
+
value: z.string(),
|
|
78
|
+
options: z.string(),
|
|
79
|
+
workspaceId: z.string(),
|
|
80
|
+
owner: z.string(),
|
|
81
|
+
created_at: z.string(),
|
|
82
|
+
updated_at: z.string(),
|
|
83
|
+
created_by: z.string(),
|
|
84
|
+
updated_by: z.string(),
|
|
85
|
+
doc_status: z.string().transform(val => parseInt(val, 10)),
|
|
86
|
+
label: z.string()
|
|
87
|
+
}))
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
app.post("/workspace", async (ctx) => {
|
|
91
|
+
console.log("Parsed workspace form data:", ctx.body);
|
|
92
|
+
|
|
93
|
+
return ctx.json({
|
|
94
|
+
message: "Workspace processed successfully",
|
|
95
|
+
data: ctx.body
|
|
96
|
+
});
|
|
97
|
+
}, {
|
|
98
|
+
body: WorkspaceFormSchema,
|
|
99
|
+
detail: {
|
|
100
|
+
summary: "Process workspace with deep nested array objects",
|
|
101
|
+
description: "Handles form data like workspace_items[0][id], workspace_items[0][type]",
|
|
102
|
+
tags: ["Workspace"]
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
66
106
|
// Test route to show how the parsing works
|
|
67
107
|
app.get("/test-parsing", async (ctx) => {
|
|
68
108
|
const html = `
|
|
@@ -156,6 +196,80 @@ app.get("/test-parsing", async (ctx) => {
|
|
|
156
196
|
<button type="submit">Submit Items Form</button>
|
|
157
197
|
</form>
|
|
158
198
|
|
|
199
|
+
<h2>Test 3: Deep Nested Array Objects (workspace_items[0][id])</h2>
|
|
200
|
+
<form id="workspaceForm" enctype="multipart/form-data">
|
|
201
|
+
<div class="form-group">
|
|
202
|
+
<label>ID:</label>
|
|
203
|
+
<input type="text" name="id" value="01993f54-758e-7000-9f98-4533a7cf8ce9">
|
|
204
|
+
</div>
|
|
205
|
+
<div class="form-group">
|
|
206
|
+
<label>Created At:</label>
|
|
207
|
+
<input type="text" name="created_at" value="2025-09-13 02:08:43">
|
|
208
|
+
</div>
|
|
209
|
+
<div class="form-group">
|
|
210
|
+
<label>Updated At:</label>
|
|
211
|
+
<input type="text" name="updated_at" value="2025-09-13 02:08:43">
|
|
212
|
+
</div>
|
|
213
|
+
<div class="form-group">
|
|
214
|
+
<label>Updated By:</label>
|
|
215
|
+
<input type="text" name="updated_by" value="01995120-fae9-7000-8d46-8f3502e901b6">
|
|
216
|
+
</div>
|
|
217
|
+
<div class="form-group">
|
|
218
|
+
<label>Doc Status:</label>
|
|
219
|
+
<input type="text" name="doc_status" value="0">
|
|
220
|
+
</div>
|
|
221
|
+
<div class="form-group">
|
|
222
|
+
<label>Index:</label>
|
|
223
|
+
<input type="text" name="idx" value="0">
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<h3>Workspace Item 1:</h3>
|
|
227
|
+
<div class="form-group">
|
|
228
|
+
<label>Item ID:</label>
|
|
229
|
+
<input type="text" name="workspace_items[0][id]" value="temp_1758097169599">
|
|
230
|
+
</div>
|
|
231
|
+
<div class="form-group">
|
|
232
|
+
<label>Item Type:</label>
|
|
233
|
+
<input type="text" name="workspace_items[0][type]" value="Link - URL">
|
|
234
|
+
</div>
|
|
235
|
+
<div class="form-group">
|
|
236
|
+
<label>Item Value:</label>
|
|
237
|
+
<input type="text" name="workspace_items[0][value]" value="asd">
|
|
238
|
+
</div>
|
|
239
|
+
<div class="form-group">
|
|
240
|
+
<label>Item Options:</label>
|
|
241
|
+
<input type="text" name="workspace_items[0][options]" value="asdasd">
|
|
242
|
+
</div>
|
|
243
|
+
<div class="form-group">
|
|
244
|
+
<label>Item Label:</label>
|
|
245
|
+
<input type="text" name="workspace_items[0][label]" value="asdasd">
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<h3>Workspace Item 2:</h3>
|
|
249
|
+
<div class="form-group">
|
|
250
|
+
<label>Item ID:</label>
|
|
251
|
+
<input type="text" name="workspace_items[1][id]" value="temp_1758097169600">
|
|
252
|
+
</div>
|
|
253
|
+
<div class="form-group">
|
|
254
|
+
<label>Item Type:</label>
|
|
255
|
+
<input type="text" name="workspace_items[1][type]" value="Text">
|
|
256
|
+
</div>
|
|
257
|
+
<div class="form-group">
|
|
258
|
+
<label>Item Value:</label>
|
|
259
|
+
<input type="text" name="workspace_items[1][value]" value="Another item">
|
|
260
|
+
</div>
|
|
261
|
+
<div class="form-group">
|
|
262
|
+
<label>Item Options:</label>
|
|
263
|
+
<input type="text" name="workspace_items[1][options]" value="More options">
|
|
264
|
+
</div>
|
|
265
|
+
<div class="form-group">
|
|
266
|
+
<label>Item Label:</label>
|
|
267
|
+
<input type="text" name="workspace_items[1][label]" value="Second item">
|
|
268
|
+
</div>
|
|
269
|
+
|
|
270
|
+
<button type="submit">Submit Workspace Form</button>
|
|
271
|
+
</form>
|
|
272
|
+
|
|
159
273
|
<div id="result" class="result" style="display: none;">
|
|
160
274
|
<h3>Result:</h3>
|
|
161
275
|
<pre id="resultContent"></pre>
|
|
@@ -187,6 +301,11 @@ app.get("/test-parsing", async (ctx) => {
|
|
|
187
301
|
e.preventDefault();
|
|
188
302
|
submitForm(e.target, '/items');
|
|
189
303
|
});
|
|
304
|
+
|
|
305
|
+
document.getElementById('workspaceForm').addEventListener('submit', (e) => {
|
|
306
|
+
e.preventDefault();
|
|
307
|
+
submitForm(e.target, '/workspace');
|
|
308
|
+
});
|
|
190
309
|
</script>
|
|
191
310
|
</body>
|
|
192
311
|
</html>
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -196,6 +196,35 @@ function formDataToObject(fd: FormData): Record<string, any> {
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
function setNestedValue(obj: Record<string, any>, key: string, value: any): void {
|
|
199
|
+
// Handle deeply nested array objects like workspace_items[0][id], workspace_items[0][type]
|
|
200
|
+
const deepArrayMatch = key.match(/^(.+)\[(\d+)\]\[([^\]]+)\]$/);
|
|
201
|
+
if (deepArrayMatch) {
|
|
202
|
+
const [, arrayKey, index, propertyKey] = deepArrayMatch;
|
|
203
|
+
const arrayIndex = parseInt(index, 10);
|
|
204
|
+
|
|
205
|
+
if (!obj[arrayKey]) {
|
|
206
|
+
obj[arrayKey] = [];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Ensure it's an array
|
|
210
|
+
if (!Array.isArray(obj[arrayKey])) {
|
|
211
|
+
obj[arrayKey] = [];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Ensure the object at the index exists
|
|
215
|
+
if (!obj[arrayKey][arrayIndex]) {
|
|
216
|
+
obj[arrayKey][arrayIndex] = {};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Ensure it's an object
|
|
220
|
+
if (typeof obj[arrayKey][arrayIndex] !== 'object' || Array.isArray(obj[arrayKey][arrayIndex])) {
|
|
221
|
+
obj[arrayKey][arrayIndex] = {};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
obj[arrayKey][arrayIndex][propertyKey] = value;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
199
228
|
// Handle array notation like items[0], items[1]
|
|
200
229
|
const arrayMatch = key.match(/^(.+)\[(\d+)\]$/);
|
|
201
230
|
if (arrayMatch) {
|