@hablala/api-contract 0.6.0 → 0.8.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/data/image-classification-cases.json +69 -0
- package/data/image-extensions.json +4 -0
- package/dist/index.d.ts +884 -46
- package/openapi.json +1377 -84
- package/package.json +5 -2
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Casos borde COMPARTIDOS del criterio is-image, leidos por el contract test de AMBOS lados: ExUnit (image_attribute_test.exs) y vitest (attachments.test.ts). Cada caso es un sobre parcial (subset de FileEnvelope: url obligatoria; filename/content_type opcionales) + 'expected' = si ese sobre debe clasificar como IMAGEN. Si un lado difiere del 'expected', su suite falla: es el guard mecanico contra el drift entre el avatar del nodo (backend) y el thumbnail de la galeria (frontend). Anadir un caso aqui lo verifica en los dos toolchains a la vez. Las claves van en snake_case (content_type) porque el sobre vive dentro de properties (jsonb, no camelizado), igual en Elixir y TS.",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"name": "content_type image/* es imagen",
|
|
6
|
+
"envelope": { "url": "https://cdn/x", "content_type": "image/png" },
|
|
7
|
+
"expected": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "content_type no-imagen (pdf) no es imagen",
|
|
11
|
+
"envelope": { "url": "https://cdn/x.pdf", "content_type": "application/pdf" },
|
|
12
|
+
"expected": false
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "content_type generico pero url .jpg -> imagen (fallback por extension de url)",
|
|
16
|
+
"envelope": { "url": "https://cdn/x.jpg", "content_type": "application/octet-stream" },
|
|
17
|
+
"expected": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "content_type generico + filename con extension de imagen -> imagen",
|
|
21
|
+
"envelope": {
|
|
22
|
+
"url": "https://cdn/blob123",
|
|
23
|
+
"filename": "gato.webp",
|
|
24
|
+
"content_type": "application/octet-stream"
|
|
25
|
+
},
|
|
26
|
+
"expected": true
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "DIVERGENCIA HISTORICA: sin filename, url .png con query string, octet-stream -> imagen",
|
|
30
|
+
"envelope": { "url": "https://cdn/blob123.png?token=xyz", "content_type": "application/octet-stream" },
|
|
31
|
+
"expected": true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "sin filename ni content_type, url .heic -> imagen (fallback por extension de url)",
|
|
35
|
+
"envelope": { "url": "https://cdn/org-1/abc.heic" },
|
|
36
|
+
"expected": true
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "extension desconocida (.txt) no es imagen",
|
|
40
|
+
"envelope": { "url": "https://cdn/notas.txt" },
|
|
41
|
+
"expected": false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "sin extension reconocible y sin content_type no es imagen",
|
|
45
|
+
"envelope": { "url": "https://cdn/blob123" },
|
|
46
|
+
"expected": false
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "extension en mayusculas -> imagen (normaliza a minusculas)",
|
|
50
|
+
"envelope": { "url": "https://cdn/FOTO.PNG" },
|
|
51
|
+
"expected": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "punto en un segmento de path, no en el ultimo -> no es imagen",
|
|
55
|
+
"envelope": { "url": "https://cdn/v1.2/blob" },
|
|
56
|
+
"expected": false
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "filename tiene prioridad sobre la url: filename .txt aunque la url sea .png -> no es imagen",
|
|
60
|
+
"envelope": { "url": "https://cdn/abc.png", "filename": "notas.txt" },
|
|
61
|
+
"expected": false
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "svg cuenta como imagen",
|
|
65
|
+
"envelope": { "url": "https://cdn/logo.svg" },
|
|
66
|
+
"expected": true
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "SSOT (single source of truth) de las extensiones de archivo que cuentan como IMAGEN, compartida por el backend Elixir (Objects.ImageAttribute, el avatar del nodo en el Mapa de Datos) y el frontend TS (attachmentKind en attachments.ts, el thumbnail vs icono de la galeria/tabla). Vive en @hablala/api-contract porque es el paquete-contrato donde backend y frontend ya se encuentran. NO se genera desde OpenAPI: es un asset de dominio escrito a mano. Un record se retrata identico en la galeria de la ficha y en el Mapa SOLO si ambos lados leen esta lista; el contract test en ambos toolchains (ExUnit + vitest) falla si divergen. Criterio is-image (identico en los dos lados): content_type empieza por 'image/', O la extension (del filename, o de la url como respaldo, sin query string) esta en 'extensions'. Anadir una extension aqui la habilita en AMBOS lados a la vez.",
|
|
3
|
+
"extensions": ["png", "jpg", "jpeg", "gif", "webp", "avif", "svg", "heic", "bmp"]
|
|
4
|
+
}
|