@profullstack/nichedb 0.30.0 → 0.32.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/package.json +1 -1
- package/src/index.js +66 -1
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.32.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');
|
|
@@ -182,6 +182,13 @@ export const COMMANDS = [
|
|
|
182
182
|
summary: 'Print the RSS URL (or the feed itself with --fetch).',
|
|
183
183
|
options: ['--fetch'],
|
|
184
184
|
},
|
|
185
|
+
{
|
|
186
|
+
name: 'population',
|
|
187
|
+
usage: 'population [<country> [<state> [<city>]]] | zip <zip> | find <name>',
|
|
188
|
+
summary:
|
|
189
|
+
'Population from the world to the ZIP code: an area, its measures and its largest children.',
|
|
190
|
+
options: ['--level country|state|city|zip', '--limit', '--offset', '--json'],
|
|
191
|
+
},
|
|
185
192
|
{
|
|
186
193
|
name: 'profiles',
|
|
187
194
|
usage: 'profiles [<query>] [--since <iso>] [--mine]',
|
|
@@ -740,6 +747,64 @@ export async function run(
|
|
|
740
747
|
out(await res.text());
|
|
741
748
|
return 0;
|
|
742
749
|
}
|
|
750
|
+
case 'population': {
|
|
751
|
+
const qs = new URLSearchParams();
|
|
752
|
+
if (flags.level) qs.set('level', flags.level);
|
|
753
|
+
if (flags.limit) qs.set('limit', flags.limit);
|
|
754
|
+
if (flags.offset) qs.set('offset', flags.offset);
|
|
755
|
+
const people = (n) =>
|
|
756
|
+
n === null || n === undefined ? '—' : Math.round(n).toLocaleString('en-US');
|
|
757
|
+
const [sub, ...args] = rest;
|
|
758
|
+
|
|
759
|
+
if (sub === 'find') {
|
|
760
|
+
const name = args.join(' ');
|
|
761
|
+
if (!name) throw new Error('population find <name>');
|
|
762
|
+
const { areas } = await client.get(
|
|
763
|
+
`/api/v1/population/search?q=${encodeURIComponent(name)}`,
|
|
764
|
+
);
|
|
765
|
+
if (json) {
|
|
766
|
+
out(JSON.stringify(areas, null, 2));
|
|
767
|
+
return 0;
|
|
768
|
+
}
|
|
769
|
+
for (const a of areas)
|
|
770
|
+
out(`${pad(a.key, 34)} ${pad(a.level, 8)} ${pad(people(a.population), 14)} ${a.title}`);
|
|
771
|
+
if (areas.length === 0) out('(no place by that name)');
|
|
772
|
+
return 0;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
let path = '/api/v1/population';
|
|
776
|
+
if (sub === 'zip') {
|
|
777
|
+
if (!args[0]) throw new Error('population zip <zip>');
|
|
778
|
+
path = `/api/v1/population/zip/${encodeURIComponent(String(args[0]).trim())}`;
|
|
779
|
+
} else if (sub) {
|
|
780
|
+
path = `/api/v1/population/${encodeURIComponent(rest.join('-').toLowerCase())}`;
|
|
781
|
+
}
|
|
782
|
+
const body = await client.get(`${path}${qs.size ? `?${qs}` : ''}`);
|
|
783
|
+
if (json) {
|
|
784
|
+
out(JSON.stringify(body, null, 2));
|
|
785
|
+
return 0;
|
|
786
|
+
}
|
|
787
|
+
if (body.area) {
|
|
788
|
+
const a = body.area;
|
|
789
|
+
out(`${a.title} (${a.key}, ${a.level})`);
|
|
790
|
+
out(
|
|
791
|
+
` ${pad('population', 24)} ${people(a.population)}${a.year ? ` (${a.survey ?? a.year})` : ''}`,
|
|
792
|
+
);
|
|
793
|
+
for (const [k, v] of Object.entries(a.measures ?? {})) {
|
|
794
|
+
if (typeof v === 'number') out(` ${pad(k, 24)} ${v.toLocaleString('en-US')}`);
|
|
795
|
+
}
|
|
796
|
+
out(` ${a.page}`);
|
|
797
|
+
}
|
|
798
|
+
const kids = body.children?.areas ?? body.countries ?? [];
|
|
799
|
+
const total = body.children?.total ?? body.total ?? kids.length;
|
|
800
|
+
if (kids.length) {
|
|
801
|
+
out(
|
|
802
|
+
`\n${body.children?.level ?? 'country'}: ${kids.length} of ${Number(total).toLocaleString('en-US')}`,
|
|
803
|
+
);
|
|
804
|
+
for (const k of kids) out(` ${pad(k.key, 34)} ${pad(people(k.population), 14)} ${k.name}`);
|
|
805
|
+
}
|
|
806
|
+
return 0;
|
|
807
|
+
}
|
|
743
808
|
case 'profiles': {
|
|
744
809
|
const term = rest.join(' ');
|
|
745
810
|
const qs = new URLSearchParams();
|