Skip to content

Commit f50598b

Browse files
committed
feat: add lnk list command
1 parent 6768d22 commit f50598b

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

scripts/lnk

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ function usage() {
2424
Usage:
2525
./scripts/lnk LONG_URL [SLUG]
2626
./scripts/lnk --splat LONG_URL_WITH_:splat SLUG
27+
./scripts/lnk list [SLUG]
2728
2829
Schedules:
2930
./scripts/lnk schedule add SLUG TARGET --label LABEL --days mon,tue --from HH:MM --to HH:MM [--timezone TZ]
@@ -37,6 +38,7 @@ Block policies:
3738
./scripts/lnk block allow DOMAIN --reason TEXT
3839
3940
Options:
41+
--format FORMAT table | json for list output
4042
--state STATE permanent | ephemeral | expired | disabled | maintenance | deactivated
4143
--title TEXT Human-readable title
4244
--description TEXT Human-readable description
@@ -66,6 +68,8 @@ Notes:
6668
Successful write operations run npm run check, then commit and push automatically.
6769
6870
Examples:
71+
./scripts/lnk list
72+
./scripts/lnk list social/x
6973
./scripts/lnk https://github.com/vanityURLs github
7074
./scripts/lnk https://x.com/vanityURLs social/x
7175
./scripts/lnk https://www.linkedin.com/company/example social/linkedin
@@ -101,6 +105,7 @@ function run(command, args) {
101105

102106
function parseArgs(argv) {
103107
const options = {
108+
format: "table",
104109
state: "permanent",
105110
splat: false,
106111
title: "",
@@ -117,6 +122,9 @@ function parseArgs(argv) {
117122

118123
if (arg === "--help" || arg === "-h") {
119124
options.help = true;
125+
} else if (arg === "--format") {
126+
options.format = readOptionValue(argv, index, arg);
127+
index += 1;
120128
} else if (arg === "--splat") {
121129
options.splat = true;
122130
} else if (arg === "--state") {
@@ -232,6 +240,70 @@ function readJson(filePath, fallback) {
232240
return JSON.parse(fs.readFileSync(filePath, "utf8"));
233241
}
234242

243+
function ensureRegistry() {
244+
const registryPath = "build/v8s.json";
245+
if (!fs.existsSync(registryPath)) {
246+
run("npm", ["run", "build"]);
247+
}
248+
249+
return readJson(registryPath, { links: [] });
250+
}
251+
252+
function listLinks(requestedSlug, options) {
253+
const registry = ensureRegistry();
254+
const slug = requestedSlug ? normalizeSlug(requestedSlug) : "";
255+
const links = (registry.links || [])
256+
.filter((link) => !slug || link.slug === slug)
257+
.sort((a, b) => a.slug.localeCompare(b.slug));
258+
259+
if (options.format === "json") {
260+
console.log(JSON.stringify(links, null, 2));
261+
return;
262+
}
263+
264+
if (options.format !== "table") {
265+
throw new Error("--format must be table or json");
266+
}
267+
268+
if (!links.length) {
269+
console.log(slug ? `No link found for ${slug}` : "No links configured");
270+
return;
271+
}
272+
273+
printTable(links.map((link) => {
274+
return [
275+
link.slug,
276+
link.state || "permanent",
277+
link.owner || "",
278+
link.title || "",
279+
link.target || ""
280+
];
281+
}), ["Slug", "State", "Owner", "Title", "Target"]);
282+
}
283+
284+
function printTable(rows, headers) {
285+
const widths = headers.map((header, index) => {
286+
return Math.min(40, Math.max(header.length, ...rows.map((row) => String(row[index] || "").length)));
287+
});
288+
289+
console.log(headers.map((header, index) => padCell(header, widths[index])).join(" "));
290+
console.log(widths.map((width) => "-".repeat(width)).join(" "));
291+
292+
for (const row of rows) {
293+
console.log(row.map((cell, index) => padCell(truncateCell(cell, widths[index]), widths[index])).join(" "));
294+
}
295+
}
296+
297+
function truncateCell(value, width) {
298+
const text = String(value || "");
299+
if (text.length <= width) return text;
300+
return `${text.slice(0, Math.max(0, width - 1))}…`;
301+
}
302+
303+
function padCell(value, width) {
304+
return String(value || "").padEnd(width, " ");
305+
}
306+
235307
function writeJson(filePath, value) {
236308
fs.mkdirSync(dirname(filePath), {
237309
recursive: true
@@ -452,6 +524,11 @@ function main() {
452524
return;
453525
}
454526

527+
if (positionals[0] === "list") {
528+
listLinks(positionals[1] || "", options);
529+
return;
530+
}
531+
455532
const target = positionals[0] || "";
456533
let slug = positionals[1] || "";
457534

0 commit comments

Comments
 (0)