@countrystatecity/cli 0.1.5 → 0.1.7
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/README.md +4 -1
- package/dist/index.js +98 -101
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,12 +64,15 @@ csc search states -c US --filter "new"
|
|
|
64
64
|
|
|
65
65
|
# List all cities for a country
|
|
66
66
|
csc search cities --country IN
|
|
67
|
-
csc search cities --country IN --json
|
|
68
67
|
|
|
69
68
|
# List cities for a specific state
|
|
70
69
|
csc search cities --country IN --state MH
|
|
71
70
|
csc search cities -c US -s CA --json
|
|
72
71
|
|
|
72
|
+
# List all world regions (requires Starter plan+)
|
|
73
|
+
csc search regions
|
|
74
|
+
csc search regions --filter "asia"
|
|
75
|
+
|
|
73
76
|
# Global search (matches country names)
|
|
74
77
|
csc search india
|
|
75
78
|
```
|
package/dist/index.js
CHANGED
|
@@ -74,6 +74,11 @@ async function get(path) {
|
|
|
74
74
|
console.error(chalk.dim("Run `csc auth login` to set your key."));
|
|
75
75
|
process.exit(1);
|
|
76
76
|
}
|
|
77
|
+
if (status === 403) {
|
|
78
|
+
console.error(chalk.red("Access denied \u2014 this endpoint requires a higher plan."));
|
|
79
|
+
console.error(chalk.dim("Run `csc upgrade` to view available plans."));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
77
82
|
if (status === 429) {
|
|
78
83
|
console.error(chalk.red("Daily limit reached."));
|
|
79
84
|
console.error(chalk.yellow("Run `csc upgrade` to increase your limits."));
|
|
@@ -417,15 +422,14 @@ function printDetail(label, value) {
|
|
|
417
422
|
}
|
|
418
423
|
|
|
419
424
|
// src/commands/search.ts
|
|
425
|
+
function resolveFlags(cmd) {
|
|
426
|
+
const g = cmd.optsWithGlobals();
|
|
427
|
+
return { json: g.json ?? false, quiet: g.quiet ?? false, noFooter: g.footer === false };
|
|
428
|
+
}
|
|
420
429
|
function registerSearchCommands(program2) {
|
|
421
|
-
const search3 = program2.command("search").description("Search countries, states, and
|
|
430
|
+
const search3 = program2.command("search").description("Search countries, states, cities, and more");
|
|
422
431
|
search3.command("countries").description("List all countries").option("--filter <text>", "Filter by name").action(async (options, cmd) => {
|
|
423
|
-
const
|
|
424
|
-
const flags = {
|
|
425
|
-
json: globalOpts.json ?? false,
|
|
426
|
-
quiet: globalOpts.quiet ?? false,
|
|
427
|
-
noFooter: globalOpts.footer === false
|
|
428
|
-
};
|
|
432
|
+
const flags = resolveFlags(cmd);
|
|
429
433
|
const spinner = await createSpinner("Fetching countries...", flags);
|
|
430
434
|
const { data, usage } = await get("/countries");
|
|
431
435
|
spinner.stop();
|
|
@@ -437,112 +441,103 @@ function registerSearchCommands(program2) {
|
|
|
437
441
|
if (flags.json) {
|
|
438
442
|
printJson(countries);
|
|
439
443
|
} else {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
c
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
444
|
+
printTable(
|
|
445
|
+
["ISO2", "ISO3", "Name", "Capital", "Phone", "Currency"],
|
|
446
|
+
countries.map((c) => [
|
|
447
|
+
c.iso2,
|
|
448
|
+
c.iso3,
|
|
449
|
+
c.name,
|
|
450
|
+
c.capital || "",
|
|
451
|
+
c.phonecode ? `+${c.phonecode.replace(/^\+/, "")}` : "",
|
|
452
|
+
c.currency || ""
|
|
453
|
+
])
|
|
454
|
+
);
|
|
449
455
|
}
|
|
450
456
|
printUsageFooter(usage, flags);
|
|
451
457
|
});
|
|
452
458
|
search3.command("states").description("List states for a country, or all states globally").option("-c, --country <iso2>", "Country ISO2 code (omit to get all states globally)").option("--filter <text>", "Filter by name").action(async (options, cmd) => {
|
|
453
|
-
const
|
|
454
|
-
const flags = {
|
|
455
|
-
json: globalOpts.json ?? false,
|
|
456
|
-
quiet: globalOpts.quiet ?? false,
|
|
457
|
-
noFooter: globalOpts.footer === false
|
|
458
|
-
};
|
|
459
|
+
const flags = resolveFlags(cmd);
|
|
459
460
|
const code = options.country?.toUpperCase();
|
|
461
|
+
const endpoint = code ? `/countries/${code}/states` : "/states";
|
|
462
|
+
const spinner = await createSpinner(code ? `Fetching states for ${code}...` : "Fetching all states...", flags);
|
|
463
|
+
const { data, usage } = await get(endpoint);
|
|
464
|
+
spinner.stop();
|
|
465
|
+
let states = data;
|
|
466
|
+
if (options.filter) {
|
|
467
|
+
const term = options.filter.toLowerCase();
|
|
468
|
+
states = states.filter((s) => s.name.toLowerCase().includes(term));
|
|
469
|
+
}
|
|
470
|
+
if (flags.json) {
|
|
471
|
+
printJson(states);
|
|
472
|
+
} else {
|
|
473
|
+
printTable(
|
|
474
|
+
code ? ["ID", "Name", "ISO2", "Type"] : ["ID", "Name", "ISO2", "Type", "Country"],
|
|
475
|
+
states.map(
|
|
476
|
+
(s) => code ? [String(s.id), s.name, s.iso2 || "", s.type || ""] : [String(s.id), s.name, s.iso2 || "", s.type || "", s.country_code || ""]
|
|
477
|
+
)
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
printUsageFooter(usage, flags);
|
|
481
|
+
});
|
|
482
|
+
search3.command("cities").description("List cities globally, for a country, or for a state").option("-c, --country <iso2>", "Country ISO2 code").option("-s, --state <iso2>", "State ISO2 code").option("--filter <text>", "Filter by name").action(async (options, cmd) => {
|
|
483
|
+
const flags = resolveFlags(cmd);
|
|
484
|
+
const countryCode = options.country?.toUpperCase();
|
|
485
|
+
const stateCode = options.state?.toUpperCase();
|
|
460
486
|
let endpoint;
|
|
461
487
|
let spinnerText;
|
|
462
|
-
if (
|
|
463
|
-
endpoint = `/countries/${
|
|
464
|
-
spinnerText = `Fetching
|
|
488
|
+
if (countryCode && stateCode) {
|
|
489
|
+
endpoint = `/countries/${countryCode}/states/${stateCode}/cities`;
|
|
490
|
+
spinnerText = `Fetching cities for ${countryCode}/${stateCode}...`;
|
|
491
|
+
} else if (countryCode) {
|
|
492
|
+
endpoint = `/countries/${countryCode}/cities`;
|
|
493
|
+
spinnerText = `Fetching all cities for ${countryCode}...`;
|
|
465
494
|
} else {
|
|
466
|
-
|
|
467
|
-
|
|
495
|
+
process.stderr.write(chalk5.red("Country code required. Use --country IN\n"));
|
|
496
|
+
process.stderr.write(chalk5.dim("Use --state MH to filter by state.\n"));
|
|
497
|
+
process.exit(1);
|
|
498
|
+
return;
|
|
468
499
|
}
|
|
469
500
|
const spinner = await createSpinner(spinnerText, flags);
|
|
470
501
|
const { data, usage } = await get(endpoint);
|
|
471
502
|
spinner.stop();
|
|
472
|
-
let
|
|
503
|
+
let cities = data;
|
|
473
504
|
if (options.filter) {
|
|
474
505
|
const term = options.filter.toLowerCase();
|
|
475
|
-
|
|
506
|
+
cities = cities.filter((c) => c.name.toLowerCase().includes(term));
|
|
476
507
|
}
|
|
477
508
|
if (flags.json) {
|
|
478
|
-
printJson(
|
|
509
|
+
printJson(cities);
|
|
479
510
|
} else {
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
511
|
+
const hasExtra = !countryCode;
|
|
512
|
+
printTable(
|
|
513
|
+
hasExtra ? ["ID", "Name", "State", "Country"] : ["ID", "Name"],
|
|
514
|
+
cities.map(
|
|
515
|
+
(c) => hasExtra ? [String(c.id), c.name, c.state_code || "", c.country_code || ""] : [String(c.id), c.name]
|
|
516
|
+
)
|
|
517
|
+
);
|
|
487
518
|
}
|
|
488
519
|
printUsageFooter(usage, flags);
|
|
489
520
|
});
|
|
490
|
-
search3.command("
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (!countryCode) {
|
|
500
|
-
if (isTTY()) {
|
|
501
|
-
const countrySpinner = await createSpinner("Loading countries...", flags);
|
|
502
|
-
const { data: allCountries } = await get("/countries");
|
|
503
|
-
countrySpinner.stop();
|
|
504
|
-
countryCode = await promptCountry(allCountries);
|
|
505
|
-
} else {
|
|
506
|
-
process.stderr.write(chalk5.red("Country code required. Use --country IN\n"));
|
|
507
|
-
process.exit(1);
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
const stateCode = options.state?.toUpperCase();
|
|
512
|
-
let endpoint;
|
|
513
|
-
let spinnerText;
|
|
514
|
-
if (stateCode) {
|
|
515
|
-
endpoint = `/countries/${countryCode}/states/${stateCode}/cities`;
|
|
516
|
-
spinnerText = `Fetching cities for ${countryCode}/${stateCode}...`;
|
|
517
|
-
} else {
|
|
518
|
-
endpoint = `/countries/${countryCode}/cities`;
|
|
519
|
-
spinnerText = `Fetching all cities for ${countryCode}...`;
|
|
520
|
-
}
|
|
521
|
-
const spinner = await createSpinner(spinnerText, flags);
|
|
522
|
-
const { data, usage } = await get(endpoint);
|
|
523
|
-
spinner.stop();
|
|
524
|
-
let cities = data;
|
|
525
|
-
if (options.filter) {
|
|
526
|
-
const term = options.filter.toLowerCase();
|
|
527
|
-
cities = cities.filter((c) => c.name.toLowerCase().includes(term));
|
|
528
|
-
}
|
|
529
|
-
if (flags.json) {
|
|
530
|
-
printJson(cities);
|
|
531
|
-
} else {
|
|
532
|
-
const rows = cities.map((c) => [String(c.id), c.name]);
|
|
533
|
-
printTable(["ID", "Name"], rows);
|
|
534
|
-
}
|
|
535
|
-
printUsageFooter(usage, flags);
|
|
521
|
+
search3.command("regions").description("List all world regions").option("--filter <text>", "Filter by name").action(async (options, cmd) => {
|
|
522
|
+
const flags = resolveFlags(cmd);
|
|
523
|
+
const spinner = await createSpinner("Fetching regions...", flags);
|
|
524
|
+
const { data, usage } = await get("/regions");
|
|
525
|
+
spinner.stop();
|
|
526
|
+
let regions = data;
|
|
527
|
+
if (options.filter) {
|
|
528
|
+
const term = options.filter.toLowerCase();
|
|
529
|
+
regions = regions.filter((r) => r.name.toLowerCase().includes(term));
|
|
536
530
|
}
|
|
537
|
-
|
|
531
|
+
if (flags.json) {
|
|
532
|
+
printJson(regions);
|
|
533
|
+
} else {
|
|
534
|
+
printTable(["ID", "Name"], regions.map((r) => [String(r.id), r.name]));
|
|
535
|
+
}
|
|
536
|
+
printUsageFooter(usage, flags);
|
|
537
|
+
});
|
|
538
538
|
search3.argument("[query]", "Search term to match country names").action(async (query, options, cmd) => {
|
|
539
539
|
if (!query) return;
|
|
540
|
-
const
|
|
541
|
-
const flags = {
|
|
542
|
-
json: globalOpts.json ?? false,
|
|
543
|
-
quiet: globalOpts.quiet ?? false,
|
|
544
|
-
noFooter: globalOpts.footer === false
|
|
545
|
-
};
|
|
540
|
+
const flags = resolveFlags(cmd);
|
|
546
541
|
const spinner = await createSpinner("Searching...", flags);
|
|
547
542
|
const { data, usage } = await get("/countries");
|
|
548
543
|
spinner.stop();
|
|
@@ -553,15 +548,17 @@ function registerSearchCommands(program2) {
|
|
|
553
548
|
} else if (matches.length === 0) {
|
|
554
549
|
console.log(chalk5.yellow(`No countries matching "${query}".`));
|
|
555
550
|
} else {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
c
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
551
|
+
printTable(
|
|
552
|
+
["ISO2", "ISO3", "Name", "Capital", "Phone", "Currency"],
|
|
553
|
+
matches.map((c) => [
|
|
554
|
+
c.iso2,
|
|
555
|
+
c.iso3,
|
|
556
|
+
c.name,
|
|
557
|
+
c.capital || "",
|
|
558
|
+
c.phonecode ? `+${c.phonecode.replace(/^\+/, "")}` : "",
|
|
559
|
+
c.currency || ""
|
|
560
|
+
])
|
|
561
|
+
);
|
|
565
562
|
}
|
|
566
563
|
if (!flags.json) {
|
|
567
564
|
process.stderr.write(
|
|
@@ -1317,7 +1314,7 @@ async function promptCountry2(countries) {
|
|
|
1317
1314
|
}
|
|
1318
1315
|
});
|
|
1319
1316
|
}
|
|
1320
|
-
async function
|
|
1317
|
+
async function promptState2(states) {
|
|
1321
1318
|
return search2({
|
|
1322
1319
|
message: "Select a state",
|
|
1323
1320
|
source: (input) => {
|
|
@@ -1385,7 +1382,7 @@ async function runExploreSession(flags) {
|
|
|
1385
1382
|
stderr(`No states found for ${countryIso}.`);
|
|
1386
1383
|
return latestUsage;
|
|
1387
1384
|
}
|
|
1388
|
-
const stateIso = await
|
|
1385
|
+
const stateIso = await promptState2(states);
|
|
1389
1386
|
const selectedState = states.find((s) => s.iso2 === stateIso);
|
|
1390
1387
|
const stateName = selectedState?.name ?? stateIso;
|
|
1391
1388
|
let running = true;
|