latinfo 0.18.0 → 0.19.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/dist/index.js +47 -35
- package/dist/sdk.d.ts +3 -1
- package/dist/sdk.js +16 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47,7 +47,7 @@ const local_search_1 = require("./local-search");
|
|
|
47
47
|
const client_search_1 = require("./client-search");
|
|
48
48
|
const odis_search_1 = require("./odis-search");
|
|
49
49
|
const mphf_search_1 = require("./mphf-search");
|
|
50
|
-
const VERSION = '0.18.
|
|
50
|
+
const VERSION = '0.18.1';
|
|
51
51
|
const API_URL = process.env.LATINFO_API_URL || 'https://api.latinfo.dev';
|
|
52
52
|
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID || 'Ov23li5fcQaiCsVtaMKK';
|
|
53
53
|
const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.latinfo');
|
|
@@ -760,42 +760,54 @@ async function searchServerStatus() {
|
|
|
760
760
|
console.error(' Linux Mint not reachable. Is it on?');
|
|
761
761
|
process.exit(1);
|
|
762
762
|
}
|
|
763
|
-
//
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
763
|
+
// Live loop until ready
|
|
764
|
+
while (true) {
|
|
765
|
+
// Check health
|
|
766
|
+
try {
|
|
767
|
+
const health = execSync(`ssh ${RUNNER} "curl -s http://localhost:3001/health"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
768
|
+
const data = JSON.parse(health);
|
|
769
|
+
if (data.status === 'ok') {
|
|
770
|
+
if (process.stdout.isTTY)
|
|
771
|
+
process.stdout.write('\r' + ' '.repeat(80) + '\r');
|
|
772
|
+
console.log(`\n Search server: READY`);
|
|
773
|
+
console.log(` Mode: ${data.mode || 'ram'}`);
|
|
774
|
+
console.log(` Sources: ${data.sources.join(', ')}`);
|
|
775
|
+
console.log(` Disk shards: ${data.diskShards || 0}`);
|
|
776
|
+
console.log(` RAM shards: ${data.ramShards || 0}`);
|
|
777
|
+
console.log(` RAM: ${data.ramMB || '?'} MB`);
|
|
778
|
+
// Quick search test per source
|
|
779
|
+
for (const src of data.sources) {
|
|
780
|
+
try {
|
|
781
|
+
const testResult = execSync(`ssh ${RUNNER} "curl -s 'http://localhost:3001/search?source=${src}&q=banco'"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
782
|
+
const testData = JSON.parse(testResult);
|
|
783
|
+
console.log(` Search ${src}: ${testData.results?.length || 0} results in ${testData.ms}ms`);
|
|
784
|
+
}
|
|
785
|
+
catch { }
|
|
786
|
+
}
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
catch { }
|
|
791
|
+
// Not ready — show progress bar (overwrites same line)
|
|
792
|
+
try {
|
|
793
|
+
const diskUsage = execSync(`ssh ${RUNNER} "du -sm /tmp/latinfo-search-data/ 2>/dev/null | awk '{print \\$1}'"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
794
|
+
const currentMB = parseInt(diskUsage) || 0;
|
|
795
|
+
const totalExpected = 6400;
|
|
796
|
+
const pct = Math.min(Math.floor(currentMB / totalExpected * 100), 99);
|
|
797
|
+
const filled = Math.floor(pct * 30 / 100);
|
|
798
|
+
const bar = '█'.repeat(filled) + '░'.repeat(30 - filled);
|
|
799
|
+
const lastLog = execSync(`ssh ${RUNNER} "sudo journalctl -u latinfo-search --no-pager -n 5 2>/dev/null | grep -oE '(Shard [0-9]+|Loading [^ ]+)' | tail -1"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
800
|
+
if (process.stdout.isTTY) {
|
|
801
|
+
process.stdout.write(`\r [${bar}] ${currentMB}/${totalExpected} MB (${pct}%) — ${lastLog || '...'} `);
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
console.log(` [${bar}] ${currentMB}/${totalExpected} MB (${pct}%) — ${lastLog || '...'}`);
|
|
805
|
+
return; // non-TTY: print once
|
|
806
|
+
}
|
|
780
807
|
}
|
|
808
|
+
catch { }
|
|
809
|
+
await new Promise(r => setTimeout(r, 10_000));
|
|
781
810
|
}
|
|
782
|
-
catch { }
|
|
783
|
-
// Not ready — show download progress
|
|
784
|
-
console.log(`\n Search server: LOADING\n`);
|
|
785
|
-
const diskUsage = execSync(`ssh ${RUNNER} "du -sm /tmp/latinfo-search-data/ 2>/dev/null | awk '{print \\$1}'"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
786
|
-
const currentMB = parseInt(diskUsage) || 0;
|
|
787
|
-
const totalExpected = 6400;
|
|
788
|
-
const pct = Math.min(Math.floor(currentMB / totalExpected * 100), 99);
|
|
789
|
-
const filled = Math.floor(pct * 30 / 100);
|
|
790
|
-
const bar = '█'.repeat(filled) + '░'.repeat(30 - filled);
|
|
791
|
-
console.log(` [${bar}] ${currentMB}/${totalExpected} MB (${pct}%)`);
|
|
792
|
-
// Show last shard activity
|
|
793
|
-
const lastLog = execSync(`ssh ${RUNNER} "sudo journalctl -u latinfo-search --no-pager -n 5 2>/dev/null | grep -oE '(Shard [0-9]+|Loading [^ ]+)' | tail -1"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
794
|
-
if (lastLog)
|
|
795
|
-
console.log(` Last: ${lastLog}`);
|
|
796
|
-
// Show RAM
|
|
797
|
-
const ram = execSync(`ssh ${RUNNER} "free -h | awk '/Mem:/{print \\$3\"/\"\\$2}'"`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
|
|
798
|
-
console.log(` RAM: ${ram}`);
|
|
799
811
|
}
|
|
800
812
|
// Seed queries used to discover real data from the API
|
|
801
813
|
const SEED_QUERIES = ['banco', 'empresa', 'servicios', 'comercial', 'grupo'];
|
package/dist/sdk.d.ts
CHANGED
|
@@ -137,8 +137,10 @@ declare class Country {
|
|
|
137
137
|
protected cfg: SourceConfig;
|
|
138
138
|
private mphfIndex;
|
|
139
139
|
constructor(request: <T>(path: string) => Promise<T>, rawRequest: (path: string) => Promise<Response>, cfg: SourceConfig);
|
|
140
|
-
/** Download and load MPHF index
|
|
140
|
+
/** Download and load MPHF index. Call once — enables offline search. */
|
|
141
141
|
loadIndex(): Promise<void>;
|
|
142
|
+
/** Check if there is a newer MPHF and update in background. Safe to call on every app open. */
|
|
143
|
+
refreshIndex(): void;
|
|
142
144
|
/** Load MPHF index from a pre-fetched buffer (e.g., bundled in APK). */
|
|
143
145
|
loadIndexFromBuffer(buf: ArrayBuffer): void;
|
|
144
146
|
/** Whether MPHF index is loaded (offline search available). */
|
package/dist/sdk.js
CHANGED
|
@@ -18,24 +18,19 @@ class Country {
|
|
|
18
18
|
this.rawRequest = rawRequest;
|
|
19
19
|
this.cfg = cfg;
|
|
20
20
|
}
|
|
21
|
-
/** Download and load MPHF index
|
|
21
|
+
/** Download and load MPHF index. Call once — enables offline search. */
|
|
22
22
|
async loadIndex() {
|
|
23
|
-
const res = await this.rawRequest(`/${this.cfg.prefix}/
|
|
23
|
+
const res = await this.rawRequest(`/${this.cfg.prefix}/mphf`);
|
|
24
24
|
if (!res.ok)
|
|
25
25
|
throw new Error(`Failed to download MPHF index: ${res.status}`);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
throw new Error('MPHF index not available');
|
|
35
|
-
this.mphfIndex = (0, mphf_runtime_1.deserializeMphfIndex)(await cdnRes.arrayBuffer());
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
this.mphfIndex = (0, mphf_runtime_1.deserializeMphfIndex)(await mphfRes.arrayBuffer());
|
|
26
|
+
this.mphfIndex = (0, mphf_runtime_1.deserializeMphfIndex)(await res.arrayBuffer());
|
|
27
|
+
}
|
|
28
|
+
/** Check if there is a newer MPHF and update in background. Safe to call on every app open. */
|
|
29
|
+
refreshIndex() {
|
|
30
|
+
this.rawRequest(`/${this.cfg.prefix}/mphf`).then(async (res) => {
|
|
31
|
+
if (res.ok)
|
|
32
|
+
this.mphfIndex = (0, mphf_runtime_1.deserializeMphfIndex)(await res.arrayBuffer());
|
|
33
|
+
}).catch(() => { });
|
|
39
34
|
}
|
|
40
35
|
/** Load MPHF index from a pre-fetched buffer (e.g., bundled in APK). */
|
|
41
36
|
loadIndexFromBuffer(buf) {
|
|
@@ -71,13 +66,16 @@ class Country {
|
|
|
71
66
|
return [];
|
|
72
67
|
resolved.push(r);
|
|
73
68
|
}
|
|
74
|
-
// Fetch posting lists from
|
|
69
|
+
// Fetch posting lists directly from R2 CDN (no Worker, no tunnel)
|
|
75
70
|
const tokenPostings = [];
|
|
76
71
|
for (const r of resolved) {
|
|
77
72
|
const lists = await Promise.all(r.entries.map(async (entry) => {
|
|
78
73
|
const byteLen = Math.min(entry.count, 50000) * idx.entrySize;
|
|
79
|
-
const
|
|
80
|
-
|
|
74
|
+
const cdnUrl = `https://data.latinfo.dev/${this.cfg.baseName}-search-${entry.shard}.dat`;
|
|
75
|
+
const res = await fetch(cdnUrl, {
|
|
76
|
+
headers: { Range: `bytes=${entry.offset}-${entry.offset + byteLen - 1}` },
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok && res.status !== 206)
|
|
81
79
|
return [];
|
|
82
80
|
const buf = await res.arrayBuffer();
|
|
83
81
|
return (0, mphf_runtime_1.parseV2PostingList)(buf, this.cfg.idLength);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "latinfo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Tax registry & procurement API for Latin America. Query RUC, DNI, NIT, licitaciones from Peru & Colombia. Offline MPHF search, full OCDS data, updated daily.",
|
|
5
5
|
"homepage": "https://latinfo.dev",
|
|
6
6
|
"repository": {
|