coding-friend-cli 1.0.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/dist/chunk-6CGGT2FD.js +32 -0
- package/dist/chunk-6DUFTBTO.js +14 -0
- package/dist/chunk-AQXTNLQD.js +39 -0
- package/dist/chunk-HRVSKMNA.js +31 -0
- package/dist/chunk-IUTXHCP7.js +28 -0
- package/dist/chunk-KZT4AFDW.js +44 -0
- package/dist/chunk-VHZQ6KEU.js +73 -0
- package/dist/host-3GAEZKKJ.js +83 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +34 -0
- package/dist/init-ONRXFOZ5.js +431 -0
- package/dist/json-2XS56OJY.js +10 -0
- package/dist/mcp-LMMIFH4B.js +104 -0
- package/dist/postinstall.d.ts +1 -0
- package/dist/postinstall.js +8 -0
- package/dist/statusline-7D6YU5YM.js +64 -0
- package/dist/update-K5PYOB52.js +160 -0
- package/lib/learn-host/next-env.d.ts +6 -0
- package/lib/learn-host/next.config.ts +9 -0
- package/lib/learn-host/package-lock.json +3943 -0
- package/lib/learn-host/package.json +31 -0
- package/lib/learn-host/postcss.config.mjs +7 -0
- package/lib/learn-host/scripts/build-search-index.ts +11 -0
- package/lib/learn-host/src/app/[category]/[slug]/page.tsx +61 -0
- package/lib/learn-host/src/app/[category]/page.tsx +35 -0
- package/lib/learn-host/src/app/globals.css +31 -0
- package/lib/learn-host/src/app/layout.tsx +32 -0
- package/lib/learn-host/src/app/page.tsx +63 -0
- package/lib/learn-host/src/app/search/page.tsx +94 -0
- package/lib/learn-host/src/app/search/search-index.json +42 -0
- package/lib/learn-host/src/components/Breadcrumbs.tsx +28 -0
- package/lib/learn-host/src/components/DocCard.tsx +32 -0
- package/lib/learn-host/src/components/MarkdownRenderer.tsx +13 -0
- package/lib/learn-host/src/components/MobileNav.tsx +56 -0
- package/lib/learn-host/src/components/SearchBar.tsx +36 -0
- package/lib/learn-host/src/components/Sidebar.tsx +44 -0
- package/lib/learn-host/src/components/TagBadge.tsx +12 -0
- package/lib/learn-host/src/components/ThemeToggle.tsx +30 -0
- package/lib/learn-host/src/lib/docs.ts +113 -0
- package/lib/learn-host/src/lib/search.ts +27 -0
- package/lib/learn-host/src/lib/types.ts +31 -0
- package/lib/learn-host/tsconfig.json +21 -0
- package/lib/learn-mcp/package-lock.json +1829 -0
- package/lib/learn-mcp/package.json +24 -0
- package/lib/learn-mcp/src/bin/learn-mcp.ts +2 -0
- package/lib/learn-mcp/src/index.ts +17 -0
- package/lib/learn-mcp/src/lib/docs.ts +199 -0
- package/lib/learn-mcp/src/lib/knowledge.ts +95 -0
- package/lib/learn-mcp/src/lib/types.ts +36 -0
- package/lib/learn-mcp/src/server.ts +22 -0
- package/lib/learn-mcp/src/tools/create-doc.ts +29 -0
- package/lib/learn-mcp/src/tools/get-review-list.ts +29 -0
- package/lib/learn-mcp/src/tools/improve-doc.ts +95 -0
- package/lib/learn-mcp/src/tools/list-categories.ts +19 -0
- package/lib/learn-mcp/src/tools/list-docs.ts +30 -0
- package/lib/learn-mcp/src/tools/read-doc.ts +29 -0
- package/lib/learn-mcp/src/tools/search-docs.ts +23 -0
- package/lib/learn-mcp/src/tools/track-knowledge.ts +35 -0
- package/lib/learn-mcp/src/tools/update-doc.ts +43 -0
- package/lib/learn-mcp/tsconfig.json +15 -0
- package/package.json +47 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/lib/exec.ts
|
|
2
|
+
import { execFileSync, spawn } from "child_process";
|
|
3
|
+
function run(cmd, args = [], opts) {
|
|
4
|
+
try {
|
|
5
|
+
return execFileSync(cmd, args, {
|
|
6
|
+
encoding: "utf-8",
|
|
7
|
+
cwd: opts?.cwd,
|
|
8
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
9
|
+
}).trim();
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function streamExec(cmd, args, opts) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const child = spawn(cmd, args, {
|
|
17
|
+
stdio: "inherit",
|
|
18
|
+
...opts
|
|
19
|
+
});
|
|
20
|
+
child.on("close", (code) => resolve(code ?? 0));
|
|
21
|
+
child.on("error", reject);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function commandExists(cmd) {
|
|
25
|
+
return run("which", [cmd]) !== null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
run,
|
|
30
|
+
streamExec,
|
|
31
|
+
commandExists
|
|
32
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/lib/log.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
var log = {
|
|
4
|
+
info: (msg) => console.log(chalk.blue("\u2139"), msg),
|
|
5
|
+
success: (msg) => console.log(chalk.green("\u2714"), msg),
|
|
6
|
+
warn: (msg) => console.log(chalk.yellow("\u26A0"), msg),
|
|
7
|
+
error: (msg) => console.log(chalk.red("\u2716"), msg),
|
|
8
|
+
step: (msg) => console.log(chalk.cyan("\u2192"), msg),
|
|
9
|
+
dim: (msg) => console.log(chalk.dim(msg))
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
log
|
|
14
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/lib/paths.ts
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { resolve, join } from "path";
|
|
4
|
+
function resolvePath(p, base = process.cwd()) {
|
|
5
|
+
if (p.startsWith("/")) return p;
|
|
6
|
+
if (p.startsWith("~/")) return join(homedir(), p.slice(2));
|
|
7
|
+
return resolve(base, p);
|
|
8
|
+
}
|
|
9
|
+
function localConfigPath() {
|
|
10
|
+
return resolve(process.cwd(), ".coding-friend", "config.json");
|
|
11
|
+
}
|
|
12
|
+
function globalConfigPath() {
|
|
13
|
+
return join(homedir(), ".coding-friend", "config.json");
|
|
14
|
+
}
|
|
15
|
+
function claudeSettingsPath() {
|
|
16
|
+
return join(homedir(), ".claude", "settings.json");
|
|
17
|
+
}
|
|
18
|
+
function installedPluginsPath() {
|
|
19
|
+
return join(homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
20
|
+
}
|
|
21
|
+
function pluginCachePath() {
|
|
22
|
+
return join(
|
|
23
|
+
homedir(),
|
|
24
|
+
".claude",
|
|
25
|
+
"plugins",
|
|
26
|
+
"cache",
|
|
27
|
+
"coding-friend-marketplace",
|
|
28
|
+
"coding-friend"
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
resolvePath,
|
|
34
|
+
localConfigPath,
|
|
35
|
+
globalConfigPath,
|
|
36
|
+
claudeSettingsPath,
|
|
37
|
+
installedPluginsPath,
|
|
38
|
+
pluginCachePath
|
|
39
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var DEFAULT_CONFIG = {
|
|
3
|
+
language: "en",
|
|
4
|
+
docsDir: "docs",
|
|
5
|
+
devRulesReminder: true,
|
|
6
|
+
learn: {
|
|
7
|
+
outputDir: "docs/learn",
|
|
8
|
+
categories: [
|
|
9
|
+
{
|
|
10
|
+
name: "concepts",
|
|
11
|
+
description: "Design patterns, algorithms, architecture principles"
|
|
12
|
+
},
|
|
13
|
+
{ name: "patterns", description: "Repository pattern, observer pattern" },
|
|
14
|
+
{
|
|
15
|
+
name: "languages",
|
|
16
|
+
description: "Language-specific features, syntax, idioms"
|
|
17
|
+
},
|
|
18
|
+
{ name: "tools", description: "Libraries, frameworks, CLI tools" },
|
|
19
|
+
{
|
|
20
|
+
name: "debugging",
|
|
21
|
+
description: "Debugging techniques, bug fixes"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
autoCommit: false,
|
|
25
|
+
readmeIndex: false
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
DEFAULT_CONFIG
|
|
31
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/lib/json.ts
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
function readJson(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
const content = readFileSync(filePath, "utf-8");
|
|
7
|
+
return JSON.parse(content);
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function writeJson(filePath, data) {
|
|
13
|
+
const dir = dirname(filePath);
|
|
14
|
+
if (!existsSync(dir)) {
|
|
15
|
+
mkdirSync(dir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
18
|
+
}
|
|
19
|
+
function mergeJson(filePath, data) {
|
|
20
|
+
const existing = readJson(filePath) ?? {};
|
|
21
|
+
writeJson(filePath, { ...existing, ...data });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
readJson,
|
|
26
|
+
writeJson,
|
|
27
|
+
mergeJson
|
|
28
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
globalConfigPath,
|
|
3
|
+
localConfigPath,
|
|
4
|
+
resolvePath
|
|
5
|
+
} from "./chunk-AQXTNLQD.js";
|
|
6
|
+
import {
|
|
7
|
+
readJson
|
|
8
|
+
} from "./chunk-IUTXHCP7.js";
|
|
9
|
+
|
|
10
|
+
// src/lib/config.ts
|
|
11
|
+
function resolveDocsDir(explicitPath) {
|
|
12
|
+
if (explicitPath) {
|
|
13
|
+
return resolvePath(explicitPath);
|
|
14
|
+
}
|
|
15
|
+
const local = readJson(localConfigPath());
|
|
16
|
+
if (local?.learn?.outputDir) {
|
|
17
|
+
return resolvePath(local.learn.outputDir);
|
|
18
|
+
}
|
|
19
|
+
const global = readJson(globalConfigPath());
|
|
20
|
+
if (global?.learn?.outputDir) {
|
|
21
|
+
return resolvePath(global.learn.outputDir);
|
|
22
|
+
}
|
|
23
|
+
return resolvePath("docs/learn");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/lib/lib-path.ts
|
|
27
|
+
import { existsSync } from "fs";
|
|
28
|
+
import { dirname, join } from "path";
|
|
29
|
+
import { fileURLToPath } from "url";
|
|
30
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
function getLibPath(name) {
|
|
32
|
+
const bundled = join(__dirname, "..", "..", "lib", name);
|
|
33
|
+
if (existsSync(bundled)) return bundled;
|
|
34
|
+
const sibling = join(__dirname, "..", "..", "..", "lib", name);
|
|
35
|
+
if (existsSync(sibling)) return sibling;
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Could not find lib/${name}. Ensure it exists in the CLI package or repo.`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
resolveDocsDir,
|
|
43
|
+
getLibPath
|
|
44
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
log
|
|
3
|
+
} from "./chunk-6DUFTBTO.js";
|
|
4
|
+
|
|
5
|
+
// src/lib/shell-completion.ts
|
|
6
|
+
import { appendFileSync, existsSync, readFileSync } from "fs";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
var MARKER_START = "# >>> coding-friend CLI completion >>>";
|
|
9
|
+
var MARKER_END = "# <<< coding-friend CLI completion <<<";
|
|
10
|
+
var BASH_BLOCK = `
|
|
11
|
+
|
|
12
|
+
${MARKER_START}
|
|
13
|
+
_cf_completions() {
|
|
14
|
+
local cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
15
|
+
local commands="init host mcp statusline update"
|
|
16
|
+
COMPREPLY=($(compgen -W "$commands" -- "$cur"))
|
|
17
|
+
}
|
|
18
|
+
complete -o default -F _cf_completions cf
|
|
19
|
+
${MARKER_END}
|
|
20
|
+
`;
|
|
21
|
+
var ZSH_BLOCK = `
|
|
22
|
+
|
|
23
|
+
${MARKER_START}
|
|
24
|
+
_cf() {
|
|
25
|
+
local -a commands
|
|
26
|
+
commands=(
|
|
27
|
+
'init:Initialize coding-friend in current project'
|
|
28
|
+
'host:Build and serve learning docs as a static website'
|
|
29
|
+
'mcp:Setup MCP server for learning docs'
|
|
30
|
+
'statusline:Setup coding-friend statusline in Claude Code'
|
|
31
|
+
'update:Update coding-friend plugin and refresh statusline'
|
|
32
|
+
)
|
|
33
|
+
_describe 'command' commands
|
|
34
|
+
}
|
|
35
|
+
compdef _cf cf
|
|
36
|
+
${MARKER_END}
|
|
37
|
+
`;
|
|
38
|
+
function getShellRcPath() {
|
|
39
|
+
const shell = process.env.SHELL ?? "";
|
|
40
|
+
if (shell.includes("zsh")) return `${homedir()}/.zshrc`;
|
|
41
|
+
return `${homedir()}/.bashrc`;
|
|
42
|
+
}
|
|
43
|
+
function getRcName(rcPath) {
|
|
44
|
+
return rcPath.endsWith(".zshrc") ? ".zshrc" : ".bashrc";
|
|
45
|
+
}
|
|
46
|
+
function isZsh(rcPath) {
|
|
47
|
+
return rcPath.endsWith(".zshrc");
|
|
48
|
+
}
|
|
49
|
+
function hasShellCompletion() {
|
|
50
|
+
const rcPath = getShellRcPath();
|
|
51
|
+
if (!existsSync(rcPath)) return false;
|
|
52
|
+
return readFileSync(rcPath, "utf-8").includes(MARKER_START);
|
|
53
|
+
}
|
|
54
|
+
function ensureShellCompletion(opts) {
|
|
55
|
+
const rcPath = getShellRcPath();
|
|
56
|
+
const rcName = getRcName(rcPath);
|
|
57
|
+
if (hasShellCompletion()) {
|
|
58
|
+
if (!opts?.silent) log.dim(`Tab completion already in ~/${rcName}`);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const block = isZsh(rcPath) ? ZSH_BLOCK : BASH_BLOCK;
|
|
62
|
+
appendFileSync(rcPath, block);
|
|
63
|
+
if (!opts?.silent) {
|
|
64
|
+
log.success(`Tab completion added to ~/${rcName}`);
|
|
65
|
+
log.dim(`Run \`source ~/${rcName}\` or open a new terminal to activate.`);
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export {
|
|
71
|
+
hasShellCompletion,
|
|
72
|
+
ensureShellCompletion
|
|
73
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLibPath,
|
|
3
|
+
resolveDocsDir
|
|
4
|
+
} from "./chunk-KZT4AFDW.js";
|
|
5
|
+
import "./chunk-HRVSKMNA.js";
|
|
6
|
+
import {
|
|
7
|
+
run,
|
|
8
|
+
streamExec
|
|
9
|
+
} from "./chunk-6CGGT2FD.js";
|
|
10
|
+
import "./chunk-AQXTNLQD.js";
|
|
11
|
+
import {
|
|
12
|
+
log
|
|
13
|
+
} from "./chunk-6DUFTBTO.js";
|
|
14
|
+
import "./chunk-IUTXHCP7.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/host.ts
|
|
17
|
+
import { existsSync, readdirSync } from "fs";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
function countMdFiles(dir) {
|
|
20
|
+
let count = 0;
|
|
21
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
22
|
+
if (entry.isDirectory()) {
|
|
23
|
+
count += countMdFiles(join(dir, entry.name));
|
|
24
|
+
} else if (entry.name.endsWith(".md") && entry.name !== "README.md") {
|
|
25
|
+
count++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return count;
|
|
29
|
+
}
|
|
30
|
+
function countCategories(dir) {
|
|
31
|
+
return readdirSync(dir, { withFileTypes: true }).filter(
|
|
32
|
+
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
33
|
+
).length;
|
|
34
|
+
}
|
|
35
|
+
async function hostCommand(path, opts) {
|
|
36
|
+
const docsDir = resolveDocsDir(path);
|
|
37
|
+
const port = opts?.port ?? "3333";
|
|
38
|
+
const hostDir = getLibPath("learn-host");
|
|
39
|
+
if (!existsSync(docsDir)) {
|
|
40
|
+
log.error(`Docs folder not found: ${docsDir}`);
|
|
41
|
+
log.dim("Run /cf-learn first to generate some docs.");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const docCount = countMdFiles(docsDir);
|
|
45
|
+
if (docCount === 0) {
|
|
46
|
+
log.error(`No .md files found in ${docsDir}`);
|
|
47
|
+
log.dim("Run /cf-learn first to generate some docs.");
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
const catCount = countCategories(docsDir);
|
|
51
|
+
console.log("=== \u{1F33F} Coding Friend Host \u{1F33F} ===");
|
|
52
|
+
log.info(`Docs folder: ${docsDir}`);
|
|
53
|
+
log.info(`Found: ${docCount} docs in ${catCount} categories`);
|
|
54
|
+
console.log();
|
|
55
|
+
if (!existsSync(join(hostDir, "node_modules"))) {
|
|
56
|
+
log.step("Installing dependencies (one-time setup)...");
|
|
57
|
+
const result = run("npm", ["install", "--silent"], { cwd: hostDir });
|
|
58
|
+
if (result === null) {
|
|
59
|
+
log.error("Failed to install dependencies");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
log.success("Done.");
|
|
63
|
+
console.log();
|
|
64
|
+
}
|
|
65
|
+
log.step("Building static site...");
|
|
66
|
+
const buildCode = await streamExec("npm", ["run", "build", "--silent"], {
|
|
67
|
+
cwd: hostDir,
|
|
68
|
+
env: { ...process.env, DOCS_DIR: docsDir }
|
|
69
|
+
});
|
|
70
|
+
if (buildCode !== 0) {
|
|
71
|
+
log.error("Build failed");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
console.log();
|
|
75
|
+
log.step("Starting local preview server...");
|
|
76
|
+
log.info(`Site: http://localhost:${port}`);
|
|
77
|
+
log.dim("Press Ctrl+C to stop.");
|
|
78
|
+
console.log();
|
|
79
|
+
await streamExec("npx", ["serve", "out", "-p", port], { cwd: hostDir });
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
hostCommand
|
|
83
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
var pkg = JSON.parse(
|
|
10
|
+
readFileSync(join(__dirname, "..", "package.json"), "utf-8")
|
|
11
|
+
);
|
|
12
|
+
var program = new Command();
|
|
13
|
+
program.name("cf").description("coding-friend CLI \u2014 host learning docs, setup MCP, init projects").version(pkg.version);
|
|
14
|
+
program.command("init").description("Initialize coding-friend in current project").action(async () => {
|
|
15
|
+
const { initCommand } = await import("./init-ONRXFOZ5.js");
|
|
16
|
+
await initCommand();
|
|
17
|
+
});
|
|
18
|
+
program.command("host").description("Build and serve learning docs as a static website").argument("[path]", "path to docs folder").option("-p, --port <port>", "port number", "3333").action(async (path, opts) => {
|
|
19
|
+
const { hostCommand } = await import("./host-3GAEZKKJ.js");
|
|
20
|
+
await hostCommand(path, opts);
|
|
21
|
+
});
|
|
22
|
+
program.command("mcp").description("Setup MCP server for learning docs").argument("[path]", "path to docs folder").action(async (path) => {
|
|
23
|
+
const { mcpCommand } = await import("./mcp-LMMIFH4B.js");
|
|
24
|
+
await mcpCommand(path);
|
|
25
|
+
});
|
|
26
|
+
program.command("statusline").description("Setup coding-friend statusline in Claude Code").action(async () => {
|
|
27
|
+
const { statuslineCommand } = await import("./statusline-7D6YU5YM.js");
|
|
28
|
+
await statuslineCommand();
|
|
29
|
+
});
|
|
30
|
+
program.command("update").description("Update coding-friend plugin and refresh statusline").action(async () => {
|
|
31
|
+
const { updateCommand } = await import("./update-K5PYOB52.js");
|
|
32
|
+
await updateCommand();
|
|
33
|
+
});
|
|
34
|
+
program.parse();
|