@dotrino/geo 0.2.2 → 0.7.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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/index.js +20 -9
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dotrino/geo",
3
- "version": "0.2.2",
4
- "description": "Cliente del índice geo de Dotrino (geo.dotrino.com): pins georreferenciados firmados con el vault, consulta por radio (PostGIS)",
3
+ "version": "0.7.0",
4
+ "description": "Dotrino geo index client (geo.dotrino.com): vault-signed georeferenced pins, radius queries (PostGIS)",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
7
7
  "module": "src/index.js",
package/src/index.js CHANGED
@@ -30,17 +30,20 @@ const DEFAULT_TTL_MS = 10 * 60 * 1000 // 10 min: pins efímeros por diseño
30
30
  * Crea un cliente del índice geo.
31
31
  *
32
32
  * @param {object} opts
33
- * @param {(data:object)=>Promise<string>} opts.signData firma canónica → base64 (del vault)
34
- * @param {()=>Promise<string>} opts.getPublicKeyJwk pubkey JWK string (del vault)
33
+ * @param {(data:object)=>Promise<{signature:string, publickey:string, chain:object[]}>} opts.signData
34
+ * Firma del vault. Devuelve el paquete: quién firmó y la cadena que lo prueba.
35
+ * @param {()=>Promise<string>} opts.getPublicKeyJwk
36
+ * MI IDENTIDAD (`profileId`), no la llave de este aparato: si pasas la del aparato,
37
+ * publicar desde el teléfono y desde el PC crea dos autores distintos.
35
38
  * @param {string} [opts.baseUrl] default https://geo.dotrino.com
36
39
  * @param {typeof fetch} [opts.fetch] fetch inyectable (tests/SSR)
37
40
  */
38
41
  export function createGeoClient ({ signData, getPublicKeyJwk, baseUrl = DEFAULT_BASE, fetch: f } = {}) {
39
42
  if (typeof signData !== 'function' || typeof getPublicKeyJwk !== 'function') {
40
- throw new Error('dotrino-geo: signData y getPublicKeyJwk son requeridos (inyectalos desde el vault de identidad)')
43
+ throw new Error('dotrino-geo: signData and getPublicKeyJwk are required (inject them from the identity vault)')
41
44
  }
42
45
  const doFetch = f || (typeof fetch !== 'undefined' ? fetch.bind(globalThis) : null)
43
- if (!doFetch) throw new Error('dotrino-geo: no hay fetch disponible; inyectalo en opts.fetch')
46
+ if (!doFetch) throw new Error('dotrino-geo: no fetch available; inject it in opts.fetch')
44
47
  const base = baseUrl.replace(/\/+$/, '')
45
48
 
46
49
  /**
@@ -58,6 +61,9 @@ export function createGeoClient ({ signData, getPublicKeyJwk, baseUrl = DEFAULT_
58
61
  */
59
62
  async function publishPin ({ lat, lng, payload = {}, tags, ttlMs = DEFAULT_TTL_MS, geohashPrecision = 7, now } = {}) {
60
63
  assertLatLng(lat, lng)
64
+ // `publickey` ES LA IDENTIDAD, no la llave del aparato que firma. Antes se ponía la
65
+ // del aparato, así que publicar desde el teléfono y desde el PC creaba dos «autores»
66
+ // distintos para la misma persona — y quien mirara el mapa vería dos.
61
67
  const publickey = await getPublicKeyJwk()
62
68
  const ts = now ?? Date.now()
63
69
  const data = {
@@ -71,11 +77,16 @@ export function createGeoClient ({ signData, getPublicKeyJwk, baseUrl = DEFAULT_
71
77
  }
72
78
  const cleanTags = normalizeTags(tags)
73
79
  if (cleanTags.length) data.tags = cleanTags
74
- const signature = await signData(data)
80
+ const firma = await signData(data)
81
+ // Un vault viejo devuelve solo la firma; uno nuevo, el paquete con quién firmó y la
82
+ // cadena que prueba que ese firmante habla por esta identidad.
83
+ const sobre = typeof firma === 'string'
84
+ ? { data, signature: firma }
85
+ : { data, signature: firma.signature, ...(firma.publickey ? { signer: firma.publickey } : {}), ...(firma.chain?.length ? { chain: firma.chain } : {}) }
75
86
  const res = await doFetch(`${base}/pins`, {
76
87
  method: 'PUT',
77
88
  headers: { 'content-type': 'application/json' },
78
- body: JSON.stringify({ data, signature })
89
+ body: JSON.stringify(sobre)
79
90
  })
80
91
  return handle(res)
81
92
  }
@@ -94,7 +105,7 @@ export function createGeoClient ({ signData, getPublicKeyJwk, baseUrl = DEFAULT_
94
105
  */
95
106
  async function queryRadius ({ lat, lng, radiusMeters, limit = 50, filter, tags } = {}) {
96
107
  assertLatLng(lat, lng)
97
- if (!(radiusMeters > 0)) throw new Error('dotrino-geo: radiusMeters debe ser > 0')
108
+ if (!(radiusMeters > 0)) throw new Error('dotrino-geo: radiusMeters must be > 0')
98
109
  const params = new URLSearchParams({
99
110
  lat: String(lat), lng: String(lng), r: String(radiusMeters), limit: String(limit)
100
111
  })
@@ -127,8 +138,8 @@ export function createGeoClient ({ signData, getPublicKeyJwk, baseUrl = DEFAULT_
127
138
  // ----- helpers -----------------------------------------------------------
128
139
 
129
140
  function assertLatLng (lat, lng) {
130
- if (typeof lat !== 'number' || lat < -90 || lat > 90) throw new Error('dotrino-geo: lat inválida')
131
- if (typeof lng !== 'number' || lng < -180 || lng > 180) throw new Error('dotrino-geo: lng inválida')
141
+ if (typeof lat !== 'number' || lat < -90 || lat > 90) throw new Error('dotrino-geo: invalid lat')
142
+ if (typeof lng !== 'number' || lng < -180 || lng > 180) throw new Error('dotrino-geo: invalid lng')
132
143
  }
133
144
 
134
145
  function round (n, decimals) {