@profullstack/nichedb 0.35.8 → 0.36.1
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 +1 -1
- package/src/index.js +60 -11
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { homedir, tmpdir } from 'node:os';
|
|
|
15
15
|
import { join } from 'node:path';
|
|
16
16
|
import { createInterface } from 'node:readline';
|
|
17
17
|
|
|
18
|
-
export const VERSION = '0.
|
|
18
|
+
export const VERSION = '0.36.0';
|
|
19
19
|
const GEO_FLAGS = ['lat', 'long', 'radius', 'unit', 'bbox', 'sort', 'offset'];
|
|
20
20
|
const DEFAULT_API = process.env.NICHEDB_API ?? 'https://nichedb.dev';
|
|
21
21
|
const CONFIG_DIR = join(process.env.XDG_CONFIG_HOME ?? join(homedir(), '.config'), 'nichedb');
|
|
@@ -225,9 +225,22 @@ export const COMMANDS = [
|
|
|
225
225
|
},
|
|
226
226
|
{
|
|
227
227
|
name: 'profiles',
|
|
228
|
-
usage:
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
usage:
|
|
229
|
+
'profiles [<query>] [--title …] [--company …] [--seniority …] [--tags …] [--linkedin <url>] [--since <iso>] [--mine]',
|
|
230
|
+
summary:
|
|
231
|
+
'People with an OpenProfile.md: search them (by text, or the job title, company and seniority they publish), find the one a LinkedIn URL belongs to, or list the ones your key owns.',
|
|
232
|
+
options: [
|
|
233
|
+
'--title <job title>',
|
|
234
|
+
'--company <domain|url|name>',
|
|
235
|
+
'--seniority <c-suite|vp|director|manager|senior|entry>',
|
|
236
|
+
'--tags <title:…,company:…,seniority:…>',
|
|
237
|
+
'--linkedin <url>',
|
|
238
|
+
'--since <iso>',
|
|
239
|
+
'--mine',
|
|
240
|
+
'--limit',
|
|
241
|
+
'--json',
|
|
242
|
+
'--urls',
|
|
243
|
+
],
|
|
231
244
|
},
|
|
232
245
|
{
|
|
233
246
|
name: 'profile',
|
|
@@ -244,10 +257,20 @@ export const COMMANDS = [
|
|
|
244
257
|
},
|
|
245
258
|
{
|
|
246
259
|
name: 'profile edit',
|
|
247
|
-
usage:
|
|
260
|
+
usage:
|
|
261
|
+
'profile edit <ref> [--file openprofile.md] [--emoji …] [--pronouns …] [--web …] [--handle …] [--public|--private]',
|
|
248
262
|
summary:
|
|
249
|
-
'Edit a profile you own (key required). Opens $EDITOR on the file when
|
|
250
|
-
options: [
|
|
263
|
+
'Edit a profile you own (key required). Opens $EDITOR on the file when nothing else is given. --emoji, --pronouns and --web set those identity keys alone (--pronouns= clears).',
|
|
264
|
+
options: [
|
|
265
|
+
'--file <path>',
|
|
266
|
+
'--emoji <emoji|:shortcode:>',
|
|
267
|
+
'--pronouns <as written>',
|
|
268
|
+
'--web <url>',
|
|
269
|
+
'--handle <handle>',
|
|
270
|
+
'--public',
|
|
271
|
+
'--private',
|
|
272
|
+
'--json',
|
|
273
|
+
],
|
|
251
274
|
},
|
|
252
275
|
{
|
|
253
276
|
name: 'profile handle',
|
|
@@ -400,6 +423,16 @@ const pad = (s, n) =>
|
|
|
400
423
|
.slice(0, n);
|
|
401
424
|
const when = (d) => (d ? new Date(d).toISOString().slice(0, 16).replace('T', ' ') : '-');
|
|
402
425
|
|
|
426
|
+
/** `CTO, Example (example.com) [c-suite]` for a profile that publishes them; '' when it does not. */
|
|
427
|
+
export function professionalLine(p) {
|
|
428
|
+
const company = p?.company
|
|
429
|
+
? [p.company.name, p.company.domain ? `(${p.company.domain})` : null].filter(Boolean).join(' ')
|
|
430
|
+
: '';
|
|
431
|
+
const head = [p?.title, company].filter(Boolean).join(', ');
|
|
432
|
+
if (!head && !p?.seniority) return '';
|
|
433
|
+
return [head, p?.seniority ? `[${p.seniority}]` : null].filter(Boolean).join(' ');
|
|
434
|
+
}
|
|
435
|
+
|
|
403
436
|
function printItems(items, { json, urls }) {
|
|
404
437
|
if (json) return out(JSON.stringify(items, null, 2));
|
|
405
438
|
if (urls) {
|
|
@@ -958,6 +991,8 @@ export async function run(
|
|
|
958
991
|
if (flags.since) qs.set('since', flags.since);
|
|
959
992
|
if (flags.limit) qs.set('limit', flags.limit);
|
|
960
993
|
if (flags.mine) qs.set('mine', '1');
|
|
994
|
+
for (const f of ['title', 'company', 'seniority', 'tags', 'linkedin'])
|
|
995
|
+
if (typeof flags[f] === 'string' && flags[f]) qs.set(f, flags[f]);
|
|
961
996
|
const { profiles } = await client.get(`/api/v1/profiles?${qs}`);
|
|
962
997
|
if (json) {
|
|
963
998
|
out(JSON.stringify(profiles, null, 2));
|
|
@@ -968,7 +1003,10 @@ export async function run(
|
|
|
968
1003
|
out(p.page);
|
|
969
1004
|
continue;
|
|
970
1005
|
}
|
|
971
|
-
|
|
1006
|
+
const name = `${p.emoji ? `${p.emoji} ` : ''}${p.name}${p.pronouns ? ` (${p.pronouns})` : ''}`;
|
|
1007
|
+
out(`${pad(p.ref, 34)} ${pad(p.kind ?? '', 12)} ${name}${p.claimed ? ' (claimed)' : ''}`);
|
|
1008
|
+
const work = professionalLine(p);
|
|
1009
|
+
if (work) out(` ${work}`);
|
|
972
1010
|
if (p.headline) out(` ${p.headline}`);
|
|
973
1011
|
}
|
|
974
1012
|
if (profiles.length === 0) out('(nobody yet)');
|
|
@@ -1000,11 +1038,22 @@ export async function run(
|
|
|
1000
1038
|
}
|
|
1001
1039
|
if (sub === 'edit') {
|
|
1002
1040
|
if (!arg)
|
|
1003
|
-
throw new Error(
|
|
1041
|
+
throw new Error(
|
|
1042
|
+
'profile edit <ref> [--file …] [--emoji …] [--pronouns …] [--web …] [--handle …] [--public|--private]',
|
|
1043
|
+
);
|
|
1004
1044
|
const ref = encodeURIComponent(arg);
|
|
1045
|
+
// Emoji, Pronouns and Web on their own; an empty value (--pronouns=) removes the key.
|
|
1046
|
+
const fields = {};
|
|
1047
|
+
for (const f of ['emoji', 'pronouns', 'web'])
|
|
1048
|
+
if (flags[f] !== undefined) fields[f] = flags[f] === true ? '' : String(flags[f]);
|
|
1005
1049
|
let markdown = null;
|
|
1006
1050
|
if (flags.file) markdown = await readFile(String(flags.file), 'utf8');
|
|
1007
|
-
else if (
|
|
1051
|
+
else if (
|
|
1052
|
+
!flags.handle &&
|
|
1053
|
+
!flags.public &&
|
|
1054
|
+
!flags.private &&
|
|
1055
|
+
Object.keys(fields).length === 0
|
|
1056
|
+
) {
|
|
1008
1057
|
// No file and nothing else to set: the editor, on the file as served.
|
|
1009
1058
|
const current = await client.text(`/api/v1/profiles/${ref}/openprofile.md`);
|
|
1010
1059
|
const path = join(tmpdir(), `nichedb-profile-${Date.now()}.md`);
|
|
@@ -1029,7 +1078,7 @@ export async function run(
|
|
|
1029
1078
|
markdown,
|
|
1030
1079
|
'text/markdown; charset=utf-8',
|
|
1031
1080
|
);
|
|
1032
|
-
const patch = {};
|
|
1081
|
+
const patch = { ...fields };
|
|
1033
1082
|
if (flags.handle) patch.handle = String(flags.handle);
|
|
1034
1083
|
if (flags.public) patch.public = true;
|
|
1035
1084
|
if (flags.private) patch.public = false;
|