latinfo 0.1.0 → 0.3.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 +91 -62
- package/dist/sdk.d.ts +13 -3
- package/dist/sdk.js +27 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,8 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const http_1 = __importDefault(require("http"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const child_process_1 = require("child_process");
|
|
10
12
|
const API_URL = process.env.LATINFO_API_URL || 'https://api.latinfo.dev';
|
|
11
13
|
const GITHUB_CLIENT_ID = 'Ov23li5fcQaiCsVtaMKK';
|
|
12
14
|
const CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.latinfo');
|
|
@@ -29,75 +31,68 @@ function deleteConfig() {
|
|
|
29
31
|
}
|
|
30
32
|
catch { }
|
|
31
33
|
}
|
|
32
|
-
// --- GitHub
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
body: JSON.stringify({
|
|
55
|
-
client_id: GITHUB_CLIENT_ID,
|
|
56
|
-
device_code: codeData.device_code,
|
|
57
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
58
|
-
}),
|
|
34
|
+
// --- GitHub Authorization Code Flow ---
|
|
35
|
+
function openBrowser(url) {
|
|
36
|
+
const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
37
|
+
(0, child_process_1.exec)(`${cmd} "${url}"`);
|
|
38
|
+
}
|
|
39
|
+
async function waitForCallback(port) {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
const server = http_1.default.createServer((req, res) => {
|
|
42
|
+
const url = new URL(req.url || '', `http://localhost:${port}`);
|
|
43
|
+
const code = url.searchParams.get('code');
|
|
44
|
+
if (code) {
|
|
45
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
46
|
+
res.end('<h2>Done. You can close this window.</h2>');
|
|
47
|
+
server.close();
|
|
48
|
+
resolve(code);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
res.writeHead(400);
|
|
52
|
+
res.end('Missing code');
|
|
53
|
+
server.close();
|
|
54
|
+
reject(new Error('No code received from GitHub'));
|
|
55
|
+
}
|
|
59
56
|
});
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
// 3. Exchange for Latinfo API key
|
|
57
|
+
server.listen(port, () => { });
|
|
58
|
+
setTimeout(() => { server.close(); reject(new Error('Timeout waiting for authorization')); }, 120_000);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async function login() {
|
|
62
|
+
const port = 8400;
|
|
63
|
+
const redirectUri = `http://localhost:${port}/callback`;
|
|
64
|
+
const scope = 'read:user,user:email';
|
|
65
|
+
const authUrl = `https://github.com/login/oauth/authorize?client_id=${GITHUB_CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${scope}`;
|
|
66
|
+
console.log('Opening GitHub...');
|
|
67
|
+
openBrowser(authUrl);
|
|
68
|
+
// 1. Wait for GitHub to redirect back with code
|
|
69
|
+
const code = await waitForCallback(port);
|
|
70
|
+
// 2. Exchange code for access token (server-side, needs client_secret)
|
|
76
71
|
const authRes = await fetch(`${API_URL}/auth/github`, {
|
|
77
72
|
method: 'POST',
|
|
78
73
|
headers: { 'Content-Type': 'application/json' },
|
|
79
|
-
body: JSON.stringify({
|
|
74
|
+
body: JSON.stringify({ code, redirect_uri: redirectUri }),
|
|
80
75
|
});
|
|
81
76
|
if (!authRes.ok) {
|
|
82
|
-
console.error('Error
|
|
77
|
+
console.error('Error getting API key:', await authRes.text());
|
|
83
78
|
process.exit(1);
|
|
84
79
|
}
|
|
85
80
|
const authData = await authRes.json();
|
|
86
81
|
saveConfig({ api_key: authData.api_key, github_username: authData.github_username });
|
|
87
|
-
console.log(
|
|
82
|
+
console.log(`Logged in as ${authData.github_username}`);
|
|
88
83
|
}
|
|
89
84
|
// --- Commands ---
|
|
90
85
|
async function ruc(rucNumber) {
|
|
91
86
|
const config = loadConfig();
|
|
92
87
|
if (!config) {
|
|
93
|
-
console.error('
|
|
88
|
+
console.error('Not logged in. Run: latinfo login');
|
|
94
89
|
process.exit(1);
|
|
95
90
|
}
|
|
96
91
|
if (!/^\d{11}$/.test(rucNumber)) {
|
|
97
|
-
console.error('RUC
|
|
92
|
+
console.error('Invalid RUC. Must be 11 digits.');
|
|
98
93
|
process.exit(1);
|
|
99
94
|
}
|
|
100
|
-
const res = await fetch(`${API_URL}/ruc/${rucNumber}`, {
|
|
95
|
+
const res = await fetch(`${API_URL}/pe/ruc/${rucNumber}`, {
|
|
101
96
|
headers: { Authorization: `Bearer ${config.api_key}` },
|
|
102
97
|
});
|
|
103
98
|
if (!res.ok) {
|
|
@@ -116,13 +111,43 @@ async function ruc(rucNumber) {
|
|
|
116
111
|
Zona: ${[data.codigoZona, data.tipoZona].filter(v => v && v !== '-').join(' ')}
|
|
117
112
|
`.trim());
|
|
118
113
|
}
|
|
114
|
+
async function dni(dniNumber) {
|
|
115
|
+
const config = loadConfig();
|
|
116
|
+
if (!config) {
|
|
117
|
+
console.error('Not logged in. Run: latinfo login');
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
if (!/^\d{8}$/.test(dniNumber)) {
|
|
121
|
+
console.error('Invalid DNI. Must be 8 digits.');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const res = await fetch(`${API_URL}/pe/dni/${dniNumber}`, {
|
|
125
|
+
headers: { Authorization: `Bearer ${config.api_key}` },
|
|
126
|
+
});
|
|
127
|
+
if (!res.ok) {
|
|
128
|
+
const err = await res.json();
|
|
129
|
+
console.error(err.message || err.error);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
const data = await res.json();
|
|
133
|
+
console.log(`
|
|
134
|
+
DNI: ${data.dni}
|
|
135
|
+
RUC: ${data.ruc}
|
|
136
|
+
Razón Social: ${data.razonSocial}
|
|
137
|
+
Estado: ${data.estado}
|
|
138
|
+
Condición: ${data.condicion}
|
|
139
|
+
Ubigeo: ${data.ubigeo}
|
|
140
|
+
Dirección: ${[data.tipoVia, data.nombreVia, data.numero].filter(v => v && v !== '-').join(' ')}
|
|
141
|
+
Zona: ${[data.codigoZona, data.tipoZona].filter(v => v && v !== '-').join(' ')}
|
|
142
|
+
`.trim());
|
|
143
|
+
}
|
|
119
144
|
async function search(query) {
|
|
120
145
|
const config = loadConfig();
|
|
121
146
|
if (!config) {
|
|
122
|
-
console.error('
|
|
147
|
+
console.error('Not logged in. Run: latinfo login');
|
|
123
148
|
process.exit(1);
|
|
124
149
|
}
|
|
125
|
-
const res = await fetch(`${API_URL}/search?q=${encodeURIComponent(query)}`, {
|
|
150
|
+
const res = await fetch(`${API_URL}/pe/search?q=${encodeURIComponent(query)}`, {
|
|
126
151
|
headers: { Authorization: `Bearer ${config.api_key}` },
|
|
127
152
|
});
|
|
128
153
|
if (!res.ok) {
|
|
@@ -132,37 +157,38 @@ async function search(query) {
|
|
|
132
157
|
}
|
|
133
158
|
const data = await res.json();
|
|
134
159
|
if (data.count === 0) {
|
|
135
|
-
console.log('
|
|
160
|
+
console.log('No results found.');
|
|
136
161
|
return;
|
|
137
162
|
}
|
|
138
163
|
for (const r of data.results) {
|
|
139
164
|
console.log(` ${r.ruc} ${r.razonSocial} [${r.estado}]`);
|
|
140
165
|
}
|
|
141
|
-
console.log(`\n${data.count}
|
|
166
|
+
console.log(`\n${data.count} result(s)`);
|
|
142
167
|
}
|
|
143
168
|
function whoami() {
|
|
144
169
|
const config = loadConfig();
|
|
145
170
|
if (!config) {
|
|
146
|
-
console.error('
|
|
171
|
+
console.error('Not logged in. Run: latinfo login');
|
|
147
172
|
process.exit(1);
|
|
148
173
|
}
|
|
149
174
|
console.log(config.github_username);
|
|
150
175
|
}
|
|
151
176
|
function logout() {
|
|
152
177
|
deleteConfig();
|
|
153
|
-
console.log('
|
|
178
|
+
console.log('Logged out.');
|
|
154
179
|
}
|
|
155
180
|
function help() {
|
|
156
181
|
console.log(`
|
|
157
182
|
latinfo - Public data API for Latin America
|
|
158
183
|
|
|
159
|
-
|
|
160
|
-
login
|
|
161
|
-
logout
|
|
162
|
-
whoami
|
|
163
|
-
ruc <ruc>
|
|
164
|
-
|
|
165
|
-
|
|
184
|
+
Commands:
|
|
185
|
+
login Authenticate with GitHub
|
|
186
|
+
logout Sign out
|
|
187
|
+
whoami Show current user
|
|
188
|
+
ruc <ruc> Lookup by RUC (11 digits)
|
|
189
|
+
dni <dni> Lookup by DNI (8 digits)
|
|
190
|
+
search <query> Search by business name
|
|
191
|
+
help Show this help
|
|
166
192
|
`.trim());
|
|
167
193
|
}
|
|
168
194
|
// --- Main ---
|
|
@@ -180,6 +206,9 @@ switch (command) {
|
|
|
180
206
|
case 'ruc':
|
|
181
207
|
ruc(args[0]).catch(e => { console.error(e); process.exit(1); });
|
|
182
208
|
break;
|
|
209
|
+
case 'dni':
|
|
210
|
+
dni(args[0]).catch(e => { console.error(e); process.exit(1); });
|
|
211
|
+
break;
|
|
183
212
|
case 'search':
|
|
184
213
|
search(args.join(' ')).catch(e => { console.error(e); process.exit(1); });
|
|
185
214
|
break;
|
package/dist/sdk.d.ts
CHANGED
|
@@ -28,15 +28,25 @@ interface SearchResponse {
|
|
|
28
28
|
count: number;
|
|
29
29
|
results: SearchResult[];
|
|
30
30
|
}
|
|
31
|
+
declare class Country {
|
|
32
|
+
private request;
|
|
33
|
+
private prefix;
|
|
34
|
+
constructor(request: <T>(path: string) => Promise<T>, prefix: string);
|
|
35
|
+
protected countryRequest<T>(path: string): Promise<T>;
|
|
36
|
+
}
|
|
37
|
+
declare class Peru extends Country {
|
|
38
|
+
constructor(request: <T>(path: string) => Promise<T>);
|
|
39
|
+
ruc(ruc: string): Promise<RucResult>;
|
|
40
|
+
dni(dni: string): Promise<DniResult>;
|
|
41
|
+
search(query: string): Promise<SearchResponse>;
|
|
42
|
+
}
|
|
31
43
|
export declare class Latinfo {
|
|
32
44
|
private apiKey;
|
|
33
45
|
private baseUrl;
|
|
46
|
+
pe: Peru;
|
|
34
47
|
constructor(apiKey: string, options?: {
|
|
35
48
|
baseUrl?: string;
|
|
36
49
|
});
|
|
37
50
|
private request;
|
|
38
|
-
ruc(ruc: string): Promise<RucResult>;
|
|
39
|
-
dni(dni: string): Promise<DniResult>;
|
|
40
|
-
search(query: string): Promise<SearchResponse>;
|
|
41
51
|
}
|
|
42
52
|
export {};
|
package/dist/sdk.js
CHANGED
|
@@ -2,12 +2,39 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Latinfo = void 0;
|
|
4
4
|
const DEFAULT_API_URL = 'https://api.latinfo.dev';
|
|
5
|
+
class Country {
|
|
6
|
+
request;
|
|
7
|
+
prefix;
|
|
8
|
+
constructor(request, prefix) {
|
|
9
|
+
this.request = request;
|
|
10
|
+
this.prefix = prefix;
|
|
11
|
+
}
|
|
12
|
+
countryRequest(path) {
|
|
13
|
+
return this.request(`/${this.prefix}${path}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class Peru extends Country {
|
|
17
|
+
constructor(request) {
|
|
18
|
+
super(request, 'pe');
|
|
19
|
+
}
|
|
20
|
+
async ruc(ruc) {
|
|
21
|
+
return this.countryRequest(`/ruc/${ruc}`);
|
|
22
|
+
}
|
|
23
|
+
async dni(dni) {
|
|
24
|
+
return this.countryRequest(`/dni/${dni}`);
|
|
25
|
+
}
|
|
26
|
+
async search(query) {
|
|
27
|
+
return this.countryRequest(`/search?q=${encodeURIComponent(query)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
5
30
|
class Latinfo {
|
|
6
31
|
apiKey;
|
|
7
32
|
baseUrl;
|
|
33
|
+
pe;
|
|
8
34
|
constructor(apiKey, options) {
|
|
9
35
|
this.apiKey = apiKey;
|
|
10
36
|
this.baseUrl = options?.baseUrl || DEFAULT_API_URL;
|
|
37
|
+
this.pe = new Peru(this.request.bind(this));
|
|
11
38
|
}
|
|
12
39
|
async request(path) {
|
|
13
40
|
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
@@ -19,14 +46,5 @@ class Latinfo {
|
|
|
19
46
|
}
|
|
20
47
|
return res.json();
|
|
21
48
|
}
|
|
22
|
-
async ruc(ruc) {
|
|
23
|
-
return this.request(`/ruc/${ruc}`);
|
|
24
|
-
}
|
|
25
|
-
async dni(dni) {
|
|
26
|
-
return this.request(`/dni/${dni}`);
|
|
27
|
-
}
|
|
28
|
-
async search(query) {
|
|
29
|
-
return this.request(`/search?q=${encodeURIComponent(query)}`);
|
|
30
|
-
}
|
|
31
49
|
}
|
|
32
50
|
exports.Latinfo = Latinfo;
|