arckode-framework 1.3.0 → 1.3.1

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.
Files changed (2) hide show
  1. package/README.md +54 -4
  2. package/package.json +2 -1
package/README.md CHANGED
@@ -317,13 +317,63 @@ await mail.send({ to: 'user@example.com', subject: 'Bienvenido', html: '<p>Hola<
317
317
  ### Storage
318
318
 
319
319
  ```ts
320
- import { StorageService } from 'arckode-framework/storage'
321
- import { LocalAdapter } from 'arckode-framework/storage/local'
320
+ import { StorageService } from 'arckode-framework/modules/storage'
321
+ import { LocalStorageAdapter } from 'arckode-framework/modules/storage/local-adapter'
322
+
323
+ // En composition-root.ts
324
+ const storage = new StorageService(
325
+ new LocalStorageAdapter('./uploads', '/uploads')
326
+ )
327
+
328
+ // Subir un archivo
329
+ const stored = await storage.upload(file, 'avatars')
330
+ // stored.url → '/uploads/avatars/1234567890-abc.jpg'
331
+ // stored.path → 'avatars/1234567890-abc.jpg'
332
+ ```
333
+
334
+ ### File Uploads (multipart/form-data)
335
+
336
+ El servidor detecta `Content-Type: multipart/form-data` automáticamente y parsea el body
337
+ sin dependencias externas. Los archivos quedan en `req.files`, los campos de texto en `req.body`.
338
+
339
+ ```ts
340
+ import type { UploadedFile } from 'arckode-framework'
341
+ import { ValidationError } from 'arckode-framework'
322
342
 
323
- const storage = new StorageService(new LocalAdapter({ path: './uploads' }))
324
- const url = await storage.save('avatars/user.png', fileBuffer)
343
+ router.post('/avatar', [auth.authenticate()], async (req) => {
344
+ const file = req.files?.['avatar']
345
+ if (!file) throw new ValidationError('Se requiere un archivo')
346
+
347
+ const stored = await storageService.upload(file, 'avatars')
348
+ return { status: 200, body: { url: stored.url } }
349
+ })
325
350
  ```
326
351
 
352
+ **Desde el cliente:**
353
+
354
+ ```ts
355
+ const form = new FormData()
356
+ form.append('avatar', blob, 'photo.jpg')
357
+ await fetch('/avatar', { method: 'POST', body: form })
358
+ ```
359
+
360
+ **Estructura de `UploadedFile`:**
361
+
362
+ ```ts
363
+ interface UploadedFile {
364
+ fieldName: string // nombre del campo en el form
365
+ originalName: string // nombre del archivo enviado
366
+ buffer: Buffer // contenido binario
367
+ mimeType: string // 'image/jpeg', 'application/pdf', etc.
368
+ size: number // bytes
369
+ }
370
+ ```
371
+
372
+ > Combiná con `bodyLimit()` para limitar el tamaño máximo:
373
+ > ```ts
374
+ > router.post('/avatar', [bodyLimit(5 * 1024 * 1024)], handler) // 5MB máx
375
+ > ```
376
+
327
377
  ---
328
378
 
329
379
  ## Middlewares
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arckode-framework",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "AI-first TypeScript/Bun framework. Modular, SOLID, zero magic. The AI reads the composition root and knows everything.",
5
5
  "type": "module",
6
6
  "main": "./kernel/framework.ts",
@@ -17,6 +17,7 @@
17
17
  "./adapters/mysql": "./adapters/mysql.ts",
18
18
  "./modules/mail": "./modules/mail/index.ts",
19
19
  "./modules/storage": "./modules/storage/index.ts",
20
+ "./modules/storage/local-adapter": "./modules/storage/local-adapter.ts",
20
21
  "./modules/queue": "./modules/queue/index.ts",
21
22
  "./testing": "./kernel/testing.ts"
22
23
  },