@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.
- package/package.json +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.
|
|
4
|
-
"description": "
|
|
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
|
|
34
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
131
|
-
if (typeof lng !== 'number' || lng < -180 || lng > 180) throw new Error('dotrino-geo: lng
|
|
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) {
|