@dotrino/identity 0.20.0 → 0.21.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/identity",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "Identidad y rating de usuarios compartidos entre apps de Dotrino (vault iframe + postMessage)",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -17,7 +17,11 @@
17
17
  "./capabilities": {
18
18
  "import": "./vault/capabilities.js"
19
19
  },
20
- "./vault/core.js": "./vault/core.js"
20
+ "./avatar": {
21
+ "import": "./vault/avatar.js"
22
+ },
23
+ "./vault/core.js": "./vault/core.js",
24
+ "./vault/remote.js": "./vault/remote.js"
21
25
  },
22
26
  "files": [
23
27
  "src",
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @dotrino/identity/avatar — el AVATAR identicon, solo.
3
+ *
4
+ * Vive aparte de `capabilities.js` a propósito: es una función pura de ~30
5
+ * líneas, sin dependencias, sin crypto y sin vault, pero `capabilities.js`
6
+ * importa `core.js` (55 KB) y `core.js` importa de vuelta `capabilities.js`
7
+ * (dependencia circular). O sea que quien solo quería el identicon —el topbar,
8
+ * la tarjeta de perfil— se arrastraba el vault entero, o dependía de que el
9
+ * bundler podara `core.js` de milagro (ningún paquete declara `sideEffects`).
10
+ *
11
+ * Este subpath da la garantía: importar el avatar cuesta el avatar.
12
+ *
13
+ * NO copies estas funciones dentro de tu app. El identicon es DETERMINISTA a
14
+ * partir del pubkey: si cada app llevara su copia, el mismo usuario podría
15
+ * derivar un avatar distinto según dónde lo miren.
16
+ *
17
+ * `capabilities.js` re-exporta de aquí, así que los importadores viejos siguen
18
+ * funcionando igual.
19
+ */
20
+
21
+ /** Hash FNV-1a + xorshift. Sin necesidades de seguridad: es decorativo. */
22
+ function _hashSeed (s) {
23
+ let h = 2166136261 >>> 0
24
+ for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619) }
25
+ const bytes = []
26
+ let x = (h ^ 0x9e3779b9) >>> 0
27
+ for (let i = 0; i < 16; i++) { x ^= x << 13; x ^= x >>> 17; x ^= x << 5; x >>>= 0; bytes.push(x & 0xff) }
28
+ return { h: h >>> 0, bytes }
29
+ }
30
+
31
+ /**
32
+ * Identicon determinista de una semilla (normalmente el pubkey): así cada perfil
33
+ * nace con imagen sin que el usuario tenga que subir nada. Síncrono → usable
34
+ * directo en plantillas. Rejilla 5×5 simétrica sobre una "moneda" redondeada,
35
+ * con color derivado del hash.
36
+ */
37
+ export function avatarSvg (seed, { size = 80 } = {}) {
38
+ const { h, bytes } = _hashSeed(String(seed || 'dotrino'))
39
+ const hue = h % 360
40
+ const hue2 = (hue + 40) % 360
41
+ const fg = `hsl(${hue} 62% 46%)`
42
+ const bg1 = `hsl(${hue} 48% 95%)`
43
+ const bg2 = `hsl(${hue2} 48% 90%)`
44
+ const cells = 5
45
+ const unit = size / cells
46
+ let rects = ''
47
+ for (let col = 0; col < 3; col++) {
48
+ for (let row = 0; row < cells; row++) {
49
+ if (!(bytes[col * cells + row] & 1)) continue
50
+ for (const c of (col === 2 ? [2] : [col, cells - 1 - col])) {
51
+ rects += `<rect x="${(c * unit).toFixed(2)}" y="${(row * unit).toFixed(2)}" width="${unit.toFixed(2)}" height="${unit.toFixed(2)}"/>`
52
+ }
53
+ }
54
+ }
55
+ const id = 'g' + (h % 100000)
56
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">` +
57
+ `<defs><linearGradient id="${id}" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="${bg1}"/><stop offset="1" stop-color="${bg2}"/></linearGradient></defs>` +
58
+ `<rect width="${size}" height="${size}" rx="${(size * 0.5).toFixed(2)}" fill="url(#${id})"/>` +
59
+ `<g fill="${fg}" transform="translate(${(size * 0.12).toFixed(2)} ${(size * 0.12).toFixed(2)}) scale(0.76)">${rects}</g></svg>`
60
+ }
61
+
62
+ /** El avatar como data-URI listo para `<img src>` o `background-image`. */
63
+ export function avatarDataUri (seed, opts) {
64
+ return 'data:image/svg+xml,' + encodeURIComponent(avatarSvg(seed, opts))
65
+ }
@@ -99,49 +99,11 @@ export async function commitCode ({ code, dpub, sn }) {
99
99
  return [...new Uint8Array(h)].map((x) => x.toString(16).padStart(2, '0')).join('')
100
100
  }
101
101
 
102
- /**
103
- * Avatar generado (identicon de Dotrino): SVG DETERMINISTA a partir de una semilla
104
- * (típicamente el pubkey del perfil) cada perfil/identidad nace con imagen, sin que el
105
- * usuario tenga que subir nada. Síncrono (hash FNV-1a + xorshift, sin necesidades de
106
- * seguridad: es solo decorativo) → usable directo en plantillas. Rejilla 5×5 simétrica
107
- * sobre una "moneda" redondeada, con color derivado del hash.
108
- */
109
- function _hashSeed (s) {
110
- let h = 2166136261 >>> 0
111
- for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619) }
112
- const bytes = []
113
- let x = (h ^ 0x9e3779b9) >>> 0
114
- for (let i = 0; i < 16; i++) { x ^= x << 13; x ^= x >>> 17; x ^= x << 5; x >>>= 0; bytes.push(x & 0xff) }
115
- return { h: h >>> 0, bytes }
116
- }
117
- export function avatarSvg (seed, { size = 80 } = {}) {
118
- const { h, bytes } = _hashSeed(String(seed || 'dotrino'))
119
- const hue = h % 360
120
- const hue2 = (hue + 40) % 360
121
- const fg = `hsl(${hue} 62% 46%)`
122
- const bg1 = `hsl(${hue} 48% 95%)`
123
- const bg2 = `hsl(${hue2} 48% 90%)`
124
- const cells = 5
125
- const unit = size / cells
126
- let rects = ''
127
- for (let col = 0; col < 3; col++) {
128
- for (let row = 0; row < cells; row++) {
129
- if (!(bytes[col * cells + row] & 1)) continue
130
- for (const c of (col === 2 ? [2] : [col, cells - 1 - col])) {
131
- rects += `<rect x="${(c * unit).toFixed(2)}" y="${(row * unit).toFixed(2)}" width="${unit.toFixed(2)}" height="${unit.toFixed(2)}"/>`
132
- }
133
- }
134
- }
135
- const id = 'g' + (h % 100000)
136
- return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">` +
137
- `<defs><linearGradient id="${id}" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="${bg1}"/><stop offset="1" stop-color="${bg2}"/></linearGradient></defs>` +
138
- `<rect width="${size}" height="${size}" rx="${(size * 0.5).toFixed(2)}" fill="url(#${id})"/>` +
139
- `<g fill="${fg}" transform="translate(${(size * 0.12).toFixed(2)} ${(size * 0.12).toFixed(2)}) scale(0.76)">${rects}</g></svg>`
140
- }
141
- /** El avatar como data-URI listo para `<img src>` o `background-image`. */
142
- export function avatarDataUri (seed, opts) {
143
- return 'data:image/svg+xml,' + encodeURIComponent(avatarSvg(seed, opts))
144
- }
102
+ // El identicon vive en ./avatar.js (función pura, sin dependencias) y se
103
+ // re-exporta aquí por compatibilidad: importarlo desde este módulo arrastra
104
+ // core.js (55 KB), así que si SOLO quieres el avatar usa el subpath
105
+ // '@dotrino/identity/avatar'.
106
+ export { avatarSvg, avatarDataUri } from './avatar.js'
145
107
 
146
108
  /** Cuerpo canónico del certificado (lo que se firma): el cert SIN la firma. */
147
109
  export function delegationBody (cert) {