@next-generation-collective/factory 0.3.1 → 0.3.2
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/lib/banner.js +86 -0
- package/lib/cli.js +2 -1
- package/package.json +1 -1
package/lib/banner.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { basename, join } from "node:path";
|
|
5
|
+
import { colors } from "./util.js";
|
|
6
|
+
|
|
7
|
+
// The Next-Gen mark in the terminal: an N whose diagonal runs into a G, in the brand gold.
|
|
8
|
+
const MARK = [
|
|
9
|
+
"█▄ █ ▄▀▀▀▀",
|
|
10
|
+
"█ ▀▄█ █ ▄▄",
|
|
11
|
+
"█ █ ▀▄▄▄▀",
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const truecolor = /truecolor|24bit/i.test(process.env.COLORTERM ?? "");
|
|
15
|
+
const gold = (t) => colors.paint(truecolor ? "38;2;245;166;35" : "38;5;214", t);
|
|
16
|
+
const cream = (t) => colors.paint(truecolor ? "38;2;253;251;247" : "97", t);
|
|
17
|
+
|
|
18
|
+
const width = (text) => [...text.replace(/\u001b\[[0-9;]*m/g, "")].length;
|
|
19
|
+
|
|
20
|
+
// The builder's first name, from their git identity or, on a Mac, their account's full
|
|
21
|
+
// name. Nothing is sent anywhere.
|
|
22
|
+
export function firstName() {
|
|
23
|
+
const ask = (cmd, args) => {
|
|
24
|
+
try {
|
|
25
|
+
return execFileSync(cmd, args, { encoding: "utf8", timeout: 1000, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
26
|
+
} catch {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const full = ask("git", ["config", "user.name"]) || (process.platform === "darwin" ? ask("id", ["-F"]) : "");
|
|
31
|
+
return full.split(/\s+/)[0] || null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// One small file in the builder's own settings folder, so the first welcome happens once.
|
|
35
|
+
function welcomeFile() {
|
|
36
|
+
const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
37
|
+
return join(base, "next-gen", "welcomed");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isFirstVisit() {
|
|
41
|
+
try {
|
|
42
|
+
return !existsSync(welcomeFile());
|
|
43
|
+
} catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function rememberVisit() {
|
|
49
|
+
try {
|
|
50
|
+
const file = welcomeFile();
|
|
51
|
+
mkdirSync(join(file, ".."), { recursive: true });
|
|
52
|
+
writeFileSync(file, `${new Date().toISOString().slice(0, 10)}\n`);
|
|
53
|
+
} catch {
|
|
54
|
+
// A read-only home folder only means the long welcome shows again.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function welcomeLines({ name, first, version }) {
|
|
59
|
+
const you = name ? `, ${name}` : "";
|
|
60
|
+
return first
|
|
61
|
+
? [
|
|
62
|
+
colors.bold(cream(`Welcome to Next-Gen Factory${you}.`)),
|
|
63
|
+
cream("You are one of the builders of the AI economy."),
|
|
64
|
+
`${gold("Africa builds.")} ${colors.dim(`v${version}`)}`,
|
|
65
|
+
]
|
|
66
|
+
: [
|
|
67
|
+
colors.bold(cream(`Welcome back${you}.`)),
|
|
68
|
+
cream("Every build you prove makes every builder stronger."),
|
|
69
|
+
`${gold("Africa builds.")} ${colors.dim(`v${version}`)}`,
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function banner(version, root, { name = firstName(), first = isFirstVisit() } = {}) {
|
|
74
|
+
const lines = welcomeLines({ name, first, version });
|
|
75
|
+
const rows = lines.map((line, i) => ` ${gold(MARK[i] ?? " ".repeat(width(MARK[0])))} ${line}`);
|
|
76
|
+
const inner = Math.max(...rows.map(width)) + 2;
|
|
77
|
+
const edge = (l, r) => colors.dim(`${l}${"─".repeat(inner)}${r}`);
|
|
78
|
+
if (first) rememberVisit();
|
|
79
|
+
return [
|
|
80
|
+
edge("╭", "╮"),
|
|
81
|
+
...rows.map((row) => `${colors.dim("│")}${row}${" ".repeat(inner - width(row))}${colors.dim("│")}`),
|
|
82
|
+
edge("╰", "╯"),
|
|
83
|
+
colors.dim(` Reading ${basename(root) || root}...`),
|
|
84
|
+
"",
|
|
85
|
+
].join("\n");
|
|
86
|
+
}
|
package/lib/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
|
+
import { banner } from "./banner.js";
|
|
2
3
|
import { parse as parse_, resolve } from "node:path";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import {
|
|
@@ -132,7 +133,7 @@ export async function main(argv) {
|
|
|
132
133
|
console.error(refusal);
|
|
133
134
|
return 1;
|
|
134
135
|
}
|
|
135
|
-
if (process.
|
|
136
|
+
if (process.stdout.isTTY) console.log(banner(VERSION, root));
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
if (!command) return start(root, flags);
|
package/package.json
CHANGED