latinfo 0.20.2 → 0.20.3

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/dist/index.js +66 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1605,6 +1605,8 @@ Free and unlimited. No credit card needed.`);
1605
1605
  console.log(`
1606
1606
  TEAM
1607
1607
  tasks My tasks
1608
+ tasks board Bounty board (available tasks)
1609
+ tasks claim <id> Claim a bounty
1608
1610
  tasks complete <id> Mark done
1609
1611
  tasks rank Team ranking
1610
1612
  pipe local <source> Import data locally
@@ -1616,7 +1618,8 @@ ADMIN
1616
1618
  team add <username> [--admin] Add team member
1617
1619
  team remove <username> Remove member
1618
1620
  team list List all members
1619
- tasks assign <user> "<title>" [--points N] Assign task
1621
+ tasks post "<title>" [--points N] Post bounty (anyone can claim)
1622
+ tasks assign <user> "<title>" [--points N] Assign task to specific member
1620
1623
  tasks approve <id> Approve + award points
1621
1624
  tasks reject <id> "<reason>" Reject back
1622
1625
  tasks delete <id> Delete task
@@ -4130,9 +4133,16 @@ async function teamCmd(args) {
4130
4133
  async function tasksCmd(args) {
4131
4134
  const sub = args[0];
4132
4135
  // Admin commands use ADMIN_SECRET
4133
- if (['assign', 'approve', 'reject', 'delete'].includes(sub)) {
4136
+ if (['assign', 'approve', 'reject', 'delete', 'post'].includes(sub)) {
4134
4137
  const adminSecret = requireAdmin();
4135
- const headers = { Authorization: `Bearer ${adminSecret}`, 'Content-Type': 'application/json' };
4138
+ const config = loadConfig();
4139
+ // approve/reject need API key auth + admin secret header; others use admin secret directly
4140
+ const needsApiKey = ['approve', 'reject'].includes(sub) && config?.api_key;
4141
+ const headers = {
4142
+ Authorization: needsApiKey ? `Bearer ${config.api_key}` : `Bearer ${adminSecret}`,
4143
+ 'Content-Type': 'application/json',
4144
+ ...(needsApiKey ? { 'X-Admin-Secret': adminSecret } : {}),
4145
+ };
4136
4146
  switch (sub) {
4137
4147
  case 'assign': {
4138
4148
  const username = args[1];
@@ -4155,6 +4165,26 @@ async function tasksCmd(args) {
4155
4165
  console.log(`Task #${data.id} assigned to ${username}: "${title}" (${data.points} pts)`);
4156
4166
  break;
4157
4167
  }
4168
+ case 'post': {
4169
+ const title = args[1];
4170
+ const pointsIdx = args.indexOf('--points');
4171
+ const points = pointsIdx !== -1 ? parseInt(args[pointsIdx + 1]) : 10;
4172
+ if (!title) {
4173
+ console.error('Usage: latinfo tasks post "<title>" [--points N]');
4174
+ process.exit(1);
4175
+ }
4176
+ const res = await fetch(`${API_URL}/team/tasks`, {
4177
+ method: 'POST', headers,
4178
+ body: JSON.stringify({ title, points }),
4179
+ });
4180
+ const data = await res.json();
4181
+ if (!res.ok) {
4182
+ console.error(data.message || data.error);
4183
+ process.exit(1);
4184
+ }
4185
+ console.log(`Bounty #${data.id} posted: "${title}" (${data.points} pts)`);
4186
+ break;
4187
+ }
4158
4188
  case 'approve': {
4159
4189
  const taskId = args[1];
4160
4190
  if (!taskId) {
@@ -4218,6 +4248,39 @@ async function tasksCmd(args) {
4218
4248
  }
4219
4249
  const headers = { Authorization: `Bearer ${config.api_key}`, 'Content-Type': 'application/json' };
4220
4250
  switch (sub) {
4251
+ case 'board': {
4252
+ const res = await fetch(`${API_URL}/team/board`, { headers });
4253
+ const bounties = await res.json();
4254
+ if (!res.ok) {
4255
+ console.error('Failed to get board');
4256
+ process.exit(1);
4257
+ }
4258
+ if (bounties.length === 0) {
4259
+ console.log('No bounties available.');
4260
+ return;
4261
+ }
4262
+ console.log('\n BOUNTY BOARD\n');
4263
+ for (const b of bounties) {
4264
+ console.log(` [#${b.id}] ${String(b.points).padStart(3)} pts ${b.title}`);
4265
+ }
4266
+ console.log(`\n Claim one: latinfo tasks claim <id>\n`);
4267
+ break;
4268
+ }
4269
+ case 'claim': {
4270
+ const taskId = args[1];
4271
+ if (!taskId) {
4272
+ console.error('Usage: latinfo tasks claim <task-id>');
4273
+ process.exit(1);
4274
+ }
4275
+ const res = await fetch(`${API_URL}/team/tasks/${taskId}/claim`, { method: 'POST', headers });
4276
+ const data = await res.json();
4277
+ if (!res.ok) {
4278
+ console.error(data.message || data.error);
4279
+ process.exit(1);
4280
+ }
4281
+ console.log(`Bounty #${taskId} claimed. Complete it: latinfo tasks complete ${taskId}`);
4282
+ break;
4283
+ }
4221
4284
  case 'complete': {
4222
4285
  const taskId = args[1];
4223
4286
  if (!taskId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "latinfo",
3
- "version": "0.20.2",
3
+ "version": "0.20.3",
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": {