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.
- package/README.md +54 -4
- 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 {
|
|
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
|
-
|
|
324
|
-
const
|
|
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.
|
|
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
|
},
|