latinfo 0.6.1 → 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/dist/index.js +171 -1
- package/dist/licitaciones.d.ts +20 -0
- package/dist/licitaciones.js +141 -0
- package/dist/sdk.d.ts +26 -0
- package/dist/sdk.js +20 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const os_1 = __importDefault(require("os"));
|
|
11
11
|
const child_process_1 = require("child_process");
|
|
12
12
|
const demo_data_1 = require("./demo-data");
|
|
13
|
-
const VERSION = '0.
|
|
13
|
+
const VERSION = '0.7.0';
|
|
14
14
|
const API_URL = process.env.LATINFO_API_URL || 'https://api.latinfo.dev';
|
|
15
15
|
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID || 'Ov23li5fcQaiCsVtaMKK';
|
|
16
16
|
const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.latinfo');
|
|
@@ -391,6 +391,124 @@ function costsSimulate(usersStr, rpmStr, proPctStr) {
|
|
|
391
391
|
const margin = revenue - cfCost;
|
|
392
392
|
printCosts({ users, pro_users: proUsers, requests, cf_tier: cfTier, cf_cost: cfCost, revenue, margin, safe: margin >= 0 });
|
|
393
393
|
}
|
|
394
|
+
// --- Licitaciones ---
|
|
395
|
+
function parseFlag(args, flag) {
|
|
396
|
+
const idx = args.indexOf(flag);
|
|
397
|
+
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
|
|
398
|
+
}
|
|
399
|
+
async function licitaciones(args) {
|
|
400
|
+
// Parse flags from raw process.argv to avoid them being stripped
|
|
401
|
+
const allArgs = process.argv.slice(2);
|
|
402
|
+
const opts = {
|
|
403
|
+
category: parseFlag(allArgs, '--category') || parseFlag(allArgs, '-c'),
|
|
404
|
+
minAmount: parseFlag(allArgs, '--min-amount') ? Number(parseFlag(allArgs, '--min-amount')) : undefined,
|
|
405
|
+
maxAmount: parseFlag(allArgs, '--max-amount') ? Number(parseFlag(allArgs, '--max-amount')) : undefined,
|
|
406
|
+
buyer: parseFlag(allArgs, '--buyer') || parseFlag(allArgs, '-b'),
|
|
407
|
+
method: parseFlag(allArgs, '--method') || parseFlag(allArgs, '-m'),
|
|
408
|
+
status: parseFlag(allArgs, '--status') || parseFlag(allArgs, '-s'),
|
|
409
|
+
limit: parseFlag(allArgs, '--limit') || parseFlag(allArgs, '-l') ? Number(parseFlag(allArgs, '--limit') || parseFlag(allArgs, '-l')) : undefined,
|
|
410
|
+
};
|
|
411
|
+
// Query: everything in args that isn't a flag or flag value
|
|
412
|
+
const flagNames = ['--category', '-c', '--min-amount', '--max-amount', '--buyer', '-b', '--method', '-m', '--status', '-s', '--limit', '-l', '--json'];
|
|
413
|
+
const queryParts = [];
|
|
414
|
+
for (let i = 0; i < args.length; i++) {
|
|
415
|
+
if (flagNames.includes(args[i])) {
|
|
416
|
+
i++;
|
|
417
|
+
continue;
|
|
418
|
+
} // skip flag + value
|
|
419
|
+
queryParts.push(args[i]);
|
|
420
|
+
}
|
|
421
|
+
if (queryParts.length > 0)
|
|
422
|
+
opts.query = queryParts.join(' ');
|
|
423
|
+
// Subcommand: info
|
|
424
|
+
if (args[0] === 'info') {
|
|
425
|
+
const config = requireAuth();
|
|
426
|
+
const res = await apiRequest(config, '/pe/licitaciones/info');
|
|
427
|
+
const info = await res.json();
|
|
428
|
+
if (jsonFlag) {
|
|
429
|
+
console.log(JSON.stringify(info));
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
console.log(` Records: ${info.records.toLocaleString()}`);
|
|
433
|
+
}
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
// Subcommand: help
|
|
437
|
+
if (args[0] === 'help' || (!opts.query && !opts.category && !opts.buyer && !opts.method && !opts.status && opts.minAmount === undefined && opts.maxAmount === undefined)) {
|
|
438
|
+
console.log(`latinfo licitaciones — Search Peru government procurement (OECE/SEACE)
|
|
439
|
+
|
|
440
|
+
USAGE
|
|
441
|
+
latinfo licitaciones <query> [flags]
|
|
442
|
+
latinfo licitaciones [flags]
|
|
443
|
+
latinfo licitaciones info
|
|
444
|
+
latinfo licitaciones help
|
|
445
|
+
|
|
446
|
+
EXAMPLES
|
|
447
|
+
latinfo licitaciones "construccion puente"
|
|
448
|
+
latinfo licitaciones "servicio alimentacion" --category services
|
|
449
|
+
latinfo licitaciones --category works --min-amount 1000000
|
|
450
|
+
latinfo licitaciones --buyer "municipalidad" --limit 5
|
|
451
|
+
latinfo licitaciones "software" --json
|
|
452
|
+
|
|
453
|
+
FILTERS
|
|
454
|
+
--category, -c goods, services, works
|
|
455
|
+
--min-amount Minimum amount in PEN
|
|
456
|
+
--max-amount Maximum amount in PEN
|
|
457
|
+
--buyer, -b Buyer name (substring match)
|
|
458
|
+
--method, -m Procurement method (substring match)
|
|
459
|
+
--status, -s Status: CONVOCADO, CONTRATADO, DESIERTO, NULO, CONSENTIDO
|
|
460
|
+
--limit, -l Max results (default: 20)
|
|
461
|
+
--json JSON output
|
|
462
|
+
|
|
463
|
+
DATA
|
|
464
|
+
Source: OECE/SEACE (contratacionesabiertas.oece.gob.pe)
|
|
465
|
+
License: CC BY 4.0`);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const config = requireAuth();
|
|
469
|
+
// Build query string
|
|
470
|
+
const params = new URLSearchParams();
|
|
471
|
+
if (opts.query)
|
|
472
|
+
params.set('q', opts.query);
|
|
473
|
+
if (opts.category)
|
|
474
|
+
params.set('category', opts.category);
|
|
475
|
+
if (opts.minAmount !== undefined)
|
|
476
|
+
params.set('min_amount', String(opts.minAmount));
|
|
477
|
+
if (opts.maxAmount !== undefined)
|
|
478
|
+
params.set('max_amount', String(opts.maxAmount));
|
|
479
|
+
if (opts.buyer)
|
|
480
|
+
params.set('buyer', opts.buyer);
|
|
481
|
+
if (opts.method)
|
|
482
|
+
params.set('method', opts.method);
|
|
483
|
+
if (opts.status)
|
|
484
|
+
params.set('status', opts.status);
|
|
485
|
+
if (opts.limit !== undefined)
|
|
486
|
+
params.set('limit', String(opts.limit));
|
|
487
|
+
const res = await apiRequest(config, `/pe/licitaciones?${params}`);
|
|
488
|
+
const results = await res.json();
|
|
489
|
+
if (jsonFlag) {
|
|
490
|
+
console.log(JSON.stringify(results));
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (results.length === 0) {
|
|
494
|
+
console.log('No results found.');
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
for (const r of results) {
|
|
498
|
+
const monto = parseFloat(r.monto);
|
|
499
|
+
const montoFmt = monto > 0 ? `S/ ${monto.toLocaleString('es-PE', { minimumFractionDigits: 2 })}` : 'N/A';
|
|
500
|
+
const fecha = r.fecha?.split('T')[0] || '';
|
|
501
|
+
const desc = r.descripcion?.length > 100 ? r.descripcion.substring(0, 100) + '...' : (r.descripcion || '');
|
|
502
|
+
console.log(` ${fecha} ${montoFmt} [${r.categoria}] [${r.estado}]`);
|
|
503
|
+
console.log(` ${desc}`);
|
|
504
|
+
console.log(` Buyer: ${r.buyer_nombre}`);
|
|
505
|
+
if (r.url)
|
|
506
|
+
console.log(` ${r.url}`);
|
|
507
|
+
console.log(` ${r.metodo} — ${r.ocid}`);
|
|
508
|
+
console.log();
|
|
509
|
+
}
|
|
510
|
+
console.log(`${results.length} result(s)`);
|
|
511
|
+
}
|
|
394
512
|
function logout() {
|
|
395
513
|
deleteConfig();
|
|
396
514
|
console.log('Logged out.');
|
|
@@ -451,6 +569,16 @@ COMMANDS
|
|
|
451
569
|
Real-time cost report from production (admin only).
|
|
452
570
|
Requires LATINFO_ADMIN_SECRET env var.
|
|
453
571
|
|
|
572
|
+
licitaciones <query> [flags]
|
|
573
|
+
Search Peru government procurement (OECE/SEACE).
|
|
574
|
+
Flags: --category, --min-amount, --max-amount, --buyer, --method, --status, --limit
|
|
575
|
+
Run 'latinfo licitaciones help' for details.
|
|
576
|
+
|
|
577
|
+
completion [bash|zsh]
|
|
578
|
+
Output shell completion script.
|
|
579
|
+
bash: eval "$(latinfo completion bash)"
|
|
580
|
+
zsh: eval "$(latinfo completion zsh)"
|
|
581
|
+
|
|
454
582
|
help Show this help text.
|
|
455
583
|
|
|
456
584
|
FLAGS
|
|
@@ -482,6 +610,41 @@ EXIT CODES
|
|
|
482
610
|
function version() {
|
|
483
611
|
console.log(`latinfo/${VERSION}`);
|
|
484
612
|
}
|
|
613
|
+
function completion() {
|
|
614
|
+
const shell = rawArgs[1] || 'bash';
|
|
615
|
+
if (shell === 'zsh') {
|
|
616
|
+
console.log(`#compdef latinfo
|
|
617
|
+
_latinfo() {
|
|
618
|
+
local -a commands=(login logout whoami plan costs ruc dni search licitaciones lic help)
|
|
619
|
+
local -a lic_flags=(--category --min-amount --max-amount --buyer --method --status --limit --json)
|
|
620
|
+
local -a global_flags=(--json --live --version --token)
|
|
621
|
+
if (( CURRENT == 2 )); then
|
|
622
|
+
_describe 'command' commands
|
|
623
|
+
elif [[ "\${words[2]}" == "licitaciones" || "\${words[2]}" == "lic" ]]; then
|
|
624
|
+
_describe 'flag' lic_flags
|
|
625
|
+
else
|
|
626
|
+
_describe 'flag' global_flags
|
|
627
|
+
fi
|
|
628
|
+
}
|
|
629
|
+
compdef _latinfo latinfo`);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
console.log(`_latinfo_completions() {
|
|
633
|
+
local cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
634
|
+
local prev="\${COMP_WORDS[1]}"
|
|
635
|
+
if [[ \${COMP_CWORD} -eq 1 ]]; then
|
|
636
|
+
COMPREPLY=( $(compgen -W "login logout whoami plan costs ruc dni search licitaciones lic help" -- "$cur") )
|
|
637
|
+
elif [[ "$prev" == "licitaciones" || "$prev" == "lic" ]]; then
|
|
638
|
+
COMPREPLY=( $(compgen -W "--category --min-amount --max-amount --buyer --method --status --limit --json info help" -- "$cur") )
|
|
639
|
+
elif [[ "$prev" == "--category" || "$prev" == "-c" ]]; then
|
|
640
|
+
COMPREPLY=( $(compgen -W "goods services works" -- "$cur") )
|
|
641
|
+
elif [[ "$prev" == "--status" || "$prev" == "-s" ]]; then
|
|
642
|
+
COMPREPLY=( $(compgen -W "CONVOCADO CONTRATADO DESIERTO NULO CONSENTIDO" -- "$cur") )
|
|
643
|
+
fi
|
|
644
|
+
}
|
|
645
|
+
complete -F _latinfo_completions latinfo`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
485
648
|
// --- Main ---
|
|
486
649
|
const [command, ...args] = rawArgs;
|
|
487
650
|
if (rawArgs.includes('--version') || rawArgs.includes('-v')) {
|
|
@@ -513,6 +676,13 @@ else {
|
|
|
513
676
|
case 'search':
|
|
514
677
|
search(args.join(' ')).catch(e => { console.error(e); process.exit(1); });
|
|
515
678
|
break;
|
|
679
|
+
case 'licitaciones':
|
|
680
|
+
case 'lic':
|
|
681
|
+
licitaciones(args).catch(e => { console.error(e); process.exit(1); });
|
|
682
|
+
break;
|
|
683
|
+
case 'completion':
|
|
684
|
+
completion();
|
|
685
|
+
break;
|
|
516
686
|
case 'help':
|
|
517
687
|
help();
|
|
518
688
|
break;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local licitaciones search for CLI prototype.
|
|
3
|
+
* Reads binary files from ~/.latinfo/data/
|
|
4
|
+
*/
|
|
5
|
+
export interface LicitacionesOptions {
|
|
6
|
+
query?: string;
|
|
7
|
+
category?: string;
|
|
8
|
+
minAmount?: number;
|
|
9
|
+
maxAmount?: number;
|
|
10
|
+
buyer?: string;
|
|
11
|
+
method?: string;
|
|
12
|
+
status?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function searchLicitaciones(opts: LicitacionesOptions): Record<string, string>[];
|
|
16
|
+
export declare function dataInfo(): {
|
|
17
|
+
records: number;
|
|
18
|
+
binSize: number;
|
|
19
|
+
date: string;
|
|
20
|
+
} | null;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Local licitaciones search for CLI prototype.
|
|
4
|
+
* Reads binary files from ~/.latinfo/data/
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.searchLicitaciones = searchLicitaciones;
|
|
44
|
+
exports.dataInfo = dataInfo;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const os_1 = __importDefault(require("os"));
|
|
48
|
+
const BASE_NAME = 'pe-oece-licitaciones';
|
|
49
|
+
const FIELD_COUNT = 12;
|
|
50
|
+
const DATA_DIR = path.join(os_1.default.homedir(), '.latinfo', 'data');
|
|
51
|
+
const FIELD_NAMES = [
|
|
52
|
+
'ocid', 'titulo', 'descripcion', 'monto', 'moneda',
|
|
53
|
+
'categoria', 'metodo', 'buyer_nombre', 'buyer_id',
|
|
54
|
+
'fecha', 'estado', 'unspsc',
|
|
55
|
+
];
|
|
56
|
+
function decodeRecord(data, offset) {
|
|
57
|
+
if (offset + 4 > data.length)
|
|
58
|
+
return null;
|
|
59
|
+
const recordLen = data.readUInt32LE(offset);
|
|
60
|
+
if (offset + recordLen > data.length)
|
|
61
|
+
return null;
|
|
62
|
+
const fields = [];
|
|
63
|
+
let pos = offset + 4;
|
|
64
|
+
for (let i = 0; i < FIELD_COUNT; i++) {
|
|
65
|
+
if (pos + 2 > offset + recordLen)
|
|
66
|
+
break;
|
|
67
|
+
const fieldLen = data.readUInt16LE(pos);
|
|
68
|
+
pos += 2;
|
|
69
|
+
fields.push(data.subarray(pos, pos + fieldLen).toString('utf-8'));
|
|
70
|
+
pos += fieldLen;
|
|
71
|
+
}
|
|
72
|
+
return { fields, size: recordLen };
|
|
73
|
+
}
|
|
74
|
+
function fieldsToObject(fields) {
|
|
75
|
+
const obj = {};
|
|
76
|
+
for (let i = 0; i < FIELD_NAMES.length && i < fields.length; i++) {
|
|
77
|
+
obj[FIELD_NAMES[i]] = fields[i];
|
|
78
|
+
}
|
|
79
|
+
return obj;
|
|
80
|
+
}
|
|
81
|
+
function searchLicitaciones(opts) {
|
|
82
|
+
const binPath = path.join(DATA_DIR, `${BASE_NAME}.bin`);
|
|
83
|
+
const idxPath = path.join(DATA_DIR, `${BASE_NAME}.idx`);
|
|
84
|
+
if (!fs.existsSync(binPath) || !fs.existsSync(idxPath)) {
|
|
85
|
+
throw new Error('Licitaciones data not found. Build it first:\n' +
|
|
86
|
+
' npx tsx src/imports/pe-oece-build.ts <input.jsonl> ~/.latinfo/data');
|
|
87
|
+
}
|
|
88
|
+
const bin = fs.readFileSync(binPath);
|
|
89
|
+
const idx = fs.readFileSync(idxPath);
|
|
90
|
+
if (idx.subarray(0, 4).toString() !== 'LOCE')
|
|
91
|
+
throw new Error('Invalid index file');
|
|
92
|
+
const count = idx.readUInt32LE(4);
|
|
93
|
+
const maxResults = opts.limit || 20;
|
|
94
|
+
const results = [];
|
|
95
|
+
const queryTokens = opts.query
|
|
96
|
+
? opts.query.toLowerCase().split(/\s+/).filter(t => t.length > 0)
|
|
97
|
+
: [];
|
|
98
|
+
const categoryFilter = opts.category?.toLowerCase();
|
|
99
|
+
const buyerFilter = opts.buyer?.toLowerCase();
|
|
100
|
+
const methodFilter = opts.method?.toLowerCase();
|
|
101
|
+
const statusFilter = opts.status?.toUpperCase();
|
|
102
|
+
for (let i = 0; i < count && results.length < maxResults; i++) {
|
|
103
|
+
const offset = idx.readUInt32LE(12 + i * 8);
|
|
104
|
+
const decoded = decodeRecord(bin, offset);
|
|
105
|
+
if (!decoded)
|
|
106
|
+
continue;
|
|
107
|
+
const obj = fieldsToObject(decoded.fields);
|
|
108
|
+
if (categoryFilter && obj.categoria.toLowerCase() !== categoryFilter)
|
|
109
|
+
continue;
|
|
110
|
+
const monto = parseFloat(obj.monto);
|
|
111
|
+
if (opts.minAmount !== undefined && monto < opts.minAmount)
|
|
112
|
+
continue;
|
|
113
|
+
if (opts.maxAmount !== undefined && monto > opts.maxAmount)
|
|
114
|
+
continue;
|
|
115
|
+
if (buyerFilter && !obj.buyer_nombre.toLowerCase().includes(buyerFilter))
|
|
116
|
+
continue;
|
|
117
|
+
if (methodFilter && !obj.metodo.toLowerCase().includes(methodFilter))
|
|
118
|
+
continue;
|
|
119
|
+
if (statusFilter && obj.estado.toUpperCase() !== statusFilter)
|
|
120
|
+
continue;
|
|
121
|
+
if (queryTokens.length > 0) {
|
|
122
|
+
const searchText = (obj.titulo + ' ' + obj.descripcion + ' ' + obj.buyer_nombre).toLowerCase();
|
|
123
|
+
const allMatch = queryTokens.every(token => searchText.includes(token));
|
|
124
|
+
if (!allMatch)
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
results.push(obj);
|
|
128
|
+
}
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
function dataInfo() {
|
|
132
|
+
const binPath = path.join(DATA_DIR, `${BASE_NAME}.bin`);
|
|
133
|
+
const idxPath = path.join(DATA_DIR, `${BASE_NAME}.idx`);
|
|
134
|
+
if (!fs.existsSync(binPath) || !fs.existsSync(idxPath))
|
|
135
|
+
return null;
|
|
136
|
+
const idx = fs.readFileSync(idxPath);
|
|
137
|
+
const records = idx.readUInt32LE(4);
|
|
138
|
+
const binSize = fs.statSync(binPath).size;
|
|
139
|
+
const date = fs.statSync(binPath).mtime.toISOString().split('T')[0];
|
|
140
|
+
return { records, binSize, date };
|
|
141
|
+
}
|
package/dist/sdk.d.ts
CHANGED
|
@@ -15,6 +15,31 @@ export interface PeRecord {
|
|
|
15
15
|
manzana: string;
|
|
16
16
|
kilometro: string;
|
|
17
17
|
}
|
|
18
|
+
export interface PeLicitacion {
|
|
19
|
+
ocid: string;
|
|
20
|
+
titulo: string;
|
|
21
|
+
descripcion: string;
|
|
22
|
+
monto: string;
|
|
23
|
+
moneda: string;
|
|
24
|
+
categoria: string;
|
|
25
|
+
metodo: string;
|
|
26
|
+
buyer_nombre: string;
|
|
27
|
+
buyer_id: string;
|
|
28
|
+
fecha: string;
|
|
29
|
+
estado: string;
|
|
30
|
+
unspsc: string;
|
|
31
|
+
url: string;
|
|
32
|
+
}
|
|
33
|
+
export interface LicitacionesQuery {
|
|
34
|
+
q?: string;
|
|
35
|
+
category?: string;
|
|
36
|
+
min_amount?: number;
|
|
37
|
+
max_amount?: number;
|
|
38
|
+
buyer?: string;
|
|
39
|
+
method?: string;
|
|
40
|
+
status?: string;
|
|
41
|
+
limit?: number;
|
|
42
|
+
}
|
|
18
43
|
declare class Country {
|
|
19
44
|
private request;
|
|
20
45
|
private prefix;
|
|
@@ -26,6 +51,7 @@ declare class Peru extends Country {
|
|
|
26
51
|
ruc(ruc: string): Promise<PeRecord>;
|
|
27
52
|
dni(dni: string): Promise<PeRecord>;
|
|
28
53
|
search(query: string): Promise<PeRecord[]>;
|
|
54
|
+
licitaciones(query: LicitacionesQuery): Promise<PeLicitacion[]>;
|
|
29
55
|
}
|
|
30
56
|
export declare class Latinfo {
|
|
31
57
|
private apiKey;
|
package/dist/sdk.js
CHANGED
|
@@ -26,6 +26,26 @@ class Peru extends Country {
|
|
|
26
26
|
async search(query) {
|
|
27
27
|
return this.countryRequest(`/search?q=${encodeURIComponent(query)}`);
|
|
28
28
|
}
|
|
29
|
+
async licitaciones(query) {
|
|
30
|
+
const params = new URLSearchParams();
|
|
31
|
+
if (query.q)
|
|
32
|
+
params.set('q', query.q);
|
|
33
|
+
if (query.category)
|
|
34
|
+
params.set('category', query.category);
|
|
35
|
+
if (query.min_amount !== undefined)
|
|
36
|
+
params.set('min_amount', String(query.min_amount));
|
|
37
|
+
if (query.max_amount !== undefined)
|
|
38
|
+
params.set('max_amount', String(query.max_amount));
|
|
39
|
+
if (query.buyer)
|
|
40
|
+
params.set('buyer', query.buyer);
|
|
41
|
+
if (query.method)
|
|
42
|
+
params.set('method', query.method);
|
|
43
|
+
if (query.status)
|
|
44
|
+
params.set('status', query.status);
|
|
45
|
+
if (query.limit !== undefined)
|
|
46
|
+
params.set('limit', String(query.limit));
|
|
47
|
+
return this.countryRequest(`/licitaciones?${params}`);
|
|
48
|
+
}
|
|
29
49
|
}
|
|
30
50
|
class Latinfo {
|
|
31
51
|
apiKey;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "latinfo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Tax registry API for Latin America. Query RUC, DNI, and company data from SUNAT Peru. 18M+ records, updated daily, sub-100ms from anywhere.",
|
|
5
5
|
"homepage": "https://latinfo.dev",
|
|
6
6
|
"repository": {
|